Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use androidboot.partition_map as a fallback for matching partition names in the preinit finding. #8293

Merged
merged 4 commits into from
Aug 15, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 28 additions & 6 deletions native/src/init/getinfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -41,16 +41,16 @@ static string extract_quoted_str_until(chars<escapes...>, chars<breaks...>,
}

// Parse string into key value pairs.
// The string format: [delim][key][padding]=[padding][value][delim]
template<char delim, char... padding>
// The string format: [delim][key][padding][eq][padding][value][delim]
template<char delim, char eq, char... padding>
static kv_pairs parse_impl(chars<padding...>, string_view str) {
kv_pairs kv;
char skip_array[] = {'=', padding...};
char skip_array[] = {eq, padding...};
string_view skip(skip_array, std::size(skip_array));
bool quoted = false;
for (size_t pos = 0u; pos < str.size(); pos = str.find_first_not_of(delim, pos)) {
auto key = extract_quoted_str_until(
chars<padding..., delim>{}, chars<'='>{}, str, pos, quoted);
chars<padding..., delim>{}, chars<eq>{}, str, pos, quoted);
pos = str.find_first_not_of(skip, pos);
if (pos == string_view::npos || str[pos] == delim) {
kv.emplace_back(key, "");
Expand All @@ -63,10 +63,13 @@ static kv_pairs parse_impl(chars<padding...>, string_view str) {
}

static kv_pairs parse_cmdline(string_view str) {
return parse_impl<' '>(chars<>{}, str);
return parse_impl<' ', '='>(chars<>{}, str);
}
static kv_pairs parse_bootconfig(string_view str) {
return parse_impl<'\n'>(chars<' '>{}, str);
return parse_impl<'\n', '='>(chars<' '>{}, str);
}
static kv_pairs parse_partition_map(std::string_view str) {
return parse_impl<';', ','>(chars<>{}, str);
}

#define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8)))
Expand Down Expand Up @@ -207,6 +210,25 @@ void load_kernel_info(BootConfig *config) {
config->print();
}

// `androidboot.partition_map` allows associating a partition name for a raw block device
// through a comma separated and semicolon deliminated list. For example,
// `androidboot.partition_map=vdb,metadata;vdc,userdata` maps `vdb` to `metadata` and `vdc` to
// `userdata`.
// https://android.googlesource.com/platform/system/core/+/refs/heads/android13-release/init/devices.cpp#191

kv_pairs load_partition_map() {
const string_view kPartitionMapKey = "androidboot.partition_map";
for (const auto &[key, value] : parse_cmdline(full_read("/proc/cmdline"))) {
if (key == kPartitionMapKey)
return parse_partition_map(value);
}
for (const auto &[key, value] : parse_bootconfig(full_read("/proc/bootconfig"))) {
if (key == kPartitionMapKey)
return parse_partition_map(value);
}
return {};
}

bool check_two_stage() {
if (access("/apex", F_OK) == 0)
return true;
Expand Down
1 change: 1 addition & 0 deletions native/src/init/init.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ extern std::vector<std::string> mount_list;
int magisk_proxy_main(int argc, char *argv[]);
bool unxz(out_stream &strm, rust::Slice<const uint8_t> bytes);
void load_kernel_info(BootConfig *config);
kv_pairs load_partition_map();
bool check_two_stage();
const char *backup_init();
void restore_ramdisk_init();
Expand Down
21 changes: 15 additions & 6 deletions native/src/init/mount.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,23 @@ bool avd_hack = false;
static void parse_device(devinfo *dev, const char *uevent) {
dev->partname[0] = '\0';
dev->devpath[0] = '\0';
dev->dmname[0] = '\0';
dev->devname[0] = '\0';
parse_prop_file(uevent, [=](string_view key, string_view value) -> bool {
if (key == "MAJOR")
dev->major = parse_int(value.data());
else if (key == "MINOR")
dev->minor = parse_int(value.data());
else if (key == "DEVNAME")
strcpy(dev->devname, value.data());
strscpy(dev->devname, value.data(), sizeof(dev->devname));
else if (key == "PARTNAME")
strcpy(dev->partname, value.data());
strscpy(dev->partname, value.data(), sizeof(dev->devname));

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it intentional that this is using sizeof(dev->devname) instead of sizeof(dev->partname)? Might be irrelevant, I'm not exactly sure how this code is called, I just happened to glance at it the other day.

Copy link
Contributor Author

@chsbuffer chsbuffer Aug 29, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It doesn't really matter, partname and devname are both 32.
@yujincheng08 Can you answer whether this is intentional or not?

I'm also worried that strscpy doesn't add zero terminators, maybe we should use strncat(dst, src, buffer_size - 1) or use strncasecmp instead of strcastcmp when comparing.


return true;
});
}

static void collect_devices() {
static void collect_devices(const auto &partition_map) {
char path[PATH_MAX];
devinfo dev{};
if (auto dir = xopen_dir("/sys/dev/block"); dir) {
Expand All @@ -55,7 +57,13 @@ static void collect_devices() {
sprintf(path, "/sys/dev/block/%s/dm/name", entry->d_name);
if (access(path, F_OK) == 0) {
auto name = rtrim(full_read(path));
strcpy(dev.dmname, name.data());
strscpy(dev.dmname, name.data(), sizeof(dev.dmname));
}
if (auto it = std::ranges::find_if(partition_map, [&](const auto &i) {
return i.first == dev.devname;
}); dev.partname[0] == '\0' && it != partition_map.end()) {
// use androidboot.partition_map as partname fallback.
strscpy(dev.partname, it->second.data(), sizeof(dev.partname));
}
sprintf(path, "/sys/dev/block/%s", entry->d_name);
xrealpath(path, dev.devpath, sizeof(dev.devpath));
Expand All @@ -70,8 +78,9 @@ static struct {
} blk_info;

static dev_t setup_block() {
const auto partition_map = load_partition_map();
yujincheng08 marked this conversation as resolved.
Show resolved Hide resolved
if (dev_list.empty())
collect_devices();
collect_devices(partition_map);

for (int tries = 0; tries < 3; ++tries) {
for (auto &dev : dev_list) {
Expand All @@ -93,7 +102,7 @@ static dev_t setup_block() {
// Wait 10ms and try again
usleep(10000);
dev_list.clear();
collect_devices();
collect_devices(partition_map);
}

// The requested partname does not exist
Expand Down