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 /system/bin/init based on
22 // this 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 'vendor'
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 either /vendor/etc/selinux/precompiled_sepolicy or
38 //    /odm/etc/selinux/precompiled_sepolicy if odm parition is present.  Stored along with this file
39 //    are the sha256 hashes of the parts of the SEPolicy on /system, /system_ext and /product that
40 //    were used to compile this precompiled policy.  The system partition contains a similar sha256
41 //    of the parts of the SEPolicy that it currently contains.  Symmetrically, system_ext and
42 //    product paritition contain sha256 hashes of their SEPolicy.  The init loads this
43 //    precompiled_sepolicy directly if and only if the hashes along with the precompiled SEPolicy on
44 //    /vendor or /odm match the hashes for system, system_ext and product SEPolicy, respectively.
45 // 2) If these hashes do not match, then either /system or /system_ext or /product (or some of them)
46 //    have been updated out of sync with /vendor (or /odm if it is present) and the init needs to
47 //    compile the SEPolicy.  /system contains the SEPolicy compiler, secilc, and it is used by the
48 //    OpenSplitPolicy() function below to compile the SEPolicy to a temp directory and load it.
49 //    That function contains even more documentation with the specific implementation details of how
50 //    the SEPolicy is compiled if needed.
51 
52 #include "selinux.h"
53 
54 #include <android/api-level.h>
55 #include <fcntl.h>
56 #include <linux/audit.h>
57 #include <linux/netlink.h>
58 #include <stdlib.h>
59 #include <sys/wait.h>
60 #include <unistd.h>
61 
62 #include <android-base/chrono_utils.h>
63 #include <android-base/file.h>
64 #include <android-base/logging.h>
65 #include <android-base/parseint.h>
66 #include <android-base/result.h>
67 #include <android-base/strings.h>
68 #include <android-base/unique_fd.h>
69 #include <android/avf_cc_flags.h>
70 #include <fs_avb/fs_avb.h>
71 #include <fs_mgr.h>
72 #include <libgsi/libgsi.h>
73 #include <libsnapshot/snapshot.h>
74 #include <selinux/android.h>
75 
76 #include "block_dev_initializer.h"
77 #include "debug_ramdisk.h"
78 #include "reboot_utils.h"
79 #include "snapuserd_transition.h"
80 #include "util.h"
81 
82 using namespace std::string_literals;
83 
84 using android::base::ParseInt;
85 using android::base::Timer;
86 using android::base::unique_fd;
87 using android::fs_mgr::AvbHandle;
88 using android::snapshot::SnapshotManager;
89 
90 namespace android {
91 namespace init {
92 
93 namespace {
94 
95 enum EnforcingStatus { SELINUX_PERMISSIVE, SELINUX_ENFORCING };
96 
StatusFromProperty()97 EnforcingStatus StatusFromProperty() {
98     std::string value;
99     if (android::fs_mgr::GetKernelCmdline("androidboot.selinux", &value) && value == "permissive") {
100         return SELINUX_PERMISSIVE;
101     }
102     if (android::fs_mgr::GetBootconfig("androidboot.selinux", &value) && value == "permissive") {
103         return SELINUX_PERMISSIVE;
104     }
105     return SELINUX_ENFORCING;
106 }
107 
IsEnforcing()108 bool IsEnforcing() {
109     if (ALLOW_PERMISSIVE_SELINUX) {
110         return StatusFromProperty() == SELINUX_ENFORCING;
111     }
112     return true;
113 }
114 
ReadFirstLine(const char * file,std::string * line)115 bool ReadFirstLine(const char* file, std::string* line) {
116     line->clear();
117 
118     std::string contents;
119     if (!android::base::ReadFileToString(file, &contents, true /* follow symlinks */)) {
120         return false;
121     }
122     std::istringstream in(contents);
123     std::getline(in, *line);
124     return true;
125 }
126 
FindPrecompiledSplitPolicy()127 Result<std::string> FindPrecompiledSplitPolicy() {
128     std::string precompiled_sepolicy;
129     // If there is an odm partition, precompiled_sepolicy will be in
130     // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
131     static constexpr const char vendor_precompiled_sepolicy[] =
132             "/vendor/etc/selinux/precompiled_sepolicy";
133     static constexpr const char odm_precompiled_sepolicy[] =
134             "/odm/etc/selinux/precompiled_sepolicy";
135     if (access(odm_precompiled_sepolicy, R_OK) == 0) {
136         precompiled_sepolicy = odm_precompiled_sepolicy;
137     } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
138         precompiled_sepolicy = vendor_precompiled_sepolicy;
139     } else {
140         return ErrnoError() << "No precompiled sepolicy at " << vendor_precompiled_sepolicy;
141     }
142 
143     // Use precompiled sepolicy only when all corresponding hashes are equal.
144     std::vector<std::pair<std::string, std::string>> sepolicy_hashes{
145             {"/system/etc/selinux/plat_sepolicy_and_mapping.sha256",
146              precompiled_sepolicy + ".plat_sepolicy_and_mapping.sha256"},
147             {"/system_ext/etc/selinux/system_ext_sepolicy_and_mapping.sha256",
148              precompiled_sepolicy + ".system_ext_sepolicy_and_mapping.sha256"},
149             {"/product/etc/selinux/product_sepolicy_and_mapping.sha256",
150              precompiled_sepolicy + ".product_sepolicy_and_mapping.sha256"},
151     };
152 
153     for (const auto& [actual_id_path, precompiled_id_path] : sepolicy_hashes) {
154         // Both of them should exist or both of them shouldn't exist.
155         if (access(actual_id_path.c_str(), R_OK) != 0) {
156             if (access(precompiled_id_path.c_str(), R_OK) == 0) {
157                 return Error() << precompiled_id_path << " exists but " << actual_id_path
158                                << " doesn't";
159             }
160             continue;
161         }
162 
163         std::string actual_id;
164         if (!ReadFirstLine(actual_id_path.c_str(), &actual_id)) {
165             return ErrnoError() << "Failed to read " << actual_id_path;
166         }
167 
168         std::string precompiled_id;
169         if (!ReadFirstLine(precompiled_id_path.c_str(), &precompiled_id)) {
170             return ErrnoError() << "Failed to read " << precompiled_id_path;
171         }
172 
173         if (actual_id.empty() || actual_id != precompiled_id) {
174             return Error() << actual_id_path << " and " << precompiled_id_path << " differ";
175         }
176     }
177 
178     return precompiled_sepolicy;
179 }
180 
GetVendorMappingVersion(std::string * plat_vers)181 bool GetVendorMappingVersion(std::string* plat_vers) {
182     if (!ReadFirstLine("/vendor/etc/selinux/plat_sepolicy_vers.txt", plat_vers)) {
183         PLOG(ERROR) << "Failed to read /vendor/etc/selinux/plat_sepolicy_vers.txt";
184         return false;
185     }
186     if (plat_vers->empty()) {
187         LOG(ERROR) << "No version present in plat_sepolicy_vers.txt";
188         return false;
189     }
190     return true;
191 }
192 
193 constexpr const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil";
194 
IsSplitPolicyDevice()195 bool IsSplitPolicyDevice() {
196     return access(plat_policy_cil_file, R_OK) != -1;
197 }
198 
GetUserdebugPlatformPolicyFile()199 std::optional<const char*> GetUserdebugPlatformPolicyFile() {
200     // See if we need to load userdebug_plat_sepolicy.cil instead of plat_sepolicy.cil.
201     const char* force_debuggable_env = getenv("INIT_FORCE_DEBUGGABLE");
202     if (force_debuggable_env && "true"s == force_debuggable_env && AvbHandle::IsDeviceUnlocked()) {
203         const std::vector<const char*> debug_policy_candidates = {
204 #if INSTALL_DEBUG_POLICY_TO_SYSTEM_EXT == 1
205             "/system_ext/etc/selinux/userdebug_plat_sepolicy.cil",
206 #endif
207             kDebugRamdiskSEPolicy,
208         };
209         for (const char* debug_policy : debug_policy_candidates) {
210             if (access(debug_policy, F_OK) == 0) {
211                 return debug_policy;
212             }
213         }
214     }
215     return std::nullopt;
216 }
217 
218 struct PolicyFile {
219     unique_fd fd;
220     std::string path;
221 };
222 
OpenSplitPolicy(PolicyFile * policy_file)223 bool OpenSplitPolicy(PolicyFile* policy_file) {
224     // IMPLEMENTATION NOTE: Split policy consists of three or more CIL files:
225     // * platform -- policy needed due to logic contained in the system image,
226     // * vendor -- policy needed due to logic contained in the vendor image,
227     // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
228     //   with newer versions of platform policy.
229     // * (optional) policy needed due to logic on product, system_ext, or odm images.
230     // secilc is invoked to compile the above three policy files into a single monolithic policy
231     // file. This file is then loaded into the kernel.
232 
233     const auto userdebug_plat_sepolicy = GetUserdebugPlatformPolicyFile();
234     const bool use_userdebug_policy = userdebug_plat_sepolicy.has_value();
235     if (use_userdebug_policy) {
236         LOG(INFO) << "Using userdebug system sepolicy " << *userdebug_plat_sepolicy;
237     }
238 
239     // Load precompiled policy from vendor image, if a matching policy is found there. The policy
240     // must match the platform policy on the system image.
241     // use_userdebug_policy requires compiling sepolicy with userdebug_plat_sepolicy.cil.
242     // Thus it cannot use the precompiled policy from vendor image.
243     if (!use_userdebug_policy) {
244         if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {
245             unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
246             if (fd != -1) {
247                 policy_file->fd = std::move(fd);
248                 policy_file->path = std::move(*res);
249                 return true;
250             }
251         } else {
252             LOG(INFO) << res.error();
253         }
254     }
255     // No suitable precompiled policy could be loaded
256 
257     LOG(INFO) << "Compiling SELinux policy";
258 
259     // We store the output of the compilation on /dev because this is the most convenient tmpfs
260     // storage mount available this early in the boot sequence.
261     char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
262     unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
263     if (compiled_sepolicy_fd < 0) {
264         PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
265         return false;
266     }
267 
268     // Determine which mapping file to include
269     std::string vend_plat_vers;
270     if (!GetVendorMappingVersion(&vend_plat_vers)) {
271         return false;
272     }
273     std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
274 
275     std::string plat_compat_cil_file("/system/etc/selinux/mapping/" + vend_plat_vers +
276                                      ".compat.cil");
277     if (access(plat_compat_cil_file.c_str(), F_OK) == -1) {
278         plat_compat_cil_file.clear();
279     }
280 
281     std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");
282     if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {
283         system_ext_policy_cil_file.clear();
284     }
285 
286     std::string system_ext_mapping_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
287                                         ".cil");
288     if (access(system_ext_mapping_file.c_str(), F_OK) == -1) {
289         system_ext_mapping_file.clear();
290     }
291 
292     std::string system_ext_compat_cil_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
293                                            ".compat.cil");
294     if (access(system_ext_compat_cil_file.c_str(), F_OK) == -1) {
295         system_ext_compat_cil_file.clear();
296     }
297 
298     std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
299     if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
300         product_policy_cil_file.clear();
301     }
302 
303     std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");
304     if (access(product_mapping_file.c_str(), F_OK) == -1) {
305         product_mapping_file.clear();
306     }
307 
308     std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");
309     if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {
310         LOG(ERROR) << "Missing " << vendor_policy_cil_file;
311         return false;
312     }
313 
314     std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");
315     if (access(plat_pub_versioned_cil_file.c_str(), F_OK) == -1) {
316         LOG(ERROR) << "Missing " << plat_pub_versioned_cil_file;
317         return false;
318     }
319 
320     // odm_sepolicy.cil is default but optional.
321     std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");
322     if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
323         odm_policy_cil_file.clear();
324     }
325     const std::string version_as_string = std::to_string(SEPOLICY_VERSION);
326 
327     // clang-format off
328     std::vector<const char*> compile_args {
329         "/system/bin/secilc",
330         use_userdebug_policy ? *userdebug_plat_sepolicy : plat_policy_cil_file,
331         "-m", "-M", "true", "-G", "-N",
332         "-c", version_as_string.c_str(),
333         plat_mapping_file.c_str(),
334         "-o", compiled_sepolicy,
335         // We don't care about file_contexts output by the compiler
336         "-f", "/sys/fs/selinux/null",  // /dev/null is not yet available
337     };
338     // clang-format on
339 
340     if (!plat_compat_cil_file.empty()) {
341         compile_args.push_back(plat_compat_cil_file.c_str());
342     }
343     if (!system_ext_policy_cil_file.empty()) {
344         compile_args.push_back(system_ext_policy_cil_file.c_str());
345     }
346     if (!system_ext_mapping_file.empty()) {
347         compile_args.push_back(system_ext_mapping_file.c_str());
348     }
349     if (!system_ext_compat_cil_file.empty()) {
350         compile_args.push_back(system_ext_compat_cil_file.c_str());
351     }
352     if (!product_policy_cil_file.empty()) {
353         compile_args.push_back(product_policy_cil_file.c_str());
354     }
355     if (!product_mapping_file.empty()) {
356         compile_args.push_back(product_mapping_file.c_str());
357     }
358     if (!plat_pub_versioned_cil_file.empty()) {
359         compile_args.push_back(plat_pub_versioned_cil_file.c_str());
360     }
361     if (!vendor_policy_cil_file.empty()) {
362         compile_args.push_back(vendor_policy_cil_file.c_str());
363     }
364     if (!odm_policy_cil_file.empty()) {
365         compile_args.push_back(odm_policy_cil_file.c_str());
366     }
367     compile_args.push_back(nullptr);
368 
369     if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
370         unlink(compiled_sepolicy);
371         return false;
372     }
373     unlink(compiled_sepolicy);
374 
375     policy_file->fd = std::move(compiled_sepolicy_fd);
376     policy_file->path = compiled_sepolicy;
377     return true;
378 }
379 
OpenMonolithicPolicy(PolicyFile * policy_file)380 bool OpenMonolithicPolicy(PolicyFile* policy_file) {
381     static constexpr char kSepolicyFile[] = "/sepolicy";
382 
383     LOG(INFO) << "Opening SELinux policy from monolithic file " << kSepolicyFile;
384     policy_file->fd.reset(open(kSepolicyFile, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
385     if (policy_file->fd < 0) {
386         PLOG(ERROR) << "Failed to open monolithic SELinux policy";
387         return false;
388     }
389     policy_file->path = kSepolicyFile;
390     return true;
391 }
392 
ReadPolicy(std::string * policy)393 void ReadPolicy(std::string* policy) {
394     PolicyFile policy_file;
395 
396     bool ok = IsSplitPolicyDevice() ? OpenSplitPolicy(&policy_file)
397                                     : OpenMonolithicPolicy(&policy_file);
398     if (!ok) {
399         LOG(FATAL) << "Unable to open SELinux policy";
400     }
401 
402     if (!android::base::ReadFdToString(policy_file.fd, policy)) {
403         PLOG(FATAL) << "Failed to read policy file: " << policy_file.path;
404     }
405 }
406 
SelinuxSetEnforcement()407 void SelinuxSetEnforcement() {
408     bool kernel_enforcing = (security_getenforce() == 1);
409     bool is_enforcing = IsEnforcing();
410     if (kernel_enforcing != is_enforcing) {
411         if (security_setenforce(is_enforcing)) {
412             PLOG(FATAL) << "security_setenforce(" << (is_enforcing ? "true" : "false")
413                         << ") failed";
414         }
415     }
416 }
417 
418 constexpr size_t kKlogMessageSize = 1024;
419 
SelinuxAvcLog(char * buf)420 void SelinuxAvcLog(char* buf) {
421     struct NetlinkMessage {
422         nlmsghdr hdr;
423         char buf[kKlogMessageSize];
424     } request = {};
425 
426     request.hdr.nlmsg_flags = NLM_F_REQUEST;
427     request.hdr.nlmsg_type = AUDIT_USER_AVC;
428     request.hdr.nlmsg_len = sizeof(request);
429     strlcpy(request.buf, buf, sizeof(request.buf));
430 
431     auto fd = unique_fd{socket(PF_NETLINK, SOCK_RAW | SOCK_CLOEXEC, NETLINK_AUDIT)};
432     if (!fd.ok()) {
433         return;
434     }
435 
436     TEMP_FAILURE_RETRY(send(fd.get(), &request, sizeof(request), 0));
437 }
438 
RestoreconIfExists(const char * path,unsigned int flags)439 int RestoreconIfExists(const char* path, unsigned int flags) {
440     if (access(path, F_OK) != 0 && errno == ENOENT) {
441         // Avoid error message for path that is expected to not always exist.
442         return 0;
443     }
444     return selinux_android_restorecon(path, flags);
445 }
446 
447 }  // namespace
448 
SelinuxRestoreContext()449 void SelinuxRestoreContext() {
450     LOG(INFO) << "Running restorecon...";
451     selinux_android_restorecon("/dev", 0);
452     selinux_android_restorecon("/dev/console", 0);
453     selinux_android_restorecon("/dev/kmsg", 0);
454     if constexpr (WORLD_WRITABLE_KMSG) {
455         selinux_android_restorecon("/dev/kmsg_debug", 0);
456     }
457     selinux_android_restorecon("/dev/null", 0);
458     selinux_android_restorecon("/dev/ptmx", 0);
459     selinux_android_restorecon("/dev/socket", 0);
460     selinux_android_restorecon("/dev/random", 0);
461     selinux_android_restorecon("/dev/urandom", 0);
462     selinux_android_restorecon("/dev/__properties__", 0);
463 
464     selinux_android_restorecon("/dev/block", SELINUX_ANDROID_RESTORECON_RECURSE);
465     selinux_android_restorecon("/dev/dm-user", SELINUX_ANDROID_RESTORECON_RECURSE);
466     selinux_android_restorecon("/dev/device-mapper", 0);
467 
468     selinux_android_restorecon("/apex", 0);
469     selinux_android_restorecon("/bootstrap-apex", 0);
470     selinux_android_restorecon("/linkerconfig", 0);
471 
472     // adb remount, snapshot-based updates, and DSUs all create files during
473     // first-stage init.
474     RestoreconIfExists(SnapshotManager::GetGlobalRollbackIndicatorPath().c_str(), 0);
475     RestoreconIfExists("/metadata/gsi",
476                        SELINUX_ANDROID_RESTORECON_RECURSE | SELINUX_ANDROID_RESTORECON_SKIP_SEHASH);
477 }
478 
SelinuxKlogCallback(int type,const char * fmt,...)479 int SelinuxKlogCallback(int type, const char* fmt, ...) {
480     android::base::LogSeverity severity = android::base::ERROR;
481     if (type == SELINUX_WARNING) {
482         severity = android::base::WARNING;
483     } else if (type == SELINUX_INFO) {
484         severity = android::base::INFO;
485     }
486     char buf[kKlogMessageSize];
487     va_list ap;
488     va_start(ap, fmt);
489     int length_written = vsnprintf(buf, sizeof(buf), fmt, ap);
490     va_end(ap);
491     if (length_written <= 0) {
492         return 0;
493     }
494 
495     // libselinux log messages usually contain a new line character, while
496     // Android LOG() does not expect it. Remove it to avoid empty lines in
497     // the log buffers.
498     size_t str_len = strlen(buf);
499     if (buf[str_len - 1] == '\n') {
500         buf[str_len - 1] = '\0';
501     }
502 
503     if (type == SELINUX_AVC) {
504         SelinuxAvcLog(buf);
505     } else {
506         android::base::KernelLogger(android::base::MAIN, severity, "selinux", nullptr, 0, buf);
507     }
508     return 0;
509 }
510 
SelinuxSetupKernelLogging()511 void SelinuxSetupKernelLogging() {
512     selinux_callback cb;
513     cb.func_log = SelinuxKlogCallback;
514     selinux_set_callback(SELINUX_CB_LOG, cb);
515 }
516 
SelinuxGetVendorAndroidVersion()517 int SelinuxGetVendorAndroidVersion() {
518     if (IsMicrodroid()) {
519         // As of now Microdroid doesn't have any vendor code.
520         return __ANDROID_API_FUTURE__;
521     }
522     static int vendor_android_version = [] {
523         if (!IsSplitPolicyDevice()) {
524             // If this device does not split sepolicy files, it's not a Treble device and therefore,
525             // we assume it's always on the latest platform.
526             return __ANDROID_API_FUTURE__;
527         }
528 
529         std::string version;
530         if (!GetVendorMappingVersion(&version)) {
531             LOG(FATAL) << "Could not read vendor SELinux version";
532         }
533 
534         int major_version;
535         std::string major_version_str(version, 0, version.find('.'));
536         if (!ParseInt(major_version_str, &major_version)) {
537             PLOG(FATAL) << "Failed to parse the vendor sepolicy major version "
538                         << major_version_str;
539         }
540 
541         return major_version;
542     }();
543     return vendor_android_version;
544 }
545 
546 // This is for R system.img/system_ext.img to work on old vendor.img as system_ext.img
547 // is introduced in R. We mount system_ext in second stage init because the first-stage
548 // init in boot.img won't be updated in the system-only OTA scenario.
MountMissingSystemPartitions()549 void MountMissingSystemPartitions() {
550     android::fs_mgr::Fstab fstab;
551     if (!ReadDefaultFstab(&fstab)) {
552         LOG(ERROR) << "Could not read default fstab";
553     }
554 
555     android::fs_mgr::Fstab mounts;
556     if (!ReadFstabFromFile("/proc/mounts", &mounts)) {
557         LOG(ERROR) << "Could not read /proc/mounts";
558     }
559 
560     static const std::vector<std::string> kPartitionNames = {"system_ext", "product"};
561 
562     android::fs_mgr::Fstab extra_fstab;
563     for (const auto& name : kPartitionNames) {
564         if (GetEntryForMountPoint(&mounts, "/"s + name)) {
565             // The partition is already mounted.
566             continue;
567         }
568 
569         auto system_entries = GetEntriesForMountPoint(&fstab, "/system");
570         for (auto& system_entry : system_entries) {
571             if (!system_entry) {
572                 LOG(ERROR) << "Could not find mount entry for /system";
573                 break;
574             }
575             if (!system_entry->fs_mgr_flags.logical) {
576                 LOG(INFO) << "Skipping mount of " << name << ", system is not dynamic.";
577                 break;
578             }
579 
580             auto entry = *system_entry;
581             auto partition_name = name + fs_mgr_get_slot_suffix();
582             auto replace_name = "system"s + fs_mgr_get_slot_suffix();
583 
584             entry.mount_point = "/"s + name;
585             entry.blk_device =
586                 android::base::StringReplace(entry.blk_device, replace_name, partition_name, false);
587             if (!fs_mgr_update_logical_partition(&entry)) {
588                 LOG(ERROR) << "Could not update logical partition";
589                 continue;
590             }
591 
592             extra_fstab.emplace_back(std::move(entry));
593         }
594     }
595 
596     SkipMountingPartitions(&extra_fstab, true /* verbose */);
597     if (extra_fstab.empty()) {
598         return;
599     }
600 
601     BlockDevInitializer block_dev_init;
602     for (auto& entry : extra_fstab) {
603         if (access(entry.blk_device.c_str(), F_OK) != 0) {
604             auto block_dev = android::base::Basename(entry.blk_device);
605             if (!block_dev_init.InitDmDevice(block_dev)) {
606                 LOG(ERROR) << "Failed to find device-mapper node: " << block_dev;
607                 continue;
608             }
609         }
610         if (fs_mgr_do_mount_one(entry)) {
611             LOG(ERROR) << "Could not mount " << entry.mount_point;
612         }
613     }
614 }
615 
LoadSelinuxPolicy(std::string & policy)616 static void LoadSelinuxPolicy(std::string& policy) {
617     LOG(INFO) << "Loading SELinux policy";
618 
619     set_selinuxmnt("/sys/fs/selinux");
620     if (security_load_policy(policy.data(), policy.size()) < 0) {
621         PLOG(FATAL) << "SELinux:  Could not load policy";
622     }
623 }
624 
625 // Encapsulates steps to load SELinux policy in Microdroid.
626 // So far the process is very straightforward - just load the precompiled policy from /system.
LoadSelinuxPolicyMicrodroid()627 void LoadSelinuxPolicyMicrodroid() {
628     constexpr const char kMicrodroidPrecompiledSepolicy[] =
629             "/system/etc/selinux/microdroid_precompiled_sepolicy";
630 
631     LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
632     unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
633     if (policy_fd < 0) {
634         PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
635     }
636 
637     std::string policy;
638     if (!android::base::ReadFdToString(policy_fd, &policy)) {
639         PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
640     }
641 
642     LoadSelinuxPolicy(policy);
643 }
644 
645 // The SELinux setup process is carefully orchestrated around snapuserd. Policy
646 // must be loaded off dynamic partitions, and during an OTA, those partitions
647 // cannot be read without snapuserd. But, with kernel-privileged snapuserd
648 // running, loading the policy will immediately trigger audits.
649 //
650 // We use a five-step process to address this:
651 //  (1) Read the policy into a string, with snapuserd running.
652 //  (2) Rewrite the snapshot device-mapper tables, to generate new dm-user
653 //      devices and to flush I/O.
654 //  (3) Kill snapuserd, which no longer has any dm-user devices to attach to.
655 //  (4) Load the sepolicy and issue critical restorecons in /dev, carefully
656 //      avoiding anything that would read from /system.
657 //  (5) Re-launch snapuserd and attach it to the dm-user devices from step (2).
658 //
659 // After this sequence, it is safe to enable enforcing mode and continue booting.
LoadSelinuxPolicyAndroid()660 void LoadSelinuxPolicyAndroid() {
661     MountMissingSystemPartitions();
662 
663     LOG(INFO) << "Opening SELinux policy";
664 
665     // Read the policy before potentially killing snapuserd.
666     std::string policy;
667     ReadPolicy(&policy);
668 
669     auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
670     if (snapuserd_helper) {
671         // Kill the old snapused to avoid audit messages. After this we cannot read from /system
672         // (or other dynamic partitions) until we call FinishTransition().
673         snapuserd_helper->StartTransition();
674     }
675 
676     LoadSelinuxPolicy(policy);
677 
678     if (snapuserd_helper) {
679         // Before enforcing, finish the pending snapuserd transition.
680         snapuserd_helper->FinishTransition();
681         snapuserd_helper = nullptr;
682     }
683 }
684 
SetupSelinux(char ** argv)685 int SetupSelinux(char** argv) {
686     SetStdioToDevNull(argv);
687     InitKernelLogging(argv);
688 
689     if (REBOOT_BOOTLOADER_ON_PANIC) {
690         InstallRebootSignalHandlers();
691     }
692 
693     boot_clock::time_point start_time = boot_clock::now();
694 
695     SelinuxSetupKernelLogging();
696 
697     // TODO(b/287206497): refactor into different headers to only include what we need.
698     if (IsMicrodroid()) {
699         LoadSelinuxPolicyMicrodroid();
700     } else {
701         LoadSelinuxPolicyAndroid();
702     }
703 
704     SelinuxSetEnforcement();
705 
706     if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
707         // We run restorecon of /microdroid_resources while we are still in kernel context to avoid
708         // granting init `tmpfs:file relabelfrom` capability.
709         const int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
710         if (selinux_android_restorecon("/microdroid_resources", flags) == -1) {
711             PLOG(FATAL) << "restorecon of /microdroid_resources failed";
712         }
713     }
714 
715     // We're in the kernel domain and want to transition to the init domain.  File systems that
716     // store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
717     // but other file systems do.  In particular, this is needed for ramdisks such as the
718     // recovery image for A/B devices.
719     if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
720         PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
721     }
722 
723     setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);
724 
725     const char* path = "/system/bin/init";
726     const char* args[] = {path, "second_stage", nullptr};
727     execv(path, const_cast<char**>(args));
728 
729     // execv() only returns if an error happened, in which case we
730     // panic and never return from this function.
731     PLOG(FATAL) << "execv(\"" << path << "\") failed";
732 
733     return 1;
734 }
735 
736 }  // namespace init
737 }  // namespace android
738