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