[LTP] [PATCH v2] squashfs: Add regression test for sanity check bug

Joerg Vehlow lkml@jv-coder.de
Wed Jul 14 11:26:09 CEST 2021


Hi Cyril,

On 7/14/2021 10:35 AM, Cyril Hrubis wrote:
> Hi!
>> Adds a regression test for the fixes
>> c1b2028315 ("squashfs: fix inode lookup sanity checks")
>> and
>> 8b44ca2b62 ("squashfs: fix xattr id and id lookup sanity checks")
>>
>> Signed-off-by: Joerg Vehlow <joerg.vehlow@aox-tech.de>
>> ---
>>
>> Changes to v1:
>>   - Implement whole test in c
>>   - Fixed whitespaces...
>>
>>   runtest/fs                                    |  2 +
>>   testcases/kernel/fs/squashfs/.gitignore       |  1 +
>>   testcases/kernel/fs/squashfs/Makefile         |  9 ++
>>   .../kernel/fs/squashfs/squashfs_regression.c  | 99 +++++++++++++++++++
>>   4 files changed, 111 insertions(+)
>>   create mode 100644 testcases/kernel/fs/squashfs/.gitignore
>>   create mode 100644 testcases/kernel/fs/squashfs/Makefile
>>   create mode 100644 testcases/kernel/fs/squashfs/squashfs_regression.c
>>
>> diff --git a/runtest/fs b/runtest/fs
>> index 17b1415eb..2091b00f8 100644
>> --- a/runtest/fs
>> +++ b/runtest/fs
>> @@ -85,3 +85,5 @@ fs_fill fs_fill
>>   
>>   binfmt_misc01 binfmt_misc01.sh
>>   binfmt_misc02 binfmt_misc02.sh
>> +
>> +squashfs_regression squashfs_regression
> I wonder if we should add a number suffix or just rename it to
> squashfs01
Is there any guideline? I used regression suffix, because it 
specifically is a regression test and there are several regression 
tests, that use it.
I dropped a number prefix, because there are several tests without a 
number...
I don't really care what the name is here. If you don't have a strong 
opinion on the regression suffix, I will use squashfs_regression01.

>> diff --git a/testcases/kernel/fs/squashfs/.gitignore b/testcases/kernel/fs/squashfs/.gitignore
>> new file mode 100644
>> index 000000000..45c908fff
>> --- /dev/null
>> +++ b/testcases/kernel/fs/squashfs/.gitignore
>> @@ -0,0 +1 @@
>> +squashfs_regression
>> diff --git a/testcases/kernel/fs/squashfs/Makefile b/testcases/kernel/fs/squashfs/Makefile
>> new file mode 100644
>> index 000000000..67021139c
>> --- /dev/null
>> +++ b/testcases/kernel/fs/squashfs/Makefile
>> @@ -0,0 +1,9 @@
>> +# SPDX-License-Identifier: GPL-2.0-or-later
>> +# Copyright (C) 2009, Cisco Systems Inc.
>> +# Ngie Cooper, July 2009
>> +
>> +top_srcdir		?= ../../../..
>> +
>> +include $(top_srcdir)/include/mk/testcases.mk
>> +
>> +include $(top_srcdir)/include/mk/generic_leaf_target.mk
>> diff --git a/testcases/kernel/fs/squashfs/squashfs_regression.c b/testcases/kernel/fs/squashfs/squashfs_regression.c
>> new file mode 100644
>> index 000000000..23f681367
>> --- /dev/null
>> +++ b/testcases/kernel/fs/squashfs/squashfs_regression.c
>> @@ -0,0 +1,99 @@
>> +// SPDX-License-Identifier: GPL-2.0-or-later
>> +/*
>> + * Copyright (c) 2021 Joerg Vehlow <joerg.vehlow@aox-tech.de>
>> + */
>> +
>> +/*\
>> + * [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 <stdio.h>
>> +#include <sys/mount.h>
>> +
>> +#include "tst_test.h"
>> +#include "tst_safe_macros.h"
>> +
>> +static void cleanup(void)
>> +{
>> +	umount("mnt");
> We do have tst_umount() in the test library that retries the umount if
> it failed because the mount point was bussy. This is because certain
> damons scan all newly mounted filesystems and prevent us from umounting
> shortly after mount.
>
> Also we usually keep track if device was mounted in a global flag that
> is set after succesful mount and unset after successful umount and the
> cleanup does:
>
> 	if (device_mounted)
> 		tst_umount("mnt");
Ok, but this could leave the mount, if the test is aborted between 
mounting and setting of the flag, but that should be a rare case.

>
>> +}
>> +
>> +static void run(void)
>> +{
>> +	int i;
>> +
>> +	tst_res(TINFO, "Test squashfs sanity check regressions");
>> +
>> +	SAFE_MKDIR("data", 0777);
>> +
>> +	for (i = 0; i < 2048; ++i) {
>> +		int fd;
>> +		char name[20];
>> +
>> +		sprintf(name, "data/%d", 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 comporession.
>> +	 * This allows reasoning about block sizes
>> +	 */
>> +	TST_EXP_PASS(tst_system(
>> +		"mksquashfs data image.raw -noI -noD -noX -noF >/dev/null 2>&1"
>> +	), "Create squashfs");
> We do have tst_cmd() that can do all this easily in C including the
> redirection, it will look like:
>
> 	const char *argv[] = {"mksquashfs", "data", "image.raw", "-noI", "-noD", "-noX", "-noF"};
>
> 	tst_cmd(argv, "/dev/null", "/dev/null", 0);
>
> And this will redirect stdout and stderr to "/dev/null" and also do all
> the error checks and exit the test if mksquashfs has failed.
Did not know about that, also it requires a NULL at the end.

>
>> +	SAFE_MKDIR("mnt", 0777);
> This preparatory part should be in the test setup otherwise the test
> will fail with '-i 2'.
Right, I'll move the whole setup part to setup.
>
>> +	TST_EXP_PASS(tst_system("mount -tsquashfs -oloop image.raw mnt"));
> Can we please use the mount() syscall here instead? That should be as
> easy as mount("image.raw", "mnt", "squashfs", 0, "-oloop")
Nope, -oloop does not work, because this is interpreted by the mount 
utility, not by the syscall.
I guess I'll use the need_device stuff, to get rid of mount utility call 
then.

>> +
>> +	SAFE_UMOUNT("mnt");
> Here as well, please use tst_umount();
Ok

>
>> +	tst_res(TPASS, "Test passed");
> This is redundant, isn't it? Or is the umount part that fails?
Since I cannot use TST_EXP_PASS further up, I will keep this and check 
the return of mount manually like this:

static void run(void)
{
     tst_res(TINFO, "Test squashfs sanity check regressions");

     if (mount(tst_device->dev, MOUNT_DIR, "squashfs", 0, NULL) != 0) {
         tst_brk(TFAIL | TERRNO, "Mount failed");
     }
     mounted = 1;

     tst_umount("mnt");
     mounted = 0;

     tst_res(TPASS, "Test passed");
}

Would that be ok for you or is there another variant of TST_EXP*, that 
uses tst_brk?

Joerg



More information about the ltp mailing list