seccomp: require child memory peek in the availability probe
With Yama ptrace_scope=2 and no CAP_SYS_PTRACE, process_vm_readv and /proc/<pid>/mem both fail, so sc_decide cannot read path strings and every workspace write gets EACCES. The old probe only checked the USER_NOTIF round trip, so CST_SANDBOX=seccomp and the forced-seccomp test pass looked available and then failed on the first write. sc_can_peek() forks a child, places a marker on its stack, and retries the same sc_peek path. sc_probe() now needs that too, so those hosts fall back to none (or keep landlock) instead of a silent deny-all sandbox.
This commit is contained in:
+42
-1
@@ -391,6 +391,47 @@ static ssize_t sc_peek(int pid, uint64_t addr, void *out, size_t n) {
|
||||
return k;
|
||||
}
|
||||
|
||||
/* Path decisions need sc_peek on the sandboxed child. Yama
|
||||
* kernel.yama.ptrace_scope=2 (and no CAP_SYS_PTRACE) denies that, so a
|
||||
* listener-only probe would report seccomp available while every write
|
||||
* fails with EACCES. */
|
||||
static int sc_can_peek(void) {
|
||||
static const char want[] = "cst-peek-ok";
|
||||
int sp[2];
|
||||
if (pipe2(sp, O_CLOEXEC) != 0)
|
||||
return 0;
|
||||
pid_t pid = fork();
|
||||
if (pid == 0) {
|
||||
char marker[] = "cst-peek-ok";
|
||||
uint64_t addr = (uint64_t)(uintptr_t)marker;
|
||||
close(sp[0]);
|
||||
if (write(sp[1], &addr, sizeof(addr)) != (ssize_t)sizeof(addr))
|
||||
_exit(1);
|
||||
close(sp[1]);
|
||||
pause();
|
||||
_exit(0);
|
||||
}
|
||||
close(sp[1]);
|
||||
if (pid < 0) {
|
||||
close(sp[0]);
|
||||
return 0;
|
||||
}
|
||||
uint64_t addr = 0;
|
||||
int ok = 0;
|
||||
if (read(sp[0], &addr, sizeof(addr)) == (ssize_t)sizeof(addr) && addr) {
|
||||
char got[sizeof(want)];
|
||||
if (sc_peek((int)pid, addr, got, sizeof(got)) == (ssize_t)sizeof(got) &&
|
||||
memcmp(got, want, sizeof(got)) == 0)
|
||||
ok = 1;
|
||||
}
|
||||
close(sp[0]);
|
||||
kill(pid, SIGKILL);
|
||||
int st = 0;
|
||||
while (waitpid(pid, &st, 0) < 0 && errno == EINTR)
|
||||
;
|
||||
return ok;
|
||||
}
|
||||
|
||||
static int sc_read_mem(int pid, uint64_t addr, void *out, size_t n) {
|
||||
size_t got = 0;
|
||||
while (got < n) {
|
||||
@@ -862,7 +903,7 @@ static int sc_probe(void) {
|
||||
int st = 0;
|
||||
while (waitpid(pid, &st, 0) < 0 && errno == EINTR)
|
||||
;
|
||||
return ok && WIFEXITED(st) && WEXITSTATUS(st) == 0;
|
||||
return ok && WIFEXITED(st) && WEXITSTATUS(st) == 0 && sc_can_peek();
|
||||
}
|
||||
|
||||
#endif /* CST_HAVE_SECCOMP */
|
||||
|
||||
Reference in New Issue
Block a user