security_control_failure; severity high; confidence certain.
ptracesandbox.c:805
ptrace_sandbox_permit_open(..., 0) installs validate_open_readonly for __NR_open, but the validator only enforced the access mode bits. Because O_CREAT is not part of O_ACCMODE, a sandboxed tracee could call open("newfile", O_RDONLY | O_CREAT, 0600) and create a filesystem entry despite a read-only open policy.
Reported and reproduced from scanner output attributed to Swival Security Scanner: https://swival.dev
- The ptrace sandbox is active on the supported Linux i386 path.
- The policy permits
openwithwriteableset to0. - The attacker controls a sandboxed tracee syscall to
open.
ptrace_sandbox_permit_open(..., 0)installsvalidate_open_readonlyas the__NR_openvalidator.validate_open_readonlyfirst callsvalidate_open_default.validate_open_defaultrejects onlyO_ASYNC,O_DIRECT, andO_SYNC.validate_open_readonlythen checks only(arg2 & O_ACCMODE) != O_RDONLY.O_RDONLY | O_CREATpasses that check becauseO_CREATis outsideO_ACCMODE.get_actiontreats validator return0as allow and continues the traced syscall.- Result:
open("newfile", O_RDONLY | O_CREAT, 0600)creates a new filesystem entry under a read-only open policy.
This is the sandbox syscall access-control layer. The named read-only open control deterministically allows a mutating open flag. File creation changes filesystem state, so allowing O_CREAT violates the intended read-only policy and causes a sandbox integrity failure.
Reject mutating flags in the read-only open validator, including at least O_CREAT, O_TRUNC, and O_APPEND, while continuing to require O_RDONLY access mode.
The patch extends validate_open_readonly so a call is denied when either the access mode is not O_RDONLY or any mutating open flag is present. This preserves legitimate read-only opens while blocking creation, truncation, and append-oriented mutation attempts that contradict the read-only policy.
None
diff --git a/ptracesandbox.c b/ptracesandbox.c
index 37efd5a..a5b84d4 100644
--- a/ptracesandbox.c
+++ b/ptracesandbox.c
@@ -804,7 +804,8 @@ validate_open_readonly(struct pt_sandbox* p_sandbox, void* p_arg)
{
return ret;
}
- if ((arg2 & O_ACCMODE) != O_RDONLY)
+ if ((arg2 & O_ACCMODE) != O_RDONLY ||
+ (arg2 & (O_CREAT | O_TRUNC | O_APPEND)))
{
return -1;
}