init: move selinux and seccomp set up to 2nd stage init.

If there is no valid pre-compiled SEPolicy policy, init may call
secilc, which exists on the system partition.  1st stage init won't
always live on this partition, so we need to move this SELinux setup
to 2nd stage init, which always lives on the system partition, to
ensure that both secilc and its caller are updated together.

Bug: 114059212
Test: hikey boots, sailfish boots
Change-Id: Iaf7b4af4a5c2ace16755ec2e54510ab95c53f041
This commit is contained in:
Tom Cherry 2018-09-05 15:37:26 -07:00
parent 146fd24c4b
commit d9e53dacf5
2 changed files with 47 additions and 28 deletions

View file

@ -19,6 +19,7 @@
#include <dirent.h>
#include <fcntl.h>
#include <pthread.h>
#include <seccomp_policy.h>
#include <signal.h>
#include <stdlib.h>
#include <string.h>
@ -40,6 +41,7 @@
#include <cutils/android_reboot.h>
#include <keyutils.h>
#include <libavb/libavb.h>
#include <selinux/android.h>
#ifndef RECOVERY
#include <binder/ProcessState.h>
@ -585,6 +587,43 @@ static void InitKernelLogging(char* argv[]) {
android::base::InitLogging(argv, &android::base::KernelLogger, InitAborter);
}
static void GlobalSeccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
bool in_qemu) {
if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
LOG(FATAL) << "Failed to globally enable seccomp!";
}
});
}
static void SetupSelinux(char** argv) {
android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
});
// Set up SELinux, loading the SELinux policy.
SelinuxSetupKernelLogging();
SelinuxInitialize();
// We're in the kernel domain and want to transition to the init domain. File systems that
// store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
// but other file systems do. In particular, this is needed for ramdisks such as the
// recovery image for A/B devices.
if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
}
setenv("SELINUX_INITIALIZED", "true", 1);
const char* path = "/system/bin/init";
const char* args[] = {path, nullptr};
execv(path, const_cast<char**>(args));
// execv() only returns if an error happened, in which case we
// panic and never return from this function.
PLOG(FATAL) << "execv(\"" << path << "\") failed";
}
int main(int argc, char** argv) {
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
@ -600,9 +639,16 @@ int main(int argc, char** argv) {
InstallRebootSignalHandlers();
}
if (getenv("SELINUX_INITIALIZED") == nullptr) {
SetupSelinux(argv);
}
InitKernelLogging(argv);
LOG(INFO) << "init second stage started!";
// Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
GlobalSeccomp();
// Set up a session keyring that all processes will have access to. It
// will hold things like FBE encryption keys. No process should override
// its session keyring.
@ -631,6 +677,7 @@ int main(int argc, char** argv) {
if (avb_version) property_set("ro.boot.avb_version", avb_version);
// Clean up our environment.
unsetenv("SELINUX_INITIALIZED");
unsetenv("INIT_STARTED_AT");
unsetenv("INIT_SELINUX_TOOK");
unsetenv("INIT_AVB_VERSION");

View file

@ -15,7 +15,6 @@
*/
#include <paths.h>
#include <seccomp_policy.h>
#include <stdlib.h>
#include <sys/mount.h>
#include <sys/stat.h>
@ -30,11 +29,9 @@
#include <android-base/logging.h>
#include <cutils/android_reboot.h>
#include <private/android_filesystem_config.h>
#include <selinux/android.h>
#include "first_stage_mount.h"
#include "reboot_utils.h"
#include "selinux.h"
#include "util.h"
using android::base::boot_clock;
@ -42,15 +39,6 @@ using android::base::boot_clock;
namespace android {
namespace init {
static void GlobalSeccomp() {
import_kernel_cmdline(false, [](const std::string& key, const std::string& value,
bool in_qemu) {
if (key == "androidboot.seccomp" && value == "global" && !set_global_seccomp_filter()) {
LOG(FATAL) << "Failed to globally enable seccomp!";
}
});
}
int main(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
@ -130,22 +118,6 @@ int main(int argc, char** argv) {
SetInitAvbVersionInRecovery();
// Does this need to be done in first stage init or can it be done later?
// Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
GlobalSeccomp();
// Set up SELinux, loading the SELinux policy.
SelinuxSetupKernelLogging();
SelinuxInitialize();
// We're in the kernel domain and want to transition to the init domain when we exec second
// stage init. File systems that store SELabels in their xattrs, such as ext4 do not need an
// explicit restorecon here, but other file systems do. In particular, this is needed for
// ramdisks such as the recovery image for A/B devices.
if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
}
static constexpr uint32_t kNanosecondsPerMillisecond = 1e6;
uint64_t start_ms = start_time.time_since_epoch().count() / kNanosecondsPerMillisecond;
setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);