From 6b373937047c81eb068c3cacc060072df83e9844 Mon Sep 17 00:00:00 2001 From: vxtls <187420201+vxtls@users.noreply.github.com> Date: Mon, 2 Mar 2026 07:53:37 -0500 Subject: [PATCH] fix(payload-import): remove mount(8) dependency and import by kernel-enumerated block devices via /proc/partitions --- steps/improve/import_payload.sh | 37 +--- steps/payload-import-1.0/src/payload-import.c | 187 ++++++++++++++++-- 2 files changed, 170 insertions(+), 54 deletions(-) diff --git a/steps/improve/import_payload.sh b/steps/improve/import_payload.sh index 3dbdf397..599abba5 100644 --- a/steps/improve/import_payload.sh +++ b/steps/improve/import_payload.sh @@ -7,41 +7,8 @@ set -ex if [ "${PAYLOAD_REQUIRED}" = True ]; then mkdir -p /external/distfiles - mkdir -p /proc - - # Reliable enumeration in Fiwix: mount procfs and read /proc/partitions. - if [ ! -r /proc/partitions ]; then - mount -t proc proc /proc - fi - if [ ! -r /proc/partitions ]; then - echo "payload-import failed: /proc/partitions is unavailable." >&2 - exit 1 - fi - - found_payload=0 - while read -r major minor blocks name; do - case "${name}" in - ""|name|ram*|loop*|fd*|sr*|md*|dm-*|nbd*) - continue - ;; - *[0-9]) - # Skip partitions (hda1, sdb2, ...); payload is a whole disk. - continue - ;; - esac - - dev_path="/dev/${name}" - [ -b "${dev_path}" ] || mknod -m 600 "${dev_path}" b "${major}" "${minor}" - - if payload-import --probe "${dev_path}"; then - payload-import --device "${dev_path}" /external/distfiles - found_payload=1 - break - fi - done < /proc/partitions - - if [ "${found_payload}" != 1 ]; then - echo "payload-import failed: no payload image found in /proc/partitions." >&2 + if ! payload-import /external/distfiles; then + echo "payload-import failed: no payload image found on block devices." >&2 exit 1 fi fi diff --git a/steps/payload-import-1.0/src/payload-import.c b/steps/payload-import-1.0/src/payload-import.c index d937d70b..66815d16 100644 --- a/steps/payload-import-1.0/src/payload-import.c +++ b/steps/payload-import-1.0/src/payload-import.c @@ -2,10 +2,12 @@ /* SPDX-License-Identifier: MIT */ #include +#include #include #include #include #include +#include #include #define MAGIC "LBPAYLD1" @@ -13,6 +15,11 @@ #define MAX_NAME_LEN 1024 #define COPY_BUFSZ 65536 +/* mount(2) is available in the bootstrap libc, but some header stacks + * don't expose a prototype consistently. */ +extern int mount(const char *source, const char *target, + const char *filesystemtype, unsigned int mountflags, const void *data); + static unsigned int read_u32le(const unsigned char *buf) { return (unsigned int)buf[0] @@ -106,6 +113,55 @@ static int has_payload_magic(const char *path) return 0; } +static int starts_with(const char *s, const char *prefix) +{ + while (*prefix != 0) { + if (*s != *prefix) { + return 0; + } + s++; + prefix++; + } + return 1; +} + +static int ends_with_digit(const char *s) +{ + char c = 0; + + while (*s != 0) { + c = *s; + s++; + } + return c >= '0' && c <= '9'; +} + +static int is_proc_partition_candidate(const char *name) +{ + if (*name == 0 || strcmp(name, "name") == 0) { + return 0; + } + if (starts_with(name, "ram") + || starts_with(name, "loop") + || starts_with(name, "fd") + || starts_with(name, "sr") + || starts_with(name, "md") + || starts_with(name, "dm-") + || starts_with(name, "nbd")) { + return 0; + } + if (ends_with_digit(name)) { + /* Skip partitions; payload is attached as a whole disk. */ + return 0; + } + return 1; +} + +static unsigned int mkdev_u8(unsigned int major, unsigned int minor) +{ + return ((major & 0xFFU) << 8) | (minor & 0xFFU); +} + static int extract_payload(const char *device, const char *dest_dir) { FILE *in; @@ -225,28 +281,110 @@ static int extract_payload(const char *device, const char *dest_dir) return 0; } -static int import_from_first_payload(const char *dest_dir) +static int ensure_proc_partitions(void) { - const char *prefixes[] = {"/dev/sd", "/dev/hd", "/dev/vd", "/dev/xvd"}; - int p; + struct stat st; - for (p = 0; p < 4; ++p) { - char letter; - for (letter = 'b'; letter <= 'z'; ++letter) { - char device[16]; - if (snprintf(device, sizeof(device), "%s%c", prefixes[p], letter) >= (int)sizeof(device)) { - continue; - } - if (access(device, R_OK) != 0) { - continue; - } - if (has_payload_magic(device) == 0) { - return extract_payload(device, dest_dir); - } + if (stat("/proc/partitions", &st) == 0) { + return 0; + } + + if (stat("/proc", &st) != 0) { + if (mkdir("/proc", 0755) != 0 && errno != EEXIST) { + return 1; } } - fputs("payload-import: no payload disk found\n", stderr); + if (mount("proc", "/proc", "proc", 0, (const void *)0) != 0) { + return 1; + } + + if (stat("/proc/partitions", &st) != 0) { + return 1; + } + return 0; +} + +static int import_from_proc_partitions(const char *dest_dir) +{ + FILE *fp; + char line[256]; + + if (ensure_proc_partitions() != 0) { + return 1; + } + + fp = fopen("/proc/partitions", "r"); + if (fp == NULL) { + return 1; + } + + while (fgets(line, sizeof(line), fp) != NULL) { + unsigned int major, minor, blocks; + char name[64]; + char dev_path[96]; + + if (sscanf(line, " %u %u %u %63s", &major, &minor, &blocks, name) != 4) { + continue; + } + if (!is_proc_partition_candidate(name)) { + continue; + } + + if (snprintf(dev_path, sizeof(dev_path), "/dev/%s", name) >= (int)sizeof(dev_path)) { + continue; + } + + if (access(dev_path, F_OK) != 0) { + if (mknod(dev_path, S_IFBLK | 0600, mkdev_u8(major, minor)) != 0) { + continue; + } + } + if (has_payload_magic(dev_path) == 0) { + fclose(fp); + return extract_payload(dev_path, dest_dir); + } + } + + fclose(fp); + return 2; +} + +static int import_from_dev_nodes(const char *dest_dir) +{ + DIR *dir; + struct dirent *entry; + + dir = opendir("/dev"); + if (dir == NULL) { + return 2; + } + + entry = readdir(dir); + while (entry != NULL) { + char path[512]; + struct stat st; + + if (entry->d_name[0] == '.') { + entry = readdir(dir); + continue; + } + if (snprintf(path, sizeof(path), "/dev/%s", entry->d_name) >= (int)sizeof(path)) { + entry = readdir(dir); + continue; + } + if (lstat(path, &st) != 0 || !S_ISBLK(st.st_mode)) { + entry = readdir(dir); + continue; + } + if (has_payload_magic(path) == 0) { + closedir(dir); + return extract_payload(path, dest_dir); + } + entry = readdir(dir); + } + + closedir(dir); return 2; } @@ -255,8 +393,9 @@ static void usage(const char *name) fprintf(stderr, "Usage:\n" " %s --probe \n" + " %s --from-proc \n" " %s [--device ] \n", - name, name); + name, name, name); } int main(int argc, char **argv) @@ -268,6 +407,9 @@ int main(int argc, char **argv) if (argc == 3 && strcmp(argv[1], "--probe") == 0) { return has_payload_magic(argv[2]); } + if (argc == 3 && strcmp(argv[1], "--from-proc") == 0) { + return import_from_proc_partitions(argv[2]); + } for (i = 1; i < argc; ++i) { if (strcmp(argv[i], "--device") == 0) { @@ -293,5 +435,12 @@ int main(int argc, char **argv) if (device != NULL) { return extract_payload(device, dest_dir); } - return import_from_first_payload(dest_dir); + i = import_from_proc_partitions(dest_dir); + if (i == 0) { + return 0; + } + if (i == 1) { + fputs("payload-import: /proc/partitions unavailable, falling back to /dev scan\n", stderr); + } + return import_from_dev_nodes(dest_dir); }