Merge "Mount /vendor and /odm early"
This commit is contained in:
commit
35569e9d68
|
@ -905,3 +905,22 @@ int fs_mgr_get_crypt_info(struct fstab *fstab, char *key_loc, char *real_blk_dev
|
|||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int fs_mgr_early_setup_verity(struct fstab_rec *fstab_rec)
|
||||
{
|
||||
if ((fstab_rec->fs_mgr_flags & MF_VERIFY) && device_is_secure()) {
|
||||
int rc = fs_mgr_setup_verity(fstab_rec);
|
||||
if (device_is_debuggable() && rc == FS_MGR_SETUP_VERITY_DISABLED) {
|
||||
INFO("Verity disabled");
|
||||
return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
|
||||
} else if (rc == FS_MGR_SETUP_VERITY_SUCCESS) {
|
||||
return FS_MGR_EARLY_SETUP_VERITY_SUCCESS;
|
||||
} else {
|
||||
return FS_MGR_EARLY_SETUP_VERITY_FAIL;
|
||||
}
|
||||
} else if (device_is_secure()) {
|
||||
ERROR("Verity must be enabled for early mounted partitions on secured devices.\n");
|
||||
return FS_MGR_EARLY_SETUP_VERITY_FAIL;
|
||||
}
|
||||
return FS_MGR_EARLY_SETUP_VERITY_NO_VERITY;
|
||||
}
|
||||
|
|
|
@ -210,9 +210,8 @@ static int parse_flags(char *flags, struct flag_list *fl,
|
|||
return f;
|
||||
}
|
||||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
||||
struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file)
|
||||
{
|
||||
FILE *fstab_file;
|
||||
int cnt, entries;
|
||||
ssize_t len;
|
||||
size_t alloc_len = 0;
|
||||
|
@ -224,12 +223,6 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
|||
#define FS_OPTIONS_LEN 1024
|
||||
char tmp_fs_options[FS_OPTIONS_LEN];
|
||||
|
||||
fstab_file = fopen(fstab_path, "r");
|
||||
if (!fstab_file) {
|
||||
ERROR("Cannot open file %s\n", fstab_path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
entries = 0;
|
||||
while ((len = getline(&line, &alloc_len, fstab_file)) != -1) {
|
||||
/* if the last character is a newline, shorten the string by 1 byte */
|
||||
|
@ -255,7 +248,6 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
|||
/* Allocate and init the fstab structure */
|
||||
fstab = calloc(1, sizeof(struct fstab));
|
||||
fstab->num_entries = entries;
|
||||
fstab->fstab_filename = strdup(fstab_path);
|
||||
fstab->recs = calloc(fstab->num_entries, sizeof(struct fstab_rec));
|
||||
|
||||
fseek(fstab_file, 0, SEEK_SET);
|
||||
|
@ -338,18 +330,34 @@ struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
|||
ERROR("Error updating for slotselect\n");
|
||||
goto err;
|
||||
}
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
return fstab;
|
||||
|
||||
err:
|
||||
fclose(fstab_file);
|
||||
free(line);
|
||||
if (fstab)
|
||||
fs_mgr_free_fstab(fstab);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path)
|
||||
{
|
||||
FILE *fstab_file;
|
||||
struct fstab *fstab;
|
||||
|
||||
fstab_file = fopen(fstab_path, "r");
|
||||
if (!fstab_file) {
|
||||
ERROR("Cannot open file %s\n", fstab_path);
|
||||
return NULL;
|
||||
}
|
||||
fstab = fs_mgr_read_fstab_file(fstab_file);
|
||||
if (fstab) {
|
||||
fstab->fstab_filename = strdup(fstab_path);
|
||||
}
|
||||
fclose(fstab_file);
|
||||
return fstab;
|
||||
}
|
||||
|
||||
void fs_mgr_free_fstab(struct fstab *fstab)
|
||||
{
|
||||
int i;
|
||||
|
|
|
@ -341,17 +341,6 @@ static int resume_verity_table(struct dm_ioctl *io, char *name, int fd)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int test_access(char *device) {
|
||||
int tries = 25;
|
||||
while (tries--) {
|
||||
if (!access(device, F_OK) || errno != ENOENT) {
|
||||
return 0;
|
||||
}
|
||||
usleep(40 * 1000);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int check_verity_restart(const char *fname)
|
||||
{
|
||||
char buffer[VERITY_KMSG_BUFSIZE + 1];
|
||||
|
@ -1031,11 +1020,6 @@ loaded:
|
|||
fstab->blk_device = verity_blk_name;
|
||||
verity_blk_name = 0;
|
||||
|
||||
// make sure we've set everything up properly
|
||||
if (test_access(fstab->blk_device) < 0) {
|
||||
goto out;
|
||||
}
|
||||
|
||||
retval = FS_MGR_SETUP_VERITY_SUCCESS;
|
||||
|
||||
out:
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#ifndef __CORE_FS_MGR_H
|
||||
#define __CORE_FS_MGR_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <linux/dm-ioctl.h>
|
||||
|
@ -72,6 +73,7 @@ struct fstab_rec {
|
|||
typedef void (*fs_mgr_verity_state_callback)(struct fstab_rec *fstab,
|
||||
const char *mount_point, int mode, int status);
|
||||
|
||||
struct fstab *fs_mgr_read_fstab_file(FILE *fstab_file);
|
||||
struct fstab *fs_mgr_read_fstab(const char *fstab_path);
|
||||
void fs_mgr_free_fstab(struct fstab *fstab);
|
||||
|
||||
|
@ -111,6 +113,11 @@ int fs_mgr_swapon_all(struct fstab *fstab);
|
|||
|
||||
int fs_mgr_do_format(struct fstab_rec *fstab, bool reserve_footer);
|
||||
|
||||
#define FS_MGR_EARLY_SETUP_VERITY_NO_VERITY -2
|
||||
#define FS_MGR_EARLY_SETUP_VERITY_FAIL -1
|
||||
#define FS_MGR_EARLY_SETUP_VERITY_SUCCESS 0
|
||||
int fs_mgr_early_setup_verity(struct fstab_rec *fstab);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
105
init/devices.cpp
105
init/devices.cpp
|
@ -44,6 +44,7 @@
|
|||
|
||||
#include <android-base/file.h>
|
||||
#include <android-base/stringprintf.h>
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <cutils/list.h>
|
||||
#include <cutils/uevent.h>
|
||||
|
||||
|
@ -601,14 +602,17 @@ static const char *parse_device_name(struct uevent *uevent, unsigned int len)
|
|||
return name;
|
||||
}
|
||||
|
||||
#define DEVPATH_LEN 96
|
||||
#define MAX_DEV_NAME 64
|
||||
|
||||
static void handle_block_device_event(struct uevent *uevent)
|
||||
{
|
||||
const char *base = "/dev/block/";
|
||||
const char *name;
|
||||
char devpath[96];
|
||||
char devpath[DEVPATH_LEN];
|
||||
char **links = NULL;
|
||||
|
||||
name = parse_device_name(uevent, 64);
|
||||
name = parse_device_name(uevent, MAX_DEV_NAME);
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
|
@ -622,8 +626,6 @@ static void handle_block_device_event(struct uevent *uevent)
|
|||
uevent->major, uevent->minor, links);
|
||||
}
|
||||
|
||||
#define DEVPATH_LEN 96
|
||||
|
||||
static bool assemble_devpath(char *devpath, const char *dirname,
|
||||
const char *devname)
|
||||
{
|
||||
|
@ -657,7 +659,7 @@ static void handle_generic_device_event(struct uevent *uevent)
|
|||
char devpath[DEVPATH_LEN] = {0};
|
||||
char **links = NULL;
|
||||
|
||||
name = parse_device_name(uevent, 64);
|
||||
name = parse_device_name(uevent, MAX_DEV_NAME);
|
||||
if (!name)
|
||||
return;
|
||||
|
||||
|
@ -900,7 +902,8 @@ static void handle_firmware_event(struct uevent *uevent)
|
|||
}
|
||||
|
||||
#define UEVENT_MSG_LEN 2048
|
||||
void handle_device_fd()
|
||||
|
||||
static inline void handle_device_fd_with(void (handle_uevent)(struct uevent*))
|
||||
{
|
||||
char msg[UEVENT_MSG_LEN+2];
|
||||
int n;
|
||||
|
@ -913,21 +916,28 @@ void handle_device_fd()
|
|||
|
||||
struct uevent uevent;
|
||||
parse_event(msg, &uevent);
|
||||
|
||||
if (selinux_status_updated() > 0) {
|
||||
struct selabel_handle *sehandle2;
|
||||
sehandle2 = selinux_android_file_context_handle();
|
||||
if (sehandle2) {
|
||||
selabel_close(sehandle);
|
||||
sehandle = sehandle2;
|
||||
}
|
||||
}
|
||||
|
||||
handle_device_event(&uevent);
|
||||
handle_firmware_event(&uevent);
|
||||
handle_uevent(&uevent);
|
||||
}
|
||||
}
|
||||
|
||||
void handle_device_fd()
|
||||
{
|
||||
handle_device_fd_with(
|
||||
[](struct uevent *uevent) {
|
||||
if (selinux_status_updated() > 0) {
|
||||
struct selabel_handle *sehandle2;
|
||||
sehandle2 = selinux_android_file_context_handle();
|
||||
if (sehandle2) {
|
||||
selabel_close(sehandle);
|
||||
sehandle = sehandle2;
|
||||
}
|
||||
}
|
||||
|
||||
handle_device_event(uevent);
|
||||
handle_firmware_event(uevent);
|
||||
});
|
||||
}
|
||||
|
||||
/* Coldboot walks parts of the /sys tree and pokes the uevent files
|
||||
** to cause the kernel to regenerate device add events that happened
|
||||
** before init's device manager was started
|
||||
|
@ -979,6 +989,65 @@ static void coldboot(const char *path)
|
|||
}
|
||||
}
|
||||
|
||||
static void early_uevent_handler(struct uevent *uevent, const char *base, bool is_block)
|
||||
{
|
||||
const char *name;
|
||||
char devpath[DEVPATH_LEN];
|
||||
|
||||
if (is_block && strncmp(uevent->subsystem, "block", 5))
|
||||
return;
|
||||
|
||||
name = parse_device_name(uevent, MAX_DEV_NAME);
|
||||
if (!name) {
|
||||
LOG(ERROR) << "Failed to parse dev name from uevent: " << uevent->action
|
||||
<< " " << uevent->partition_name << " " << uevent->partition_num
|
||||
<< " " << uevent->major << ":" << uevent->minor;
|
||||
return;
|
||||
}
|
||||
|
||||
snprintf(devpath, sizeof(devpath), "%s%s", base, name);
|
||||
make_dir(base, 0755);
|
||||
|
||||
dev_t dev = makedev(uevent->major, uevent->minor);
|
||||
mode_t mode = 0600 | (is_block ? S_IFBLK : S_IFCHR);
|
||||
mknod(devpath, mode, dev);
|
||||
}
|
||||
|
||||
void early_create_dev(const std::string& syspath, early_device_type dev_type)
|
||||
{
|
||||
android::base::unique_fd dfd(open(syspath.c_str(), O_RDONLY));
|
||||
if (dfd < 0) {
|
||||
LOG(ERROR) << "Failed to open " << syspath;
|
||||
return;
|
||||
}
|
||||
|
||||
android::base::unique_fd fd(openat(dfd, "uevent", O_WRONLY));
|
||||
if (fd < 0) {
|
||||
LOG(ERROR) << "Failed to open " << syspath << "/uevent";
|
||||
return;
|
||||
}
|
||||
|
||||
fcntl(device_fd, F_SETFL, O_NONBLOCK);
|
||||
|
||||
write(fd, "add\n", 4);
|
||||
handle_device_fd_with(dev_type == EARLY_BLOCK_DEV ?
|
||||
[](struct uevent *uevent) {
|
||||
early_uevent_handler(uevent, "/dev/block/", true);
|
||||
} :
|
||||
[](struct uevent *uevent) {
|
||||
early_uevent_handler(uevent, "/dev/", false);
|
||||
});
|
||||
}
|
||||
|
||||
int early_device_socket_open() {
|
||||
device_fd = uevent_open_socket(256*1024, true);
|
||||
return device_fd < 0;
|
||||
}
|
||||
|
||||
void early_device_socket_close() {
|
||||
close(device_fd);
|
||||
}
|
||||
|
||||
void device_init() {
|
||||
sehandle = selinux_android_file_context_handle();
|
||||
selinux_status_open(true);
|
||||
|
|
|
@ -21,6 +21,13 @@
|
|||
|
||||
extern void handle_device_fd();
|
||||
extern void device_init(void);
|
||||
|
||||
enum early_device_type { EARLY_BLOCK_DEV, EARLY_CHAR_DEV };
|
||||
|
||||
extern int early_device_socket_open();
|
||||
extern void early_device_socket_close();
|
||||
extern void early_create_dev(const std::string& syspath, early_device_type dev_type);
|
||||
|
||||
extern int add_dev_perms(const char *name, const char *attr,
|
||||
mode_t perm, unsigned int uid,
|
||||
unsigned int gid, unsigned short prefix,
|
||||
|
|
108
init/init.cpp
108
init/init.cpp
|
@ -54,6 +54,7 @@
|
|||
#include "action.h"
|
||||
#include "bootchart.h"
|
||||
#include "devices.h"
|
||||
#include "fs_mgr.h"
|
||||
#include "import_parser.h"
|
||||
#include "init.h"
|
||||
#include "init_parser.h"
|
||||
|
@ -342,9 +343,6 @@ static void process_kernel_dt() {
|
|||
}
|
||||
|
||||
static void process_kernel_cmdline() {
|
||||
// Don't expose the raw commandline to unprivileged processes.
|
||||
chmod("/proc/cmdline", 0440);
|
||||
|
||||
// The first pass does the common stuff, and finds if we are in qemu.
|
||||
// The second pass is only necessary for qemu to export all kernel params
|
||||
// as properties.
|
||||
|
@ -461,6 +459,104 @@ static void set_usb_controller() {
|
|||
}
|
||||
}
|
||||
|
||||
/* Returns a new path consisting of base_path and the file name in reference_path. */
|
||||
static std::string get_path(const std::string& base_path, const std::string& reference_path) {
|
||||
std::string::size_type pos = reference_path.rfind('/');
|
||||
if (pos == std::string::npos) {
|
||||
return base_path + '/' + reference_path;
|
||||
} else {
|
||||
return base_path + reference_path.substr(pos);
|
||||
}
|
||||
}
|
||||
|
||||
/* Imports the fstab info from cmdline. */
|
||||
static std::string import_cmdline_fstab() {
|
||||
std::string prefix, fstab, fstab_full;
|
||||
|
||||
import_kernel_cmdline(false,
|
||||
[&](const std::string& key, const std::string& value, bool in_qemu __attribute__((__unused__))) {
|
||||
if (key == "android.early.prefix") {
|
||||
prefix = value;
|
||||
} else if (key == "android.early.fstab") {
|
||||
fstab = value;
|
||||
}
|
||||
});
|
||||
if (!fstab.empty()) {
|
||||
// Convert "mmcblk0p09+/odm+ext4+ro+verify" to "mmcblk0p09 /odm ext4 ro verify"
|
||||
std::replace(fstab.begin(), fstab.end(), '+', ' ');
|
||||
for (const auto& entry : android::base::Split(fstab, "\n")) {
|
||||
fstab_full += prefix + entry + '\n';
|
||||
}
|
||||
}
|
||||
return fstab_full;
|
||||
}
|
||||
|
||||
/* Early mount vendor and ODM partitions. The fstab info is read from kernel cmdline. */
|
||||
static void early_mount() {
|
||||
std::string fstab_string = import_cmdline_fstab();
|
||||
if (fstab_string.empty()) {
|
||||
LOG(INFO) << "Failed to load vendor fstab from kernel cmdline";
|
||||
return;
|
||||
}
|
||||
FILE *fstab_file = fmemopen((void *)fstab_string.c_str(), fstab_string.length(), "r");
|
||||
if (!fstab_file) {
|
||||
PLOG(ERROR) << "Failed to open fstab string as FILE";
|
||||
return;
|
||||
}
|
||||
std::unique_ptr<struct fstab, decltype(&fs_mgr_free_fstab)> fstab(fs_mgr_read_fstab_file(fstab_file), fs_mgr_free_fstab);
|
||||
fclose(fstab_file);
|
||||
if (!fstab) {
|
||||
LOG(ERROR) << "Failed to parse fstab string: " << fstab_string;
|
||||
return;
|
||||
}
|
||||
LOG(INFO) << "Loaded vendor fstab from cmdline";
|
||||
|
||||
if (early_device_socket_open()) {
|
||||
LOG(ERROR) << "Failed to open device uevent socket";
|
||||
return;
|
||||
}
|
||||
|
||||
/* Create /dev/device-mapper for dm-verity */
|
||||
early_create_dev("/sys/devices/virtual/misc/device-mapper", EARLY_CHAR_DEV);
|
||||
|
||||
for (int i = 0; i < fstab->num_entries; ++i) {
|
||||
struct fstab_rec *rec = &fstab->recs[i];
|
||||
std::string mount_point = rec->mount_point;
|
||||
std::string syspath = rec->blk_device;
|
||||
|
||||
if (mount_point != "/vendor" && mount_point != "/odm")
|
||||
continue;
|
||||
|
||||
/* Create mount target under /dev/block/ from sysfs via uevent */
|
||||
LOG(INFO) << "Mounting " << mount_point << " from " << syspath << "...";
|
||||
char *devpath = strdup(get_path("/dev/block", syspath).c_str());
|
||||
if (!devpath) {
|
||||
PLOG(ERROR) << "Failed to strdup dev path in early mount " << syspath;
|
||||
continue;
|
||||
}
|
||||
rec->blk_device = devpath;
|
||||
early_create_dev(syspath, EARLY_BLOCK_DEV);
|
||||
|
||||
int rc = fs_mgr_early_setup_verity(rec);
|
||||
if (rc == FS_MGR_EARLY_SETUP_VERITY_SUCCESS) {
|
||||
/* Mount target is changed to /dev/block/dm-<n>; initiate its creation from sysfs counterpart */
|
||||
early_create_dev(get_path("/sys/devices/virtual/block", rec->blk_device), EARLY_BLOCK_DEV);
|
||||
} else if (rc == FS_MGR_EARLY_SETUP_VERITY_FAIL) {
|
||||
LOG(ERROR) << "Failed to set up dm-verity on " << rec->blk_device;
|
||||
continue;
|
||||
} else { /* FS_MGR_EARLY_SETUP_VERITY_NO_VERITY */
|
||||
LOG(INFO) << "dm-verity disabled on debuggable device; mount directly on " << rec->blk_device;
|
||||
}
|
||||
|
||||
mkdir(mount_point.c_str(), 0755);
|
||||
rc = mount(rec->blk_device, mount_point.c_str(), rec->fs_type, rec->flags, rec->fs_options);
|
||||
if (rc) {
|
||||
PLOG(ERROR) << "Failed to mount on " << rec->blk_device;
|
||||
}
|
||||
}
|
||||
early_device_socket_close();
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
if (!strcmp(basename(argv[0]), "ueventd")) {
|
||||
return ueventd_main(argc, argv);
|
||||
|
@ -477,6 +573,9 @@ int main(int argc, char** argv) {
|
|||
|
||||
bool is_first_stage = (argc == 1) || (strcmp(argv[1], "--second-stage") != 0);
|
||||
|
||||
// Don't expose the raw commandline to unprivileged processes.
|
||||
chmod("/proc/cmdline", 0440);
|
||||
|
||||
// Get the basic filesystem setup we need put together in the initramdisk
|
||||
// on / and then we'll let the rc file figure out the rest.
|
||||
if (is_first_stage) {
|
||||
|
@ -489,6 +588,7 @@ int main(int argc, char** argv) {
|
|||
mount("sysfs", "/sys", "sysfs", 0, NULL);
|
||||
mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
|
||||
mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11));
|
||||
early_mount();
|
||||
}
|
||||
|
||||
// Now that tmpfs is mounted on /dev and we have /dev/kmsg, we can actually
|
||||
|
@ -541,6 +641,8 @@ int main(int argc, char** argv) {
|
|||
restorecon("/dev/__properties__");
|
||||
restorecon("/property_contexts");
|
||||
restorecon_recursive("/sys");
|
||||
restorecon_recursive("/dev/block");
|
||||
restorecon("/dev/device-mapper");
|
||||
|
||||
epoll_fd = epoll_create1(EPOLL_CLOEXEC);
|
||||
if (epoll_fd == -1) {
|
||||
|
|
Loading…
Reference in New Issue