xref: /aosp_15_r20/system/core/init/devices.cpp (revision 00c7fec1bb09f3284aad6a6f96d2f63dfc3650ad)
1*00c7fec1SAndroid Build Coastguard Worker /*
2*00c7fec1SAndroid Build Coastguard Worker  * Copyright (C) 2007 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 #include "devices.h"
18*00c7fec1SAndroid Build Coastguard Worker 
19*00c7fec1SAndroid Build Coastguard Worker #include <errno.h>
20*00c7fec1SAndroid Build Coastguard Worker #include <fnmatch.h>
21*00c7fec1SAndroid Build Coastguard Worker #include <sys/sysmacros.h>
22*00c7fec1SAndroid Build Coastguard Worker #include <unistd.h>
23*00c7fec1SAndroid Build Coastguard Worker 
24*00c7fec1SAndroid Build Coastguard Worker #include <chrono>
25*00c7fec1SAndroid Build Coastguard Worker #include <filesystem>
26*00c7fec1SAndroid Build Coastguard Worker #include <memory>
27*00c7fec1SAndroid Build Coastguard Worker #include <string>
28*00c7fec1SAndroid Build Coastguard Worker #include <string_view>
29*00c7fec1SAndroid Build Coastguard Worker #include <thread>
30*00c7fec1SAndroid Build Coastguard Worker 
31*00c7fec1SAndroid Build Coastguard Worker #include <android-base/chrono_utils.h>
32*00c7fec1SAndroid Build Coastguard Worker #include <android-base/file.h>
33*00c7fec1SAndroid Build Coastguard Worker #include <android-base/logging.h>
34*00c7fec1SAndroid Build Coastguard Worker #include <android-base/stringprintf.h>
35*00c7fec1SAndroid Build Coastguard Worker #include <android-base/strings.h>
36*00c7fec1SAndroid Build Coastguard Worker #include <fs_mgr.h>
37*00c7fec1SAndroid Build Coastguard Worker #include <libdm/dm.h>
38*00c7fec1SAndroid Build Coastguard Worker #include <private/android_filesystem_config.h>
39*00c7fec1SAndroid Build Coastguard Worker #include <selinux/android.h>
40*00c7fec1SAndroid Build Coastguard Worker #include <selinux/selinux.h>
41*00c7fec1SAndroid Build Coastguard Worker 
42*00c7fec1SAndroid Build Coastguard Worker #include "selabel.h"
43*00c7fec1SAndroid Build Coastguard Worker #include "util.h"
44*00c7fec1SAndroid Build Coastguard Worker 
45*00c7fec1SAndroid Build Coastguard Worker using namespace std::chrono_literals;
46*00c7fec1SAndroid Build Coastguard Worker 
47*00c7fec1SAndroid Build Coastguard Worker using android::base::Basename;
48*00c7fec1SAndroid Build Coastguard Worker using android::base::ConsumePrefix;
49*00c7fec1SAndroid Build Coastguard Worker using android::base::Dirname;
50*00c7fec1SAndroid Build Coastguard Worker using android::base::ReadFileToString;
51*00c7fec1SAndroid Build Coastguard Worker using android::base::Readlink;
52*00c7fec1SAndroid Build Coastguard Worker using android::base::Realpath;
53*00c7fec1SAndroid Build Coastguard Worker using android::base::Split;
54*00c7fec1SAndroid Build Coastguard Worker using android::base::StartsWith;
55*00c7fec1SAndroid Build Coastguard Worker using android::base::StringPrintf;
56*00c7fec1SAndroid Build Coastguard Worker using android::base::Trim;
57*00c7fec1SAndroid Build Coastguard Worker 
58*00c7fec1SAndroid Build Coastguard Worker namespace android {
59*00c7fec1SAndroid Build Coastguard Worker namespace init {
60*00c7fec1SAndroid Build Coastguard Worker 
61*00c7fec1SAndroid Build Coastguard Worker /* Given a path that may start with a PCI device, populate the supplied buffer
62*00c7fec1SAndroid Build Coastguard Worker  * with the PCI domain/bus number and the peripheral ID and return 0.
63*00c7fec1SAndroid Build Coastguard Worker  * If it doesn't start with a PCI device, or there is some error, return -1 */
FindPciDevicePrefix(const std::string & path,std::string * result)64*00c7fec1SAndroid Build Coastguard Worker static bool FindPciDevicePrefix(const std::string& path, std::string* result) {
65*00c7fec1SAndroid Build Coastguard Worker     result->clear();
66*00c7fec1SAndroid Build Coastguard Worker 
67*00c7fec1SAndroid Build Coastguard Worker     if (!StartsWith(path, "/devices/pci")) return false;
68*00c7fec1SAndroid Build Coastguard Worker 
69*00c7fec1SAndroid Build Coastguard Worker     /* Beginning of the prefix is the initial "pci" after "/devices/" */
70*00c7fec1SAndroid Build Coastguard Worker     std::string::size_type start = 9;
71*00c7fec1SAndroid Build Coastguard Worker 
72*00c7fec1SAndroid Build Coastguard Worker     /* End of the prefix is two path '/' later, capturing the domain/bus number
73*00c7fec1SAndroid Build Coastguard Worker      * and the peripheral ID. Example: pci0000:00/0000:00:1f.2 */
74*00c7fec1SAndroid Build Coastguard Worker     auto end = path.find('/', start);
75*00c7fec1SAndroid Build Coastguard Worker     if (end == std::string::npos) return false;
76*00c7fec1SAndroid Build Coastguard Worker 
77*00c7fec1SAndroid Build Coastguard Worker     end = path.find('/', end + 1);
78*00c7fec1SAndroid Build Coastguard Worker     if (end == std::string::npos) return false;
79*00c7fec1SAndroid Build Coastguard Worker 
80*00c7fec1SAndroid Build Coastguard Worker     auto length = end - start;
81*00c7fec1SAndroid Build Coastguard Worker     if (length <= 4) {
82*00c7fec1SAndroid Build Coastguard Worker         // The minimum string that will get to this check is 'pci/', which is malformed,
83*00c7fec1SAndroid Build Coastguard Worker         // so return false
84*00c7fec1SAndroid Build Coastguard Worker         return false;
85*00c7fec1SAndroid Build Coastguard Worker     }
86*00c7fec1SAndroid Build Coastguard Worker 
87*00c7fec1SAndroid Build Coastguard Worker     *result = path.substr(start, length);
88*00c7fec1SAndroid Build Coastguard Worker     return true;
89*00c7fec1SAndroid Build Coastguard Worker }
90*00c7fec1SAndroid Build Coastguard Worker 
91*00c7fec1SAndroid Build Coastguard Worker /* Given a path that may start with a virtual block device, populate
92*00c7fec1SAndroid Build Coastguard Worker  * the supplied buffer with the virtual block device ID and return 0.
93*00c7fec1SAndroid Build Coastguard Worker  * If it doesn't start with a virtual block device, or there is some
94*00c7fec1SAndroid Build Coastguard Worker  * error, return -1 */
FindVbdDevicePrefix(const std::string & path,std::string * result)95*00c7fec1SAndroid Build Coastguard Worker static bool FindVbdDevicePrefix(const std::string& path, std::string* result) {
96*00c7fec1SAndroid Build Coastguard Worker     result->clear();
97*00c7fec1SAndroid Build Coastguard Worker 
98*00c7fec1SAndroid Build Coastguard Worker     if (!StartsWith(path, "/devices/vbd-")) return false;
99*00c7fec1SAndroid Build Coastguard Worker 
100*00c7fec1SAndroid Build Coastguard Worker     /* Beginning of the prefix is the initial "vbd-" after "/devices/" */
101*00c7fec1SAndroid Build Coastguard Worker     std::string::size_type start = 13;
102*00c7fec1SAndroid Build Coastguard Worker 
103*00c7fec1SAndroid Build Coastguard Worker     /* End of the prefix is one path '/' later, capturing the
104*00c7fec1SAndroid Build Coastguard Worker        virtual block device ID. Example: 768 */
105*00c7fec1SAndroid Build Coastguard Worker     auto end = path.find('/', start);
106*00c7fec1SAndroid Build Coastguard Worker     if (end == std::string::npos) return false;
107*00c7fec1SAndroid Build Coastguard Worker 
108*00c7fec1SAndroid Build Coastguard Worker     auto length = end - start;
109*00c7fec1SAndroid Build Coastguard Worker     if (length == 0) return false;
110*00c7fec1SAndroid Build Coastguard Worker 
111*00c7fec1SAndroid Build Coastguard Worker     *result = path.substr(start, length);
112*00c7fec1SAndroid Build Coastguard Worker     return true;
113*00c7fec1SAndroid Build Coastguard Worker }
114*00c7fec1SAndroid Build Coastguard Worker 
115*00c7fec1SAndroid Build Coastguard Worker // Given a path that may start with a virtual dm block device, populate
116*00c7fec1SAndroid Build Coastguard Worker // the supplied buffer with the dm module's instantiated name.
117*00c7fec1SAndroid Build Coastguard Worker // If it doesn't start with a virtual block device, or there is some
118*00c7fec1SAndroid Build Coastguard Worker // error, return false.
FindDmDevice(const Uevent & uevent,std::string * name,std::string * uuid)119*00c7fec1SAndroid Build Coastguard Worker static bool FindDmDevice(const Uevent& uevent, std::string* name, std::string* uuid) {
120*00c7fec1SAndroid Build Coastguard Worker     if (!StartsWith(uevent.path, "/devices/virtual/block/dm-")) return false;
121*00c7fec1SAndroid Build Coastguard Worker     if (uevent.action == "remove") return false;  // Avoid error spam from ioctl
122*00c7fec1SAndroid Build Coastguard Worker 
123*00c7fec1SAndroid Build Coastguard Worker     dev_t dev = makedev(uevent.major, uevent.minor);
124*00c7fec1SAndroid Build Coastguard Worker 
125*00c7fec1SAndroid Build Coastguard Worker     auto& dm = android::dm::DeviceMapper::Instance();
126*00c7fec1SAndroid Build Coastguard Worker     return dm.GetDeviceNameAndUuid(dev, name, uuid);
127*00c7fec1SAndroid Build Coastguard Worker }
128*00c7fec1SAndroid Build Coastguard Worker 
Permissions(const std::string & name,mode_t perm,uid_t uid,gid_t gid,bool no_fnm_pathname)129*00c7fec1SAndroid Build Coastguard Worker Permissions::Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid,
130*00c7fec1SAndroid Build Coastguard Worker                          bool no_fnm_pathname)
131*00c7fec1SAndroid Build Coastguard Worker     : name_(name),
132*00c7fec1SAndroid Build Coastguard Worker       perm_(perm),
133*00c7fec1SAndroid Build Coastguard Worker       uid_(uid),
134*00c7fec1SAndroid Build Coastguard Worker       gid_(gid),
135*00c7fec1SAndroid Build Coastguard Worker       prefix_(false),
136*00c7fec1SAndroid Build Coastguard Worker       wildcard_(false),
137*00c7fec1SAndroid Build Coastguard Worker       no_fnm_pathname_(no_fnm_pathname) {
138*00c7fec1SAndroid Build Coastguard Worker     // Set 'prefix_' or 'wildcard_' based on the below cases:
139*00c7fec1SAndroid Build Coastguard Worker     //
140*00c7fec1SAndroid Build Coastguard Worker     // 1) No '*' in 'name' -> Neither are set and Match() checks a given path for strict
141*00c7fec1SAndroid Build Coastguard Worker     //    equality with 'name'
142*00c7fec1SAndroid Build Coastguard Worker     //
143*00c7fec1SAndroid Build Coastguard Worker     // 2) '*' only appears as the last character in 'name' -> 'prefix'_ is set to true and
144*00c7fec1SAndroid Build Coastguard Worker     //    Match() checks if 'name' is a prefix of a given path.
145*00c7fec1SAndroid Build Coastguard Worker     //
146*00c7fec1SAndroid Build Coastguard Worker     // 3) '*' appears elsewhere -> 'wildcard_' is set to true and Match() uses fnmatch()
147*00c7fec1SAndroid Build Coastguard Worker     //    with FNM_PATHNAME to compare 'name' to a given path.
148*00c7fec1SAndroid Build Coastguard Worker     auto wildcard_position = name_.find('*');
149*00c7fec1SAndroid Build Coastguard Worker     if (wildcard_position != std::string::npos) {
150*00c7fec1SAndroid Build Coastguard Worker         if (wildcard_position == name_.length() - 1) {
151*00c7fec1SAndroid Build Coastguard Worker             prefix_ = true;
152*00c7fec1SAndroid Build Coastguard Worker             name_.pop_back();
153*00c7fec1SAndroid Build Coastguard Worker         } else {
154*00c7fec1SAndroid Build Coastguard Worker             wildcard_ = true;
155*00c7fec1SAndroid Build Coastguard Worker         }
156*00c7fec1SAndroid Build Coastguard Worker     }
157*00c7fec1SAndroid Build Coastguard Worker }
158*00c7fec1SAndroid Build Coastguard Worker 
Match(const std::string & path) const159*00c7fec1SAndroid Build Coastguard Worker bool Permissions::Match(const std::string& path) const {
160*00c7fec1SAndroid Build Coastguard Worker     if (prefix_) return StartsWith(path, name_);
161*00c7fec1SAndroid Build Coastguard Worker     if (wildcard_)
162*00c7fec1SAndroid Build Coastguard Worker         return fnmatch(name_.c_str(), path.c_str(), no_fnm_pathname_ ? 0 : FNM_PATHNAME) == 0;
163*00c7fec1SAndroid Build Coastguard Worker     return path == name_;
164*00c7fec1SAndroid Build Coastguard Worker }
165*00c7fec1SAndroid Build Coastguard Worker 
MatchWithSubsystem(const std::string & path,const std::string & subsystem) const166*00c7fec1SAndroid Build Coastguard Worker bool SysfsPermissions::MatchWithSubsystem(const std::string& path,
167*00c7fec1SAndroid Build Coastguard Worker                                           const std::string& subsystem) const {
168*00c7fec1SAndroid Build Coastguard Worker     std::string path_basename = Basename(path);
169*00c7fec1SAndroid Build Coastguard Worker     if (name().find(subsystem) != std::string::npos) {
170*00c7fec1SAndroid Build Coastguard Worker         if (Match("/sys/class/" + subsystem + "/" + path_basename)) return true;
171*00c7fec1SAndroid Build Coastguard Worker         if (Match("/sys/bus/" + subsystem + "/devices/" + path_basename)) return true;
172*00c7fec1SAndroid Build Coastguard Worker     }
173*00c7fec1SAndroid Build Coastguard Worker     return Match(path);
174*00c7fec1SAndroid Build Coastguard Worker }
175*00c7fec1SAndroid Build Coastguard Worker 
SetPermissions(const std::string & path) const176*00c7fec1SAndroid Build Coastguard Worker void SysfsPermissions::SetPermissions(const std::string& path) const {
177*00c7fec1SAndroid Build Coastguard Worker     std::string attribute_file = path + "/" + attribute_;
178*00c7fec1SAndroid Build Coastguard Worker     LOG(VERBOSE) << "fixup " << attribute_file << " " << uid() << " " << gid() << " " << std::oct
179*00c7fec1SAndroid Build Coastguard Worker                  << perm();
180*00c7fec1SAndroid Build Coastguard Worker 
181*00c7fec1SAndroid Build Coastguard Worker     if (access(attribute_file.c_str(), F_OK) == 0) {
182*00c7fec1SAndroid Build Coastguard Worker         if (chown(attribute_file.c_str(), uid(), gid()) != 0) {
183*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "chown(" << attribute_file << ", " << uid() << ", " << gid()
184*00c7fec1SAndroid Build Coastguard Worker                         << ") failed";
185*00c7fec1SAndroid Build Coastguard Worker         }
186*00c7fec1SAndroid Build Coastguard Worker         if (chmod(attribute_file.c_str(), perm()) != 0) {
187*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "chmod(" << attribute_file << ", " << perm() << ") failed";
188*00c7fec1SAndroid Build Coastguard Worker         }
189*00c7fec1SAndroid Build Coastguard Worker     }
190*00c7fec1SAndroid Build Coastguard Worker }
191*00c7fec1SAndroid Build Coastguard Worker 
GetBlockDeviceInfo(const std::string & uevent_path) const192*00c7fec1SAndroid Build Coastguard Worker BlockDeviceInfo DeviceHandler::GetBlockDeviceInfo(const std::string& uevent_path) const {
193*00c7fec1SAndroid Build Coastguard Worker     BlockDeviceInfo info;
194*00c7fec1SAndroid Build Coastguard Worker 
195*00c7fec1SAndroid Build Coastguard Worker     if (!boot_part_uuid_.empty()) {
196*00c7fec1SAndroid Build Coastguard Worker         // Only use the more specific "MMC" / "NVME" / "SCSI" match if a
197*00c7fec1SAndroid Build Coastguard Worker         // partition UUID was passed.
198*00c7fec1SAndroid Build Coastguard Worker         //
199*00c7fec1SAndroid Build Coastguard Worker         // Old bootloaders that aren't passing the partition UUID instead
200*00c7fec1SAndroid Build Coastguard Worker         // pass the path to the closest "platform" device. It would
201*00c7fec1SAndroid Build Coastguard Worker         // break them if we chose this deeper (more specific) path.
202*00c7fec1SAndroid Build Coastguard Worker         //
203*00c7fec1SAndroid Build Coastguard Worker         // When we have a UUID we _want_ the more specific path since it can
204*00c7fec1SAndroid Build Coastguard Worker         // handle, for instance, differentiating two USB disks that are on
205*00c7fec1SAndroid Build Coastguard Worker         // the same USB controller. Using the closest platform device would
206*00c7fec1SAndroid Build Coastguard Worker         // classify them both the same by using the path to the USB controller.
207*00c7fec1SAndroid Build Coastguard Worker         if (FindMmcDevice(uevent_path, &info.str)) {
208*00c7fec1SAndroid Build Coastguard Worker             info.type = "mmc";
209*00c7fec1SAndroid Build Coastguard Worker         } else if (FindNvmeDevice(uevent_path, &info.str)) {
210*00c7fec1SAndroid Build Coastguard Worker             info.type = "nvme";
211*00c7fec1SAndroid Build Coastguard Worker         } else if (FindScsiDevice(uevent_path, &info.str)) {
212*00c7fec1SAndroid Build Coastguard Worker             info.type = "scsi";
213*00c7fec1SAndroid Build Coastguard Worker         }
214*00c7fec1SAndroid Build Coastguard Worker     } else if (FindPlatformDevice(uevent_path, &info.str)) {
215*00c7fec1SAndroid Build Coastguard Worker         info.type = "platform";
216*00c7fec1SAndroid Build Coastguard Worker     } else if (FindPciDevicePrefix(uevent_path, &info.str)) {
217*00c7fec1SAndroid Build Coastguard Worker         info.type = "pci";
218*00c7fec1SAndroid Build Coastguard Worker     } else if (FindVbdDevicePrefix(uevent_path, &info.str)) {
219*00c7fec1SAndroid Build Coastguard Worker         info.type = "vbd";
220*00c7fec1SAndroid Build Coastguard Worker     } else {
221*00c7fec1SAndroid Build Coastguard Worker         // Re-clear device to be extra certain in case one of the FindXXX()
222*00c7fec1SAndroid Build Coastguard Worker         // functions returned false but still modified it.
223*00c7fec1SAndroid Build Coastguard Worker         info.str = "";
224*00c7fec1SAndroid Build Coastguard Worker     }
225*00c7fec1SAndroid Build Coastguard Worker 
226*00c7fec1SAndroid Build Coastguard Worker     info.is_boot_device = boot_devices_.find(info.str) != boot_devices_.end();
227*00c7fec1SAndroid Build Coastguard Worker 
228*00c7fec1SAndroid Build Coastguard Worker     return info;
229*00c7fec1SAndroid Build Coastguard Worker }
230*00c7fec1SAndroid Build Coastguard Worker 
IsBootDeviceStrict() const231*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::IsBootDeviceStrict() const {
232*00c7fec1SAndroid Build Coastguard Worker     // When using the newer "boot_part_uuid" to specify the boot device then
233*00c7fec1SAndroid Build Coastguard Worker     // we require all core system partitions to be on the boot device.
234*00c7fec1SAndroid Build Coastguard Worker     return !boot_part_uuid_.empty();
235*00c7fec1SAndroid Build Coastguard Worker }
236*00c7fec1SAndroid Build Coastguard Worker 
IsBootDevice(const Uevent & uevent) const237*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::IsBootDevice(const Uevent& uevent) const {
238*00c7fec1SAndroid Build Coastguard Worker     auto device = GetBlockDeviceInfo(uevent.path);
239*00c7fec1SAndroid Build Coastguard Worker     return device.is_boot_device;
240*00c7fec1SAndroid Build Coastguard Worker }
241*00c7fec1SAndroid Build Coastguard Worker 
GetPartitionNameForDevice(const std::string & query_device)242*00c7fec1SAndroid Build Coastguard Worker std::string DeviceHandler::GetPartitionNameForDevice(const std::string& query_device) {
243*00c7fec1SAndroid Build Coastguard Worker     static const auto partition_map = [] {
244*00c7fec1SAndroid Build Coastguard Worker         std::vector<std::pair<std::string, std::string>> partition_map;
245*00c7fec1SAndroid Build Coastguard Worker         auto parser = [&partition_map](const std::string& key, const std::string& value) {
246*00c7fec1SAndroid Build Coastguard Worker             if (key != "androidboot.partition_map") {
247*00c7fec1SAndroid Build Coastguard Worker                 return;
248*00c7fec1SAndroid Build Coastguard Worker             }
249*00c7fec1SAndroid Build Coastguard Worker             for (const auto& map : Split(value, ";")) {
250*00c7fec1SAndroid Build Coastguard Worker                 auto map_pieces = Split(map, ",");
251*00c7fec1SAndroid Build Coastguard Worker                 if (map_pieces.size() != 2) {
252*00c7fec1SAndroid Build Coastguard Worker                     LOG(ERROR) << "Expected a comma separated device,partition mapping, but found '"
253*00c7fec1SAndroid Build Coastguard Worker                                << map << "'";
254*00c7fec1SAndroid Build Coastguard Worker                     continue;
255*00c7fec1SAndroid Build Coastguard Worker                 }
256*00c7fec1SAndroid Build Coastguard Worker                 partition_map.emplace_back(map_pieces[0], map_pieces[1]);
257*00c7fec1SAndroid Build Coastguard Worker             }
258*00c7fec1SAndroid Build Coastguard Worker         };
259*00c7fec1SAndroid Build Coastguard Worker         android::fs_mgr::ImportKernelCmdline(parser);
260*00c7fec1SAndroid Build Coastguard Worker         android::fs_mgr::ImportBootconfig(parser);
261*00c7fec1SAndroid Build Coastguard Worker         return partition_map;
262*00c7fec1SAndroid Build Coastguard Worker     }();
263*00c7fec1SAndroid Build Coastguard Worker 
264*00c7fec1SAndroid Build Coastguard Worker     for (const auto& [device, partition] : partition_map) {
265*00c7fec1SAndroid Build Coastguard Worker         if (query_device == device) {
266*00c7fec1SAndroid Build Coastguard Worker             return partition;
267*00c7fec1SAndroid Build Coastguard Worker         }
268*00c7fec1SAndroid Build Coastguard Worker     }
269*00c7fec1SAndroid Build Coastguard Worker     return {};
270*00c7fec1SAndroid Build Coastguard Worker }
271*00c7fec1SAndroid Build Coastguard Worker 
272*00c7fec1SAndroid Build Coastguard Worker // Given a path to a device that may have a parent in the passed set of
273*00c7fec1SAndroid Build Coastguard Worker // subsystems, find the parent device that's in the passed set of subsystems.
274*00c7fec1SAndroid Build Coastguard Worker // If we don't find a parent in the passed set of subsystems, return false.
FindSubsystemDevice(std::string path,std::string * device_path,const std::set<std::string> & subsystem_paths) const275*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::FindSubsystemDevice(std::string path, std::string* device_path,
276*00c7fec1SAndroid Build Coastguard Worker                                         const std::set<std::string>& subsystem_paths) const {
277*00c7fec1SAndroid Build Coastguard Worker     device_path->clear();
278*00c7fec1SAndroid Build Coastguard Worker 
279*00c7fec1SAndroid Build Coastguard Worker     // Uevents don't contain the mount point, so we need to add it here.
280*00c7fec1SAndroid Build Coastguard Worker     path.insert(0, sysfs_mount_point_);
281*00c7fec1SAndroid Build Coastguard Worker 
282*00c7fec1SAndroid Build Coastguard Worker     std::string directory = Dirname(path);
283*00c7fec1SAndroid Build Coastguard Worker 
284*00c7fec1SAndroid Build Coastguard Worker     while (directory != "/" && directory != ".") {
285*00c7fec1SAndroid Build Coastguard Worker         std::string subsystem_link_path;
286*00c7fec1SAndroid Build Coastguard Worker         if (Realpath(directory + "/subsystem", &subsystem_link_path) &&
287*00c7fec1SAndroid Build Coastguard Worker             subsystem_paths.find(subsystem_link_path) != subsystem_paths.end()) {
288*00c7fec1SAndroid Build Coastguard Worker             // We need to remove the mount point that we added above before returning.
289*00c7fec1SAndroid Build Coastguard Worker             directory.erase(0, sysfs_mount_point_.size());
290*00c7fec1SAndroid Build Coastguard Worker 
291*00c7fec1SAndroid Build Coastguard Worker             // Skip /devices/platform or /devices/ if present
292*00c7fec1SAndroid Build Coastguard Worker             static constexpr std::string_view devices_platform_prefix = "/devices/platform/";
293*00c7fec1SAndroid Build Coastguard Worker             static constexpr std::string_view devices_prefix = "/devices/";
294*00c7fec1SAndroid Build Coastguard Worker             std::string_view sv = directory;
295*00c7fec1SAndroid Build Coastguard Worker 
296*00c7fec1SAndroid Build Coastguard Worker             if (!ConsumePrefix(&sv, devices_platform_prefix)) {
297*00c7fec1SAndroid Build Coastguard Worker                 ConsumePrefix(&sv, devices_prefix);
298*00c7fec1SAndroid Build Coastguard Worker             }
299*00c7fec1SAndroid Build Coastguard Worker             *device_path = sv;
300*00c7fec1SAndroid Build Coastguard Worker 
301*00c7fec1SAndroid Build Coastguard Worker             return true;
302*00c7fec1SAndroid Build Coastguard Worker         }
303*00c7fec1SAndroid Build Coastguard Worker 
304*00c7fec1SAndroid Build Coastguard Worker         auto last_slash = path.rfind('/');
305*00c7fec1SAndroid Build Coastguard Worker         if (last_slash == std::string::npos) return false;
306*00c7fec1SAndroid Build Coastguard Worker 
307*00c7fec1SAndroid Build Coastguard Worker         path.erase(last_slash);
308*00c7fec1SAndroid Build Coastguard Worker         directory = Dirname(path);
309*00c7fec1SAndroid Build Coastguard Worker     }
310*00c7fec1SAndroid Build Coastguard Worker 
311*00c7fec1SAndroid Build Coastguard Worker     return false;
312*00c7fec1SAndroid Build Coastguard Worker }
313*00c7fec1SAndroid Build Coastguard Worker 
FindPlatformDevice(const std::string & path,std::string * platform_device_path) const314*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::FindPlatformDevice(const std::string& path,
315*00c7fec1SAndroid Build Coastguard Worker                                        std::string* platform_device_path) const {
316*00c7fec1SAndroid Build Coastguard Worker     const std::set<std::string> subsystem_paths = {
317*00c7fec1SAndroid Build Coastguard Worker             sysfs_mount_point_ + "/bus/platform",
318*00c7fec1SAndroid Build Coastguard Worker             sysfs_mount_point_ + "/bus/amba",
319*00c7fec1SAndroid Build Coastguard Worker     };
320*00c7fec1SAndroid Build Coastguard Worker 
321*00c7fec1SAndroid Build Coastguard Worker     return FindSubsystemDevice(path, platform_device_path, subsystem_paths);
322*00c7fec1SAndroid Build Coastguard Worker }
323*00c7fec1SAndroid Build Coastguard Worker 
FindMmcDevice(const std::string & path,std::string * mmc_device_path) const324*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::FindMmcDevice(const std::string& path, std::string* mmc_device_path) const {
325*00c7fec1SAndroid Build Coastguard Worker     const std::set<std::string> subsystem_paths = {
326*00c7fec1SAndroid Build Coastguard Worker             sysfs_mount_point_ + "/bus/mmc",
327*00c7fec1SAndroid Build Coastguard Worker     };
328*00c7fec1SAndroid Build Coastguard Worker 
329*00c7fec1SAndroid Build Coastguard Worker     return FindSubsystemDevice(path, mmc_device_path, subsystem_paths);
330*00c7fec1SAndroid Build Coastguard Worker }
331*00c7fec1SAndroid Build Coastguard Worker 
FindNvmeDevice(const std::string & path,std::string * nvme_device_path) const332*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::FindNvmeDevice(const std::string& path, std::string* nvme_device_path) const {
333*00c7fec1SAndroid Build Coastguard Worker     const std::set<std::string> subsystem_paths = {
334*00c7fec1SAndroid Build Coastguard Worker             sysfs_mount_point_ + "/class/nvme",
335*00c7fec1SAndroid Build Coastguard Worker     };
336*00c7fec1SAndroid Build Coastguard Worker 
337*00c7fec1SAndroid Build Coastguard Worker     return FindSubsystemDevice(path, nvme_device_path, subsystem_paths);
338*00c7fec1SAndroid Build Coastguard Worker }
339*00c7fec1SAndroid Build Coastguard Worker 
FindScsiDevice(const std::string & path,std::string * scsi_device_path) const340*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::FindScsiDevice(const std::string& path, std::string* scsi_device_path) const {
341*00c7fec1SAndroid Build Coastguard Worker     const std::set<std::string> subsystem_paths = {
342*00c7fec1SAndroid Build Coastguard Worker             sysfs_mount_point_ + "/bus/scsi",
343*00c7fec1SAndroid Build Coastguard Worker     };
344*00c7fec1SAndroid Build Coastguard Worker 
345*00c7fec1SAndroid Build Coastguard Worker     return FindSubsystemDevice(path, scsi_device_path, subsystem_paths);
346*00c7fec1SAndroid Build Coastguard Worker }
347*00c7fec1SAndroid Build Coastguard Worker 
TrackDeviceUevent(const Uevent & uevent)348*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::TrackDeviceUevent(const Uevent& uevent) {
349*00c7fec1SAndroid Build Coastguard Worker     // No need to track any events if we won't bother handling any bind events
350*00c7fec1SAndroid Build Coastguard Worker     // later.
351*00c7fec1SAndroid Build Coastguard Worker     if (drivers_.size() == 0) return;
352*00c7fec1SAndroid Build Coastguard Worker 
353*00c7fec1SAndroid Build Coastguard Worker     // Only track add, and not for block devices. We don't track remove because
354*00c7fec1SAndroid Build Coastguard Worker     // unbind events may arrive after remove events, so unbind will be the
355*00c7fec1SAndroid Build Coastguard Worker     // trigger to untrack those events.
356*00c7fec1SAndroid Build Coastguard Worker     if ((uevent.action != "add") || uevent.subsystem == "block" ||
357*00c7fec1SAndroid Build Coastguard Worker         (uevent.major < 0 || uevent.minor < 0)) {
358*00c7fec1SAndroid Build Coastguard Worker         return;
359*00c7fec1SAndroid Build Coastguard Worker     }
360*00c7fec1SAndroid Build Coastguard Worker 
361*00c7fec1SAndroid Build Coastguard Worker     std::string path = sysfs_mount_point_ + uevent.path + "/device";
362*00c7fec1SAndroid Build Coastguard Worker     std::string device;
363*00c7fec1SAndroid Build Coastguard Worker     if (!Realpath(path, &device)) return;
364*00c7fec1SAndroid Build Coastguard Worker 
365*00c7fec1SAndroid Build Coastguard Worker     tracked_uevents_.emplace_back(uevent, device);
366*00c7fec1SAndroid Build Coastguard Worker }
367*00c7fec1SAndroid Build Coastguard Worker 
FixupSysPermissions(const std::string & upath,const std::string & subsystem) const368*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::FixupSysPermissions(const std::string& upath,
369*00c7fec1SAndroid Build Coastguard Worker                                         const std::string& subsystem) const {
370*00c7fec1SAndroid Build Coastguard Worker     // upaths omit the "/sys" that paths in this list
371*00c7fec1SAndroid Build Coastguard Worker     // contain, so we prepend it...
372*00c7fec1SAndroid Build Coastguard Worker     std::string path = "/sys" + upath;
373*00c7fec1SAndroid Build Coastguard Worker 
374*00c7fec1SAndroid Build Coastguard Worker     for (const auto& s : sysfs_permissions_) {
375*00c7fec1SAndroid Build Coastguard Worker         if (s.MatchWithSubsystem(path, subsystem)) s.SetPermissions(path);
376*00c7fec1SAndroid Build Coastguard Worker     }
377*00c7fec1SAndroid Build Coastguard Worker 
378*00c7fec1SAndroid Build Coastguard Worker     if (!skip_restorecon_ && access(path.c_str(), F_OK) == 0) {
379*00c7fec1SAndroid Build Coastguard Worker         LOG(VERBOSE) << "restorecon_recursive: " << path;
380*00c7fec1SAndroid Build Coastguard Worker         if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_RECURSE) != 0) {
381*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "selinux_android_restorecon(" << path << ") failed";
382*00c7fec1SAndroid Build Coastguard Worker         }
383*00c7fec1SAndroid Build Coastguard Worker     }
384*00c7fec1SAndroid Build Coastguard Worker }
385*00c7fec1SAndroid Build Coastguard Worker 
GetDevicePermissions(const std::string & path,const std::vector<std::string> & links) const386*00c7fec1SAndroid Build Coastguard Worker std::tuple<mode_t, uid_t, gid_t> DeviceHandler::GetDevicePermissions(
387*00c7fec1SAndroid Build Coastguard Worker     const std::string& path, const std::vector<std::string>& links) const {
388*00c7fec1SAndroid Build Coastguard Worker     // Search the perms list in reverse so that ueventd.$hardware can override ueventd.rc.
389*00c7fec1SAndroid Build Coastguard Worker     for (auto it = dev_permissions_.crbegin(); it != dev_permissions_.crend(); ++it) {
390*00c7fec1SAndroid Build Coastguard Worker         if (it->Match(path) || std::any_of(links.cbegin(), links.cend(),
391*00c7fec1SAndroid Build Coastguard Worker                                            [it](const auto& link) { return it->Match(link); })) {
392*00c7fec1SAndroid Build Coastguard Worker             return {it->perm(), it->uid(), it->gid()};
393*00c7fec1SAndroid Build Coastguard Worker         }
394*00c7fec1SAndroid Build Coastguard Worker     }
395*00c7fec1SAndroid Build Coastguard Worker     /* Default if nothing found. */
396*00c7fec1SAndroid Build Coastguard Worker     return {0600, 0, 0};
397*00c7fec1SAndroid Build Coastguard Worker }
398*00c7fec1SAndroid Build Coastguard Worker 
MakeDevice(const std::string & path,bool block,int major,int minor,const std::vector<std::string> & links) const399*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::MakeDevice(const std::string& path, bool block, int major, int minor,
400*00c7fec1SAndroid Build Coastguard Worker                                const std::vector<std::string>& links) const {
401*00c7fec1SAndroid Build Coastguard Worker     auto [mode, uid, gid] = GetDevicePermissions(path, links);
402*00c7fec1SAndroid Build Coastguard Worker     mode |= (block ? S_IFBLK : S_IFCHR);
403*00c7fec1SAndroid Build Coastguard Worker 
404*00c7fec1SAndroid Build Coastguard Worker     std::string secontext;
405*00c7fec1SAndroid Build Coastguard Worker     if (!SelabelLookupFileContextBestMatch(path, links, mode, &secontext)) {
406*00c7fec1SAndroid Build Coastguard Worker         PLOG(ERROR) << "Device '" << path << "' not created; cannot find SELinux label";
407*00c7fec1SAndroid Build Coastguard Worker         return;
408*00c7fec1SAndroid Build Coastguard Worker     }
409*00c7fec1SAndroid Build Coastguard Worker     if (!secontext.empty()) {
410*00c7fec1SAndroid Build Coastguard Worker         setfscreatecon(secontext.c_str());
411*00c7fec1SAndroid Build Coastguard Worker     }
412*00c7fec1SAndroid Build Coastguard Worker 
413*00c7fec1SAndroid Build Coastguard Worker     gid_t new_group = -1;
414*00c7fec1SAndroid Build Coastguard Worker 
415*00c7fec1SAndroid Build Coastguard Worker     dev_t dev = makedev(major, minor);
416*00c7fec1SAndroid Build Coastguard Worker     /* Temporarily change egid to avoid race condition setting the gid of the
417*00c7fec1SAndroid Build Coastguard Worker      * device node. Unforunately changing the euid would prevent creation of
418*00c7fec1SAndroid Build Coastguard Worker      * some device nodes, so the uid has to be set with chown() and is still
419*00c7fec1SAndroid Build Coastguard Worker      * racy. Fixing the gid race at least fixed the issue with system_server
420*00c7fec1SAndroid Build Coastguard Worker      * opening dynamic input devices under the AID_INPUT gid. */
421*00c7fec1SAndroid Build Coastguard Worker     if (setegid(gid)) {
422*00c7fec1SAndroid Build Coastguard Worker         PLOG(ERROR) << "setegid(" << gid << ") for " << path << " device failed";
423*00c7fec1SAndroid Build Coastguard Worker         goto out;
424*00c7fec1SAndroid Build Coastguard Worker     }
425*00c7fec1SAndroid Build Coastguard Worker     /* If the node already exists update its SELinux label and the file mode to handle cases when
426*00c7fec1SAndroid Build Coastguard Worker      * it was created with the wrong context and file mode during coldboot procedure. */
427*00c7fec1SAndroid Build Coastguard Worker     if (mknod(path.c_str(), mode, dev) && (errno == EEXIST) && !secontext.empty()) {
428*00c7fec1SAndroid Build Coastguard Worker         char* fcon = nullptr;
429*00c7fec1SAndroid Build Coastguard Worker         int rc = lgetfilecon(path.c_str(), &fcon);
430*00c7fec1SAndroid Build Coastguard Worker         if (rc < 0) {
431*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "Cannot get SELinux label on '" << path << "' device";
432*00c7fec1SAndroid Build Coastguard Worker             goto out;
433*00c7fec1SAndroid Build Coastguard Worker         }
434*00c7fec1SAndroid Build Coastguard Worker 
435*00c7fec1SAndroid Build Coastguard Worker         bool different = fcon != secontext;
436*00c7fec1SAndroid Build Coastguard Worker         freecon(fcon);
437*00c7fec1SAndroid Build Coastguard Worker 
438*00c7fec1SAndroid Build Coastguard Worker         if (different && lsetfilecon(path.c_str(), secontext.c_str())) {
439*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "Cannot set '" << secontext << "' SELinux label on '" << path
440*00c7fec1SAndroid Build Coastguard Worker                         << "' device";
441*00c7fec1SAndroid Build Coastguard Worker         }
442*00c7fec1SAndroid Build Coastguard Worker 
443*00c7fec1SAndroid Build Coastguard Worker         struct stat s;
444*00c7fec1SAndroid Build Coastguard Worker         if (stat(path.c_str(), &s) == 0) {
445*00c7fec1SAndroid Build Coastguard Worker             if (gid != s.st_gid) {
446*00c7fec1SAndroid Build Coastguard Worker                 new_group = gid;
447*00c7fec1SAndroid Build Coastguard Worker             }
448*00c7fec1SAndroid Build Coastguard Worker             if (mode != s.st_mode) {
449*00c7fec1SAndroid Build Coastguard Worker                 if (chmod(path.c_str(), mode) != 0) {
450*00c7fec1SAndroid Build Coastguard Worker                     PLOG(ERROR) << "Cannot chmod " << path << " to " << mode;
451*00c7fec1SAndroid Build Coastguard Worker                 }
452*00c7fec1SAndroid Build Coastguard Worker             }
453*00c7fec1SAndroid Build Coastguard Worker         } else {
454*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "Cannot stat " << path;
455*00c7fec1SAndroid Build Coastguard Worker         }
456*00c7fec1SAndroid Build Coastguard Worker     }
457*00c7fec1SAndroid Build Coastguard Worker 
458*00c7fec1SAndroid Build Coastguard Worker out:
459*00c7fec1SAndroid Build Coastguard Worker     if (chown(path.c_str(), uid, new_group) < 0) {
460*00c7fec1SAndroid Build Coastguard Worker         PLOG(ERROR) << "Cannot chown " << path << " " << uid << " " << new_group;
461*00c7fec1SAndroid Build Coastguard Worker     }
462*00c7fec1SAndroid Build Coastguard Worker     if (setegid(AID_ROOT)) {
463*00c7fec1SAndroid Build Coastguard Worker         PLOG(FATAL) << "setegid(AID_ROOT) failed";
464*00c7fec1SAndroid Build Coastguard Worker     }
465*00c7fec1SAndroid Build Coastguard Worker 
466*00c7fec1SAndroid Build Coastguard Worker     if (!secontext.empty()) {
467*00c7fec1SAndroid Build Coastguard Worker         setfscreatecon(nullptr);
468*00c7fec1SAndroid Build Coastguard Worker     }
469*00c7fec1SAndroid Build Coastguard Worker }
470*00c7fec1SAndroid Build Coastguard Worker 
471*00c7fec1SAndroid Build Coastguard Worker // replaces any unacceptable characters with '_', the
472*00c7fec1SAndroid Build Coastguard Worker // length of the resulting string is equal to the input string
SanitizePartitionName(std::string * string)473*00c7fec1SAndroid Build Coastguard Worker void SanitizePartitionName(std::string* string) {
474*00c7fec1SAndroid Build Coastguard Worker     const char* accept =
475*00c7fec1SAndroid Build Coastguard Worker         "abcdefghijklmnopqrstuvwxyz"
476*00c7fec1SAndroid Build Coastguard Worker         "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
477*00c7fec1SAndroid Build Coastguard Worker         "0123456789"
478*00c7fec1SAndroid Build Coastguard Worker         "_-.";
479*00c7fec1SAndroid Build Coastguard Worker 
480*00c7fec1SAndroid Build Coastguard Worker     if (!string) return;
481*00c7fec1SAndroid Build Coastguard Worker 
482*00c7fec1SAndroid Build Coastguard Worker     std::string::size_type pos = 0;
483*00c7fec1SAndroid Build Coastguard Worker     while ((pos = string->find_first_not_of(accept, pos)) != std::string::npos) {
484*00c7fec1SAndroid Build Coastguard Worker         (*string)[pos] = '_';
485*00c7fec1SAndroid Build Coastguard Worker     }
486*00c7fec1SAndroid Build Coastguard Worker }
487*00c7fec1SAndroid Build Coastguard Worker 
GetBlockDeviceSymlinks(const Uevent & uevent) const488*00c7fec1SAndroid Build Coastguard Worker std::vector<std::string> DeviceHandler::GetBlockDeviceSymlinks(const Uevent& uevent) const {
489*00c7fec1SAndroid Build Coastguard Worker     BlockDeviceInfo info;
490*00c7fec1SAndroid Build Coastguard Worker     std::string partition;
491*00c7fec1SAndroid Build Coastguard Worker     std::string uuid;
492*00c7fec1SAndroid Build Coastguard Worker 
493*00c7fec1SAndroid Build Coastguard Worker     if (FindDmDevice(uevent, &partition, &uuid)) {
494*00c7fec1SAndroid Build Coastguard Worker         std::vector<std::string> symlinks = {"/dev/block/mapper/" + partition};
495*00c7fec1SAndroid Build Coastguard Worker         if (!uuid.empty()) {
496*00c7fec1SAndroid Build Coastguard Worker             symlinks.emplace_back("/dev/block/mapper/by-uuid/" + uuid);
497*00c7fec1SAndroid Build Coastguard Worker         }
498*00c7fec1SAndroid Build Coastguard Worker         return symlinks;
499*00c7fec1SAndroid Build Coastguard Worker     }
500*00c7fec1SAndroid Build Coastguard Worker 
501*00c7fec1SAndroid Build Coastguard Worker     info = GetBlockDeviceInfo(uevent.path);
502*00c7fec1SAndroid Build Coastguard Worker 
503*00c7fec1SAndroid Build Coastguard Worker     if (info.type.empty()) {
504*00c7fec1SAndroid Build Coastguard Worker         return {};
505*00c7fec1SAndroid Build Coastguard Worker     }
506*00c7fec1SAndroid Build Coastguard Worker 
507*00c7fec1SAndroid Build Coastguard Worker     std::vector<std::string> links;
508*00c7fec1SAndroid Build Coastguard Worker 
509*00c7fec1SAndroid Build Coastguard Worker     LOG(VERBOSE) << "found " << info.type << " device " << info.str;
510*00c7fec1SAndroid Build Coastguard Worker 
511*00c7fec1SAndroid Build Coastguard Worker     auto link_path = "/dev/block/" + info.type + "/" + info.str;
512*00c7fec1SAndroid Build Coastguard Worker 
513*00c7fec1SAndroid Build Coastguard Worker     if (!uevent.partition_name.empty()) {
514*00c7fec1SAndroid Build Coastguard Worker         std::string partition_name_sanitized(uevent.partition_name);
515*00c7fec1SAndroid Build Coastguard Worker         SanitizePartitionName(&partition_name_sanitized);
516*00c7fec1SAndroid Build Coastguard Worker         if (partition_name_sanitized != uevent.partition_name) {
517*00c7fec1SAndroid Build Coastguard Worker             LOG(VERBOSE) << "Linking partition '" << uevent.partition_name << "' as '"
518*00c7fec1SAndroid Build Coastguard Worker                          << partition_name_sanitized << "'";
519*00c7fec1SAndroid Build Coastguard Worker         }
520*00c7fec1SAndroid Build Coastguard Worker         links.emplace_back(link_path + "/by-name/" + partition_name_sanitized);
521*00c7fec1SAndroid Build Coastguard Worker         // Adds symlink: /dev/block/by-name/<partition_name>.
522*00c7fec1SAndroid Build Coastguard Worker         if (info.is_boot_device) {
523*00c7fec1SAndroid Build Coastguard Worker             links.emplace_back("/dev/block/by-name/" + partition_name_sanitized);
524*00c7fec1SAndroid Build Coastguard Worker         }
525*00c7fec1SAndroid Build Coastguard Worker     } else if (info.is_boot_device) {
526*00c7fec1SAndroid Build Coastguard Worker         // If we don't have a partition name but we are a partition on a boot device, create a
527*00c7fec1SAndroid Build Coastguard Worker         // symlink of /dev/block/by-name/<device_name> for symmetry.
528*00c7fec1SAndroid Build Coastguard Worker         links.emplace_back("/dev/block/by-name/" + uevent.device_name);
529*00c7fec1SAndroid Build Coastguard Worker         auto partition_name = GetPartitionNameForDevice(uevent.device_name);
530*00c7fec1SAndroid Build Coastguard Worker         if (!partition_name.empty()) {
531*00c7fec1SAndroid Build Coastguard Worker             links.emplace_back("/dev/block/by-name/" + partition_name);
532*00c7fec1SAndroid Build Coastguard Worker         }
533*00c7fec1SAndroid Build Coastguard Worker     }
534*00c7fec1SAndroid Build Coastguard Worker 
535*00c7fec1SAndroid Build Coastguard Worker     std::string model;
536*00c7fec1SAndroid Build Coastguard Worker     if (ReadFileToString("/sys/class/block/" + uevent.device_name + "/queue/zoned", &model) &&
537*00c7fec1SAndroid Build Coastguard Worker         !StartsWith(model, "none")) {
538*00c7fec1SAndroid Build Coastguard Worker         links.emplace_back("/dev/block/by-name/zoned_device");
539*00c7fec1SAndroid Build Coastguard Worker         links.emplace_back("/dev/sys/block/by-name/zoned_device");
540*00c7fec1SAndroid Build Coastguard Worker     }
541*00c7fec1SAndroid Build Coastguard Worker 
542*00c7fec1SAndroid Build Coastguard Worker     auto last_slash = uevent.path.rfind('/');
543*00c7fec1SAndroid Build Coastguard Worker     links.emplace_back(link_path + "/" + uevent.path.substr(last_slash + 1));
544*00c7fec1SAndroid Build Coastguard Worker 
545*00c7fec1SAndroid Build Coastguard Worker     return links;
546*00c7fec1SAndroid Build Coastguard Worker }
547*00c7fec1SAndroid Build Coastguard Worker 
RemoveDeviceMapperLinks(const std::string & devpath)548*00c7fec1SAndroid Build Coastguard Worker static void RemoveDeviceMapperLinks(const std::string& devpath) {
549*00c7fec1SAndroid Build Coastguard Worker     std::vector<std::string> dirs = {
550*00c7fec1SAndroid Build Coastguard Worker             "/dev/block/mapper",
551*00c7fec1SAndroid Build Coastguard Worker             "/dev/block/mapper/by-uuid",
552*00c7fec1SAndroid Build Coastguard Worker     };
553*00c7fec1SAndroid Build Coastguard Worker     for (const auto& dir : dirs) {
554*00c7fec1SAndroid Build Coastguard Worker         if (access(dir.c_str(), F_OK) != 0) continue;
555*00c7fec1SAndroid Build Coastguard Worker 
556*00c7fec1SAndroid Build Coastguard Worker         std::unique_ptr<DIR, decltype(&closedir)> dh(opendir(dir.c_str()), closedir);
557*00c7fec1SAndroid Build Coastguard Worker         if (!dh) {
558*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "Failed to open directory " << dir;
559*00c7fec1SAndroid Build Coastguard Worker             continue;
560*00c7fec1SAndroid Build Coastguard Worker         }
561*00c7fec1SAndroid Build Coastguard Worker 
562*00c7fec1SAndroid Build Coastguard Worker         struct dirent* dp;
563*00c7fec1SAndroid Build Coastguard Worker         std::string link_path;
564*00c7fec1SAndroid Build Coastguard Worker         while ((dp = readdir(dh.get())) != nullptr) {
565*00c7fec1SAndroid Build Coastguard Worker             if (dp->d_type != DT_LNK) continue;
566*00c7fec1SAndroid Build Coastguard Worker 
567*00c7fec1SAndroid Build Coastguard Worker             auto path = dir + "/" + dp->d_name;
568*00c7fec1SAndroid Build Coastguard Worker             if (Readlink(path, &link_path) && link_path == devpath) {
569*00c7fec1SAndroid Build Coastguard Worker                 unlink(path.c_str());
570*00c7fec1SAndroid Build Coastguard Worker             }
571*00c7fec1SAndroid Build Coastguard Worker         }
572*00c7fec1SAndroid Build Coastguard Worker     }
573*00c7fec1SAndroid Build Coastguard Worker }
574*00c7fec1SAndroid Build Coastguard Worker 
HandleDevice(const std::string & action,const std::string & devpath,bool block,int major,int minor,const std::vector<std::string> & links) const575*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::HandleDevice(const std::string& action, const std::string& devpath, bool block,
576*00c7fec1SAndroid Build Coastguard Worker                                  int major, int minor, const std::vector<std::string>& links) const {
577*00c7fec1SAndroid Build Coastguard Worker     if (action == "add") {
578*00c7fec1SAndroid Build Coastguard Worker         MakeDevice(devpath, block, major, minor, links);
579*00c7fec1SAndroid Build Coastguard Worker     }
580*00c7fec1SAndroid Build Coastguard Worker 
581*00c7fec1SAndroid Build Coastguard Worker     // Handle device-mapper nodes.
582*00c7fec1SAndroid Build Coastguard Worker     // On kernels <= 5.10, the "add" event is fired on DM_DEV_CREATE, but does not contain name
583*00c7fec1SAndroid Build Coastguard Worker     // information until DM_TABLE_LOAD - thus, we wait for a "change" event.
584*00c7fec1SAndroid Build Coastguard Worker     // On kernels >= 5.15, the "add" event is fired on DM_TABLE_LOAD, followed by a "change"
585*00c7fec1SAndroid Build Coastguard Worker     // event.
586*00c7fec1SAndroid Build Coastguard Worker     if (action == "add" || (action == "change" && StartsWith(devpath, "/dev/block/dm-"))) {
587*00c7fec1SAndroid Build Coastguard Worker         for (const auto& link : links) {
588*00c7fec1SAndroid Build Coastguard Worker             std::string target;
589*00c7fec1SAndroid Build Coastguard Worker             if (StartsWith(link, "/dev/block/")) {
590*00c7fec1SAndroid Build Coastguard Worker                 target = devpath;
591*00c7fec1SAndroid Build Coastguard Worker             } else if (StartsWith(link, "/dev/sys/block/")) {
592*00c7fec1SAndroid Build Coastguard Worker                 target = "/sys/class/block/" + Basename(devpath);
593*00c7fec1SAndroid Build Coastguard Worker             } else {
594*00c7fec1SAndroid Build Coastguard Worker                 LOG(ERROR) << "Unrecognized link type: " << link;
595*00c7fec1SAndroid Build Coastguard Worker                 continue;
596*00c7fec1SAndroid Build Coastguard Worker             }
597*00c7fec1SAndroid Build Coastguard Worker 
598*00c7fec1SAndroid Build Coastguard Worker             if (!mkdir_recursive(Dirname(link), 0755)) {
599*00c7fec1SAndroid Build Coastguard Worker                 PLOG(ERROR) << "Failed to create directory " << Dirname(link);
600*00c7fec1SAndroid Build Coastguard Worker             }
601*00c7fec1SAndroid Build Coastguard Worker 
602*00c7fec1SAndroid Build Coastguard Worker             if (symlink(target.c_str(), link.c_str())) {
603*00c7fec1SAndroid Build Coastguard Worker                 if (errno != EEXIST) {
604*00c7fec1SAndroid Build Coastguard Worker                     PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link;
605*00c7fec1SAndroid Build Coastguard Worker                 } else if (std::string link_path;
606*00c7fec1SAndroid Build Coastguard Worker                            Readlink(link, &link_path) && link_path != devpath) {
607*00c7fec1SAndroid Build Coastguard Worker                     PLOG(ERROR) << "Failed to symlink " << devpath << " to " << link
608*00c7fec1SAndroid Build Coastguard Worker                                 << ", which already links to: " << link_path;
609*00c7fec1SAndroid Build Coastguard Worker                 }
610*00c7fec1SAndroid Build Coastguard Worker             }
611*00c7fec1SAndroid Build Coastguard Worker         }
612*00c7fec1SAndroid Build Coastguard Worker     }
613*00c7fec1SAndroid Build Coastguard Worker 
614*00c7fec1SAndroid Build Coastguard Worker     if (action == "remove") {
615*00c7fec1SAndroid Build Coastguard Worker         if (StartsWith(devpath, "/dev/block/dm-")) {
616*00c7fec1SAndroid Build Coastguard Worker             RemoveDeviceMapperLinks(devpath);
617*00c7fec1SAndroid Build Coastguard Worker         }
618*00c7fec1SAndroid Build Coastguard Worker         for (const auto& link : links) {
619*00c7fec1SAndroid Build Coastguard Worker             std::string link_path;
620*00c7fec1SAndroid Build Coastguard Worker             if (Readlink(link, &link_path) && link_path == devpath) {
621*00c7fec1SAndroid Build Coastguard Worker                 unlink(link.c_str());
622*00c7fec1SAndroid Build Coastguard Worker             }
623*00c7fec1SAndroid Build Coastguard Worker         }
624*00c7fec1SAndroid Build Coastguard Worker         unlink(devpath.c_str());
625*00c7fec1SAndroid Build Coastguard Worker     }
626*00c7fec1SAndroid Build Coastguard Worker }
627*00c7fec1SAndroid Build Coastguard Worker 
HandleAshmemUevent(const Uevent & uevent)628*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::HandleAshmemUevent(const Uevent& uevent) {
629*00c7fec1SAndroid Build Coastguard Worker     if (uevent.device_name == "ashmem") {
630*00c7fec1SAndroid Build Coastguard Worker         static const std::string boot_id_path = "/proc/sys/kernel/random/boot_id";
631*00c7fec1SAndroid Build Coastguard Worker         std::string boot_id;
632*00c7fec1SAndroid Build Coastguard Worker         if (!ReadFileToString(boot_id_path, &boot_id)) {
633*00c7fec1SAndroid Build Coastguard Worker             PLOG(ERROR) << "Cannot duplicate ashmem device node. Failed to read " << boot_id_path;
634*00c7fec1SAndroid Build Coastguard Worker             return;
635*00c7fec1SAndroid Build Coastguard Worker         }
636*00c7fec1SAndroid Build Coastguard Worker         boot_id = Trim(boot_id);
637*00c7fec1SAndroid Build Coastguard Worker 
638*00c7fec1SAndroid Build Coastguard Worker         Uevent dup_ashmem_uevent = uevent;
639*00c7fec1SAndroid Build Coastguard Worker         dup_ashmem_uevent.device_name += boot_id;
640*00c7fec1SAndroid Build Coastguard Worker         dup_ashmem_uevent.path += boot_id;
641*00c7fec1SAndroid Build Coastguard Worker         HandleUevent(dup_ashmem_uevent);
642*00c7fec1SAndroid Build Coastguard Worker     }
643*00c7fec1SAndroid Build Coastguard Worker }
644*00c7fec1SAndroid Build Coastguard Worker 
645*00c7fec1SAndroid Build Coastguard Worker // Check Uevents looking for the kernel's boot partition UUID
646*00c7fec1SAndroid Build Coastguard Worker //
647*00c7fec1SAndroid Build Coastguard Worker // When we can stop checking uevents (either because we're done or because
648*00c7fec1SAndroid Build Coastguard Worker // we weren't looking for the kernel's boot partition UUID) then return
649*00c7fec1SAndroid Build Coastguard Worker // true. Return false if we're not done yet.
CheckUeventForBootPartUuid(const Uevent & uevent)650*00c7fec1SAndroid Build Coastguard Worker bool DeviceHandler::CheckUeventForBootPartUuid(const Uevent& uevent) {
651*00c7fec1SAndroid Build Coastguard Worker     // If we aren't using boot_part_uuid then we're done.
652*00c7fec1SAndroid Build Coastguard Worker     if (boot_part_uuid_.empty()) {
653*00c7fec1SAndroid Build Coastguard Worker         return true;
654*00c7fec1SAndroid Build Coastguard Worker     }
655*00c7fec1SAndroid Build Coastguard Worker 
656*00c7fec1SAndroid Build Coastguard Worker     // Finding the boot partition is a one-time thing that we do at init
657*00c7fec1SAndroid Build Coastguard Worker     // time, not steady state. This is because the boot partition isn't
658*00c7fec1SAndroid Build Coastguard Worker     // allowed to go away or change. Once we found the boot partition we don't
659*00c7fec1SAndroid Build Coastguard Worker     // expect to run again.
660*00c7fec1SAndroid Build Coastguard Worker     if (found_boot_part_uuid_) {
661*00c7fec1SAndroid Build Coastguard Worker         LOG(WARNING) << __PRETTY_FUNCTION__
662*00c7fec1SAndroid Build Coastguard Worker                      << " shouldn't run after kernel boot partition is found";
663*00c7fec1SAndroid Build Coastguard Worker         return true;
664*00c7fec1SAndroid Build Coastguard Worker     }
665*00c7fec1SAndroid Build Coastguard Worker 
666*00c7fec1SAndroid Build Coastguard Worker     // We only need to look at newly-added block devices. Note that if someone
667*00c7fec1SAndroid Build Coastguard Worker     // is replaying events all existing devices will get "add"ed.
668*00c7fec1SAndroid Build Coastguard Worker     if (uevent.subsystem != "block" || uevent.action != "add") {
669*00c7fec1SAndroid Build Coastguard Worker         return false;
670*00c7fec1SAndroid Build Coastguard Worker     }
671*00c7fec1SAndroid Build Coastguard Worker 
672*00c7fec1SAndroid Build Coastguard Worker     // If it's not the partition we care about then move on.
673*00c7fec1SAndroid Build Coastguard Worker     if (uevent.partition_uuid != boot_part_uuid_) {
674*00c7fec1SAndroid Build Coastguard Worker         return false;
675*00c7fec1SAndroid Build Coastguard Worker     }
676*00c7fec1SAndroid Build Coastguard Worker 
677*00c7fec1SAndroid Build Coastguard Worker     auto device = GetBlockDeviceInfo(uevent.path);
678*00c7fec1SAndroid Build Coastguard Worker 
679*00c7fec1SAndroid Build Coastguard Worker     LOG(INFO) << "Boot device " << device.str << " found via partition UUID";
680*00c7fec1SAndroid Build Coastguard Worker     found_boot_part_uuid_ = true;
681*00c7fec1SAndroid Build Coastguard Worker     boot_devices_.clear();
682*00c7fec1SAndroid Build Coastguard Worker     boot_devices_.insert(device.str);
683*00c7fec1SAndroid Build Coastguard Worker 
684*00c7fec1SAndroid Build Coastguard Worker     return true;
685*00c7fec1SAndroid Build Coastguard Worker }
686*00c7fec1SAndroid Build Coastguard Worker 
HandleBindInternal(std::string driver_name,std::string action,const Uevent & uevent)687*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::HandleBindInternal(std::string driver_name, std::string action,
688*00c7fec1SAndroid Build Coastguard Worker                                        const Uevent& uevent) {
689*00c7fec1SAndroid Build Coastguard Worker     if (uevent.subsystem == "block") {
690*00c7fec1SAndroid Build Coastguard Worker         LOG(FATAL) << "Tried to handle bind event for block device";
691*00c7fec1SAndroid Build Coastguard Worker     }
692*00c7fec1SAndroid Build Coastguard Worker 
693*00c7fec1SAndroid Build Coastguard Worker     // Get tracked uevents for all devices that have this uevent's path as
694*00c7fec1SAndroid Build Coastguard Worker     // their canonical device path. Then handle those again if their driver
695*00c7fec1SAndroid Build Coastguard Worker     // is one of the ones we're interested in.
696*00c7fec1SAndroid Build Coastguard Worker     const auto driver = std::find(drivers_.cbegin(), drivers_.cend(), driver_name);
697*00c7fec1SAndroid Build Coastguard Worker     if (driver == drivers_.cend()) return;
698*00c7fec1SAndroid Build Coastguard Worker 
699*00c7fec1SAndroid Build Coastguard Worker     std::string bind_path = sysfs_mount_point_ + uevent.path;
700*00c7fec1SAndroid Build Coastguard Worker     for (const TrackedUevent& tracked : tracked_uevents_) {
701*00c7fec1SAndroid Build Coastguard Worker         if (tracked.canonical_device_path != bind_path) continue;
702*00c7fec1SAndroid Build Coastguard Worker 
703*00c7fec1SAndroid Build Coastguard Worker         LOG(VERBOSE) << "Propagating " << uevent.action << " as " << action << " for "
704*00c7fec1SAndroid Build Coastguard Worker                      << uevent.path;
705*00c7fec1SAndroid Build Coastguard Worker 
706*00c7fec1SAndroid Build Coastguard Worker         std::string devpath = driver->ParseDevPath(tracked.uevent);
707*00c7fec1SAndroid Build Coastguard Worker         mkdir_recursive(Dirname(devpath), 0755);
708*00c7fec1SAndroid Build Coastguard Worker         HandleDevice(action, devpath, false, tracked.uevent.major, tracked.uevent.minor,
709*00c7fec1SAndroid Build Coastguard Worker                      std::vector<std::string>{});
710*00c7fec1SAndroid Build Coastguard Worker     }
711*00c7fec1SAndroid Build Coastguard Worker }
712*00c7fec1SAndroid Build Coastguard Worker 
HandleUevent(const Uevent & uevent)713*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::HandleUevent(const Uevent& uevent) {
714*00c7fec1SAndroid Build Coastguard Worker     if (uevent.action == "add" || uevent.action == "change" || uevent.action == "bind" ||
715*00c7fec1SAndroid Build Coastguard Worker         uevent.action == "online") {
716*00c7fec1SAndroid Build Coastguard Worker         FixupSysPermissions(uevent.path, uevent.subsystem);
717*00c7fec1SAndroid Build Coastguard Worker     }
718*00c7fec1SAndroid Build Coastguard Worker 
719*00c7fec1SAndroid Build Coastguard Worker     if (uevent.action == "bind") {
720*00c7fec1SAndroid Build Coastguard Worker         bound_drivers_[uevent.path] = uevent.driver;
721*00c7fec1SAndroid Build Coastguard Worker         HandleBindInternal(uevent.driver, "add", uevent);
722*00c7fec1SAndroid Build Coastguard Worker         return;
723*00c7fec1SAndroid Build Coastguard Worker     } else if (uevent.action == "unbind") {
724*00c7fec1SAndroid Build Coastguard Worker         if (bound_drivers_.count(uevent.path) == 0) return;
725*00c7fec1SAndroid Build Coastguard Worker         HandleBindInternal(bound_drivers_[uevent.path], "remove", uevent);
726*00c7fec1SAndroid Build Coastguard Worker 
727*00c7fec1SAndroid Build Coastguard Worker         std::string sys_path = sysfs_mount_point_ + uevent.path;
728*00c7fec1SAndroid Build Coastguard Worker         std::erase_if(tracked_uevents_, [&sys_path](const TrackedUevent& tracked) {
729*00c7fec1SAndroid Build Coastguard Worker             return sys_path == tracked.canonical_device_path;
730*00c7fec1SAndroid Build Coastguard Worker         });
731*00c7fec1SAndroid Build Coastguard Worker         return;
732*00c7fec1SAndroid Build Coastguard Worker     }
733*00c7fec1SAndroid Build Coastguard Worker 
734*00c7fec1SAndroid Build Coastguard Worker     // if it's not a /dev device, nothing to do
735*00c7fec1SAndroid Build Coastguard Worker     if (uevent.major < 0 || uevent.minor < 0) return;
736*00c7fec1SAndroid Build Coastguard Worker 
737*00c7fec1SAndroid Build Coastguard Worker     std::string devpath;
738*00c7fec1SAndroid Build Coastguard Worker     std::vector<std::string> links;
739*00c7fec1SAndroid Build Coastguard Worker     bool block = false;
740*00c7fec1SAndroid Build Coastguard Worker 
741*00c7fec1SAndroid Build Coastguard Worker     TrackDeviceUevent(uevent);
742*00c7fec1SAndroid Build Coastguard Worker 
743*00c7fec1SAndroid Build Coastguard Worker     if (uevent.subsystem == "block") {
744*00c7fec1SAndroid Build Coastguard Worker         block = true;
745*00c7fec1SAndroid Build Coastguard Worker         devpath = "/dev/block/" + Basename(uevent.path);
746*00c7fec1SAndroid Build Coastguard Worker 
747*00c7fec1SAndroid Build Coastguard Worker         if (StartsWith(uevent.path, "/devices")) {
748*00c7fec1SAndroid Build Coastguard Worker             links = GetBlockDeviceSymlinks(uevent);
749*00c7fec1SAndroid Build Coastguard Worker         }
750*00c7fec1SAndroid Build Coastguard Worker     } else if (const auto subsystem =
751*00c7fec1SAndroid Build Coastguard Worker                    std::find(subsystems_.cbegin(), subsystems_.cend(), uevent.subsystem);
752*00c7fec1SAndroid Build Coastguard Worker                subsystem != subsystems_.cend()) {
753*00c7fec1SAndroid Build Coastguard Worker         devpath = subsystem->ParseDevPath(uevent);
754*00c7fec1SAndroid Build Coastguard Worker     } else if (uevent.subsystem == "usb") {
755*00c7fec1SAndroid Build Coastguard Worker         if (!uevent.device_name.empty()) {
756*00c7fec1SAndroid Build Coastguard Worker             devpath = "/dev/" + uevent.device_name;
757*00c7fec1SAndroid Build Coastguard Worker         } else {
758*00c7fec1SAndroid Build Coastguard Worker             // This imitates the file system that would be created
759*00c7fec1SAndroid Build Coastguard Worker             // if we were using devfs instead.
760*00c7fec1SAndroid Build Coastguard Worker             // Minors are broken up into groups of 128, starting at "001"
761*00c7fec1SAndroid Build Coastguard Worker             int bus_id = uevent.minor / 128 + 1;
762*00c7fec1SAndroid Build Coastguard Worker             int device_id = uevent.minor % 128 + 1;
763*00c7fec1SAndroid Build Coastguard Worker             devpath = StringPrintf("/dev/bus/usb/%03d/%03d", bus_id, device_id);
764*00c7fec1SAndroid Build Coastguard Worker         }
765*00c7fec1SAndroid Build Coastguard Worker     } else if (StartsWith(uevent.subsystem, "usb")) {
766*00c7fec1SAndroid Build Coastguard Worker         // ignore other USB events
767*00c7fec1SAndroid Build Coastguard Worker         return;
768*00c7fec1SAndroid Build Coastguard Worker     } else if (uevent.subsystem == "misc" && StartsWith(uevent.device_name, "dm-user/")) {
769*00c7fec1SAndroid Build Coastguard Worker         devpath = "/dev/dm-user/" + uevent.device_name.substr(8);
770*00c7fec1SAndroid Build Coastguard Worker     } else if (uevent.subsystem == "misc" && uevent.device_name == "vfio/vfio") {
771*00c7fec1SAndroid Build Coastguard Worker         devpath = "/dev/" + uevent.device_name;
772*00c7fec1SAndroid Build Coastguard Worker     } else {
773*00c7fec1SAndroid Build Coastguard Worker         devpath = "/dev/" + Basename(uevent.path);
774*00c7fec1SAndroid Build Coastguard Worker     }
775*00c7fec1SAndroid Build Coastguard Worker 
776*00c7fec1SAndroid Build Coastguard Worker     mkdir_recursive(Dirname(devpath), 0755);
777*00c7fec1SAndroid Build Coastguard Worker 
778*00c7fec1SAndroid Build Coastguard Worker     HandleDevice(uevent.action, devpath, block, uevent.major, uevent.minor, links);
779*00c7fec1SAndroid Build Coastguard Worker 
780*00c7fec1SAndroid Build Coastguard Worker     // Duplicate /dev/ashmem device and name it /dev/ashmem<boot_id>.
781*00c7fec1SAndroid Build Coastguard Worker     // TODO(b/111903542): remove once all users of /dev/ashmem are migrated to libcutils API.
782*00c7fec1SAndroid Build Coastguard Worker     HandleAshmemUevent(uevent);
783*00c7fec1SAndroid Build Coastguard Worker }
784*00c7fec1SAndroid Build Coastguard Worker 
ColdbootDone()785*00c7fec1SAndroid Build Coastguard Worker void DeviceHandler::ColdbootDone() {
786*00c7fec1SAndroid Build Coastguard Worker     skip_restorecon_ = false;
787*00c7fec1SAndroid Build Coastguard Worker }
788*00c7fec1SAndroid Build Coastguard Worker 
DeviceHandler(std::vector<Permissions> dev_permissions,std::vector<SysfsPermissions> sysfs_permissions,std::vector<Subsystem> drivers,std::vector<Subsystem> subsystems,std::set<std::string> boot_devices,std::string boot_part_uuid,bool skip_restorecon)789*00c7fec1SAndroid Build Coastguard Worker DeviceHandler::DeviceHandler(std::vector<Permissions> dev_permissions,
790*00c7fec1SAndroid Build Coastguard Worker                              std::vector<SysfsPermissions> sysfs_permissions,
791*00c7fec1SAndroid Build Coastguard Worker                              std::vector<Subsystem> drivers, std::vector<Subsystem> subsystems,
792*00c7fec1SAndroid Build Coastguard Worker                              std::set<std::string> boot_devices, std::string boot_part_uuid,
793*00c7fec1SAndroid Build Coastguard Worker                              bool skip_restorecon)
794*00c7fec1SAndroid Build Coastguard Worker     : dev_permissions_(std::move(dev_permissions)),
795*00c7fec1SAndroid Build Coastguard Worker       sysfs_permissions_(std::move(sysfs_permissions)),
796*00c7fec1SAndroid Build Coastguard Worker       drivers_(std::move(drivers)),
797*00c7fec1SAndroid Build Coastguard Worker       subsystems_(std::move(subsystems)),
798*00c7fec1SAndroid Build Coastguard Worker       boot_devices_(std::move(boot_devices)),
799*00c7fec1SAndroid Build Coastguard Worker       boot_part_uuid_(boot_part_uuid),
800*00c7fec1SAndroid Build Coastguard Worker       skip_restorecon_(skip_restorecon),
801*00c7fec1SAndroid Build Coastguard Worker       sysfs_mount_point_("/sys") {
802*00c7fec1SAndroid Build Coastguard Worker     // If both a boot partition UUID and a list of boot devices are
803*00c7fec1SAndroid Build Coastguard Worker     // specified then we ignore the boot_devices in favor of boot_part_uuid.
804*00c7fec1SAndroid Build Coastguard Worker     if (boot_devices_.size() && !boot_part_uuid.empty()) {
805*00c7fec1SAndroid Build Coastguard Worker         LOG(WARNING) << "Both boot_devices and boot_part_uuid provided; ignoring bootdevices";
806*00c7fec1SAndroid Build Coastguard Worker         boot_devices_.clear();
807*00c7fec1SAndroid Build Coastguard Worker     }
808*00c7fec1SAndroid Build Coastguard Worker }
809*00c7fec1SAndroid Build Coastguard Worker 
DeviceHandler()810*00c7fec1SAndroid Build Coastguard Worker DeviceHandler::DeviceHandler()
811*00c7fec1SAndroid Build Coastguard Worker     : DeviceHandler(std::vector<Permissions>{}, std::vector<SysfsPermissions>{},
812*00c7fec1SAndroid Build Coastguard Worker                     std::vector<Subsystem>{}, std::vector<Subsystem>{}, std::set<std::string>{}, "",
813*00c7fec1SAndroid Build Coastguard Worker                     false) {}
814*00c7fec1SAndroid Build Coastguard Worker 
815*00c7fec1SAndroid Build Coastguard Worker }  // namespace init
816*00c7fec1SAndroid Build Coastguard Worker }  // namespace android
817