Bug 1749606 - Allow clock_gettime() for same-process r=jld,gerald

This is used by the new code from the profiler that is able to detect
unregistered threads. Blocking it will make child-process hit sandbox
violation.

Differential Revision: https://phabricator.services.mozilla.com/D135648
This commit is contained in:
Alexandre Lissy 2022-01-21 23:03:26 +00:00
parent c95531067d
commit 52bcca7a4f
5 changed files with 57 additions and 18 deletions

View file

@ -22,6 +22,7 @@
# include <sched.h> # include <sched.h>
# include <sys/syscall.h> # include <sys/syscall.h>
# include <sys/un.h> # include <sys/un.h>
# include "mozilla/ProcInfo_linux.h"
# endif // XP_LINUX # endif // XP_LINUX
# include <sys/socket.h> # include <sys/socket.h>
# include <sys/stat.h> # include <sys/stat.h>
@ -83,6 +84,26 @@ void RunTestsContent(SandboxTestingChild* child) {
child->ErrnoTest("clock_getres"_ns, true, child->ErrnoTest("clock_getres"_ns, true,
[&] { return clock_getres(CLOCK_REALTIME, &res); }); [&] { return clock_getres(CLOCK_REALTIME, &res); });
// same process is allowed
struct timespec tproc = {0, 0};
clockid_t same_process = MAKE_PROCESS_CPUCLOCK(getpid(), CPUCLOCK_SCHED);
child->ErrnoTest("clock_gettime_same_process"_ns, true,
[&] { return clock_gettime(same_process, &tproc); });
// different process is blocked by sandbox (SIGSYS, kernel would return
// EINVAL)
struct timespec tprocd = {0, 0};
clockid_t diff_process = MAKE_PROCESS_CPUCLOCK(1, CPUCLOCK_SCHED);
child->ErrnoValueTest("clock_gettime_diff_process"_ns, ENOSYS,
[&] { return clock_gettime(diff_process, &tprocd); });
// thread is allowed
struct timespec tthread = {0, 0};
clockid_t thread =
MAKE_THREAD_CPUCLOCK((pid_t)syscall(__NR_gettid), CPUCLOCK_SCHED);
child->ErrnoTest("clock_gettime_thread"_ns, true,
[&] { return clock_gettime(thread, &tthread); });
// An abstract socket that does not starts with '/', so we don't want it to // An abstract socket that does not starts with '/', so we don't want it to
// work. // work.
// Checking ENETUNREACH should be thrown by SandboxBrokerClient::Connect() // Checking ENETUNREACH should be thrown by SandboxBrokerClient::Connect()
@ -245,7 +266,7 @@ void RunTestsRDD(SandboxTestingChild* child) {
return rv; return rv;
}); });
struct rusage res; struct rusage res = {};
child->ErrnoTest("getrusage"_ns, true, [&] { child->ErrnoTest("getrusage"_ns, true, [&] {
int rv = getrusage(RUSAGE_SELF, &res); int rv = getrusage(RUSAGE_SELF, &res);
return rv; return rv;

View file

@ -35,6 +35,7 @@
#include "SandboxLogging.h" #include "SandboxLogging.h"
#include "SandboxOpenedFiles.h" #include "SandboxOpenedFiles.h"
#include "mozilla/PodOperations.h" #include "mozilla/PodOperations.h"
#include "mozilla/ProcInfo_linux.h"
#include "mozilla/TemplateLib.h" #include "mozilla/TemplateLib.h"
#include "mozilla/UniquePtr.h" #include "mozilla/UniquePtr.h"
#include "prenv.h" #include "prenv.h"
@ -746,6 +747,8 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
// source). Those values could be detected by bit masking, // source). Those values could be detected by bit masking,
// but it's simpler to just have a default-deny policy. // but it's simpler to just have a default-deny policy.
Arg<clockid_t> clk_id(0); Arg<clockid_t> clk_id(0);
clockid_t this_process =
MAKE_PROCESS_CPUCLOCK(getpid(), CPUCLOCK_SCHED);
return If(clk_id == CLOCK_MONOTONIC, Allow()) return If(clk_id == CLOCK_MONOTONIC, Allow())
#ifdef CLOCK_MONOTONIC_COARSE #ifdef CLOCK_MONOTONIC_COARSE
// Used by SandboxReporter, among other things. // Used by SandboxReporter, among other things.
@ -758,9 +761,11 @@ class SandboxPolicyCommon : public SandboxPolicyBase {
#endif #endif
.ElseIf(clk_id == CLOCK_THREAD_CPUTIME_ID, Allow()) .ElseIf(clk_id == CLOCK_THREAD_CPUTIME_ID, Allow())
#ifdef MOZ_GECKO_PROFILER #ifdef MOZ_GECKO_PROFILER
// Allow clock_gettime on the same process.
.ElseIf(clk_id == this_process, Allow())
// Allow clock_gettime on a thread. // Allow clock_gettime on a thread.
// 4 -> CPUCLOCK_PERTHREAD_MASK. 2 -> CPUCLOCK_SCHED. .ElseIf((clk_id & 7u) == (CPUCLOCK_PERTHREAD_MASK | CPUCLOCK_SCHED),
.ElseIf((clk_id & 7u) == (4u | 2u), Allow()) Allow())
#endif #endif
#ifdef CLOCK_BOOTTIME #ifdef CLOCK_BOOTTIME
.ElseIf(clk_id == CLOCK_BOOTTIME, Allow()) .ElseIf(clk_id == CLOCK_BOOTTIME, Allow())

View file

@ -5,6 +5,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "mozilla/ProcInfo.h" #include "mozilla/ProcInfo.h"
#include "mozilla/ProcInfo_linux.h"
#include "mozilla/Sprintf.h" #include "mozilla/Sprintf.h"
#include "mozilla/Logging.h" #include "mozilla/Logging.h"
#include "mozilla/ScopeExit.h" #include "mozilla/ScopeExit.h"
@ -19,21 +20,6 @@
#define NANOPERSEC 1000000000. #define NANOPERSEC 1000000000.
#ifndef CPUCLOCK_SCHED
# define CPUCLOCK_SCHED 2
#endif
#ifndef CPUCLOCK_PERTHREAD_MASK
# define CPUCLOCK_PERTHREAD_MASK 4
#endif
#ifndef MAKE_PROCESS_CPUCLOCK
# define MAKE_PROCESS_CPUCLOCK(pid, clock) \
((int)(~(unsigned)(pid) << 3) | (int)(clock))
#endif
#ifndef MAKE_THREAD_CPUCLOCK
# define MAKE_THREAD_CPUCLOCK(tid, clock) \
MAKE_PROCESS_CPUCLOCK(tid, (clock) | CPUCLOCK_PERTHREAD_MASK)
#endif
namespace mozilla { namespace mozilla {
int GetCycleTimeFrequencyMHz() { return 0; } int GetCycleTimeFrequencyMHz() { return 0; }

View file

@ -0,0 +1,26 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#ifndef __mozilla_ProcInfo_linux_h
#define __mozilla_ProcInfo_linux_h
// The following is directly inspired from kernel:
// https://github.com/torvalds/linux/blob/v5.16/include/linux/posix-timers.h#L29-L48
#ifndef CPUCLOCK_SCHED
# define CPUCLOCK_SCHED 2
#endif
#ifndef CPUCLOCK_PERTHREAD_MASK
# define CPUCLOCK_PERTHREAD_MASK 4
#endif
#ifndef MAKE_PROCESS_CPUCLOCK
# define MAKE_PROCESS_CPUCLOCK(pid, clock) \
((int)(~(unsigned)(pid) << 3) | (int)(clock))
#endif
#ifndef MAKE_THREAD_CPUCLOCK
# define MAKE_THREAD_CPUCLOCK(tid, clock) \
MAKE_PROCESS_CPUCLOCK(tid, (clock) | CPUCLOCK_PERTHREAD_MASK)
#endif
#endif // ProcInfo_linux_h

View file

@ -19,6 +19,7 @@ XPIDL_SOURCES += [
EXPORTS.mozilla += [ EXPORTS.mozilla += [
"ProcInfo.h", "ProcInfo.h",
"ProcInfo_linux.h",
] ]
EXPORTS += [ EXPORTS += [