Loading init/init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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... Loading init/security.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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 init/security.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading rootdir/init.rc +22 −3 Original line number Diff line number Diff line Loading @@ -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 Loading
init/init.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -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... Loading
init/security.cpp +61 −0 Original line number Diff line number Diff line Loading @@ -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 { Loading Loading @@ -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
init/security.h +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
rootdir/init.rc +22 −3 Original line number Diff line number Diff line Loading @@ -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