Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions new_changelogs/20261029T075739Z-fixed-sandbox-unique-shm.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
- **Sandbox grant transport is isolated and validated.**
Linux and FreeBSD now allocate an exclusive shared-memory object per
`spawn_sandboxed` call. Empty grant lists run as deny-all policies, while
malformed or oversized lists are rejected instead of being skipped or
truncated during serialization.
58 changes: 58 additions & 0 deletions runtime/sandbox/aether_sandbox_grants.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
#ifndef AETHER_SANDBOX_GRANTS_H
#define AETHER_SANDBOX_GRANTS_H

#include <errno.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

#define AETHER_SANDBOX_GRANTS_SIZE 8192

extern int list_size(void*);
extern void* list_get_raw(void*, int);
extern const char* aether_string_data(const void*);

static int aether_sandbox_serialize_grants(void* grant_list, char* buf,
size_t buf_size, size_t* data_size) {
if (!grant_list || !buf || !data_size || buf_size == 0) {
errno = EINVAL;
return -1;
}

int n = list_size(grant_list);
if (n < 0 || n % 2 != 0) {
errno = EINVAL;
return -1;
}

size_t pos = 0;
buf[0] = '\0';
for (int i = 0; i < n; i += 2) {
void* category_item = list_get_raw(grant_list, i);
void* pattern_item = list_get_raw(grant_list, i + 1);
if (!category_item || !pattern_item) {
errno = EINVAL;
return -1;
}
const char* category = aether_string_data(category_item);
const char* pattern = aether_string_data(pattern_item);
if (strchr(category, ':') ||
strpbrk(category, "\r\n") || strpbrk(pattern, "\r\n")) {
errno = EINVAL;
return -1;
}

int written = snprintf(buf + pos, buf_size - pos, "%s:%s\n",
category, pattern);
if (written < 0 || (size_t)written >= buf_size - pos) {
errno = E2BIG;
return -1;
}
pos += (size_t)written;
}

*data_size = pos + 1;
return 0;
}

#endif
77 changes: 77 additions & 0 deletions runtime/sandbox/aether_sandbox_shm.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
#ifndef AETHER_SANDBOX_SHM_H
#define AETHER_SANDBOX_SHM_H

#include <errno.h>
#include <fcntl.h>
#include <stdatomic.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <unistd.h>

#define AETHER_SANDBOX_SHM_NAME_SIZE 64
#define AETHER_SANDBOX_SHM_CREATE_ATTEMPTS 128

static atomic_uint aether_sandbox_shm_sequence = ATOMIC_VAR_INIT(0);

static int aether_sandbox_shm_create(char* name, size_t name_size) {
for (int attempt = 0; attempt < AETHER_SANDBOX_SHM_CREATE_ATTEMPTS; attempt++) {
unsigned sequence = atomic_fetch_add_explicit(
&aether_sandbox_shm_sequence, 1, memory_order_relaxed);
int written = snprintf(name, name_size, "/aether_sandbox_%ld_%u",
(long)getpid(), sequence);
if (written < 0 || (size_t)written >= name_size) {
errno = ENAMETOOLONG;
return -1;
}

int fd = shm_open(name, O_CREAT | O_EXCL | O_RDWR, 0600);
if (fd >= 0) return fd;
if (errno != EEXIST) return -1;
}
errno = EEXIST;
return -1;
}

static int aether_sandbox_shm_write(char* name, size_t name_size,
const void* data, size_t data_size) {
int fd = aether_sandbox_shm_create(name, name_size);
if (fd < 0) return -1;

if (ftruncate(fd, (off_t)data_size) != 0) {
int saved = errno;
close(fd);
shm_unlink(name);
errno = saved;
return -1;
}

void* mem = mmap(NULL, data_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (mem == MAP_FAILED) {
int saved = errno;
close(fd);
shm_unlink(name);
errno = saved;
return -1;
}

memcpy(mem, data, data_size);
if (munmap(mem, data_size) != 0) {
int saved = errno;
close(fd);
shm_unlink(name);
errno = saved;
return -1;
}
if (close(fd) != 0) {
int saved = errno;
shm_unlink(name);
errno = saved;
return -1;
}
return 0;
}

#endif
47 changes: 12 additions & 35 deletions runtime/sandbox/spawn_sandboxed_bsd.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 12 additions & 35 deletions runtime/sandbox/spawn_sandboxed_linux.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

78 changes: 78 additions & 0 deletions tests/integration/sandbox_grant_transport/harness.c

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading