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
This commit is contained in:
Jed Davis 2020-12-08 01:02:18 +00:00
Родитель f2254ae972
Коммит 145e038874
3 изменённых файлов: 58 добавлений и 20 удалений

Просмотреть файл

@ -13,6 +13,7 @@
# include <fcntl.h> # include <fcntl.h>
# include <sys/stat.h> # include <sys/stat.h>
# include <sys/types.h> # include <sys/types.h>
# include <time.h>
# include <unistd.h> # include <unistd.h>
#endif #endif
@ -70,16 +71,25 @@ void SandboxTestingChild::Bind(Endpoint<PSandboxTestingChild>&& aEndpoint) {
ErrnoTest("fstatat_as_lstat"_ns, true, [&] { ErrnoTest("fstatat_as_lstat"_ns, true, [&] {
return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW); return fstatat(AT_FDCWD, kAllowedPath, &st, AT_SYMLINK_NOFOLLOW);
}); });
# ifdef XP_LINUX # ifdef XP_LINUX
ErrnoTest("fstatat_as_fstat"_ns, true, ErrnoTest("fstatat_as_fstat"_ns, true,
[&] { return fstatat(0, "", &st, AT_EMPTY_PATH); }); [&] { return fstatat(0, "", &st, AT_EMPTY_PATH); });
# endif // XP_LINUX # 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, SendReportTestResults("dummy_test"_ns,
/* shouldSucceed */ true, /* shouldSucceed */ true,
/* didSucceed */ true, /* didSucceed */ true,
"The test framework fails if there are no cases."_ns); "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. // Tell SandboxTest that this process is done with all tests.

Просмотреть файл

@ -619,12 +619,19 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
switch (sysno) { switch (sysno) {
// Timekeeping // Timekeeping
case __NR_clock_nanosleep: //
case __NR_clock_getres: // (Note: the switch needs to start with a literal case, not a
#ifdef __NR_clock_gettime64 // macro; otherwise clang-format gets confused.)
case __NR_clock_gettime64: case __NR_gettimeofday:
#ifdef __NR_time
case __NR_time:
#endif #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 // clockid_t can encode a pid or tid to monitor another
// process or thread's CPU usage (see CPUCLOCK_PID and related // process or thread's CPU usage (see CPUCLOCK_PID and related
// definitions in include/linux/posix-timers.h in the kernel // definitions in include/linux/posix-timers.h in the kernel
@ -645,15 +652,8 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
.Else(InvalidSyscall()); .Else(InvalidSyscall());
} }
case __NR_gettimeofday:
#ifdef __NR_time
case __NR_time:
#endif
case __NR_nanosleep:
return Allow();
// Thread synchronization // Thread synchronization
case __NR_futex: CASES_FOR_futex:
// FIXME(bug 1441993): This could be more restrictive. // FIXME(bug 1441993): This could be more restrictive.
return Allow(); return Allow();

Просмотреть файл

@ -156,24 +156,52 @@ class SandboxPolicyBase : public sandbox::bpf_dsl::Policy {
# define CASES_FOR_sigreturn case __NR_rt_sigreturn # define CASES_FOR_sigreturn case __NR_rt_sigreturn
#endif #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) #if defined(__NR__newselect)
# define CASES_FOR_select \ # define CASES_FOR_select \
case __NR__newselect: \ case __NR__newselect: \
case __NR_pselect6 CASES_FOR_pselect6
#elif defined(__NR_select) #elif defined(__NR_select)
# define CASES_FOR_select \ # define CASES_FOR_select \
case __NR_select: \ case __NR_select: \
case __NR_pselect6 CASES_FOR_pselect6
#else #else
# define CASES_FOR_select case __NR_pselect6 # define CASES_FOR_select CASES_FOR_pselect6
#endif #endif
#ifdef __NR_poll #ifdef __NR_poll
# define CASES_FOR_poll \ # define CASES_FOR_poll \
case __NR_poll: \ case __NR_poll: \
case __NR_ppoll CASES_FOR_ppoll
#else #else
# define CASES_FOR_poll case __NR_ppoll # define CASES_FOR_poll CASES_FOR_ppoll
#endif #endif
#ifdef __NR_epoll_create #ifdef __NR_epoll_create