From 145e0388742999098745063d0a27721c320c7827 Mon Sep 17 00:00:00 2001 From: Jed Davis Date: Tue, 8 Dec 2020 01:02:18 +0000 Subject: [PATCH] Bug 1678174 - Add remaining time64 syscalls to the Linux sandboxes. r=gcp 32-bit Linux architectures have gained new versions of every system call handling time values, to allow a transition to 64-bit time_t that will continue to work after the year 2038; newer versions of glibc will attempt them and fall back to the 32-bit path (without caching the failure, so at best we take the overhead of handling SIGSYS). This patch allows time64 syscalls in the same cases where we allow their time32 versions, including the restrictions on clockid_t to prevent interacting with other processes or threads of other processes. (I've confirmed that the argument types match otherwise, so it's safe to reuse the same policies.) Differential Revision: https://phabricator.services.mozilla.com/D98693 --- .../common/test/SandboxTestingChild.cpp | 14 ++++++- security/sandbox/linux/SandboxFilter.cpp | 26 ++++++------- security/sandbox/linux/SandboxFilterUtil.h | 38 ++++++++++++++++--- 3 files changed, 58 insertions(+), 20 deletions(-) diff --git a/security/sandbox/common/test/SandboxTestingChild.cpp b/security/sandbox/common/test/SandboxTestingChild.cpp index 68d5f8356944..be68b2ba4635 100644 --- a/security/sandbox/common/test/SandboxTestingChild.cpp +++ b/security/sandbox/common/test/SandboxTestingChild.cpp @@ -13,6 +13,7 @@ # include # include # include +# include # include #endif @@ -70,16 +71,25 @@ void SandboxTestingChild::Bind(Endpoint&& aEndpoint) { ErrnoTest("fstatat_as_lstat"_ns, true, [&] { return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW); }); + # ifdef XP_LINUX ErrnoTest("fstatat_as_fstat"_ns, true, [&] { return fstatat(0, "", &st, AT_EMPTY_PATH); }); # endif // XP_LINUX -#else // XP_UNIX + + const struct timespec usec = {0, 1000}; + ErrnoTest("nanosleep"_ns, true, [&] { return nanosleep(&usec, nullptr); }); + + struct timespec res = {0, 0}; + ErrnoTest("clock_getres"_ns, true, + [&] { return clock_getres(CLOCK_REALTIME, &res); }); + +#else // XP_UNIX SendReportTestResults("dummy_test"_ns, /* shouldSucceed */ true, /* didSucceed */ true, "The test framework fails if there are no cases."_ns); -#endif // XP_UNIX +#endif // XP_UNIX } // Tell SandboxTest that this process is done with all tests. diff --git a/security/sandbox/linux/SandboxFilter.cpp b/security/sandbox/linux/SandboxFilter.cpp index b25e6eaa243a..9fddcf0e6d16 100644 --- a/security/sandbox/linux/SandboxFilter.cpp +++ b/security/sandbox/linux/SandboxFilter.cpp @@ -619,12 +619,19 @@ class SandboxPolicyCommon : public SandboxPolicyBase { switch (sysno) { // Timekeeping - case __NR_clock_nanosleep: - case __NR_clock_getres: -#ifdef __NR_clock_gettime64 - case __NR_clock_gettime64: + // + // (Note: the switch needs to start with a literal case, not a + // macro; otherwise clang-format gets confused.) + case __NR_gettimeofday: +#ifdef __NR_time + case __NR_time: #endif - case __NR_clock_gettime: { + case __NR_nanosleep: + return Allow(); + + CASES_FOR_clock_gettime: + CASES_FOR_clock_getres: + CASES_FOR_clock_nanosleep : { // clockid_t can encode a pid or tid to monitor another // process or thread's CPU usage (see CPUCLOCK_PID and related // definitions in include/linux/posix-timers.h in the kernel @@ -645,15 +652,8 @@ class SandboxPolicyCommon : public SandboxPolicyBase { .Else(InvalidSyscall()); } - case __NR_gettimeofday: -#ifdef __NR_time - case __NR_time: -#endif - case __NR_nanosleep: - return Allow(); - // Thread synchronization - case __NR_futex: + CASES_FOR_futex: // FIXME(bug 1441993): This could be more restrictive. return Allow(); diff --git a/security/sandbox/linux/SandboxFilterUtil.h b/security/sandbox/linux/SandboxFilterUtil.h index 526dce07dfc6..367a0964bdfc 100644 --- a/security/sandbox/linux/SandboxFilterUtil.h +++ b/security/sandbox/linux/SandboxFilterUtil.h @@ -156,24 +156,52 @@ class SandboxPolicyBase : public sandbox::bpf_dsl::Policy { # define CASES_FOR_sigreturn case __NR_rt_sigreturn #endif +#ifdef __NR_clock_gettime64 +# define CASES_FOR_clock_gettime \ + case __NR_clock_gettime: \ + case __NR_clock_gettime64 +# define CASES_FOR_clock_getres \ + case __NR_clock_getres: \ + case __NR_clock_getres_time64 +# define CASES_FOR_clock_nanosleep \ + case __NR_clock_nanosleep: \ + case __NR_clock_nanosleep_time64 +# define CASES_FOR_pselect6 \ + case __NR_pselect6: \ + case __NR_pselect6_time64 +# define CASES_FOR_ppoll \ + case __NR_ppoll: \ + case __NR_ppoll_time64 +# define CASES_FOR_futex \ + case __NR_futex: \ + case __NR_futex_time64 +#else +# define CASES_FOR_clock_gettime case __NR_clock_gettime +# define CASES_FOR_clock_getres case __NR_clock_getres +# define CASES_FOR_clock_nanosleep case __NR_clock_nanosleep +# define CASES_FOR_pselect6 case __NR_pselect6 +# define CASES_FOR_ppoll case __NR_ppoll +# define CASES_FOR_futex case __NR_futex +#endif + #if defined(__NR__newselect) # define CASES_FOR_select \ case __NR__newselect: \ - case __NR_pselect6 + CASES_FOR_pselect6 #elif defined(__NR_select) # define CASES_FOR_select \ case __NR_select: \ - case __NR_pselect6 + CASES_FOR_pselect6 #else -# define CASES_FOR_select case __NR_pselect6 +# define CASES_FOR_select CASES_FOR_pselect6 #endif #ifdef __NR_poll # define CASES_FOR_poll \ case __NR_poll: \ - case __NR_ppoll + CASES_FOR_ppoll #else -# define CASES_FOR_poll case __NR_ppoll +# define CASES_FOR_poll CASES_FOR_ppoll #endif #ifdef __NR_epoll_create