// SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2021 Joerg Vehlow */ /*\ * [Description] * * Kernel commits * * - f37aa4c7366 (squashfs: add more sanity checks in id lookup) * - eabac19e40c (squashfs: add more sanity checks in inode lookup) * - 506220d2ba2 (squashfs: add more sanity checks in xattr id lookup) * * added some sanity checks, that verify the size of * inode lookup, id (uid/gid) and xattr blocks in the squashfs, * but broke mounting filesystems with completely filled blocks. * A block has a max size of 8192. * An inode lookup entry has an uncompressed size of 8 bytes, * an id block 4 bytes and an xattr block 16 bytes. * * * To fill up at least one block for each of the three tables, * 2048 files with unique uid/gid and xattr are created. * * * The bugs are fixed in kernel commits * * - c1b2028315c (squashfs: fix inode lookup sanity checks) * - 8b44ca2b634 (squashfs: fix xattr id and id lookup sanity checks) */ #include #include #include "tst_test.h" #include "tst_safe_macros.h" static const char *MOUNT_DIR = "mnt"; static const char *DATA_DIR = "data"; static int mounted; static void cleanup(void) { if (mounted) SAFE_UMOUNT("mnt"); } static void setup(void) { int i; tst_res(TINFO, "Test squashfs sanity check regressions"); SAFE_MKDIR(DATA_DIR, 0777); for (i = 0; i < 2048; ++i) { int fd; char name[20]; sprintf(name, "%s/%d", DATA_DIR, i); fd = SAFE_OPEN(name, O_CREAT | O_EXCL, 0666); SAFE_FCHOWN(fd, i, i); /* This must be either "security", "user" or "trusted" namespace, * because squashfs cannot store other namespaces. * Since the files are most likely created on a tmpfs, * "user" namespace is not possible, because it is not allowed. */ SAFE_FSETXATTR(fd, "security.x", &i, sizeof(i), 0); close(fd); } /* Create squashfs without any compression. * This allows reasoning about block sizes. * Redirect stdout, to get rid of undefined uid messages */ const char *argv[] = { "mksquashfs", DATA_DIR, tst_device->dev, "-noappend", "-noI", "-noD", "-noX", "-noF", NULL }; tst_cmd(argv, "/dev/null", NULL, 0); SAFE_MKDIR(MOUNT_DIR, 0777); } static void run(void) { if (mount(tst_device->dev, MOUNT_DIR, "squashfs", 0, NULL) != 0) tst_brk(TFAIL | TERRNO, "Mount failed"); mounted = 1; SAFE_UMOUNT("mnt"); mounted = 0; tst_res(TPASS, "Regression not detected"); } static struct tst_test test = { .test_all = run, .cleanup = cleanup, .setup = setup, .needs_root = 1, .needs_device = 1, .dev_min_size = 1, .needs_cmds = (const char *const []) { "mksquashfs", NULL }, .needs_drivers = (const char *const []) { "squashfs", NULL }, .tags = (const struct tst_tag[]) { {"linux-git", "c1b2028315c"}, {"linux-git", "8b44ca2b634"}, {} }, };