Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

Merge tag 'vfs-6.15-rc1.initramfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs

Pull vfs initramfs updates from Christian Brauner:
"This adds basic kunit test coverage for initramfs unpacking and cleans
up some buffer handling issues and inefficiencies"

* tag 'vfs-6.15-rc1.initramfs' of git://git.kernel.org/pub/scm/linux/kernel/git/vfs/vfs:
MAINTAINERS: append initramfs files to the VFS section
initramfs: avoid static buffer for error message
initramfs: fix hardlink hash leak without TRAILER
initramfs: reuse name_len for dir mtime tracking
initramfs: allocate heap buffers together
initramfs: avoid memcpy for hex header fields
vsprintf: add simple_strntoul
initramfs_test: kunit tests for initramfs unpacking
init: add initramfs_internal.h

+475 -28
+3
MAINTAINERS
··· 8903 8903 F: include/linux/fs_types.h 8904 8904 F: include/uapi/linux/fs.h 8905 8905 F: include/uapi/linux/openat2.h 8906 + F: Documentation/driver-api/early-userspace/buffer-format.rst 8907 + F: init/do_mounts* 8908 + F: init/*initramfs* 8906 8909 8907 8910 FILESYSTEMS [EXPORTFS] 8908 8911 M: Chuck Lever <chuck.lever@oracle.com>
+1
include/linux/kstrtox.h
··· 143 143 */ 144 144 145 145 extern unsigned long simple_strtoul(const char *,char **,unsigned int); 146 + extern unsigned long simple_strntoul(const char *,char **,unsigned int,size_t); 146 147 extern long simple_strtol(const char *,char **,unsigned int); 147 148 extern unsigned long long simple_strtoull(const char *,char **,unsigned int); 148 149 extern long long simple_strtoll(const char *,char **,unsigned int);
+3
init/.kunitconfig
··· 1 + CONFIG_KUNIT=y 2 + CONFIG_BLK_DEV_INITRD=y 3 + CONFIG_INITRAMFS_TEST=y
+7
init/Kconfig
··· 1454 1454 1455 1455 If unsure, say Y. 1456 1456 1457 + config INITRAMFS_TEST 1458 + bool "Test initramfs cpio archive extraction" if !KUNIT_ALL_TESTS 1459 + depends on BLK_DEV_INITRD && KUNIT=y 1460 + default KUNIT_ALL_TESTS 1461 + help 1462 + Build KUnit tests for initramfs. See Documentation/dev-tools/kunit 1463 + 1457 1464 choice 1458 1465 prompt "Compiler optimization level" 1459 1466 default CC_OPTIMIZE_FOR_PERFORMANCE
+1
init/Makefile
··· 12 12 obj-$(CONFIG_BLK_DEV_INITRD) += initramfs.o 13 13 endif 14 14 obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o 15 + obj-$(CONFIG_INITRAMFS_TEST) += initramfs_test.o 15 16 16 17 obj-y += init_task.o 17 18
+38 -28
init/initramfs.c
··· 20 20 #include <linux/security.h> 21 21 22 22 #include "do_mounts.h" 23 + #include "initramfs_internal.h" 23 24 24 25 static __initdata bool csum_present; 25 26 static __initdata u32 io_csum; ··· 76 75 struct hash *next; 77 76 char name[N_ALIGN(PATH_MAX)]; 78 77 } *head[32]; 78 + static __initdata bool hardlink_seen; 79 79 80 80 static inline int hash(int major, int minor, int ino) 81 81 { ··· 110 108 strcpy(q->name, name); 111 109 q->next = NULL; 112 110 *p = q; 111 + hardlink_seen = true; 113 112 return NULL; 114 113 } 115 114 116 115 static void __init free_hash(void) 117 116 { 118 117 struct hash **p, *q; 119 - for (p = head; p < head + 32; p++) { 118 + for (p = head; hardlink_seen && p < head + 32; p++) { 120 119 while (*p) { 121 120 q = *p; 122 121 *p = q->next; 123 122 kfree(q); 124 123 } 125 124 } 125 + hardlink_seen = false; 126 126 } 127 127 128 128 #ifdef CONFIG_INITRAMFS_PRESERVE_MTIME ··· 147 143 char name[]; 148 144 }; 149 145 150 - static void __init dir_add(const char *name, time64_t mtime) 146 + static void __init dir_add(const char *name, size_t nlen, time64_t mtime) 151 147 { 152 - size_t nlen = strlen(name) + 1; 153 148 struct dir_entry *de; 154 149 155 150 de = kmalloc(sizeof(struct dir_entry) + nlen, GFP_KERNEL); ··· 172 169 #else 173 170 static void __init do_utime(char *filename, time64_t mtime) {} 174 171 static void __init do_utime_path(const struct path *path, time64_t mtime) {} 175 - static void __init dir_add(const char *name, time64_t mtime) {} 172 + static void __init dir_add(const char *name, size_t nlen, time64_t mtime) {} 176 173 static void __init dir_utime(void) {} 177 174 #endif 178 175 ··· 191 188 static void __init parse_header(char *s) 192 189 { 193 190 unsigned long parsed[13]; 194 - char buf[9]; 195 191 int i; 196 192 197 - buf[8] = '\0'; 198 - for (i = 0, s += 6; i < 13; i++, s += 8) { 199 - memcpy(buf, s, 8); 200 - parsed[i] = simple_strtoul(buf, NULL, 16); 201 - } 193 + for (i = 0, s += 6; i < 13; i++, s += 8) 194 + parsed[i] = simple_strntoul(s, NULL, 16, 8); 195 + 202 196 ino = parsed[0]; 203 197 mode = parsed[1]; 204 198 uid = parsed[2]; ··· 256 256 257 257 static int __init do_start(void) 258 258 { 259 - read_into(header_buf, 110, GotHeader); 259 + read_into(header_buf, CPIO_HDRLEN, GotHeader); 260 260 return 0; 261 261 } 262 262 ··· 396 396 init_mkdir(collected, mode); 397 397 init_chown(collected, uid, gid, 0); 398 398 init_chmod(collected, mode); 399 - dir_add(collected, mtime); 399 + dir_add(collected, name_len, mtime); 400 400 } else if (S_ISBLK(mode) || S_ISCHR(mode) || 401 401 S_ISFIFO(mode) || S_ISSOCK(mode)) { 402 402 if (maybe_link() == 0) { ··· 497 497 498 498 #include <linux/decompress/generic.h> 499 499 500 - static char * __init unpack_to_rootfs(char *buf, unsigned long len) 500 + /** 501 + * unpack_to_rootfs - decompress and extract an initramfs archive 502 + * @buf: input initramfs archive to extract 503 + * @len: length of initramfs data to process 504 + * 505 + * Returns: NULL for success or an error message string 506 + * 507 + * This symbol shouldn't be used externally. It's available for unit tests. 508 + */ 509 + char * __init unpack_to_rootfs(char *buf, unsigned long len) 501 510 { 502 511 long written; 503 512 decompress_fn decompress; 504 513 const char *compress_name; 505 - static __initdata char msg_buf[64]; 514 + struct { 515 + char header[CPIO_HDRLEN]; 516 + char symlink[PATH_MAX + N_ALIGN(PATH_MAX) + 1]; 517 + char name[N_ALIGN(PATH_MAX)]; 518 + } *bufs = kmalloc(sizeof(*bufs), GFP_KERNEL); 506 519 507 - header_buf = kmalloc(110, GFP_KERNEL); 508 - symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL); 509 - name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL); 510 - 511 - if (!header_buf || !symlink_buf || !name_buf) 520 + if (!bufs) 512 521 panic_show_mem("can't allocate buffers"); 522 + 523 + header_buf = bufs->header; 524 + symlink_buf = bufs->symlink; 525 + name_buf = bufs->name; 513 526 514 527 state = Start; 515 528 this_header = 0; ··· 551 538 if (res) 552 539 error("decompressor failed"); 553 540 } else if (compress_name) { 554 - if (!message) { 555 - snprintf(msg_buf, sizeof msg_buf, 556 - "compression method %s not configured", 557 - compress_name); 558 - message = msg_buf; 559 - } 541 + pr_err("compression method %s not configured\n", 542 + compress_name); 543 + error("decompressor failed"); 560 544 } else 561 545 error("invalid magic at start of compressed archive"); 562 546 if (state != Reset) ··· 563 553 len -= my_inptr; 564 554 } 565 555 dir_utime(); 566 - kfree(name_buf); 567 - kfree(symlink_buf); 568 - kfree(header_buf); 556 + /* free any hardlink state collected without optional TRAILER!!! */ 557 + free_hash(); 558 + kfree(bufs); 569 559 return message; 570 560 } 571 561
+8
init/initramfs_internal.h
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #ifndef __INITRAMFS_INTERNAL_H__ 3 + #define __INITRAMFS_INTERNAL_H__ 4 + 5 + char *unpack_to_rootfs(char *buf, unsigned long len); 6 + #define CPIO_HDRLEN 110 7 + 8 + #endif
+407
init/initramfs_test.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + #include <kunit/test.h> 3 + #include <linux/fcntl.h> 4 + #include <linux/file.h> 5 + #include <linux/fs.h> 6 + #include <linux/init_syscalls.h> 7 + #include <linux/stringify.h> 8 + #include <linux/timekeeping.h> 9 + #include "initramfs_internal.h" 10 + 11 + struct initramfs_test_cpio { 12 + char *magic; 13 + unsigned int ino; 14 + unsigned int mode; 15 + unsigned int uid; 16 + unsigned int gid; 17 + unsigned int nlink; 18 + unsigned int mtime; 19 + unsigned int filesize; 20 + unsigned int devmajor; 21 + unsigned int devminor; 22 + unsigned int rdevmajor; 23 + unsigned int rdevminor; 24 + unsigned int namesize; 25 + unsigned int csum; 26 + char *fname; 27 + char *data; 28 + }; 29 + 30 + static size_t fill_cpio(struct initramfs_test_cpio *cs, size_t csz, char *out) 31 + { 32 + int i; 33 + size_t off = 0; 34 + 35 + for (i = 0; i < csz; i++) { 36 + char *pos = &out[off]; 37 + struct initramfs_test_cpio *c = &cs[i]; 38 + size_t thislen; 39 + 40 + /* +1 to account for nulterm */ 41 + thislen = sprintf(pos, "%s" 42 + "%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x" 43 + "%s", 44 + c->magic, c->ino, c->mode, c->uid, c->gid, c->nlink, 45 + c->mtime, c->filesize, c->devmajor, c->devminor, 46 + c->rdevmajor, c->rdevminor, c->namesize, c->csum, 47 + c->fname) + 1; 48 + pr_debug("packing (%zu): %.*s\n", thislen, (int)thislen, pos); 49 + off += thislen; 50 + while (off & 3) 51 + out[off++] = '\0'; 52 + 53 + memcpy(&out[off], c->data, c->filesize); 54 + off += c->filesize; 55 + while (off & 3) 56 + out[off++] = '\0'; 57 + } 58 + 59 + return off; 60 + } 61 + 62 + static void __init initramfs_test_extract(struct kunit *test) 63 + { 64 + char *err, *cpio_srcbuf; 65 + size_t len; 66 + struct timespec64 ts_before, ts_after; 67 + struct kstat st = {}; 68 + struct initramfs_test_cpio c[] = { { 69 + .magic = "070701", 70 + .ino = 1, 71 + .mode = S_IFREG | 0777, 72 + .uid = 12, 73 + .gid = 34, 74 + .nlink = 1, 75 + .mtime = 56, 76 + .filesize = 0, 77 + .devmajor = 0, 78 + .devminor = 1, 79 + .rdevmajor = 0, 80 + .rdevminor = 0, 81 + .namesize = sizeof("initramfs_test_extract"), 82 + .csum = 0, 83 + .fname = "initramfs_test_extract", 84 + }, { 85 + .magic = "070701", 86 + .ino = 2, 87 + .mode = S_IFDIR | 0777, 88 + .nlink = 1, 89 + .mtime = 57, 90 + .devminor = 1, 91 + .namesize = sizeof("initramfs_test_extract_dir"), 92 + .fname = "initramfs_test_extract_dir", 93 + }, { 94 + .magic = "070701", 95 + .namesize = sizeof("TRAILER!!!"), 96 + .fname = "TRAILER!!!", 97 + } }; 98 + 99 + /* +3 to cater for any 4-byte end-alignment */ 100 + cpio_srcbuf = kzalloc(ARRAY_SIZE(c) * (CPIO_HDRLEN + PATH_MAX + 3), 101 + GFP_KERNEL); 102 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 103 + 104 + ktime_get_real_ts64(&ts_before); 105 + err = unpack_to_rootfs(cpio_srcbuf, len); 106 + ktime_get_real_ts64(&ts_after); 107 + if (err) { 108 + KUNIT_FAIL(test, "unpack failed %s", err); 109 + goto out; 110 + } 111 + 112 + KUNIT_EXPECT_EQ(test, init_stat(c[0].fname, &st, 0), 0); 113 + KUNIT_EXPECT_TRUE(test, S_ISREG(st.mode)); 114 + KUNIT_EXPECT_TRUE(test, uid_eq(st.uid, KUIDT_INIT(c[0].uid))); 115 + KUNIT_EXPECT_TRUE(test, gid_eq(st.gid, KGIDT_INIT(c[0].gid))); 116 + KUNIT_EXPECT_EQ(test, st.nlink, 1); 117 + if (IS_ENABLED(CONFIG_INITRAMFS_PRESERVE_MTIME)) { 118 + KUNIT_EXPECT_EQ(test, st.mtime.tv_sec, c[0].mtime); 119 + } else { 120 + KUNIT_EXPECT_GE(test, st.mtime.tv_sec, ts_before.tv_sec); 121 + KUNIT_EXPECT_LE(test, st.mtime.tv_sec, ts_after.tv_sec); 122 + } 123 + KUNIT_EXPECT_EQ(test, st.blocks, c[0].filesize); 124 + 125 + KUNIT_EXPECT_EQ(test, init_stat(c[1].fname, &st, 0), 0); 126 + KUNIT_EXPECT_TRUE(test, S_ISDIR(st.mode)); 127 + if (IS_ENABLED(CONFIG_INITRAMFS_PRESERVE_MTIME)) { 128 + KUNIT_EXPECT_EQ(test, st.mtime.tv_sec, c[1].mtime); 129 + } else { 130 + KUNIT_EXPECT_GE(test, st.mtime.tv_sec, ts_before.tv_sec); 131 + KUNIT_EXPECT_LE(test, st.mtime.tv_sec, ts_after.tv_sec); 132 + } 133 + 134 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 135 + KUNIT_EXPECT_EQ(test, init_rmdir(c[1].fname), 0); 136 + out: 137 + kfree(cpio_srcbuf); 138 + } 139 + 140 + /* 141 + * Don't terminate filename. Previously, the cpio filename field was passed 142 + * directly to filp_open(collected, O_CREAT|..) without nulterm checks. See 143 + * https://lore.kernel.org/linux-fsdevel/20241030035509.20194-2-ddiss@suse.de 144 + */ 145 + static void __init initramfs_test_fname_overrun(struct kunit *test) 146 + { 147 + char *err, *cpio_srcbuf; 148 + size_t len, suffix_off; 149 + struct initramfs_test_cpio c[] = { { 150 + .magic = "070701", 151 + .ino = 1, 152 + .mode = S_IFREG | 0777, 153 + .uid = 0, 154 + .gid = 0, 155 + .nlink = 1, 156 + .mtime = 1, 157 + .filesize = 0, 158 + .devmajor = 0, 159 + .devminor = 1, 160 + .rdevmajor = 0, 161 + .rdevminor = 0, 162 + .namesize = sizeof("initramfs_test_fname_overrun"), 163 + .csum = 0, 164 + .fname = "initramfs_test_fname_overrun", 165 + } }; 166 + 167 + /* 168 + * poison cpio source buffer, so we can detect overrun. source 169 + * buffer is used by read_into() when hdr or fname 170 + * are already available (e.g. no compression). 171 + */ 172 + cpio_srcbuf = kmalloc(CPIO_HDRLEN + PATH_MAX + 3, GFP_KERNEL); 173 + memset(cpio_srcbuf, 'B', CPIO_HDRLEN + PATH_MAX + 3); 174 + /* limit overrun to avoid crashes / filp_open() ENAMETOOLONG */ 175 + cpio_srcbuf[CPIO_HDRLEN + strlen(c[0].fname) + 20] = '\0'; 176 + 177 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 178 + /* overwrite trailing fname terminator and padding */ 179 + suffix_off = len - 1; 180 + while (cpio_srcbuf[suffix_off] == '\0') { 181 + cpio_srcbuf[suffix_off] = 'P'; 182 + suffix_off--; 183 + } 184 + 185 + err = unpack_to_rootfs(cpio_srcbuf, len); 186 + KUNIT_EXPECT_NOT_NULL(test, err); 187 + 188 + kfree(cpio_srcbuf); 189 + } 190 + 191 + static void __init initramfs_test_data(struct kunit *test) 192 + { 193 + char *err, *cpio_srcbuf; 194 + size_t len; 195 + struct file *file; 196 + struct initramfs_test_cpio c[] = { { 197 + .magic = "070701", 198 + .ino = 1, 199 + .mode = S_IFREG | 0777, 200 + .uid = 0, 201 + .gid = 0, 202 + .nlink = 1, 203 + .mtime = 1, 204 + .filesize = sizeof("ASDF") - 1, 205 + .devmajor = 0, 206 + .devminor = 1, 207 + .rdevmajor = 0, 208 + .rdevminor = 0, 209 + .namesize = sizeof("initramfs_test_data"), 210 + .csum = 0, 211 + .fname = "initramfs_test_data", 212 + .data = "ASDF", 213 + } }; 214 + 215 + /* +6 for max name and data 4-byte padding */ 216 + cpio_srcbuf = kmalloc(CPIO_HDRLEN + c[0].namesize + c[0].filesize + 6, 217 + GFP_KERNEL); 218 + 219 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 220 + 221 + err = unpack_to_rootfs(cpio_srcbuf, len); 222 + KUNIT_EXPECT_NULL(test, err); 223 + 224 + file = filp_open(c[0].fname, O_RDONLY, 0); 225 + if (IS_ERR(file)) { 226 + KUNIT_FAIL(test, "open failed"); 227 + goto out; 228 + } 229 + 230 + /* read back file contents into @cpio_srcbuf and confirm match */ 231 + len = kernel_read(file, cpio_srcbuf, c[0].filesize, NULL); 232 + KUNIT_EXPECT_EQ(test, len, c[0].filesize); 233 + KUNIT_EXPECT_MEMEQ(test, cpio_srcbuf, c[0].data, len); 234 + 235 + fput(file); 236 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 237 + out: 238 + kfree(cpio_srcbuf); 239 + } 240 + 241 + static void __init initramfs_test_csum(struct kunit *test) 242 + { 243 + char *err, *cpio_srcbuf; 244 + size_t len; 245 + struct initramfs_test_cpio c[] = { { 246 + /* 070702 magic indicates a valid csum is present */ 247 + .magic = "070702", 248 + .ino = 1, 249 + .mode = S_IFREG | 0777, 250 + .nlink = 1, 251 + .filesize = sizeof("ASDF") - 1, 252 + .devminor = 1, 253 + .namesize = sizeof("initramfs_test_csum"), 254 + .csum = 'A' + 'S' + 'D' + 'F', 255 + .fname = "initramfs_test_csum", 256 + .data = "ASDF", 257 + }, { 258 + /* mix csum entry above with no-csum entry below */ 259 + .magic = "070701", 260 + .ino = 2, 261 + .mode = S_IFREG | 0777, 262 + .nlink = 1, 263 + .filesize = sizeof("ASDF") - 1, 264 + .devminor = 1, 265 + .namesize = sizeof("initramfs_test_csum_not_here"), 266 + /* csum ignored */ 267 + .csum = 5555, 268 + .fname = "initramfs_test_csum_not_here", 269 + .data = "ASDF", 270 + } }; 271 + 272 + cpio_srcbuf = kmalloc(8192, GFP_KERNEL); 273 + 274 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 275 + 276 + err = unpack_to_rootfs(cpio_srcbuf, len); 277 + KUNIT_EXPECT_NULL(test, err); 278 + 279 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 280 + KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), 0); 281 + 282 + /* mess up the csum and confirm that unpack fails */ 283 + c[0].csum--; 284 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 285 + 286 + err = unpack_to_rootfs(cpio_srcbuf, len); 287 + KUNIT_EXPECT_NOT_NULL(test, err); 288 + 289 + /* 290 + * file (with content) is still retained in case of bad-csum abort. 291 + * Perhaps we should change this. 292 + */ 293 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 294 + KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), -ENOENT); 295 + kfree(cpio_srcbuf); 296 + } 297 + 298 + /* 299 + * hardlink hashtable may leak when the archive omits a trailer: 300 + * https://lore.kernel.org/r/20241107002044.16477-10-ddiss@suse.de/ 301 + */ 302 + static void __init initramfs_test_hardlink(struct kunit *test) 303 + { 304 + char *err, *cpio_srcbuf; 305 + size_t len; 306 + struct kstat st0, st1; 307 + struct initramfs_test_cpio c[] = { { 308 + .magic = "070701", 309 + .ino = 1, 310 + .mode = S_IFREG | 0777, 311 + .nlink = 2, 312 + .devminor = 1, 313 + .namesize = sizeof("initramfs_test_hardlink"), 314 + .fname = "initramfs_test_hardlink", 315 + }, { 316 + /* hardlink data is present in last archive entry */ 317 + .magic = "070701", 318 + .ino = 1, 319 + .mode = S_IFREG | 0777, 320 + .nlink = 2, 321 + .filesize = sizeof("ASDF") - 1, 322 + .devminor = 1, 323 + .namesize = sizeof("initramfs_test_hardlink_link"), 324 + .fname = "initramfs_test_hardlink_link", 325 + .data = "ASDF", 326 + } }; 327 + 328 + cpio_srcbuf = kmalloc(8192, GFP_KERNEL); 329 + 330 + len = fill_cpio(c, ARRAY_SIZE(c), cpio_srcbuf); 331 + 332 + err = unpack_to_rootfs(cpio_srcbuf, len); 333 + KUNIT_EXPECT_NULL(test, err); 334 + 335 + KUNIT_EXPECT_EQ(test, init_stat(c[0].fname, &st0, 0), 0); 336 + KUNIT_EXPECT_EQ(test, init_stat(c[1].fname, &st1, 0), 0); 337 + KUNIT_EXPECT_EQ(test, st0.ino, st1.ino); 338 + KUNIT_EXPECT_EQ(test, st0.nlink, 2); 339 + KUNIT_EXPECT_EQ(test, st1.nlink, 2); 340 + 341 + KUNIT_EXPECT_EQ(test, init_unlink(c[0].fname), 0); 342 + KUNIT_EXPECT_EQ(test, init_unlink(c[1].fname), 0); 343 + 344 + kfree(cpio_srcbuf); 345 + } 346 + 347 + #define INITRAMFS_TEST_MANY_LIMIT 1000 348 + #define INITRAMFS_TEST_MANY_PATH_MAX (sizeof("initramfs_test_many-") \ 349 + + sizeof(__stringify(INITRAMFS_TEST_MANY_LIMIT))) 350 + static void __init initramfs_test_many(struct kunit *test) 351 + { 352 + char *err, *cpio_srcbuf, *p; 353 + size_t len = INITRAMFS_TEST_MANY_LIMIT * 354 + (CPIO_HDRLEN + INITRAMFS_TEST_MANY_PATH_MAX + 3); 355 + char thispath[INITRAMFS_TEST_MANY_PATH_MAX]; 356 + int i; 357 + 358 + p = cpio_srcbuf = kmalloc(len, GFP_KERNEL); 359 + 360 + for (i = 0; i < INITRAMFS_TEST_MANY_LIMIT; i++) { 361 + struct initramfs_test_cpio c = { 362 + .magic = "070701", 363 + .ino = i, 364 + .mode = S_IFREG | 0777, 365 + .nlink = 1, 366 + .devminor = 1, 367 + .fname = thispath, 368 + }; 369 + 370 + c.namesize = 1 + sprintf(thispath, "initramfs_test_many-%d", i); 371 + p += fill_cpio(&c, 1, p); 372 + } 373 + 374 + len = p - cpio_srcbuf; 375 + err = unpack_to_rootfs(cpio_srcbuf, len); 376 + KUNIT_EXPECT_NULL(test, err); 377 + 378 + for (i = 0; i < INITRAMFS_TEST_MANY_LIMIT; i++) { 379 + sprintf(thispath, "initramfs_test_many-%d", i); 380 + KUNIT_EXPECT_EQ(test, init_unlink(thispath), 0); 381 + } 382 + 383 + kfree(cpio_srcbuf); 384 + } 385 + 386 + /* 387 + * The kunit_case/_suite struct cannot be marked as __initdata as this will be 388 + * used in debugfs to retrieve results after test has run. 389 + */ 390 + static struct kunit_case __refdata initramfs_test_cases[] = { 391 + KUNIT_CASE(initramfs_test_extract), 392 + KUNIT_CASE(initramfs_test_fname_overrun), 393 + KUNIT_CASE(initramfs_test_data), 394 + KUNIT_CASE(initramfs_test_csum), 395 + KUNIT_CASE(initramfs_test_hardlink), 396 + KUNIT_CASE(initramfs_test_many), 397 + {}, 398 + }; 399 + 400 + static struct kunit_suite initramfs_test_suite = { 401 + .name = "initramfs", 402 + .test_cases = initramfs_test_cases, 403 + }; 404 + kunit_test_init_section_suites(&initramfs_test_suite); 405 + 406 + MODULE_DESCRIPTION("Initramfs KUnit test suite"); 407 + MODULE_LICENSE("GPL v2");
+7
lib/vsprintf.c
··· 114 114 } 115 115 EXPORT_SYMBOL(simple_strtoul); 116 116 117 + unsigned long simple_strntoul(const char *cp, char **endp, unsigned int base, 118 + size_t max_chars) 119 + { 120 + return simple_strntoull(cp, endp, base, max_chars); 121 + } 122 + EXPORT_SYMBOL(simple_strntoul); 123 + 117 124 /** 118 125 * simple_strtol - convert a string to a signed long 119 126 * @cp: The start of the string