From: Scott Worley Date: Wed, 3 Jun 2026 11:45:35 +0000 (-0700) Subject: Contemplate using bcarnes' squashfs label patches X-Git-Url: http://git.scottworley.com/nixos-qemu-vm-isolation/commitdiff_plain/baff8ddca8d3070ec94a8b8857b4a85ceb881d73?hp=1c40de51f4927c338c3eb981d4aaeafdd6919cac Contemplate using bcarnes' squashfs label patches --- diff --git a/modules/squashfs-tools-label.patch b/modules/squashfs-tools-label.patch new file mode 100644 index 0000000..7df2522 --- /dev/null +++ b/modules/squashfs-tools-label.patch @@ -0,0 +1,272 @@ +# From https://github.com/plougher/squashfs-tools/pull/264 +diff --git a/squashfs-tools/mksquashfs.c b/squashfs-tools/mksquashfs.c +--- a/squashfs-tools/mksquashfs.c ++++ b/squashfs-tools/mksquashfs.c +@@ -180,6 +180,12 @@ int exit_on_error = FALSE; + /* Is filesystem stored at an offset from the start of the block device/file? */ + long long start_offset = 0; + ++/* Do we have an extra_info metadata block? */ ++int extra_info = FALSE; ++/* parameters for the extra_info block */ ++char *volume_label = NULL; ++char *uuid = NULL; ++ + /* File count statistics used to print summary and fill in superblock */ + unsigned int file_count = 0, sym_count = 0, dev_count = 0, dir_count = 0, + fifo_count = 0, sock_count = 0, id_count = 0; +@@ -340,7 +346,7 @@ char *option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time", + "vaf", "taf", "faf", "read-queue", "write-queue", "fragment-queue", + "root-time", "root-uid", "root-gid", "xattrs-exclude", "xattrs-include", + "xattrs-add", "default-mode", "default-uid", "default-gid", +- "mem-percent", NULL ++ "mem-percent", "label", "uuid", NULL + }; + + char *sqfstar_option_table[] = { "comp", "b", "mkfs-time", "fstime", "all-time", +@@ -6239,6 +6245,8 @@ static void print_options(FILE *stream, char *name, int total_mem) + fprintf(stream, "-keep-as-directory\tif one source directory is specified, "); + fprintf(stream, "create a root\n"); + fprintf(stream, "\t\t\tdirectory containing that directory, rather than the\n"); ++ fprintf(stream, "-label \tSet the volume label\n"); ++ fprintf(stream, "-uuid \tSet the volume UUID\n"); + fprintf(stream, "\t\t\tcontents of the directory\n"); + fprintf(stream, "\nFilesystem filter options:\n"); + fprintf(stream, "-p \tadd pseudo file "); +@@ -7541,6 +7549,7 @@ int sqfstar(int argc, char *argv[]) + SQUASHFS_MAJOR, SQUASHFS_MINOR, + destination_file, block_size); + ++ bytes = sizeof(struct squashfs_super_block); + /* + * store any compressor specific options after the superblock, + * and set the COMP_OPT flag to show that the filesystem has +@@ -7554,11 +7563,9 @@ int sqfstar(int argc, char *argv[]) + sizeof(c_byte), &c_byte); + write_destination(fd, sizeof(struct squashfs_super_block) + + sizeof(c_byte), size, comp_data); +- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte) +- + size; ++ bytes += sizeof(c_byte) + size; + comp_opts = TRUE; +- } else +- bytes = sizeof(struct squashfs_super_block); ++ } + + if(path) + paths = add_subdir(paths, path); +@@ -7579,7 +7586,7 @@ int sqfstar(int argc, char *argv[]) + sBlk.block_log = block_log; + sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments, + always_use_fragments, duplicate_checking, exportable, +- no_xattrs, comp_opts); ++ no_xattrs, comp_opts, extra_info); + sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL); + + disable_info(); +@@ -7629,6 +7636,70 @@ int sqfstar(int argc, char *argv[]) + } + + ++void *info_dump(int *psize) { ++ int bytes = 0, pos = 0; ++ unsigned char *buf; ++ const int UUID_LEN = 16; /* avoid depending on uuid-dev for now */ ++ int label_len; ++ ++ /* The extra_info section contains one or more entries of the form: ++ TAG byte ++ LEN byte ++ VAL byte_1 ... byte_len ++ ++ Terminated by the tag: SQUASHFS_EXTRA_INFO_TAG_END ++ */ ++ if (volume_label) { ++ label_len = strlen(volume_label); ++ if (label_len > 255) label_len = 255; ++ bytes += 1 + 1 + label_len; ++ } ++ if (uuid) ++ bytes += 1 + 1 + UUID_LEN; ++ if (!bytes) ++ return NULL; ++ bytes += 1; /* TAG_END */ ++ ++ buf = malloc(bytes); ++ ++ if (volume_label) { ++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_LABEL; ++ buf[pos++] = label_len; ++ memcpy(&buf[pos], volume_label, label_len); ++ pos += label_len; ++ } ++ if (uuid) { ++ char *puuid = uuid; ++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_UUID; ++ buf[pos++] = UUID_LEN; ++ /* poor man's uuid_parse() */ ++ for (int i = 0; i < UUID_LEN; i++) { ++ char hex[3] = {}; ++ char *endptr = NULL; ++ if (*puuid == '-') { ++ puuid++; ++ } ++ if (puuid[0] && puuid[1]) { ++ memcpy(&hex[0], puuid, 2); ++ buf[pos++] = strtoul(hex, &endptr, 16); ++ } ++ if (endptr != hex + 2) { ++ ERROR("invalid UUID: %s\n", uuid); ++ exit(1); ++ } ++ puuid += 2; ++ } ++ } ++ buf[pos++] = SQUASHFS_EXTRA_INFO_TAG_END; ++ if (pos != bytes) { ++ ERROR("extra_info legth mismatch\n"); ++ exit(1); ++ } ++ *psize = bytes; ++ return buf; ++} ++ ++ + int main(int argc, char *argv[]) + { + struct stat buf, source_buf; +@@ -8420,6 +8491,20 @@ int main(int argc, char *argv[]) + } else if(strcmp(argv[i], "-comp") == 0) { + /* parsed previously */ + i++; ++ } else if (strcmp(argv[i], "-label") == 0) { ++ if(++i == argc) { ++ ERROR("%s: -label: missing label\n", ++ argv[0]); ++ exit(1); ++ } ++ volume_label = argv[i]; ++ } else if (strcmp(argv[i], "-uuid") == 0) { ++ if(++i == argc) { ++ ERROR("%s: -uuid: missing uuid\n", ++ argv[0]); ++ exit(1); ++ } ++ uuid = argv[i]; + } else { + ERROR("%s: invalid option\n\n", argv[0]); + print_options(stderr, argv[0], total_mem); +@@ -8645,6 +8730,7 @@ int main(int argc, char *argv[]) + exportable = SQUASHFS_EXPORTABLE(sBlk.flags); + no_xattrs = SQUASHFS_NO_XATTRS(sBlk.flags); + comp_opts = SQUASHFS_COMP_OPTS(sBlk.flags); ++ extra_info = SQUASHFS_EXTRA_INFO(sBlk.flags); + } + + initialise_threads(readq, fragq, bwriteq, fwriteq, !appending, +@@ -8666,33 +8752,44 @@ int main(int argc, char *argv[]) + memset(dupl_frag, 0, block_size * sizeof(struct file_info *)); + + if(!appending) { +- int size; ++ int comp_size; + void *comp_data = compressor_dump_options(comp, block_size, +- &size); ++ &comp_size); ++ ++ int info_size; ++ void *info_data = info_dump(&info_size); + + if(!quiet) + printf("Creating %d.%d filesystem on %s, block size %d.\n", + SQUASHFS_MAJOR, SQUASHFS_MINOR, + destination_file, block_size); + ++ bytes = sizeof(struct squashfs_super_block); + /* + * store any compressor specific options after the superblock, + * and set the COMP_OPT flag to show that the filesystem has + * compressor specfic options + */ + if(comp_data) { +- unsigned short c_byte = size | SQUASHFS_COMPRESSED_BIT; ++ unsigned short c_byte = comp_size | SQUASHFS_COMPRESSED_BIT; + + SQUASHFS_INSWAP_SHORTS(&c_byte, 1); +- write_destination(fd, sizeof(struct squashfs_super_block), +- sizeof(c_byte), &c_byte); +- write_destination(fd, sizeof(struct squashfs_super_block) + +- sizeof(c_byte), size, comp_data); +- bytes = sizeof(struct squashfs_super_block) + sizeof(c_byte) +- + size; ++ write_destination(fd, bytes, sizeof(c_byte), &c_byte); ++ bytes += sizeof(c_byte); ++ write_destination(fd, bytes, comp_size, comp_data); ++ bytes += comp_size; + comp_opts = TRUE; +- } else +- bytes = sizeof(struct squashfs_super_block); ++ } ++ if (info_data) { ++ unsigned short i_byte = info_size | SQUASHFS_COMPRESSED_BIT; ++ ++ SQUASHFS_INSWAP_SHORTS(&i_byte, 1); ++ write_destination(fd, bytes, sizeof(i_byte), &i_byte); ++ bytes += sizeof(i_byte); ++ write_destination(fd, bytes, info_size, info_data); ++ bytes += info_size; ++ extra_info = TRUE; ++ } + } else { + unsigned int last_directory_block, inode_dir_file_size, + root_inode_size, inode_dir_start_block, +@@ -8852,7 +8949,7 @@ int main(int argc, char *argv[]) + sBlk.block_log = block_log; + sBlk.flags = SQUASHFS_MKFLAGS(noI, noD, noF, noX, noId, no_fragments, + always_use_fragments, duplicate_checking, exportable, +- no_xattrs, comp_opts); ++ no_xattrs, comp_opts, extra_info); + sBlk.mkfs_time = mkfs_time_opt ? mkfs_time : time(NULL); + + disable_info(); +diff --git a/squashfs-tools/squashfs_fs.h b/squashfs-tools/squashfs_fs.h +--- a/squashfs-tools/squashfs_fs.h ++++ b/squashfs-tools/squashfs_fs.h +@@ -72,6 +72,7 @@ + #define SQUASHFS_NO_XATTR 9 + #define SQUASHFS_COMP_OPT 10 + #define SQUASHFS_NOID 11 ++#define SQUASHFS_INFO 12 + + #define SQUASHFS_BIT(flag, bit) ((flag >> bit) & 1) + +@@ -108,12 +109,16 @@ + #define SQUASHFS_UNCOMPRESSED_IDS(flags) SQUASHFS_BIT(flags, \ + SQUASHFS_NOID) + ++#define SQUASHFS_EXTRA_INFO(flags) SQUASHFS_BIT(flags, \ ++ SQUASHFS_INFO) ++ + #define SQUASHFS_MKFLAGS(noi, nod, nof, nox, noid, no_frag, always_frag, \ +- duplicate_checking, exportable, no_xattr, comp_opt) (noi | \ ++ duplicate_checking, exportable, no_xattr, comp_opt, \ ++ extra_info) (noi | \ + (nod << 1) | (nof << 3) | (no_frag << 4) | \ + (always_frag << 5) | (duplicate_checking << 6) | \ + (exportable << 7) | (nox << 8) | (no_xattr << 9) | \ +- (comp_opt << 10) | (noid << 11)) ++ (comp_opt << 10) | (noid << 11) | (extra_info << 12)) + + /* Max number of types and file types */ + #define SQUASHFS_DIR_TYPE 1 +@@ -289,6 +294,10 @@ typedef long long squashfs_inode; + #define LZ4_COMPRESSION 5 + #define ZSTD_COMPRESSION 6 + ++#define SQUASHFS_EXTRA_INFO_TAG_END 0 ++#define SQUASHFS_EXTRA_INFO_TAG_LABEL 1 ++#define SQUASHFS_EXTRA_INFO_TAG_UUID 2 ++ + struct squashfs_super_block { + unsigned int s_magic; + unsigned int inodes; diff --git a/modules/util-linux-squashfs-label.patch b/modules/util-linux-squashfs-label.patch new file mode 100644 index 0000000..173a542 --- /dev/null +++ b/modules/util-linux-squashfs-label.patch @@ -0,0 +1,90 @@ +# From https://github.com/plougher/squashfs-tools/pull/264 +diff --git a/libblkid/src/superblocks/squashfs.c b/libblkid/src/superblocks/squashfs.c +--- a/libblkid/src/superblocks/squashfs.c ++++ b/libblkid/src/superblocks/squashfs.c +@@ -38,11 +38,74 @@ struct sqsh_super_block { + uint64_t export_table; + } __attribute__((packed)); + ++#define SQUASHFS_COMP_OPT_FLAG (1<<10) ++#define SQUASHFS_EXTRA_INFO_FLAG (1<<12) ++ ++#define SQUASHFS_COMPRESSED_BIT (1<<15) ++#define SQUASHFS_METADATA_BLOCK_MAX 8192 ++ ++#define SQUASHFS_EXTRA_INFO_TAG_END 0 ++#define SQUASHFS_EXTRA_INFO_TAG_LABEL 1 ++#define SQUASHFS_EXTRA_INFO_TAG_UUID 2 ++ ++static const uint8_t *get_metadata_block(blkid_probe pr, uint64_t *pofs, uint16_t *pmetablock_len) ++{ ++ const uint8_t *buf = blkid_probe_get_buffer(pr, *pofs, 2); ++ if (!buf) return NULL; ++ uint16_t metablock_len = (buf[1]<<8) | buf[0]; ++ if (!(metablock_len & SQUASHFS_COMPRESSED_BIT)) { ++ /* a compressed metadata block is not valid here */ ++ return NULL; ++ } ++ metablock_len &= ~SQUASHFS_COMPRESSED_BIT; ++ if (metablock_len > SQUASHFS_METADATA_BLOCK_MAX) { ++ return NULL; ++ } ++ buf = blkid_probe_get_buffer(pr, *pofs + 2, metablock_len); ++ if (!buf) return NULL; ++ *pmetablock_len = metablock_len; ++ *pofs += 2 + metablock_len; ++ return buf; ++} ++ ++static void probe_extra_info(blkid_probe pr, uint16_t flags) ++{ ++ uint64_t ofs = sizeof(struct sqsh_super_block); ++ uint16_t metablock_len; ++ const uint8_t *buf; ++ ++ /* comp_opts, when present, comes right after the superblock */ ++ if (flags & SQUASHFS_COMP_OPT_FLAG) { ++ buf = get_metadata_block(pr, &ofs, &metablock_len); ++ if (!buf) return; ++ } ++ ++ /* extra_info comes next */ ++ buf = get_metadata_block(pr, &ofs, &metablock_len); ++ if (!buf) return; ++ ++ const uint8_t *buf_end = buf + metablock_len; ++ while (buf < buf_end) { ++ unsigned char type = *buf++; ++ if (type == SQUASHFS_EXTRA_INFO_TAG_END || buf >= buf_end) ++ return; ++ unsigned char len = *buf++; ++ if (buf + len > buf_end) return; ++ if (type == SQUASHFS_EXTRA_INFO_TAG_LABEL) { ++ blkid_probe_set_label(pr, buf, len); ++ } else if (type == SQUASHFS_EXTRA_INFO_TAG_UUID) { ++ blkid_probe_set_uuid(pr, buf); ++ } ++ buf += len; ++ } ++} ++ + static int probe_squashfs(blkid_probe pr, const struct blkid_idmag *mag) + { + struct sqsh_super_block *sq; + uint16_t vermaj; + uint16_t vermin; ++ uint16_t flags; + + sq = blkid_probe_get_sb(pr, mag, struct sqsh_super_block); + if (!sq) +@@ -58,6 +121,10 @@ static int probe_squashfs(blkid_probe pr, const struct blkid_idmag *mag) + blkid_probe_set_block_size(pr, le32_to_cpu(sq->block_size)); + blkid_probe_set_fssize(pr, le64_to_cpu(sq->bytes_used)); + ++ flags = le16_to_cpu(sq->flags); ++ if (flags & SQUASHFS_EXTRA_INFO_FLAG) { ++ probe_extra_info(pr, flags); ++ } + return 0; + } +