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