Starting with linux kernel v5.4 squashfs has a more strict parameter
checking implemented. Unlike util-linux mount, busybox never supported
the sizelimit option but simply forwards it to the kernel.
Since v5.4 mounting will fail with

    squashfs: Unknown parameter 'sizelimit'

Support the sizelimit parameter by setting it in the LOOP_SET_STATUS64
structure before handing it to the kernel.

While at it also add support for the offset option, which currently will
always be set to 0.

Signed-off-by: Steffen Trumtrar <s.trumt...@pengutronix.de>
---
 include/libbb.h      |  3 ++-
 libbb/loop.c         |  4 +++-
 util-linux/losetup.c |  2 +-
 util-linux/mount.c   | 38 +++++++++++++++++++++++++++++++++++++-
 4 files changed, 43 insertions(+), 4 deletions(-)

diff --git a/include/libbb.h b/include/libbb.h
index 6be934994499..fe7fcff40ee0 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -1515,7 +1515,8 @@ int del_loop(const char *device) FAST_FUNC;
  * malloc and return it in *devname.
  * return value is the opened fd to the loop device, or < on error
  */
-int set_loop(char **devname, const char *file, unsigned long long offset, 
unsigned flags) FAST_FUNC;
+int set_loop(char **devname, const char *file, unsigned long long offset,
+            unsigned long long sizelimit, unsigned flags) FAST_FUNC;
 /* These constants match linux/loop.h (without BB_ prefix): */
 #define BB_LO_FLAGS_READ_ONLY 1
 #define BB_LO_FLAGS_AUTOCLEAR 4
diff --git a/libbb/loop.c b/libbb/loop.c
index ada0c7638f3b..c65982c32b71 100644
--- a/libbb/loop.c
+++ b/libbb/loop.c
@@ -102,7 +102,8 @@ int FAST_FUNC get_free_loop(void)
  * search will re-use an existing loop device already bound to that
  * file/offset if it finds one.
  */
-int FAST_FUNC set_loop(char **device, const char *file, unsigned long long 
offset, unsigned flags)
+int FAST_FUNC set_loop(char **device, const char *file, unsigned long long 
offset,
+                      unsigned long long sizelimit, unsigned flags)
 {
        char dev[LOOP_NAMESIZE];
        char *try;
@@ -185,6 +186,7 @@ int FAST_FUNC set_loop(char **device, const char *file, 
unsigned long long offse
                                memset(&loopinfo, 0, sizeof(loopinfo));
                                safe_strncpy((char *)loopinfo.lo_file_name, 
file, LO_NAME_SIZE);
                                loopinfo.lo_offset = offset;
+                               loopinfo.lo_sizelimit = sizelimit;
                                /*
                                 * Used by mount to set LO_FLAGS_AUTOCLEAR.
                                 * LO_FLAGS_READ_ONLY is not set because RO is 
controlled by open type of the file.
diff --git a/util-linux/losetup.c b/util-linux/losetup.c
index cc6c2b1d54e6..ec0cf04e4502 100644
--- a/util-linux/losetup.c
+++ b/util-linux/losetup.c
@@ -151,7 +151,7 @@ int losetup_main(int argc UNUSED_PARAM, char **argv)
                        if (opt & OPT_P) {
                                flags |= BB_LO_FLAGS_PARTSCAN;
                        }
-                       if (set_loop(&d, argv[0], offset, flags) < 0)
+                       if (set_loop(&d, argv[0], offset, 0, flags) < 0)
                                bb_simple_perror_msg_and_die(argv[0]);
                        return EXIT_SUCCESS;
                }
diff --git a/util-linux/mount.c b/util-linux/mount.c
index 84c85c0578ea..bd6dfa3ba0bd 100644
--- a/util-linux/mount.c
+++ b/util-linux/mount.c
@@ -2030,9 +2030,44 @@ static int singlemount(struct mntent *mp, int 
ignore_busy)
        ) {
                // Do we need to allocate a loopback device for it?
                if (ENABLE_FEATURE_MOUNT_LOOP && S_ISREG(st.st_mode)) {
+                       char *opt;
+                       unsigned long long offset = 0;
+                       unsigned long long sizelimit = 0;
+
                        loopFile = bb_simplify_path(mp->mnt_fsname);
                        mp->mnt_fsname = NULL; // will receive malloced loop 
dev name
 
+                       /* parse options */
+                       if (filteropts)
+                               for (opt = strtok(filteropts, ","); opt; opt = 
strtok(NULL, ",")) {
+                                       char *opteq = strchr(opt, '=');
+                                       int len = strlen(opt);
+                                       char *match;
+
+                                       if (opteq) {
+                                               int idx;
+                                               static const char options[] 
ALIGN1 =
+                                                       /* 0 */ "offset\0"
+                                                       /* 1 */ "sizelimit\0";
+
+                                               *opteq++ = '\0';
+                                               idx = index_in_strings(options, 
opt);
+                                               switch (idx) {
+                                               case 0: // "offset"
+                                                       offset = 
strtoull(opteq, 0, 0);
+                                                       match = 
strstr(filteropts, opt);
+                                                       *match = '\0';
+                                                       strcat(filteropts, 
match+len);
+                                                       continue;
+                                               case 1: // "sizelimit"
+                                                       sizelimit = 
strtoull(opteq, 0, 0);
+                                                       match = 
strstr(filteropts, opt);
+                                                       *match = '\0';
+                                                       strcat(filteropts, 
match+len);
+                                                       continue;
+                                               }
+                                       }
+                               }
                        // mount always creates AUTOCLEARed loopdevs, so that 
umounting
                        // drops them without any code in the userspace.
                        // This happens since circa linux-2.6.25:
@@ -2041,7 +2076,8 @@ static int singlemount(struct mntent *mp, int ignore_busy)
                        // Subject: Allow auto-destruction of loop devices
                        loopfd = set_loop(&mp->mnt_fsname,
                                        loopFile,
-                                       0,
+                                       offset,
+                                       sizelimit,
                                        ((vfsflags & MS_RDONLY) ? 
BB_LO_FLAGS_READ_ONLY : 0)
                                                | BB_LO_FLAGS_AUTOCLEAR
                        );
-- 
2.27.0

_______________________________________________
busybox mailing list
busybox@busybox.net
http://lists.busybox.net/mailman/listinfo/busybox

Reply via email to