1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) 2021 Joerg Vehlow <joerg.vehlow@aox-tech.de>
4f08c3bdfSopenharmony_ci */
5f08c3bdfSopenharmony_ci
6f08c3bdfSopenharmony_ci/*\
7f08c3bdfSopenharmony_ci * [Description]
8f08c3bdfSopenharmony_ci *
9f08c3bdfSopenharmony_ci * Kernel commits
10f08c3bdfSopenharmony_ci *
11f08c3bdfSopenharmony_ci * - f37aa4c7366 (squashfs: add more sanity checks in id lookup)
12f08c3bdfSopenharmony_ci * - eabac19e40c (squashfs: add more sanity checks in inode lookup)
13f08c3bdfSopenharmony_ci * - 506220d2ba2 (squashfs: add more sanity checks in xattr id lookup)
14f08c3bdfSopenharmony_ci *
15f08c3bdfSopenharmony_ci * added some sanity checks, that verify the size of
16f08c3bdfSopenharmony_ci * inode lookup, id (uid/gid) and xattr blocks in the squashfs,
17f08c3bdfSopenharmony_ci * but broke mounting filesystems with completely filled blocks.
18f08c3bdfSopenharmony_ci * A block has a max size of 8192.
19f08c3bdfSopenharmony_ci * An inode lookup entry has an uncompressed size of 8 bytes,
20f08c3bdfSopenharmony_ci * an id block 4 bytes and an xattr block 16 bytes.
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci *
23f08c3bdfSopenharmony_ci * To fill up at least one block for each of the three tables,
24f08c3bdfSopenharmony_ci * 2048 files with unique uid/gid and xattr are created.
25f08c3bdfSopenharmony_ci *
26f08c3bdfSopenharmony_ci *
27f08c3bdfSopenharmony_ci * The bugs are fixed in kernel commits
28f08c3bdfSopenharmony_ci *
29f08c3bdfSopenharmony_ci * - c1b2028315c (squashfs: fix inode lookup sanity checks)
30f08c3bdfSopenharmony_ci * - 8b44ca2b634 (squashfs: fix xattr id and id lookup sanity checks)
31f08c3bdfSopenharmony_ci */
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_ci#include <stdio.h>
34f08c3bdfSopenharmony_ci#include <sys/mount.h>
35f08c3bdfSopenharmony_ci
36f08c3bdfSopenharmony_ci#include "tst_test.h"
37f08c3bdfSopenharmony_ci#include "tst_safe_macros.h"
38f08c3bdfSopenharmony_ci
39f08c3bdfSopenharmony_cistatic const char *MOUNT_DIR = "mnt";
40f08c3bdfSopenharmony_cistatic const char *DATA_DIR = "data";
41f08c3bdfSopenharmony_ci
42f08c3bdfSopenharmony_cistatic int mounted;
43f08c3bdfSopenharmony_ci
44f08c3bdfSopenharmony_cistatic void cleanup(void)
45f08c3bdfSopenharmony_ci{
46f08c3bdfSopenharmony_ci	if (mounted)
47f08c3bdfSopenharmony_ci		SAFE_UMOUNT("mnt");
48f08c3bdfSopenharmony_ci}
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_cistatic void setup(void)
51f08c3bdfSopenharmony_ci{
52f08c3bdfSopenharmony_ci	int i;
53f08c3bdfSopenharmony_ci
54f08c3bdfSopenharmony_ci	tst_res(TINFO, "Test squashfs sanity check regressions");
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci	SAFE_MKDIR(DATA_DIR, 0777);
57f08c3bdfSopenharmony_ci
58f08c3bdfSopenharmony_ci	for (i = 0; i < 2048; ++i) {
59f08c3bdfSopenharmony_ci		int fd;
60f08c3bdfSopenharmony_ci		char name[20];
61f08c3bdfSopenharmony_ci
62f08c3bdfSopenharmony_ci		sprintf(name, "%s/%d", DATA_DIR, i);
63f08c3bdfSopenharmony_ci		fd = SAFE_OPEN(name, O_CREAT | O_EXCL, 0666);
64f08c3bdfSopenharmony_ci		SAFE_FCHOWN(fd, i, i);
65f08c3bdfSopenharmony_ci
66f08c3bdfSopenharmony_ci		/* This must be either "security", "user" or "trusted" namespace,
67f08c3bdfSopenharmony_ci		 * because squashfs cannot store other namespaces.
68f08c3bdfSopenharmony_ci		 * Since the files are most likely created on a tmpfs,
69f08c3bdfSopenharmony_ci		 * "user" namespace is not possible, because it is not allowed.
70f08c3bdfSopenharmony_ci		 */
71f08c3bdfSopenharmony_ci		SAFE_FSETXATTR(fd, "security.x", &i, sizeof(i), 0);
72f08c3bdfSopenharmony_ci		close(fd);
73f08c3bdfSopenharmony_ci	}
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci	/* Create squashfs without any compression.
76f08c3bdfSopenharmony_ci	 * This allows reasoning about block sizes.
77f08c3bdfSopenharmony_ci	 * Redirect stdout, to get rid of undefined uid messages
78f08c3bdfSopenharmony_ci	 */
79f08c3bdfSopenharmony_ci	const char *argv[] = {
80f08c3bdfSopenharmony_ci		"mksquashfs", DATA_DIR, tst_device->dev,
81f08c3bdfSopenharmony_ci		"-noappend", "-noI", "-noD", "-noX", "-noF", NULL
82f08c3bdfSopenharmony_ci	};
83f08c3bdfSopenharmony_ci	tst_cmd(argv, "/dev/null", NULL, 0);
84f08c3bdfSopenharmony_ci
85f08c3bdfSopenharmony_ci	SAFE_MKDIR(MOUNT_DIR, 0777);
86f08c3bdfSopenharmony_ci}
87f08c3bdfSopenharmony_ci
88f08c3bdfSopenharmony_cistatic void run(void)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	if (mount(tst_device->dev, MOUNT_DIR, "squashfs", 0, NULL) != 0)
91f08c3bdfSopenharmony_ci		tst_brk(TFAIL | TERRNO, "Mount failed");
92f08c3bdfSopenharmony_ci	mounted = 1;
93f08c3bdfSopenharmony_ci
94f08c3bdfSopenharmony_ci	SAFE_UMOUNT("mnt");
95f08c3bdfSopenharmony_ci	mounted = 0;
96f08c3bdfSopenharmony_ci
97f08c3bdfSopenharmony_ci	tst_res(TPASS, "Regression not detected");
98f08c3bdfSopenharmony_ci}
99f08c3bdfSopenharmony_ci
100f08c3bdfSopenharmony_cistatic struct tst_test test = {
101f08c3bdfSopenharmony_ci	.test_all = run,
102f08c3bdfSopenharmony_ci	.cleanup = cleanup,
103f08c3bdfSopenharmony_ci	.setup = setup,
104f08c3bdfSopenharmony_ci	.needs_root = 1,
105f08c3bdfSopenharmony_ci	.needs_device = 1,
106f08c3bdfSopenharmony_ci	.dev_min_size = 1,
107f08c3bdfSopenharmony_ci	.needs_cmds = (const char *const []) {
108f08c3bdfSopenharmony_ci		"mksquashfs",
109f08c3bdfSopenharmony_ci		NULL
110f08c3bdfSopenharmony_ci	},
111f08c3bdfSopenharmony_ci	.needs_drivers = (const char *const []) {
112f08c3bdfSopenharmony_ci		"squashfs",
113f08c3bdfSopenharmony_ci		NULL
114f08c3bdfSopenharmony_ci	},
115f08c3bdfSopenharmony_ci	.tags = (const struct tst_tag[]) {
116f08c3bdfSopenharmony_ci		{"linux-git", "c1b2028315c"},
117f08c3bdfSopenharmony_ci		{"linux-git", "8b44ca2b634"},
118f08c3bdfSopenharmony_ci		{}
119f08c3bdfSopenharmony_ci	},
120f08c3bdfSopenharmony_ci};
121