]> git.scottworley.com Git - nixos-qemu-vm-isolation/commitdiff
Contemplate using bcarnes' squashfs label patches
authorScott Worley <scottworley@scottworley.com>
Wed, 3 Jun 2026 11:45:35 +0000 (04:45 -0700)
committerScott Worley <scottworley@scottworley.com>
Thu, 4 Jun 2026 21:10:30 +0000 (14:10 -0700)
modules/squashfs-tools-label.patch [new file with mode: 0644]
modules/util-linux-squashfs-label.patch [new file with mode: 0644]

diff --git a/modules/squashfs-tools-label.patch b/modules/squashfs-tools-label.patch
new file mode 100644 (file)
index 0000000..7df2522
--- /dev/null
@@ -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 <volume-label>\tSet the volume label\n");
++      fprintf(stream, "-uuid <UUID>\tSet the volume UUID\n");
+       fprintf(stream, "\t\t\tcontents of the directory\n");
+       fprintf(stream, "\nFilesystem filter options:\n");
+       fprintf(stream, "-p <pseudo-definition>\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 (file)
index 0000000..173a542
--- /dev/null
@@ -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;
+ }