Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/init/initramfs.c
26131 views
1
// SPDX-License-Identifier: GPL-2.0
2
#include <linux/init.h>
3
#include <linux/async.h>
4
#include <linux/export.h>
5
#include <linux/fs.h>
6
#include <linux/slab.h>
7
#include <linux/types.h>
8
#include <linux/fcntl.h>
9
#include <linux/delay.h>
10
#include <linux/string.h>
11
#include <linux/dirent.h>
12
#include <linux/syscalls.h>
13
#include <linux/utime.h>
14
#include <linux/file.h>
15
#include <linux/kstrtox.h>
16
#include <linux/memblock.h>
17
#include <linux/mm.h>
18
#include <linux/namei.h>
19
#include <linux/init_syscalls.h>
20
#include <linux/umh.h>
21
#include <linux/security.h>
22
23
#include "do_mounts.h"
24
#include "initramfs_internal.h"
25
26
static __initdata bool csum_present;
27
static __initdata u32 io_csum;
28
29
static ssize_t __init xwrite(struct file *file, const unsigned char *p,
30
size_t count, loff_t *pos)
31
{
32
ssize_t out = 0;
33
34
/* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
35
while (count) {
36
ssize_t rv = kernel_write(file, p, count, pos);
37
38
if (rv < 0) {
39
if (rv == -EINTR || rv == -EAGAIN)
40
continue;
41
return out ? out : rv;
42
} else if (rv == 0)
43
break;
44
45
if (csum_present) {
46
ssize_t i;
47
48
for (i = 0; i < rv; i++)
49
io_csum += p[i];
50
}
51
52
p += rv;
53
out += rv;
54
count -= rv;
55
}
56
57
return out;
58
}
59
60
static __initdata char *message;
61
static void __init error(char *x)
62
{
63
if (!message)
64
message = x;
65
}
66
67
#define panic_show_mem(fmt, ...) \
68
({ show_mem(); panic(fmt, ##__VA_ARGS__); })
69
70
/* link hash */
71
72
#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
73
74
static __initdata struct hash {
75
int ino, minor, major;
76
umode_t mode;
77
struct hash *next;
78
char name[N_ALIGN(PATH_MAX)];
79
} *head[32];
80
static __initdata bool hardlink_seen;
81
82
static inline int hash(int major, int minor, int ino)
83
{
84
unsigned long tmp = ino + minor + (major << 3);
85
tmp += tmp >> 5;
86
return tmp & 31;
87
}
88
89
static char __init *find_link(int major, int minor, int ino,
90
umode_t mode, char *name)
91
{
92
struct hash **p, *q;
93
for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
94
if ((*p)->ino != ino)
95
continue;
96
if ((*p)->minor != minor)
97
continue;
98
if ((*p)->major != major)
99
continue;
100
if (((*p)->mode ^ mode) & S_IFMT)
101
continue;
102
return (*p)->name;
103
}
104
q = kmalloc(sizeof(struct hash), GFP_KERNEL);
105
if (!q)
106
panic_show_mem("can't allocate link hash entry");
107
q->major = major;
108
q->minor = minor;
109
q->ino = ino;
110
q->mode = mode;
111
strcpy(q->name, name);
112
q->next = NULL;
113
*p = q;
114
hardlink_seen = true;
115
return NULL;
116
}
117
118
static void __init free_hash(void)
119
{
120
struct hash **p, *q;
121
for (p = head; hardlink_seen && p < head + 32; p++) {
122
while (*p) {
123
q = *p;
124
*p = q->next;
125
kfree(q);
126
}
127
}
128
hardlink_seen = false;
129
}
130
131
#ifdef CONFIG_INITRAMFS_PRESERVE_MTIME
132
static void __init do_utime(char *filename, time64_t mtime)
133
{
134
struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };
135
init_utimes(filename, t);
136
}
137
138
static void __init do_utime_path(const struct path *path, time64_t mtime)
139
{
140
struct timespec64 t[2] = { { .tv_sec = mtime }, { .tv_sec = mtime } };
141
vfs_utimes(path, t);
142
}
143
144
static __initdata LIST_HEAD(dir_list);
145
struct dir_entry {
146
struct list_head list;
147
time64_t mtime;
148
char name[];
149
};
150
151
static void __init dir_add(const char *name, size_t nlen, time64_t mtime)
152
{
153
struct dir_entry *de;
154
155
de = kmalloc(sizeof(struct dir_entry) + nlen, GFP_KERNEL);
156
if (!de)
157
panic_show_mem("can't allocate dir_entry buffer");
158
INIT_LIST_HEAD(&de->list);
159
strscpy(de->name, name, nlen);
160
de->mtime = mtime;
161
list_add(&de->list, &dir_list);
162
}
163
164
static void __init dir_utime(void)
165
{
166
struct dir_entry *de, *tmp;
167
list_for_each_entry_safe(de, tmp, &dir_list, list) {
168
list_del(&de->list);
169
do_utime(de->name, de->mtime);
170
kfree(de);
171
}
172
}
173
#else
174
static void __init do_utime(char *filename, time64_t mtime) {}
175
static void __init do_utime_path(const struct path *path, time64_t mtime) {}
176
static void __init dir_add(const char *name, size_t nlen, time64_t mtime) {}
177
static void __init dir_utime(void) {}
178
#endif
179
180
static __initdata time64_t mtime;
181
182
/* cpio header parsing */
183
184
static __initdata unsigned long ino, major, minor, nlink;
185
static __initdata umode_t mode;
186
static __initdata unsigned long body_len, name_len;
187
static __initdata uid_t uid;
188
static __initdata gid_t gid;
189
static __initdata unsigned rdev;
190
static __initdata u32 hdr_csum;
191
192
static void __init parse_header(char *s)
193
{
194
unsigned long parsed[13];
195
int i;
196
197
for (i = 0, s += 6; i < 13; i++, s += 8)
198
parsed[i] = simple_strntoul(s, NULL, 16, 8);
199
200
ino = parsed[0];
201
mode = parsed[1];
202
uid = parsed[2];
203
gid = parsed[3];
204
nlink = parsed[4];
205
mtime = parsed[5]; /* breaks in y2106 */
206
body_len = parsed[6];
207
major = parsed[7];
208
minor = parsed[8];
209
rdev = new_encode_dev(MKDEV(parsed[9], parsed[10]));
210
name_len = parsed[11];
211
hdr_csum = parsed[12];
212
}
213
214
/* FSM */
215
216
static __initdata enum state {
217
Start,
218
Collect,
219
GotHeader,
220
SkipIt,
221
GotName,
222
CopyFile,
223
GotSymlink,
224
Reset
225
} state, next_state;
226
227
static __initdata char *victim;
228
static unsigned long byte_count __initdata;
229
static __initdata loff_t this_header, next_header;
230
231
static inline void __init eat(unsigned n)
232
{
233
victim += n;
234
this_header += n;
235
byte_count -= n;
236
}
237
238
static __initdata char *collected;
239
static long remains __initdata;
240
static __initdata char *collect;
241
242
static void __init read_into(char *buf, unsigned size, enum state next)
243
{
244
if (byte_count >= size) {
245
collected = victim;
246
eat(size);
247
state = next;
248
} else {
249
collect = collected = buf;
250
remains = size;
251
next_state = next;
252
state = Collect;
253
}
254
}
255
256
static __initdata char *header_buf, *symlink_buf, *name_buf;
257
258
static int __init do_start(void)
259
{
260
read_into(header_buf, CPIO_HDRLEN, GotHeader);
261
return 0;
262
}
263
264
static int __init do_collect(void)
265
{
266
unsigned long n = remains;
267
if (byte_count < n)
268
n = byte_count;
269
memcpy(collect, victim, n);
270
eat(n);
271
collect += n;
272
if ((remains -= n) != 0)
273
return 1;
274
state = next_state;
275
return 0;
276
}
277
278
static int __init do_header(void)
279
{
280
if (!memcmp(collected, "070701", 6)) {
281
csum_present = false;
282
} else if (!memcmp(collected, "070702", 6)) {
283
csum_present = true;
284
} else {
285
if (memcmp(collected, "070707", 6) == 0)
286
error("incorrect cpio method used: use -H newc option");
287
else
288
error("no cpio magic");
289
return 1;
290
}
291
parse_header(collected);
292
next_header = this_header + N_ALIGN(name_len) + body_len;
293
next_header = (next_header + 3) & ~3;
294
state = SkipIt;
295
if (name_len <= 0 || name_len > PATH_MAX)
296
return 0;
297
if (S_ISLNK(mode)) {
298
if (body_len > PATH_MAX)
299
return 0;
300
collect = collected = symlink_buf;
301
remains = N_ALIGN(name_len) + body_len;
302
next_state = GotSymlink;
303
state = Collect;
304
return 0;
305
}
306
if (S_ISREG(mode) || !body_len)
307
read_into(name_buf, N_ALIGN(name_len), GotName);
308
return 0;
309
}
310
311
static int __init do_skip(void)
312
{
313
if (this_header + byte_count < next_header) {
314
eat(byte_count);
315
return 1;
316
} else {
317
eat(next_header - this_header);
318
state = next_state;
319
return 0;
320
}
321
}
322
323
static int __init do_reset(void)
324
{
325
while (byte_count && *victim == '\0')
326
eat(1);
327
if (byte_count && (this_header & 3))
328
error("broken padding");
329
return 1;
330
}
331
332
static void __init clean_path(char *path, umode_t fmode)
333
{
334
struct kstat st;
335
336
if (!init_stat(path, &st, AT_SYMLINK_NOFOLLOW) &&
337
(st.mode ^ fmode) & S_IFMT) {
338
if (S_ISDIR(st.mode))
339
init_rmdir(path);
340
else
341
init_unlink(path);
342
}
343
}
344
345
static int __init maybe_link(void)
346
{
347
if (nlink >= 2) {
348
char *old = find_link(major, minor, ino, mode, collected);
349
if (old) {
350
clean_path(collected, 0);
351
return (init_link(old, collected) < 0) ? -1 : 1;
352
}
353
}
354
return 0;
355
}
356
357
static __initdata struct file *wfile;
358
static __initdata loff_t wfile_pos;
359
360
static int __init do_name(void)
361
{
362
state = SkipIt;
363
next_state = Reset;
364
365
/* name_len > 0 && name_len <= PATH_MAX checked in do_header */
366
if (collected[name_len - 1] != '\0') {
367
pr_err("initramfs name without nulterm: %.*s\n",
368
(int)name_len, collected);
369
error("malformed archive");
370
return 1;
371
}
372
373
if (strcmp(collected, "TRAILER!!!") == 0) {
374
free_hash();
375
return 0;
376
}
377
clean_path(collected, mode);
378
if (S_ISREG(mode)) {
379
int ml = maybe_link();
380
if (ml >= 0) {
381
int openflags = O_WRONLY|O_CREAT|O_LARGEFILE;
382
if (ml != 1)
383
openflags |= O_TRUNC;
384
wfile = filp_open(collected, openflags, mode);
385
if (IS_ERR(wfile))
386
return 0;
387
wfile_pos = 0;
388
io_csum = 0;
389
390
vfs_fchown(wfile, uid, gid);
391
vfs_fchmod(wfile, mode);
392
if (body_len)
393
vfs_truncate(&wfile->f_path, body_len);
394
state = CopyFile;
395
}
396
} else if (S_ISDIR(mode)) {
397
init_mkdir(collected, mode);
398
init_chown(collected, uid, gid, 0);
399
init_chmod(collected, mode);
400
dir_add(collected, name_len, mtime);
401
} else if (S_ISBLK(mode) || S_ISCHR(mode) ||
402
S_ISFIFO(mode) || S_ISSOCK(mode)) {
403
if (maybe_link() == 0) {
404
init_mknod(collected, mode, rdev);
405
init_chown(collected, uid, gid, 0);
406
init_chmod(collected, mode);
407
do_utime(collected, mtime);
408
}
409
}
410
return 0;
411
}
412
413
static int __init do_copy(void)
414
{
415
if (byte_count >= body_len) {
416
if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
417
error("write error");
418
419
do_utime_path(&wfile->f_path, mtime);
420
fput(wfile);
421
if (csum_present && io_csum != hdr_csum)
422
error("bad data checksum");
423
eat(body_len);
424
state = SkipIt;
425
return 0;
426
} else {
427
if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
428
error("write error");
429
body_len -= byte_count;
430
eat(byte_count);
431
return 1;
432
}
433
}
434
435
static int __init do_symlink(void)
436
{
437
if (collected[name_len - 1] != '\0') {
438
pr_err("initramfs symlink without nulterm: %.*s\n",
439
(int)name_len, collected);
440
error("malformed archive");
441
return 1;
442
}
443
collected[N_ALIGN(name_len) + body_len] = '\0';
444
clean_path(collected, 0);
445
init_symlink(collected + N_ALIGN(name_len), collected);
446
init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
447
do_utime(collected, mtime);
448
state = SkipIt;
449
next_state = Reset;
450
return 0;
451
}
452
453
static __initdata int (*actions[])(void) = {
454
[Start] = do_start,
455
[Collect] = do_collect,
456
[GotHeader] = do_header,
457
[SkipIt] = do_skip,
458
[GotName] = do_name,
459
[CopyFile] = do_copy,
460
[GotSymlink] = do_symlink,
461
[Reset] = do_reset,
462
};
463
464
static long __init write_buffer(char *buf, unsigned long len)
465
{
466
byte_count = len;
467
victim = buf;
468
469
while (!actions[state]())
470
;
471
return len - byte_count;
472
}
473
474
static long __init flush_buffer(void *bufv, unsigned long len)
475
{
476
char *buf = bufv;
477
long written;
478
long origLen = len;
479
if (message)
480
return -1;
481
while ((written = write_buffer(buf, len)) < len && !message) {
482
char c = buf[written];
483
if (c == '0') {
484
buf += written;
485
len -= written;
486
state = Start;
487
} else if (c == 0) {
488
buf += written;
489
len -= written;
490
state = Reset;
491
} else
492
error("junk within compressed archive");
493
}
494
return origLen;
495
}
496
497
static unsigned long my_inptr __initdata; /* index of next byte to be processed in inbuf */
498
499
#include <linux/decompress/generic.h>
500
501
/**
502
* unpack_to_rootfs - decompress and extract an initramfs archive
503
* @buf: input initramfs archive to extract
504
* @len: length of initramfs data to process
505
*
506
* Returns: NULL for success or an error message string
507
*
508
* This symbol shouldn't be used externally. It's available for unit tests.
509
*/
510
char * __init unpack_to_rootfs(char *buf, unsigned long len)
511
{
512
long written;
513
decompress_fn decompress;
514
const char *compress_name;
515
struct {
516
char header[CPIO_HDRLEN];
517
char symlink[PATH_MAX + N_ALIGN(PATH_MAX) + 1];
518
char name[N_ALIGN(PATH_MAX)];
519
} *bufs = kmalloc(sizeof(*bufs), GFP_KERNEL);
520
521
if (!bufs)
522
panic_show_mem("can't allocate buffers");
523
524
header_buf = bufs->header;
525
symlink_buf = bufs->symlink;
526
name_buf = bufs->name;
527
528
state = Start;
529
this_header = 0;
530
message = NULL;
531
while (!message && len) {
532
loff_t saved_offset = this_header;
533
if (*buf == '0' && !(this_header & 3)) {
534
state = Start;
535
written = write_buffer(buf, len);
536
buf += written;
537
len -= written;
538
continue;
539
}
540
if (!*buf) {
541
buf++;
542
len--;
543
this_header++;
544
continue;
545
}
546
this_header = 0;
547
decompress = decompress_method(buf, len, &compress_name);
548
pr_debug("Detected %s compressed data\n", compress_name);
549
if (decompress) {
550
int res = decompress(buf, len, NULL, flush_buffer, NULL,
551
&my_inptr, error);
552
if (res)
553
error("decompressor failed");
554
} else if (compress_name) {
555
pr_err("compression method %s not configured\n",
556
compress_name);
557
error("decompressor failed");
558
} else
559
error("invalid magic at start of compressed archive");
560
if (state != Reset)
561
error("junk at the end of compressed archive");
562
this_header = saved_offset + my_inptr;
563
buf += my_inptr;
564
len -= my_inptr;
565
}
566
dir_utime();
567
/* free any hardlink state collected without optional TRAILER!!! */
568
free_hash();
569
kfree(bufs);
570
return message;
571
}
572
573
static int __initdata do_retain_initrd;
574
575
static int __init retain_initrd_param(char *str)
576
{
577
if (*str)
578
return 0;
579
do_retain_initrd = 1;
580
return 1;
581
}
582
__setup("retain_initrd", retain_initrd_param);
583
584
#ifdef CONFIG_ARCH_HAS_KEEPINITRD
585
static int __init keepinitrd_setup(char *__unused)
586
{
587
do_retain_initrd = 1;
588
return 1;
589
}
590
__setup("keepinitrd", keepinitrd_setup);
591
#endif
592
593
static bool __initdata initramfs_async = true;
594
static int __init initramfs_async_setup(char *str)
595
{
596
return kstrtobool(str, &initramfs_async) == 0;
597
}
598
__setup("initramfs_async=", initramfs_async_setup);
599
600
extern char __initramfs_start[];
601
extern unsigned long __initramfs_size;
602
#include <linux/initrd.h>
603
#include <linux/kexec.h>
604
605
static BIN_ATTR(initrd, 0440, sysfs_bin_attr_simple_read, NULL, 0);
606
607
void __init reserve_initrd_mem(void)
608
{
609
phys_addr_t start;
610
unsigned long size;
611
612
/* Ignore the virtul address computed during device tree parsing */
613
initrd_start = initrd_end = 0;
614
615
if (!phys_initrd_size)
616
return;
617
/*
618
* Round the memory region to page boundaries as per free_initrd_mem()
619
* This allows us to detect whether the pages overlapping the initrd
620
* are in use, but more importantly, reserves the entire set of pages
621
* as we don't want these pages allocated for other purposes.
622
*/
623
start = round_down(phys_initrd_start, PAGE_SIZE);
624
size = phys_initrd_size + (phys_initrd_start - start);
625
size = round_up(size, PAGE_SIZE);
626
627
if (!memblock_is_region_memory(start, size)) {
628
pr_err("INITRD: 0x%08llx+0x%08lx is not a memory region",
629
(u64)start, size);
630
goto disable;
631
}
632
633
if (memblock_is_region_reserved(start, size)) {
634
pr_err("INITRD: 0x%08llx+0x%08lx overlaps in-use memory region\n",
635
(u64)start, size);
636
goto disable;
637
}
638
639
memblock_reserve(start, size);
640
/* Now convert initrd to virtual addresses */
641
initrd_start = (unsigned long)__va(phys_initrd_start);
642
initrd_end = initrd_start + phys_initrd_size;
643
initrd_below_start_ok = 1;
644
645
return;
646
disable:
647
pr_cont(" - disabling initrd\n");
648
initrd_start = 0;
649
initrd_end = 0;
650
}
651
652
void __weak __init free_initrd_mem(unsigned long start, unsigned long end)
653
{
654
#ifdef CONFIG_ARCH_KEEP_MEMBLOCK
655
unsigned long aligned_start = ALIGN_DOWN(start, PAGE_SIZE);
656
unsigned long aligned_end = ALIGN(end, PAGE_SIZE);
657
658
memblock_free((void *)aligned_start, aligned_end - aligned_start);
659
#endif
660
661
free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
662
"initrd");
663
}
664
665
#ifdef CONFIG_CRASH_RESERVE
666
static bool __init kexec_free_initrd(void)
667
{
668
unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
669
unsigned long crashk_end = (unsigned long)__va(crashk_res.end);
670
671
/*
672
* If the initrd region is overlapped with crashkernel reserved region,
673
* free only memory that is not part of crashkernel region.
674
*/
675
if (initrd_start >= crashk_end || initrd_end <= crashk_start)
676
return false;
677
678
/*
679
* Initialize initrd memory region since the kexec boot does not do.
680
*/
681
memset((void *)initrd_start, 0, initrd_end - initrd_start);
682
if (initrd_start < crashk_start)
683
free_initrd_mem(initrd_start, crashk_start);
684
if (initrd_end > crashk_end)
685
free_initrd_mem(crashk_end, initrd_end);
686
return true;
687
}
688
#else
689
static inline bool kexec_free_initrd(void)
690
{
691
return false;
692
}
693
#endif /* CONFIG_KEXEC_CORE */
694
695
#ifdef CONFIG_BLK_DEV_RAM
696
static void __init populate_initrd_image(char *err)
697
{
698
ssize_t written;
699
struct file *file;
700
loff_t pos = 0;
701
702
printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
703
err);
704
file = filp_open("/initrd.image", O_WRONLY|O_CREAT|O_LARGEFILE, 0700);
705
if (IS_ERR(file))
706
return;
707
708
written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
709
&pos);
710
if (written != initrd_end - initrd_start)
711
pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
712
written, initrd_end - initrd_start);
713
fput(file);
714
}
715
#endif /* CONFIG_BLK_DEV_RAM */
716
717
static void __init do_populate_rootfs(void *unused, async_cookie_t cookie)
718
{
719
/* Load the built in initramfs */
720
char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
721
if (err)
722
panic_show_mem("%s", err); /* Failed to decompress INTERNAL initramfs */
723
724
if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
725
goto done;
726
727
if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
728
printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
729
else
730
printk(KERN_INFO "Unpacking initramfs...\n");
731
732
err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
733
if (err) {
734
#ifdef CONFIG_BLK_DEV_RAM
735
populate_initrd_image(err);
736
#else
737
printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
738
#endif
739
}
740
741
done:
742
security_initramfs_populated();
743
744
/*
745
* If the initrd region is overlapped with crashkernel reserved region,
746
* free only memory that is not part of crashkernel region.
747
*/
748
if (!do_retain_initrd && initrd_start && !kexec_free_initrd()) {
749
free_initrd_mem(initrd_start, initrd_end);
750
} else if (do_retain_initrd && initrd_start) {
751
bin_attr_initrd.size = initrd_end - initrd_start;
752
bin_attr_initrd.private = (void *)initrd_start;
753
if (sysfs_create_bin_file(firmware_kobj, &bin_attr_initrd))
754
pr_err("Failed to create initrd sysfs file");
755
}
756
initrd_start = 0;
757
initrd_end = 0;
758
759
init_flush_fput();
760
}
761
762
static ASYNC_DOMAIN_EXCLUSIVE(initramfs_domain);
763
static async_cookie_t initramfs_cookie;
764
765
void wait_for_initramfs(void)
766
{
767
if (!initramfs_cookie) {
768
/*
769
* Something before rootfs_initcall wants to access
770
* the filesystem/initramfs. Probably a bug. Make a
771
* note, avoid deadlocking the machine, and let the
772
* caller's access fail as it used to.
773
*/
774
pr_warn_once("wait_for_initramfs() called before rootfs_initcalls\n");
775
return;
776
}
777
async_synchronize_cookie_domain(initramfs_cookie + 1, &initramfs_domain);
778
}
779
EXPORT_SYMBOL_GPL(wait_for_initramfs);
780
781
static int __init populate_rootfs(void)
782
{
783
initramfs_cookie = async_schedule_domain(do_populate_rootfs, NULL,
784
&initramfs_domain);
785
usermodehelper_enable();
786
if (!initramfs_async)
787
wait_for_initramfs();
788
return 0;
789
}
790
rootfs_initcall(populate_rootfs);
791
792