From b2fbcdbe30cb84cd2f0b63e453f3782c49213264 Mon Sep 17 00:00:00 2001 From: Matthew Denton Date: Wed, 21 Jul 2021 17:12:27 +0000 Subject: [PATCH] Linux sandbox: ENOSYS for some statx syscalls On some platforms, glibc will default to statx for normal stat-family calls. Unfortunately there's no way to rewrite statx to something safe using a signal handler. Returning ENOSYS will cause glibc to fallback to old stat paths. Change-Id: Ieaddc8020b6555f2dfdc443197d13cb3fccc6bf1 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2823150 Commit-Queue: Matthew Denton Reviewed-by: Robert Sesek Cr-Commit-Position: refs/heads/master@{#903952} --- sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc | 11 +++++++++++ sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc | 1 + sandbox/linux/system_headers/linux_stat.h | 4 ++++ 3 files changed, 16 insertions(+) diff --git a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc index 9df0d2dbd3b5f..049e921694eda 100644 --- a/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc +++ b/sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc @@ -312,6 +312,17 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno, return RewriteFstatatSIGSYS(fs_denied_errno); } + // The statx syscall is a filesystem syscall, which will be denied below with + // fs_denied_errno. However, on some platforms, glibc will default to statx + // for normal stat-family calls. Unfortunately there's no way to rewrite statx + // to something safe using a signal handler. Returning ENOSYS will cause glibc + // to fallback to old stat paths. + if (sysno == __NR_statx) { + const Arg mask(3); + return If(mask == STATX_BASIC_STATS, Error(ENOSYS)) + .Else(Error(fs_denied_errno)); + } + if (SyscallSets::IsFileSystem(sysno) || SyscallSets::IsCurrentDirectory(sysno)) { return Error(fs_denied_errno); diff --git a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc index 96c9f490e28cd..8227dc1854643 100644 --- a/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc +++ b/sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc @@ -171,6 +171,7 @@ bool SyscallSets::IsFileSystem(int sysno) { (defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS)) case __NR_statfs64: #endif + case __NR_statx: // EPERM not a valid errno. case __NR_symlinkat: case __NR_truncate: #if defined(__i386__) || defined(__arm__) || \ diff --git a/sandbox/linux/system_headers/linux_stat.h b/sandbox/linux/system_headers/linux_stat.h index 83b89efc75e5e..e697dd6777ef5 100644 --- a/sandbox/linux/system_headers/linux_stat.h +++ b/sandbox/linux/system_headers/linux_stat.h @@ -161,6 +161,10 @@ struct kernel_stat { #define AT_EMPTY_PATH 0x1000 #endif +#if !defined(STATX_BASIC_STATS) +#define STATX_BASIC_STATS 0x000007ffU +#endif + // On 32-bit systems, we default to the 64-bit stat struct like libc // implementations do. Otherwise we default to the normal stat struct which is // already 64-bit.