Commit 54407b42 authored by Matthew Denton's avatar Matthew Denton Committed by Commit Bot

Allow restricted clock_nanosleep in Linux sandbox

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: default avatarRobert Sesek <rsesek@chromium.org>
Cr-Commit-Position: refs/heads/master@{#719421}
parent d1bda4df
......@@ -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();
}
......
......@@ -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
......
......@@ -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
......
......@@ -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();
......@@ -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()),
......@@ -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,
......
......@@ -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))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment