Merge "init: add builtin check for perf_event LSM hooks"
This commit is contained in:
commit
cdebef1d2b
4 changed files with 85 additions and 4 deletions
|
@ -730,8 +730,8 @@ int SecondStageMain(int argc, char** argv) {
|
|||
}
|
||||
|
||||
am.QueueBuiltinAction(SetupCgroupsAction, "SetupCgroups");
|
||||
|
||||
am.QueueBuiltinAction(SetKptrRestrictAction, "SetKptrRestrict");
|
||||
am.QueueBuiltinAction(TestPerfEventSelinuxAction, "TestPerfEventSelinux");
|
||||
am.QueueEventTrigger("early-init");
|
||||
|
||||
// Queue an action that waits for coldboot done so we know ueventd has set up all of /dev...
|
||||
|
|
|
@ -18,14 +18,19 @@
|
|||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/perf_event.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/syscall.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <fstream>
|
||||
|
||||
#include <android-base/logging.h>
|
||||
#include <android-base/properties.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
|
||||
using android::base::unique_fd;
|
||||
using android::base::SetProperty;
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
@ -197,5 +202,61 @@ Result<void> SetKptrRestrictAction(const BuiltinArguments&) {
|
|||
return {};
|
||||
}
|
||||
|
||||
// Test for whether the kernel has SELinux hooks for the perf_event_open()
|
||||
// syscall. If the hooks are present, we can stop using the other permission
|
||||
// mechanism (perf_event_paranoid sysctl), and use only the SELinux policy to
|
||||
// control access to the syscall. The hooks are expected on all Android R
|
||||
// release kernels, but might be absent on devices that upgrade while keeping an
|
||||
// older kernel.
|
||||
//
|
||||
// There is no direct/synchronous way of finding out that a syscall failed due
|
||||
// to SELinux. Therefore we test for a combination of a success and a failure
|
||||
// that are explained by the platform's SELinux policy for the "init" domain:
|
||||
// * cpu-scoped perf_event is allowed
|
||||
// * ioctl() on the event fd is disallowed with EACCES
|
||||
//
|
||||
// Since init has CAP_SYS_ADMIN, these tests are not affected by the system-wide
|
||||
// perf_event_paranoid sysctl.
|
||||
//
|
||||
// If the SELinux hooks are detected, a special sysprop
|
||||
// (sys.init.perf_lsm_hooks) is set, which translates to a modification of
|
||||
// perf_event_paranoid (through init.rc sysprop actions).
|
||||
//
|
||||
// TODO(b/137092007): this entire test can be removed once the platform stops
|
||||
// supporting kernels that precede the perf_event_open hooks (Android common
|
||||
// kernels 4.4 and 4.9).
|
||||
Result<void> TestPerfEventSelinuxAction(const BuiltinArguments&) {
|
||||
// Use a trivial event that will be configured, but not started.
|
||||
struct perf_event_attr pe = {
|
||||
.type = PERF_TYPE_SOFTWARE,
|
||||
.size = sizeof(struct perf_event_attr),
|
||||
.config = PERF_COUNT_SW_TASK_CLOCK,
|
||||
.disabled = 1,
|
||||
.exclude_kernel = 1,
|
||||
};
|
||||
|
||||
// Open the above event targeting cpu 0. (EINTR not possible.)
|
||||
unique_fd fd(static_cast<int>(syscall(__NR_perf_event_open, &pe, /*pid=*/-1,
|
||||
/*cpu=*/0,
|
||||
/*group_fd=*/-1, /*flags=*/0)));
|
||||
if (fd == -1) {
|
||||
PLOG(ERROR) << "Unexpected perf_event_open error";
|
||||
return {};
|
||||
}
|
||||
|
||||
int ioctl_ret = ioctl(fd, PERF_EVENT_IOC_RESET);
|
||||
if (ioctl_ret != -1) {
|
||||
// Success implies that the kernel doesn't have the hooks.
|
||||
return {};
|
||||
} else if (errno != EACCES) {
|
||||
PLOG(ERROR) << "Unexpected perf_event ioctl error";
|
||||
return {};
|
||||
}
|
||||
|
||||
// Conclude that the SELinux hooks are present.
|
||||
SetProperty("sys.init.perf_lsm_hooks", "1");
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -29,6 +29,7 @@ namespace init {
|
|||
Result<void> MixHwrngIntoLinuxRngAction(const BuiltinArguments&);
|
||||
Result<void> SetMmapRndBitsAction(const BuiltinArguments&);
|
||||
Result<void> SetKptrRestrictAction(const BuiltinArguments&);
|
||||
Result<void> TestPerfEventSelinuxAction(const BuiltinArguments&);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -945,14 +945,33 @@ on property:sys.sysctl.extra_free_kbytes=*
|
|||
on property:sys.sysctl.tcp_def_init_rwnd=*
|
||||
write /proc/sys/net/ipv4/tcp_default_init_rwnd ${sys.sysctl.tcp_def_init_rwnd}
|
||||
|
||||
on property:security.perf_harden=0
|
||||
# perf_event_open syscall security:
|
||||
# Newer kernels have the ability to control the use of the syscall via SELinux
|
||||
# hooks. init tests for this, and sets sys_init.perf_lsm_hooks to 1 if the
|
||||
# kernel has the hooks. In this case, the system-wide perf_event_paranoid
|
||||
# sysctl is set to -1 (unrestricted use), and the SELinux policy is used for
|
||||
# controlling access. On older kernels, the paranoid value is the only means of
|
||||
# controlling access. It is normally 3 (allow only root), but the shell user
|
||||
# can lower it to 1 (allowing thread-scoped pofiling) via security.perf_harden.
|
||||
on property:sys.init.perf_lsm_hooks=1
|
||||
write /proc/sys/kernel/perf_event_paranoid -1
|
||||
on property:security.perf_harden=0 && property:sys.init.perf_lsm_hooks=""
|
||||
write /proc/sys/kernel/perf_event_paranoid 1
|
||||
on property:security.perf_harden=1 && property:sys.init.perf_lsm_hooks=""
|
||||
write /proc/sys/kernel/perf_event_paranoid 3
|
||||
|
||||
# Additionally, simpleperf profiler uses debug.* and security.perf_harden
|
||||
# sysprops to be able to indirectly set these sysctls.
|
||||
on property:security.perf_harden=0
|
||||
write /proc/sys/kernel/perf_event_max_sample_rate ${debug.perf_event_max_sample_rate:-100000}
|
||||
write /proc/sys/kernel/perf_cpu_time_max_percent ${debug.perf_cpu_time_max_percent:-25}
|
||||
write /proc/sys/kernel/perf_event_mlock_kb ${debug.perf_event_mlock_kb:-516}
|
||||
|
||||
# Default values.
|
||||
on property:security.perf_harden=1
|
||||
write /proc/sys/kernel/perf_event_paranoid 3
|
||||
write /proc/sys/kernel/perf_event_max_sample_rate 100000
|
||||
write /proc/sys/kernel/perf_cpu_time_max_percent 25
|
||||
write /proc/sys/kernel/perf_event_mlock_kb 516
|
||||
|
||||
|
||||
# on shutdown
|
||||
# In device's init.rc, this trigger can be used to do device-specific actions
|
||||
|
|
Loading…
Reference in a new issue