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