Home | History | Annotate | Download | only in init
      1 /*
      2  * Copyright (C) 2017 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 // This file contains the functions that initialize SELinux during boot as well as helper functions
     18 // for SELinux operation for init.
     19 
     20 // When the system boots, there is no SEPolicy present and init is running in the kernel domain.
     21 // Init loads the SEPolicy from the file system, restores the context of /init based on this
     22 // SEPolicy, and finally exec()'s itself to run in the proper domain.
     23 
     24 // The SEPolicy on Android comes in two variants: monolithic and split.
     25 
     26 // The monolithic policy variant is for legacy non-treble devices that contain a single SEPolicy
     27 // file located at /sepolicy and is directly loaded into the kernel SELinux subsystem.
     28 
     29 // The split policy is for supporting treble devices.  It splits the SEPolicy across files on
     30 // /system/etc/selinux (the 'plat' portion of the policy) and /vendor/etc/selinux (the 'nonplat'
     31 // portion of the policy).  This is necessary to allow the system image to be updated independently
     32 // of the vendor image, while maintaining contributions from both partitions in the SEPolicy.  This
     33 // is especially important for VTS testing, where the SEPolicy on the Google System Image may not be
     34 // identical to the system image shipped on a vendor's device.
     35 
     36 // The split SEPolicy is loaded as described below:
     37 // 1) There is a precompiled SEPolicy located at /vendor/etc/selinux/precompiled_sepolicy.
     38 //    Stored along with this file is the sha256 hash of the parts of the SEPolicy on /system that
     39 //    were used to compile this precompiled policy.  The system partition contains a similar sha256
     40 //    of the parts of the SEPolicy that it currently contains.  If these two hashes match, then the
     41 //    system loads this precompiled_sepolicy directly.
     42 // 2) If these hashes do not match, then /system has been updated out of sync with /vendor and the
     43 //    init needs to compile the SEPolicy.  /system contains the SEPolicy compiler, secilc, and it
     44 //    is used by the LoadSplitPolicy() function below to compile the SEPolicy to a temp directory
     45 //    and load it.  That function contains even more documentation with the specific implementation
     46 //    details of how the SEPolicy is compiled if needed.
     47 
     48 #include "selinux.h"
     49 
     50 #include <fcntl.h>
     51 #include <stdlib.h>
     52 #include <sys/wait.h>
     53 #include <unistd.h>
     54 
     55 #include <android-base/chrono_utils.h>
     56 #include <android-base/file.h>
     57 #include <android-base/logging.h>
     58 #include <android-base/parseint.h>
     59 #include <android-base/unique_fd.h>
     60 #include <selinux/android.h>
     61 
     62 #include "log.h"
     63 #include "util.h"
     64 
     65 using android::base::ParseInt;
     66 using android::base::Timer;
     67 using android::base::unique_fd;
     68 
     69 namespace android {
     70 namespace init {
     71 
     72 namespace {
     73 
     74 selabel_handle* sehandle = nullptr;
     75 
     76 enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
     77 
     78 EnforcingStatus StatusFromCmdline() {
     79     EnforcingStatus status = SELINUX_ENFORCING;
     80 
     81     import_kernel_cmdline(false,
     82                           [&](const std::string& key, const std::string& value, bool in_qemu) {
     83                               if (key == "androidboot.selinux" && value == "permissive") {
     84                                   status = SELINUX_PERMISSIVE;
     85                               }
     86                           });
     87 
     88     return status;
     89 }
     90 
     91 bool IsEnforcing() {
     92     if (ALLOW_PERMISSIVE_SELINUX) {
     93         return StatusFromCmdline() == SELINUX_ENFORCING;
     94     }
     95     return true;
     96 }
     97 
     98 // Forks, executes the provided program in the child, and waits for the completion in the parent.
     99 // Child's stderr is captured and logged using LOG(ERROR).
    100 bool ForkExecveAndWaitForCompletion(const char* filename, char* const argv[]) {
    101     // Create a pipe used for redirecting child process's output.
    102     // * pipe_fds[0] is the FD the parent will use for reading.
    103     // * pipe_fds[1] is the FD the child will use for writing.
    104     int pipe_fds[2];
    105     if (pipe(pipe_fds) == -1) {
    106         PLOG(ERROR) << "Failed to create pipe";
    107         return false;
    108     }
    109 
    110     pid_t child_pid = fork();
    111     if (child_pid == -1) {
    112         PLOG(ERROR) << "Failed to fork for " << filename;
    113         return false;
    114     }
    115 
    116     if (child_pid == 0) {
    117         // fork succeeded -- this is executing in the child process
    118 
    119         // Close the pipe FD not used by this process
    120         close(pipe_fds[0]);
    121 
    122         // Redirect stderr to the pipe FD provided by the parent
    123         if (TEMP_FAILURE_RETRY(dup2(pipe_fds[1], STDERR_FILENO)) == -1) {
    124             PLOG(ERROR) << "Failed to redirect stderr of " << filename;
    125             _exit(127);
    126             return false;
    127         }
    128         close(pipe_fds[1]);
    129 
    130         if (execv(filename, argv) == -1) {
    131             PLOG(ERROR) << "Failed to execve " << filename;
    132             return false;
    133         }
    134         // Unreachable because execve will have succeeded and replaced this code
    135         // with child process's code.
    136         _exit(127);
    137         return false;
    138     } else {
    139         // fork succeeded -- this is executing in the original/parent process
    140 
    141         // Close the pipe FD not used by this process
    142         close(pipe_fds[1]);
    143 
    144         // Log the redirected output of the child process.
    145         // It's unfortunate that there's no standard way to obtain an istream for a file descriptor.
    146         // As a result, we're buffering all output and logging it in one go at the end of the
    147         // invocation, instead of logging it as it comes in.
    148         const int child_out_fd = pipe_fds[0];
    149         std::string child_output;
    150         if (!android::base::ReadFdToString(child_out_fd, &child_output)) {
    151             PLOG(ERROR) << "Failed to capture full output of " << filename;
    152         }
    153         close(child_out_fd);
    154         if (!child_output.empty()) {
    155             // Log captured output, line by line, because LOG expects to be invoked for each line
    156             std::istringstream in(child_output);
    157             std::string line;
    158             while (std::getline(in, line)) {
    159                 LOG(ERROR) << filename << ": " << line;
    160             }
    161         }
    162 
    163         // Wait for child to terminate
    164         int status;
    165         if (TEMP_FAILURE_RETRY(waitpid(child_pid, &status, 0)) != child_pid) {
    166             PLOG(ERROR) << "Failed to wait for " << filename;
    167             return false;
    168         }
    169 
    170         if (WIFEXITED(status)) {
    171             int status_code = WEXITSTATUS(status);
    172             if (status_code == 0) {
    173                 return true;
    174             } else {
    175                 LOG(ERROR) << filename << " exited with status " << status_code;
    176             }
    177         } else if (WIFSIGNALED(status)) {
    178             LOG(ERROR) << filename << " killed by signal " << WTERMSIG(status);
    179         } else if (WIFSTOPPED(status)) {
    180             LOG(ERROR) << filename << " stopped by signal " << WSTOPSIG(status);
    181         } else {
    182             LOG(ERROR) << "waitpid for " << filename << " returned unexpected status: " << status;
    183         }
    184 
    185         return false;
    186     }
    187 }
    188 
    189 bool ReadFirstLine(const char* file, std::string* line) {
    190     line->clear();
    191 
    192     std::string contents;
    193     if (!android::base::ReadFileToString(file, &contents, true /* follow symlinks */)) {
    194         return false;
    195     }
    196     std::istringstream in(contents);
    197     std::getline(in, *line);
    198     return true;
    199 }
    200 
    201 bool FindPrecompiledSplitPolicy(std::string* file) {
    202     file->clear();
    203     // If there is an odm partition, precompiled_sepolicy will be in
    204     // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
    205     static constexpr const char vendor_precompiled_sepolicy[] =
    206         "/vendor/etc/selinux/precompiled_sepolicy";
    207     static constexpr const char odm_precompiled_sepolicy[] =
    208         "/odm/etc/selinux/precompiled_sepolicy";
    209     if (access(odm_precompiled_sepolicy, R_OK) == 0) {
    210         *file = odm_precompiled_sepolicy;
    211     } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
    212         *file = vendor_precompiled_sepolicy;
    213     } else {
    214         PLOG(INFO) << "No precompiled sepolicy";
    215         return false;
    216     }
    217     std::string actual_plat_id;
    218     if (!ReadFirstLine("/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256", &actual_plat_id)) {
    219         PLOG(INFO) << "Failed to read "
    220                       "/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256";
    221         return false;
    222     }
    223 
    224     std::string precompiled_plat_id;
    225     std::string precompiled_sha256 = *file + ".plat_and_mapping.sha256";
    226     if (!ReadFirstLine(precompiled_sha256.c_str(), &precompiled_plat_id)) {
    227         PLOG(INFO) << "Failed to read " << precompiled_sha256;
    228         file->clear();
    229         return false;
    230     }
    231     if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
    232         file->clear();
    233         return false;
    234     }
    235     return true;
    236 }
    237 
    238 bool GetVendorMappingVersion(std::string* plat_vers) {
    239     if (!ReadFirstLine("/vendor/etc/selinux/plat_sepolicy_vers.txt", plat_vers)) {
    240         PLOG(ERROR) << "Failed to read /vendor/etc/selinux/plat_sepolicy_vers.txt";
    241         return false;
    242     }
    243     if (plat_vers->empty()) {
    244         LOG(ERROR) << "No version present in plat_sepolicy_vers.txt";
    245         return false;
    246     }
    247     return true;
    248 }
    249 
    250 constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
    251 
    252 bool IsSplitPolicyDevice() {
    253     return access(plat_policy_cil_file, R_OK) != -1;
    254 }
    255 
    256 bool LoadSplitPolicy() {
    257     // IMPLEMENTATION NOTE: Split policy consists of three CIL files:
    258     // * platform -- policy needed due to logic contained in the system image,
    259     // * non-platform -- policy needed due to logic contained in the vendor image,
    260     // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
    261     //   with newer versions of platform policy.
    262     //
    263     // secilc is invoked to compile the above three policy files into a single monolithic policy
    264     // file. This file is then loaded into the kernel.
    265 
    266     // Load precompiled policy from vendor image, if a matching policy is found there. The policy
    267     // must match the platform policy on the system image.
    268     std::string precompiled_sepolicy_file;
    269     if (FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) {
    270         unique_fd fd(open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
    271         if (fd != -1) {
    272             if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
    273                 LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
    274                 return false;
    275             }
    276             return true;
    277         }
    278     }
    279     // No suitable precompiled policy could be loaded
    280 
    281     LOG(INFO) << "Compiling SELinux policy";
    282 
    283     // Determine the highest policy language version supported by the kernel
    284     set_selinuxmnt("/sys/fs/selinux");
    285     int max_policy_version = security_policyvers();
    286     if (max_policy_version == -1) {
    287         PLOG(ERROR) << "Failed to determine highest policy version supported by kernel";
    288         return false;
    289     }
    290 
    291     // We store the output of the compilation on /dev because this is the most convenient tmpfs
    292     // storage mount available this early in the boot sequence.
    293     char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
    294     unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
    295     if (compiled_sepolicy_fd < 0) {
    296         PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
    297         return false;
    298     }
    299 
    300     // Determine which mapping file to include
    301     std::string vend_plat_vers;
    302     if (!GetVendorMappingVersion(&vend_plat_vers)) {
    303         return false;
    304     }
    305     std::string mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
    306 
    307     // vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace
    308     // nonplat_sepolicy.cil.
    309     std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");
    310     std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");
    311 
    312     if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {
    313         // For backward compatibility.
    314         // TODO: remove this after no device is using nonplat_sepolicy.cil.
    315         vendor_policy_cil_file = "/vendor/etc/selinux/nonplat_sepolicy.cil";
    316         plat_pub_versioned_cil_file.clear();
    317     } else if (access(plat_pub_versioned_cil_file.c_str(), F_OK) == -1) {
    318         LOG(ERROR) << "Missing " << plat_pub_versioned_cil_file;
    319         return false;
    320     }
    321 
    322     // odm_sepolicy.cil is default but optional.
    323     std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");
    324     if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
    325         odm_policy_cil_file.clear();
    326     }
    327     const std::string version_as_string = std::to_string(max_policy_version);
    328 
    329     // clang-format off
    330     std::vector<const char*> compile_args {
    331         "/system/bin/secilc",
    332         plat_policy_cil_file,
    333         "-m", "-M", "true", "-G", "-N",
    334         // Target the highest policy language version supported by the kernel
    335         "-c", version_as_string.c_str(),
    336         mapping_file.c_str(),
    337         "-o", compiled_sepolicy,
    338         // We don't care about file_contexts output by the compiler
    339         "-f", "/sys/fs/selinux/null",  // /dev/null is not yet available
    340     };
    341     // clang-format on
    342 
    343     if (!plat_pub_versioned_cil_file.empty()) {
    344         compile_args.push_back(plat_pub_versioned_cil_file.c_str());
    345     }
    346     if (!vendor_policy_cil_file.empty()) {
    347         compile_args.push_back(vendor_policy_cil_file.c_str());
    348     }
    349     if (!odm_policy_cil_file.empty()) {
    350         compile_args.push_back(odm_policy_cil_file.c_str());
    351     }
    352     compile_args.push_back(nullptr);
    353 
    354     if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
    355         unlink(compiled_sepolicy);
    356         return false;
    357     }
    358     unlink(compiled_sepolicy);
    359 
    360     LOG(INFO) << "Loading compiled SELinux policy";
    361     if (selinux_android_load_policy_from_fd(compiled_sepolicy_fd, compiled_sepolicy) < 0) {
    362         LOG(ERROR) << "Failed to load SELinux policy from " << compiled_sepolicy;
    363         return false;
    364     }
    365 
    366     return true;
    367 }
    368 
    369 bool LoadMonolithicPolicy() {
    370     LOG(VERBOSE) << "Loading SELinux policy from monolithic file";
    371     if (selinux_android_load_policy() < 0) {
    372         PLOG(ERROR) << "Failed to load monolithic SELinux policy";
    373         return false;
    374     }
    375     return true;
    376 }
    377 
    378 bool LoadPolicy() {
    379     return IsSplitPolicyDevice() ? LoadSplitPolicy() : LoadMonolithicPolicy();
    380 }
    381 
    382 }  // namespace
    383 
    384 void SelinuxInitialize() {
    385     Timer t;
    386 
    387     LOG(INFO) << "Loading SELinux policy";
    388     if (!LoadPolicy()) {
    389         LOG(FATAL) << "Unable to load SELinux policy";
    390     }
    391 
    392     bool kernel_enforcing = (security_getenforce() == 1);
    393     bool is_enforcing = IsEnforcing();
    394     if (kernel_enforcing != is_enforcing) {
    395         if (security_setenforce(is_enforcing)) {
    396             PLOG(FATAL) << "security_setenforce(%s) failed" << (is_enforcing ? "true" : "false");
    397         }
    398     }
    399 
    400     if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
    401         LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
    402     }
    403 
    404     // init's first stage can't set properties, so pass the time to the second stage.
    405     setenv("INIT_SELINUX_TOOK", std::to_string(t.duration().count()).c_str(), 1);
    406 }
    407 
    408 // The files and directories that were created before initial sepolicy load or
    409 // files on ramdisk need to have their security context restored to the proper
    410 // value. This must happen before /dev is populated by ueventd.
    411 void SelinuxRestoreContext() {
    412     LOG(INFO) << "Running restorecon...";
    413     selinux_android_restorecon("/dev", 0);
    414     selinux_android_restorecon("/dev/kmsg", 0);
    415     if constexpr (WORLD_WRITABLE_KMSG) {
    416         selinux_android_restorecon("/dev/kmsg_debug", 0);
    417     }
    418     selinux_android_restorecon("/dev/socket", 0);
    419     selinux_android_restorecon("/dev/random", 0);
    420     selinux_android_restorecon("/dev/urandom", 0);
    421     selinux_android_restorecon("/dev/__properties__", 0);
    422 
    423     selinux_android_restorecon("/plat_file_contexts", 0);
    424     selinux_android_restorecon("/nonplat_file_contexts", 0);
    425     selinux_android_restorecon("/vendor_file_contexts", 0);
    426     selinux_android_restorecon("/plat_property_contexts", 0);
    427     selinux_android_restorecon("/nonplat_property_contexts", 0);
    428     selinux_android_restorecon("/vendor_property_contexts", 0);
    429     selinux_android_restorecon("/plat_seapp_contexts", 0);
    430     selinux_android_restorecon("/nonplat_seapp_contexts", 0);
    431     selinux_android_restorecon("/vendor_seapp_contexts", 0);
    432     selinux_android_restorecon("/plat_service_contexts", 0);
    433     selinux_android_restorecon("/nonplat_service_contexts", 0);
    434     selinux_android_restorecon("/vendor_service_contexts", 0);
    435     selinux_android_restorecon("/plat_hwservice_contexts", 0);
    436     selinux_android_restorecon("/nonplat_hwservice_contexts", 0);
    437     selinux_android_restorecon("/vendor_hwservice_contexts", 0);
    438     selinux_android_restorecon("/sepolicy", 0);
    439     selinux_android_restorecon("/vndservice_contexts", 0);
    440 
    441     selinux_android_restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
    442     selinux_android_restorecon("/dev/device-mapper", 0);
    443 
    444     selinux_android_restorecon("/sbin/mke2fs_static", 0);
    445     selinux_android_restorecon("/sbin/e2fsdroid_static", 0);
    446 
    447     selinux_android_restorecon("/sbin/mkfs.f2fs", 0);
    448     selinux_android_restorecon("/sbin/sload.f2fs", 0);
    449 }
    450 
    451 // This function sets up SELinux logging to be written to kmsg, to match init's logging.
    452 void SelinuxSetupKernelLogging() {
    453     selinux_callback cb;
    454     cb.func_log = selinux_klog_callback;
    455     selinux_set_callback(SELINUX_CB_LOG, cb);
    456 }
    457 
    458 // This function checks whether the sepolicy supports vendor init.
    459 bool SelinuxHasVendorInit() {
    460     if (!IsSplitPolicyDevice()) {
    461         // If this device does not split sepolicy files, vendor_init will be available in the latest
    462         // monolithic sepolicy file.
    463         return true;
    464     }
    465 
    466     std::string version;
    467     if (!GetVendorMappingVersion(&version)) {
    468         // Return true as the default if we failed to load the vendor sepolicy version.
    469         return true;
    470     }
    471 
    472     int major_version;
    473     std::string major_version_str(version, 0, version.find('.'));
    474     if (!ParseInt(major_version_str, &major_version)) {
    475         PLOG(ERROR) << "Failed to parse the vendor sepolicy major version " << major_version_str;
    476         // Return true as the default if we failed to parse the major version.
    477         return true;
    478     }
    479 
    480     return major_version >= 28;
    481 }
    482 
    483 // selinux_android_file_context_handle() takes on the order of 10+ms to run, so we want to cache
    484 // its value.  selinux_android_restorecon() also needs an sehandle for file context look up.  It
    485 // will create and store its own copy, but selinux_android_set_sehandle() can be used to provide
    486 // one, thus eliminating an extra call to selinux_android_file_context_handle().
    487 void SelabelInitialize() {
    488     sehandle = selinux_android_file_context_handle();
    489     selinux_android_set_sehandle(sehandle);
    490 }
    491 
    492 // A C++ wrapper around selabel_lookup() using the cached sehandle.
    493 // If sehandle is null, this returns success with an empty context.
    494 bool SelabelLookupFileContext(const std::string& key, int type, std::string* result) {
    495     result->clear();
    496 
    497     if (!sehandle) return true;
    498 
    499     char* context;
    500     if (selabel_lookup(sehandle, &context, key.c_str(), type) != 0) {
    501         return false;
    502     }
    503     *result = context;
    504     free(context);
    505     return true;
    506 }
    507 
    508 // A C++ wrapper around selabel_lookup_best_match() using the cached sehandle.
    509 // If sehandle is null, this returns success with an empty context.
    510 bool SelabelLookupFileContextBestMatch(const std::string& key,
    511                                        const std::vector<std::string>& aliases, int type,
    512                                        std::string* result) {
    513     result->clear();
    514 
    515     if (!sehandle) return true;
    516 
    517     std::vector<const char*> c_aliases;
    518     for (const auto& alias : aliases) {
    519         c_aliases.emplace_back(alias.c_str());
    520     }
    521     c_aliases.emplace_back(nullptr);
    522 
    523     char* context;
    524     if (selabel_lookup_best_match(sehandle, &context, key.c_str(), &c_aliases[0], type) != 0) {
    525         return false;
    526     }
    527     *result = context;
    528     free(context);
    529     return true;
    530 }
    531 
    532 }  // namespace init
    533 }  // namespace android
    534