2009-03-04 04:32:55 +01:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2007 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
|
|
* you may not use this file except in compliance with the License.
|
|
|
|
* You may obtain a copy of the License at
|
|
|
|
*
|
|
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
*
|
|
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
* See the License for the specific language governing permissions and
|
|
|
|
* limitations under the License.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#ifndef _INIT_DEVICES_H
|
|
|
|
#define _INIT_DEVICES_H
|
|
|
|
|
2010-04-21 21:04:20 +02:00
|
|
|
#include <sys/stat.h>
|
2017-04-06 02:55:46 +02:00
|
|
|
#include <sys/types.h>
|
2010-04-21 21:04:20 +02:00
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
#include <algorithm>
|
Adds /dev/block/by-name/<partition> symlinks
During uevent processing, some "by-name" symlinks will be created.
/dev/block/<type>/<device>/by-name/<partition>
<type> can be: platform, pci or vbd.
<device> might be: soc.0/f9824900.sdhci, soc.0/f9824900.sdhci, etc.
<partition> might be: system, vendor, system_a, system_b, etc.
e.g., on a non-A/B device:
/dev/block/platform/soc.0/f9824900.sdhci/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
On a A/B device:
/dev/block/platform/soc/1da4000.ufshc/by-name/system_a
/dev/block/platform/soc/1da4000.ufshc/by-name/system_b
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_b
However, those symlinks are "device-specific".
This change adds the "generic" symlinks in ueventd, in addition to
the existing symlinks, when the possible "boot devices" are specified
in device tree. e.g.,
&firmware_android {
compatible = "android,firmware";
boot_devices ="soc/1da4000.ufshc,soc.0/f9824900.sdhci";
}
The following symlinks will then be created on the aforementioned non-A/B
and A/B devices, respectively.
/dev/block/by-name/system
/dev/block/by-name/vendor
/dev/block/by-name/system_a
/dev/block/by-name/system_b
/dev/block/by-name/vendor_a
/dev/block/by-name/vendor_b
Note that both <type> and <device> are skipped in the newly create symlinks.
It assumes there is no more than one devices with the same <partition>,
which is the assumption of current first stage mount flow.
Finally, when 'boot_devices' in DT is absent, it fallbacks to extract
'boot_devices' from fstab settings. e.g., using 'soc/1da4000.ufshc',
'soc.0/f9824900.sdhci' for a fstab with the following content:
/dev/block/platform/soc/1da4000.ufshc/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
Bug: 78613232
Test: adb shell ls /dev/block/by-name
Change-Id: Iec920b5a72409b6a2bdbeeb290f0a3acd2046b5d
2018-05-16 12:33:44 +02:00
|
|
|
#include <set>
|
2017-04-05 02:53:45 +02:00
|
|
|
#include <string>
|
|
|
|
#include <vector>
|
2017-04-07 01:30:22 +02:00
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
#include <android-base/file.h>
|
|
|
|
#include <selinux/label.h>
|
2017-02-08 03:11:37 +01:00
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
#include "uevent.h"
|
2018-08-01 22:12:20 +02:00
|
|
|
#include "uevent_handler.h"
|
2017-02-08 03:11:37 +01:00
|
|
|
|
2017-06-22 21:53:17 +02:00
|
|
|
namespace android {
|
|
|
|
namespace init {
|
|
|
|
|
2017-04-06 02:55:46 +02:00
|
|
|
class Permissions {
|
|
|
|
public:
|
2018-07-18 00:28:16 +02:00
|
|
|
friend void TestPermissions(const Permissions& expected, const Permissions& test);
|
|
|
|
|
2017-04-06 02:55:46 +02:00
|
|
|
Permissions(const std::string& name, mode_t perm, uid_t uid, gid_t gid);
|
|
|
|
|
|
|
|
bool Match(const std::string& path) const;
|
|
|
|
|
|
|
|
mode_t perm() const { return perm_; }
|
|
|
|
uid_t uid() const { return uid_; }
|
|
|
|
gid_t gid() const { return gid_; }
|
|
|
|
|
|
|
|
protected:
|
|
|
|
const std::string& name() const { return name_; }
|
|
|
|
|
|
|
|
private:
|
|
|
|
std::string name_;
|
|
|
|
mode_t perm_;
|
|
|
|
uid_t uid_;
|
|
|
|
gid_t gid_;
|
|
|
|
bool prefix_;
|
|
|
|
bool wildcard_;
|
|
|
|
};
|
|
|
|
|
|
|
|
class SysfsPermissions : public Permissions {
|
|
|
|
public:
|
2018-07-18 00:28:16 +02:00
|
|
|
friend void TestSysfsPermissions(const SysfsPermissions& expected, const SysfsPermissions& test);
|
|
|
|
|
2017-04-06 02:55:46 +02:00
|
|
|
SysfsPermissions(const std::string& name, const std::string& attribute, mode_t perm, uid_t uid,
|
|
|
|
gid_t gid)
|
|
|
|
: Permissions(name, perm, uid, gid), attribute_(attribute) {}
|
|
|
|
|
|
|
|
bool MatchWithSubsystem(const std::string& path, const std::string& subsystem) const;
|
|
|
|
void SetPermissions(const std::string& path) const;
|
|
|
|
|
|
|
|
private:
|
|
|
|
const std::string attribute_;
|
|
|
|
};
|
|
|
|
|
2017-04-25 01:59:05 +02:00
|
|
|
class Subsystem {
|
|
|
|
public:
|
|
|
|
friend class SubsystemParser;
|
2018-07-18 00:28:16 +02:00
|
|
|
friend void TestSubsystems(const Subsystem& expected, const Subsystem& test);
|
|
|
|
|
|
|
|
enum DevnameSource {
|
|
|
|
DEVNAME_UEVENT_DEVNAME,
|
|
|
|
DEVNAME_UEVENT_DEVPATH,
|
|
|
|
};
|
2017-04-25 01:59:05 +02:00
|
|
|
|
|
|
|
Subsystem() {}
|
2019-07-10 20:18:24 +02:00
|
|
|
Subsystem(std::string name) : name_(std::move(name)) {}
|
|
|
|
Subsystem(std::string name, DevnameSource source, std::string dir_name)
|
|
|
|
: name_(std::move(name)), devname_source_(source), dir_name_(std::move(dir_name)) {}
|
2017-04-25 01:59:05 +02:00
|
|
|
|
|
|
|
// Returns the full path for a uevent of a device that is a member of this subsystem,
|
|
|
|
// according to the rules parsed from ueventd.rc
|
2017-05-26 00:58:59 +02:00
|
|
|
std::string ParseDevPath(const Uevent& uevent) const {
|
2018-07-18 00:28:16 +02:00
|
|
|
std::string devname = devname_source_ == DEVNAME_UEVENT_DEVNAME
|
|
|
|
? uevent.device_name
|
|
|
|
: android::base::Basename(uevent.path);
|
2017-05-26 00:58:59 +02:00
|
|
|
|
|
|
|
return dir_name_ + "/" + devname;
|
|
|
|
}
|
2017-04-25 01:59:05 +02:00
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
bool operator==(const std::string& string_name) const { return name_ == string_name; }
|
2017-04-25 01:59:05 +02:00
|
|
|
|
|
|
|
private:
|
|
|
|
std::string name_;
|
2018-07-18 00:28:16 +02:00
|
|
|
DevnameSource devname_source_ = DEVNAME_UEVENT_DEVNAME;
|
2017-04-25 01:59:05 +02:00
|
|
|
std::string dir_name_ = "/dev";
|
|
|
|
};
|
|
|
|
|
2018-08-01 22:12:20 +02:00
|
|
|
class DeviceHandler : public UeventHandler {
|
2017-05-26 00:58:59 +02:00
|
|
|
public:
|
|
|
|
friend class DeviceHandlerTester;
|
|
|
|
|
|
|
|
DeviceHandler();
|
|
|
|
DeviceHandler(std::vector<Permissions> dev_permissions,
|
Adds /dev/block/by-name/<partition> symlinks
During uevent processing, some "by-name" symlinks will be created.
/dev/block/<type>/<device>/by-name/<partition>
<type> can be: platform, pci or vbd.
<device> might be: soc.0/f9824900.sdhci, soc.0/f9824900.sdhci, etc.
<partition> might be: system, vendor, system_a, system_b, etc.
e.g., on a non-A/B device:
/dev/block/platform/soc.0/f9824900.sdhci/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
On a A/B device:
/dev/block/platform/soc/1da4000.ufshc/by-name/system_a
/dev/block/platform/soc/1da4000.ufshc/by-name/system_b
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_b
However, those symlinks are "device-specific".
This change adds the "generic" symlinks in ueventd, in addition to
the existing symlinks, when the possible "boot devices" are specified
in device tree. e.g.,
&firmware_android {
compatible = "android,firmware";
boot_devices ="soc/1da4000.ufshc,soc.0/f9824900.sdhci";
}
The following symlinks will then be created on the aforementioned non-A/B
and A/B devices, respectively.
/dev/block/by-name/system
/dev/block/by-name/vendor
/dev/block/by-name/system_a
/dev/block/by-name/system_b
/dev/block/by-name/vendor_a
/dev/block/by-name/vendor_b
Note that both <type> and <device> are skipped in the newly create symlinks.
It assumes there is no more than one devices with the same <partition>,
which is the assumption of current first stage mount flow.
Finally, when 'boot_devices' in DT is absent, it fallbacks to extract
'boot_devices' from fstab settings. e.g., using 'soc/1da4000.ufshc',
'soc.0/f9824900.sdhci' for a fstab with the following content:
/dev/block/platform/soc/1da4000.ufshc/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
Bug: 78613232
Test: adb shell ls /dev/block/by-name
Change-Id: Iec920b5a72409b6a2bdbeeb290f0a3acd2046b5d
2018-05-16 12:33:44 +02:00
|
|
|
std::vector<SysfsPermissions> sysfs_permissions, std::vector<Subsystem> subsystems,
|
|
|
|
std::set<std::string> boot_devices, bool skip_restorecon);
|
2018-08-01 22:12:20 +02:00
|
|
|
virtual ~DeviceHandler() = default;
|
2017-05-26 00:58:59 +02:00
|
|
|
|
2018-08-01 22:12:20 +02:00
|
|
|
void HandleUevent(const Uevent& uevent) override;
|
|
|
|
void ColdbootDone() override;
|
2017-05-17 00:35:41 +02:00
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
std::vector<std::string> GetBlockDeviceSymlinks(const Uevent& uevent) const;
|
|
|
|
|
|
|
|
private:
|
2017-06-21 21:46:41 +02:00
|
|
|
bool FindPlatformDevice(std::string path, std::string* platform_device_path) const;
|
2017-05-26 00:58:59 +02:00
|
|
|
std::tuple<mode_t, uid_t, gid_t> GetDevicePermissions(
|
|
|
|
const std::string& path, const std::vector<std::string>& links) const;
|
2017-06-23 21:43:48 +02:00
|
|
|
void MakeDevice(const std::string& path, bool block, int major, int minor,
|
2017-05-26 00:58:59 +02:00
|
|
|
const std::vector<std::string>& links) const;
|
2017-06-23 21:43:48 +02:00
|
|
|
void HandleDevice(const std::string& action, const std::string& devpath, bool block, int major,
|
2017-05-26 00:58:59 +02:00
|
|
|
int minor, const std::vector<std::string>& links) const;
|
2017-06-21 21:46:41 +02:00
|
|
|
void FixupSysPermissions(const std::string& upath, const std::string& subsystem) const;
|
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
std::vector<Permissions> dev_permissions_;
|
|
|
|
std::vector<SysfsPermissions> sysfs_permissions_;
|
|
|
|
std::vector<Subsystem> subsystems_;
|
Adds /dev/block/by-name/<partition> symlinks
During uevent processing, some "by-name" symlinks will be created.
/dev/block/<type>/<device>/by-name/<partition>
<type> can be: platform, pci or vbd.
<device> might be: soc.0/f9824900.sdhci, soc.0/f9824900.sdhci, etc.
<partition> might be: system, vendor, system_a, system_b, etc.
e.g., on a non-A/B device:
/dev/block/platform/soc.0/f9824900.sdhci/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
On a A/B device:
/dev/block/platform/soc/1da4000.ufshc/by-name/system_a
/dev/block/platform/soc/1da4000.ufshc/by-name/system_b
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_a
/dev/block/platform/soc/1da4000.ufshc/by-name/vendor_b
However, those symlinks are "device-specific".
This change adds the "generic" symlinks in ueventd, in addition to
the existing symlinks, when the possible "boot devices" are specified
in device tree. e.g.,
&firmware_android {
compatible = "android,firmware";
boot_devices ="soc/1da4000.ufshc,soc.0/f9824900.sdhci";
}
The following symlinks will then be created on the aforementioned non-A/B
and A/B devices, respectively.
/dev/block/by-name/system
/dev/block/by-name/vendor
/dev/block/by-name/system_a
/dev/block/by-name/system_b
/dev/block/by-name/vendor_a
/dev/block/by-name/vendor_b
Note that both <type> and <device> are skipped in the newly create symlinks.
It assumes there is no more than one devices with the same <partition>,
which is the assumption of current first stage mount flow.
Finally, when 'boot_devices' in DT is absent, it fallbacks to extract
'boot_devices' from fstab settings. e.g., using 'soc/1da4000.ufshc',
'soc.0/f9824900.sdhci' for a fstab with the following content:
/dev/block/platform/soc/1da4000.ufshc/by-name/system
/dev/block/platform/soc.0/f9824900.sdhci/by-name/vendor
Bug: 78613232
Test: adb shell ls /dev/block/by-name
Change-Id: Iec920b5a72409b6a2bdbeeb290f0a3acd2046b5d
2018-05-16 12:33:44 +02:00
|
|
|
std::set<std::string> boot_devices_;
|
2017-05-17 00:35:41 +02:00
|
|
|
bool skip_restorecon_;
|
2017-06-21 21:46:41 +02:00
|
|
|
std::string sysfs_mount_point_;
|
2017-05-26 00:58:59 +02:00
|
|
|
};
|
2015-02-04 02:12:07 +01:00
|
|
|
|
2017-04-06 00:58:31 +02:00
|
|
|
// Exposed for testing
|
2017-05-26 00:58:59 +02:00
|
|
|
void SanitizePartitionName(std::string* string);
|
|
|
|
|
2017-06-22 21:53:17 +02:00
|
|
|
} // namespace init
|
|
|
|
} // namespace android
|
|
|
|
|
2017-05-26 00:58:59 +02:00
|
|
|
#endif
|