linux/init/initramfs.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <linux/init.h>
   3#include <linux/fs.h>
   4#include <linux/slab.h>
   5#include <linux/types.h>
   6#include <linux/fcntl.h>
   7#include <linux/delay.h>
   8#include <linux/string.h>
   9#include <linux/dirent.h>
  10#include <linux/syscalls.h>
  11#include <linux/utime.h>
  12#include <linux/file.h>
  13#include <linux/memblock.h>
  14#include <linux/namei.h>
  15#include <linux/init_syscalls.h>
  16
  17static ssize_t __init xwrite(struct file *file, const char *p, size_t count,
  18                loff_t *pos)
  19{
  20        ssize_t out = 0;
  21
  22        /* sys_write only can write MAX_RW_COUNT aka 2G-4K bytes at most */
  23        while (count) {
  24                ssize_t rv = kernel_write(file, p, count, pos);
  25
  26                if (rv < 0) {
  27                        if (rv == -EINTR || rv == -EAGAIN)
  28                                continue;
  29                        return out ? out : rv;
  30                } else if (rv == 0)
  31                        break;
  32
  33                p += rv;
  34                out += rv;
  35                count -= rv;
  36        }
  37
  38        return out;
  39}
  40
  41static __initdata char *message;
  42static void __init error(char *x)
  43{
  44        if (!message)
  45                message = x;
  46}
  47
  48/* link hash */
  49
  50#define N_ALIGN(len) ((((len) + 1) & ~3) + 2)
  51
  52static __initdata struct hash {
  53        int ino, minor, major;
  54        umode_t mode;
  55        struct hash *next;
  56        char name[N_ALIGN(PATH_MAX)];
  57} *head[32];
  58
  59static inline int hash(int major, int minor, int ino)
  60{
  61        unsigned long tmp = ino + minor + (major << 3);
  62        tmp += tmp >> 5;
  63        return tmp & 31;
  64}
  65
  66static char __init *find_link(int major, int minor, int ino,
  67                              umode_t mode, char *name)
  68{
  69        struct hash **p, *q;
  70        for (p = head + hash(major, minor, ino); *p; p = &(*p)->next) {
  71                if ((*p)->ino != ino)
  72                        continue;
  73                if ((*p)->minor != minor)
  74                        continue;
  75                if ((*p)->major != major)
  76                        continue;
  77                if (((*p)->mode ^ mode) & S_IFMT)
  78                        continue;
  79                return (*p)->name;
  80        }
  81        q = kmalloc(sizeof(struct hash), GFP_KERNEL);
  82        if (!q)
  83                panic("can't allocate link hash entry");
  84        q->major = major;
  85        q->minor = minor;
  86        q->ino = ino;
  87        q->mode = mode;
  88        strcpy(q->name, name);
  89        q->next = NULL;
  90        *p = q;
  91        return NULL;
  92}
  93
  94static void __init free_hash(void)
  95{
  96        struct hash **p, *q;
  97        for (p = head; p < head + 32; p++) {
  98                while (*p) {
  99                        q = *p;
 100                        *p = q->next;
 101                        kfree(q);
 102                }
 103        }
 104}
 105
 106static long __init do_utime(char *filename, time64_t mtime)
 107{
 108        struct timespec64 t[2];
 109
 110        t[0].tv_sec = mtime;
 111        t[0].tv_nsec = 0;
 112        t[1].tv_sec = mtime;
 113        t[1].tv_nsec = 0;
 114        return init_utimes(filename, t);
 115}
 116
 117static __initdata LIST_HEAD(dir_list);
 118struct dir_entry {
 119        struct list_head list;
 120        char *name;
 121        time64_t mtime;
 122};
 123
 124static void __init dir_add(const char *name, time64_t mtime)
 125{
 126        struct dir_entry *de = kmalloc(sizeof(struct dir_entry), GFP_KERNEL);
 127        if (!de)
 128                panic("can't allocate dir_entry buffer");
 129        INIT_LIST_HEAD(&de->list);
 130        de->name = kstrdup(name, GFP_KERNEL);
 131        de->mtime = mtime;
 132        list_add(&de->list, &dir_list);
 133}
 134
 135static void __init dir_utime(void)
 136{
 137        struct dir_entry *de, *tmp;
 138        list_for_each_entry_safe(de, tmp, &dir_list, list) {
 139                list_del(&de->list);
 140                do_utime(de->name, de->mtime);
 141                kfree(de->name);
 142                kfree(de);
 143        }
 144}
 145
 146static __initdata time64_t mtime;
 147
 148/* cpio header parsing */
 149
 150static __initdata unsigned long ino, major, minor, nlink;
 151static __initdata umode_t mode;
 152static __initdata unsigned long body_len, name_len;
 153static __initdata uid_t uid;
 154static __initdata gid_t gid;
 155static __initdata unsigned rdev;
 156
 157static void __init parse_header(char *s)
 158{
 159        unsigned long parsed[12];
 160        char buf[9];
 161        int i;
 162
 163        buf[8] = '\0';
 164        for (i = 0, s += 6; i < 12; i++, s += 8) {
 165                memcpy(buf, s, 8);
 166                parsed[i] = simple_strtoul(buf, NULL, 16);
 167        }
 168        ino = parsed[0];
 169        mode = parsed[1];
 170        uid = parsed[2];
 171        gid = parsed[3];
 172        nlink = parsed[4];
 173        mtime = parsed[5]; /* breaks in y2106 */
 174        body_len = parsed[6];
 175        major = parsed[7];
 176        minor = parsed[8];
 177        rdev = new_encode_dev(MKDEV(parsed[9], parsed[10]));
 178        name_len = parsed[11];
 179}
 180
 181/* FSM */
 182
 183static __initdata enum state {
 184        Start,
 185        Collect,
 186        GotHeader,
 187        SkipIt,
 188        GotName,
 189        CopyFile,
 190        GotSymlink,
 191        Reset
 192} state, next_state;
 193
 194static __initdata char *victim;
 195static unsigned long byte_count __initdata;
 196static __initdata loff_t this_header, next_header;
 197
 198static inline void __init eat(unsigned n)
 199{
 200        victim += n;
 201        this_header += n;
 202        byte_count -= n;
 203}
 204
 205static __initdata char *collected;
 206static long remains __initdata;
 207static __initdata char *collect;
 208
 209static void __init read_into(char *buf, unsigned size, enum state next)
 210{
 211        if (byte_count >= size) {
 212                collected = victim;
 213                eat(size);
 214                state = next;
 215        } else {
 216                collect = collected = buf;
 217                remains = size;
 218                next_state = next;
 219                state = Collect;
 220        }
 221}
 222
 223static __initdata char *header_buf, *symlink_buf, *name_buf;
 224
 225static int __init do_start(void)
 226{
 227        read_into(header_buf, 110, GotHeader);
 228        return 0;
 229}
 230
 231static int __init do_collect(void)
 232{
 233        unsigned long n = remains;
 234        if (byte_count < n)
 235                n = byte_count;
 236        memcpy(collect, victim, n);
 237        eat(n);
 238        collect += n;
 239        if ((remains -= n) != 0)
 240                return 1;
 241        state = next_state;
 242        return 0;
 243}
 244
 245static int __init do_header(void)
 246{
 247        if (memcmp(collected, "070707", 6)==0) {
 248                error("incorrect cpio method used: use -H newc option");
 249                return 1;
 250        }
 251        if (memcmp(collected, "070701", 6)) {
 252                error("no cpio magic");
 253                return 1;
 254        }
 255        parse_header(collected);
 256        next_header = this_header + N_ALIGN(name_len) + body_len;
 257        next_header = (next_header + 3) & ~3;
 258        state = SkipIt;
 259        if (name_len <= 0 || name_len > PATH_MAX)
 260                return 0;
 261        if (S_ISLNK(mode)) {
 262                if (body_len > PATH_MAX)
 263                        return 0;
 264                collect = collected = symlink_buf;
 265                remains = N_ALIGN(name_len) + body_len;
 266                next_state = GotSymlink;
 267                state = Collect;
 268                return 0;
 269        }
 270        if (S_ISREG(mode) || !body_len)
 271                read_into(name_buf, N_ALIGN(name_len), GotName);
 272        return 0;
 273}
 274
 275static int __init do_skip(void)
 276{
 277        if (this_header + byte_count < next_header) {
 278                eat(byte_count);
 279                return 1;
 280        } else {
 281                eat(next_header - this_header);
 282                state = next_state;
 283                return 0;
 284        }
 285}
 286
 287static int __init do_reset(void)
 288{
 289        while (byte_count && *victim == '\0')
 290                eat(1);
 291        if (byte_count && (this_header & 3))
 292                error("broken padding");
 293        return 1;
 294}
 295
 296static void __init clean_path(char *path, umode_t fmode)
 297{
 298        struct kstat st;
 299
 300        if (!init_stat(path, &st, AT_SYMLINK_NOFOLLOW) &&
 301            (st.mode ^ fmode) & S_IFMT) {
 302                if (S_ISDIR(st.mode))
 303                        init_rmdir(path);
 304                else
 305                        init_unlink(path);
 306        }
 307}
 308
 309static int __init maybe_link(void)
 310{
 311        if (nlink >= 2) {
 312                char *old = find_link(major, minor, ino, mode, collected);
 313                if (old) {
 314                        clean_path(collected, 0);
 315                        return (init_link(old, collected) < 0) ? -1 : 1;
 316                }
 317        }
 318        return 0;
 319}
 320
 321static __initdata struct file *wfile;
 322static __initdata loff_t wfile_pos;
 323
 324static int __init do_name(void)
 325{
 326        state = SkipIt;
 327        next_state = Reset;
 328        if (strcmp(collected, "TRAILER!!!") == 0) {
 329                free_hash();
 330                return 0;
 331        }
 332        clean_path(collected, mode);
 333        if (S_ISREG(mode)) {
 334                int ml = maybe_link();
 335                if (ml >= 0) {
 336                        int openflags = O_WRONLY|O_CREAT;
 337                        if (ml != 1)
 338                                openflags |= O_TRUNC;
 339                        wfile = filp_open(collected, openflags, mode);
 340                        if (IS_ERR(wfile))
 341                                return 0;
 342                        wfile_pos = 0;
 343
 344                        vfs_fchown(wfile, uid, gid);
 345                        vfs_fchmod(wfile, mode);
 346                        if (body_len)
 347                                vfs_truncate(&wfile->f_path, body_len);
 348                        state = CopyFile;
 349                }
 350        } else if (S_ISDIR(mode)) {
 351                init_mkdir(collected, mode);
 352                init_chown(collected, uid, gid, 0);
 353                init_chmod(collected, mode);
 354                dir_add(collected, mtime);
 355        } else if (S_ISBLK(mode) || S_ISCHR(mode) ||
 356                   S_ISFIFO(mode) || S_ISSOCK(mode)) {
 357                if (maybe_link() == 0) {
 358                        init_mknod(collected, mode, rdev);
 359                        init_chown(collected, uid, gid, 0);
 360                        init_chmod(collected, mode);
 361                        do_utime(collected, mtime);
 362                }
 363        }
 364        return 0;
 365}
 366
 367static int __init do_copy(void)
 368{
 369        if (byte_count >= body_len) {
 370                struct timespec64 t[2] = { };
 371                if (xwrite(wfile, victim, body_len, &wfile_pos) != body_len)
 372                        error("write error");
 373
 374                t[0].tv_sec = mtime;
 375                t[1].tv_sec = mtime;
 376                vfs_utimes(&wfile->f_path, t);
 377
 378                fput(wfile);
 379                eat(body_len);
 380                state = SkipIt;
 381                return 0;
 382        } else {
 383                if (xwrite(wfile, victim, byte_count, &wfile_pos) != byte_count)
 384                        error("write error");
 385                body_len -= byte_count;
 386                eat(byte_count);
 387                return 1;
 388        }
 389}
 390
 391static int __init do_symlink(void)
 392{
 393        collected[N_ALIGN(name_len) + body_len] = '\0';
 394        clean_path(collected, 0);
 395        init_symlink(collected + N_ALIGN(name_len), collected);
 396        init_chown(collected, uid, gid, AT_SYMLINK_NOFOLLOW);
 397        do_utime(collected, mtime);
 398        state = SkipIt;
 399        next_state = Reset;
 400        return 0;
 401}
 402
 403static __initdata int (*actions[])(void) = {
 404        [Start]         = do_start,
 405        [Collect]       = do_collect,
 406        [GotHeader]     = do_header,
 407        [SkipIt]        = do_skip,
 408        [GotName]       = do_name,
 409        [CopyFile]      = do_copy,
 410        [GotSymlink]    = do_symlink,
 411        [Reset]         = do_reset,
 412};
 413
 414static long __init write_buffer(char *buf, unsigned long len)
 415{
 416        byte_count = len;
 417        victim = buf;
 418
 419        while (!actions[state]())
 420                ;
 421        return len - byte_count;
 422}
 423
 424static long __init flush_buffer(void *bufv, unsigned long len)
 425{
 426        char *buf = (char *) bufv;
 427        long written;
 428        long origLen = len;
 429        if (message)
 430                return -1;
 431        while ((written = write_buffer(buf, len)) < len && !message) {
 432                char c = buf[written];
 433                if (c == '0') {
 434                        buf += written;
 435                        len -= written;
 436                        state = Start;
 437                } else if (c == 0) {
 438                        buf += written;
 439                        len -= written;
 440                        state = Reset;
 441                } else
 442                        error("junk within compressed archive");
 443        }
 444        return origLen;
 445}
 446
 447static unsigned long my_inptr; /* index of next byte to be processed in inbuf */
 448
 449#include <linux/decompress/generic.h>
 450
 451static char * __init unpack_to_rootfs(char *buf, unsigned long len)
 452{
 453        long written;
 454        decompress_fn decompress;
 455        const char *compress_name;
 456        static __initdata char msg_buf[64];
 457
 458        header_buf = kmalloc(110, GFP_KERNEL);
 459        symlink_buf = kmalloc(PATH_MAX + N_ALIGN(PATH_MAX) + 1, GFP_KERNEL);
 460        name_buf = kmalloc(N_ALIGN(PATH_MAX), GFP_KERNEL);
 461
 462        if (!header_buf || !symlink_buf || !name_buf)
 463                panic("can't allocate buffers");
 464
 465        state = Start;
 466        this_header = 0;
 467        message = NULL;
 468        while (!message && len) {
 469                loff_t saved_offset = this_header;
 470                if (*buf == '0' && !(this_header & 3)) {
 471                        state = Start;
 472                        written = write_buffer(buf, len);
 473                        buf += written;
 474                        len -= written;
 475                        continue;
 476                }
 477                if (!*buf) {
 478                        buf++;
 479                        len--;
 480                        this_header++;
 481                        continue;
 482                }
 483                this_header = 0;
 484                decompress = decompress_method(buf, len, &compress_name);
 485                pr_debug("Detected %s compressed data\n", compress_name);
 486                if (decompress) {
 487                        int res = decompress(buf, len, NULL, flush_buffer, NULL,
 488                                   &my_inptr, error);
 489                        if (res)
 490                                error("decompressor failed");
 491                } else if (compress_name) {
 492                        if (!message) {
 493                                snprintf(msg_buf, sizeof msg_buf,
 494                                         "compression method %s not configured",
 495                                         compress_name);
 496                                message = msg_buf;
 497                        }
 498                } else
 499                        error("invalid magic at start of compressed archive");
 500                if (state != Reset)
 501                        error("junk at the end of compressed archive");
 502                this_header = saved_offset + my_inptr;
 503                buf += my_inptr;
 504                len -= my_inptr;
 505        }
 506        dir_utime();
 507        kfree(name_buf);
 508        kfree(symlink_buf);
 509        kfree(header_buf);
 510        return message;
 511}
 512
 513static int __initdata do_retain_initrd;
 514
 515static int __init retain_initrd_param(char *str)
 516{
 517        if (*str)
 518                return 0;
 519        do_retain_initrd = 1;
 520        return 1;
 521}
 522__setup("retain_initrd", retain_initrd_param);
 523
 524#ifdef CONFIG_ARCH_HAS_KEEPINITRD
 525static int __init keepinitrd_setup(char *__unused)
 526{
 527        do_retain_initrd = 1;
 528        return 1;
 529}
 530__setup("keepinitrd", keepinitrd_setup);
 531#endif
 532
 533extern char __initramfs_start[];
 534extern unsigned long __initramfs_size;
 535#include <linux/initrd.h>
 536#include <linux/kexec.h>
 537
 538void __weak __init free_initrd_mem(unsigned long start, unsigned long end)
 539{
 540#ifdef CONFIG_ARCH_KEEP_MEMBLOCK
 541        unsigned long aligned_start = ALIGN_DOWN(start, PAGE_SIZE);
 542        unsigned long aligned_end = ALIGN(end, PAGE_SIZE);
 543
 544        memblock_free(__pa(aligned_start), aligned_end - aligned_start);
 545#endif
 546
 547        free_reserved_area((void *)start, (void *)end, POISON_FREE_INITMEM,
 548                        "initrd");
 549}
 550
 551#ifdef CONFIG_KEXEC_CORE
 552static bool __init kexec_free_initrd(void)
 553{
 554        unsigned long crashk_start = (unsigned long)__va(crashk_res.start);
 555        unsigned long crashk_end   = (unsigned long)__va(crashk_res.end);
 556
 557        /*
 558         * If the initrd region is overlapped with crashkernel reserved region,
 559         * free only memory that is not part of crashkernel region.
 560         */
 561        if (initrd_start >= crashk_end || initrd_end <= crashk_start)
 562                return false;
 563
 564        /*
 565         * Initialize initrd memory region since the kexec boot does not do.
 566         */
 567        memset((void *)initrd_start, 0, initrd_end - initrd_start);
 568        if (initrd_start < crashk_start)
 569                free_initrd_mem(initrd_start, crashk_start);
 570        if (initrd_end > crashk_end)
 571                free_initrd_mem(crashk_end, initrd_end);
 572        return true;
 573}
 574#else
 575static inline bool kexec_free_initrd(void)
 576{
 577        return false;
 578}
 579#endif /* CONFIG_KEXEC_CORE */
 580
 581#ifdef CONFIG_BLK_DEV_RAM
 582static void __init populate_initrd_image(char *err)
 583{
 584        ssize_t written;
 585        struct file *file;
 586        loff_t pos = 0;
 587
 588        unpack_to_rootfs(__initramfs_start, __initramfs_size);
 589
 590        printk(KERN_INFO "rootfs image is not initramfs (%s); looks like an initrd\n",
 591                        err);
 592        file = filp_open("/initrd.image", O_WRONLY | O_CREAT, 0700);
 593        if (IS_ERR(file))
 594                return;
 595
 596        written = xwrite(file, (char *)initrd_start, initrd_end - initrd_start,
 597                        &pos);
 598        if (written != initrd_end - initrd_start)
 599                pr_err("/initrd.image: incomplete write (%zd != %ld)\n",
 600                       written, initrd_end - initrd_start);
 601        fput(file);
 602}
 603#endif /* CONFIG_BLK_DEV_RAM */
 604
 605static int __init populate_rootfs(void)
 606{
 607        /* Load the built in initramfs */
 608        char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);
 609        if (err)
 610                panic("%s", err); /* Failed to decompress INTERNAL initramfs */
 611
 612        if (!initrd_start || IS_ENABLED(CONFIG_INITRAMFS_FORCE))
 613                goto done;
 614
 615        if (IS_ENABLED(CONFIG_BLK_DEV_RAM))
 616                printk(KERN_INFO "Trying to unpack rootfs image as initramfs...\n");
 617        else
 618                printk(KERN_INFO "Unpacking initramfs...\n");
 619
 620        err = unpack_to_rootfs((char *)initrd_start, initrd_end - initrd_start);
 621        if (err) {
 622#ifdef CONFIG_BLK_DEV_RAM
 623                populate_initrd_image(err);
 624#else
 625                printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
 626#endif
 627        }
 628
 629done:
 630        /*
 631         * If the initrd region is overlapped with crashkernel reserved region,
 632         * free only memory that is not part of crashkernel region.
 633         */
 634        if (!do_retain_initrd && initrd_start && !kexec_free_initrd())
 635                free_initrd_mem(initrd_start, initrd_end);
 636        initrd_start = 0;
 637        initrd_end = 0;
 638
 639        flush_delayed_fput();
 640        return 0;
 641}
 642rootfs_initcall(populate_rootfs);
 643