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