Skip to content

Commit

Permalink
Allow restricted clock_nanosleep in Linux sandbox
Browse files Browse the repository at this point in the history
To support glibc 2.30, allow clock_nanosleep in the baseline BPF
policy, with the same clock_id restrictions as clock_gettime and
other clock_* syscalls.

Bug: 1025739
Change-Id: Ic53a782fef01049bc61c535b50735a4a7d4c23c0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1935715
Commit-Queue: Matthew Denton <mpdenton@chromium.org>
Reviewed-by: Robert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719421}
  • Loading branch information
mdenton8 authored and Commit Bot committed Nov 26, 2019
1 parent d1bda4d commit 54407b4
Show file tree
Hide file tree
Showing 5 changed files with 54 additions and 11 deletions.
2 changes: 1 addition & 1 deletion sandbox/linux/seccomp-bpf-helpers/baseline_policy.cc
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,7 @@ ResultExpr EvaluateSyscallImpl(int fs_denied_errno,
return Allow();
#endif

if (sysno == __NR_clock_gettime) {
if (sysno == __NR_clock_gettime || sysno == __NR_clock_nanosleep) {
return RestrictClockID();
}

Expand Down
11 changes: 11 additions & 0 deletions sandbox/linux/seccomp-bpf-helpers/baseline_policy_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,17 @@ BPF_DEATH_TEST_C(BaselinePolicy,
syscall(SYS_clock_gettime, (~0) | CLOCKFD, &ts);
}

BPF_DEATH_TEST_C(BaselinePolicy,
ClockNanosleepWithDisallowedClockCrashes,
DEATH_SEGV_MESSAGE(GetErrorMessageContentForTests()),
BaselinePolicy) {
struct timespec ts;
struct timespec out_ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
syscall(SYS_clock_nanosleep, (~0) | CLOCKFD, 0, &ts, &out_ts);
}

#if !defined(GRND_RANDOM)
#define GRND_RANDOM 2
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,13 @@ SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictPrlimit64(pid_t target_pid);
// process).
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictGetrusage();

// Restrict |clk_id| for clock_getres(), clock_gettime() and clock_settime(). We
// allow accessing only CLOCK_BOOTTIME, CLOCK_MONOTONIC{,_RAW,_COARSE},
// CLOCK_PROCESS_CPUTIME_ID, CLOCK_REALTIME{,_COARSE}, and
// CLOCK_THREAD_CPUTIME_ID. In particular, this disallows access to arbitrary
// per-{process,thread} CPU-time clock IDs (such as those returned by
// {clock,pthread}_getcpuclockid), which can leak information about the state of
// the host OS.
// Restrict |clk_id| for clock_getres(), clock_gettime(), clock_settime(), and
// clock_nanosleep(). We allow accessing only CLOCK_BOOTTIME,
// CLOCK_MONOTONIC{,_RAW,_COARSE}, CLOCK_PROCESS_CPUTIME_ID,
// CLOCK_REALTIME{,_COARSE}, and CLOCK_THREAD_CPUTIME_ID. In particular, on
// non-Android platforms this disallows access to arbitrary per-{process,thread}
// CPU-time clock IDs (such as those returned by {clock,pthread}_getcpuclockid),
// which can leak information about the state of the host OS.
SANDBOX_EXPORT bpf_dsl::ResultExpr RestrictClockID();

// Restrict the flags argument to getrandom() to allow only no flags, or
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class RestrictClockIdPolicy : public bpf_dsl::Policy {
switch (sysno) {
case __NR_clock_gettime:
case __NR_clock_getres:
case __NR_clock_nanosleep:
return RestrictClockID();
default:
return Allow();
Expand Down Expand Up @@ -98,6 +99,25 @@ BPF_TEST_C(ParameterRestrictions,
#endif
}

void CheckClockNanosleep(clockid_t clockid) {
struct timespec ts;
struct timespec out_ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
clock_nanosleep(clockid, 0, &ts, &out_ts);
}

BPF_TEST_C(ParameterRestrictions,
clock_nanosleep_allowed,
RestrictClockIdPolicy) {
CheckClockNanosleep(CLOCK_MONOTONIC);
CheckClockNanosleep(CLOCK_MONOTONIC_COARSE);
CheckClockNanosleep(CLOCK_MONOTONIC_RAW);
CheckClockNanosleep(CLOCK_BOOTTIME);
CheckClockNanosleep(CLOCK_REALTIME);
CheckClockNanosleep(CLOCK_REALTIME_COARSE);
}

BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_clock_fd,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
Expand All @@ -106,6 +126,17 @@ BPF_DEATH_TEST_C(ParameterRestrictions,
syscall(SYS_clock_gettime, (~0) | CLOCKFD, &ts);
}

BPF_DEATH_TEST_C(ParameterRestrictions,
clock_nanosleep_crash_clock_fd,
DEATH_SEGV_MESSAGE(sandbox::GetErrorMessageContentForTests()),
RestrictClockIdPolicy) {
struct timespec ts;
struct timespec out_ts;
ts.tv_sec = 0;
ts.tv_nsec = 0;
syscall(SYS_clock_nanosleep, (~0) | CLOCKFD, 0, &ts, &out_ts);
}

#if !defined(OS_ANDROID)
BPF_DEATH_TEST_C(ParameterRestrictions,
clock_gettime_crash_cpu_clock,
Expand Down
7 changes: 4 additions & 3 deletions sandbox/linux/seccomp-bpf-helpers/syscall_sets.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,10 @@ bool SyscallSets::IsAllowedGettime(int sysno) {
return true;
case __NR_adjtimex: // Privileged.
case __NR_clock_adjtime: // Privileged.
case __NR_clock_getres: // Could be allowed.
case __NR_clock_gettime:
case __NR_clock_nanosleep: // Could be allowed.
case __NR_clock_getres: // Allowed only on Android with parameters
// filtered by RestrictClokID().
case __NR_clock_gettime: // Parameters filtered by RestrictClockID().
case __NR_clock_nanosleep: // Parameters filtered by RestrictClockID().
case __NR_clock_settime: // Privileged.
#if defined(__i386__) || \
(defined(ARCH_CPU_MIPS_FAMILY) && defined(ARCH_CPU_32_BITS))
Expand Down

0 comments on commit 54407b4

Please sign in to comment.