LCOV - code coverage report
Current view: top level - init - do_mounts_initrd.c (source / functions) Hit Total Coverage
Test: landlock.info Lines: 6 21 28.6 %
Date: 2021-04-22 12:43:58 Functions: 1 4 25.0 %

          Line data    Source code
       1             : // SPDX-License-Identifier: GPL-2.0
       2             : #include <linux/unistd.h>
       3             : #include <linux/kernel.h>
       4             : #include <linux/fs.h>
       5             : #include <linux/minix_fs.h>
       6             : #include <linux/romfs_fs.h>
       7             : #include <linux/initrd.h>
       8             : #include <linux/sched.h>
       9             : #include <linux/freezer.h>
      10             : #include <linux/kmod.h>
      11             : #include <uapi/linux/mount.h>
      12             : 
      13             : #include "do_mounts.h"
      14             : 
      15             : unsigned long initrd_start, initrd_end;
      16             : int initrd_below_start_ok;
      17             : unsigned int real_root_dev;     /* do_proc_dointvec cannot handle kdev_t */
      18             : static int __initdata mount_initrd = 1;
      19             : 
      20             : phys_addr_t phys_initrd_start __initdata;
      21             : unsigned long phys_initrd_size __initdata;
      22             : 
      23           0 : static int __init no_initrd(char *str)
      24             : {
      25           0 :         mount_initrd = 0;
      26           0 :         return 1;
      27             : }
      28             : 
      29             : __setup("noinitrd", no_initrd);
      30             : 
      31           0 : static int __init early_initrdmem(char *p)
      32             : {
      33           0 :         phys_addr_t start;
      34           0 :         unsigned long size;
      35           0 :         char *endp;
      36             : 
      37           0 :         start = memparse(p, &endp);
      38           0 :         if (*endp == ',') {
      39           0 :                 size = memparse(endp + 1, NULL);
      40             : 
      41           0 :                 phys_initrd_start = start;
      42           0 :                 phys_initrd_size = size;
      43             :         }
      44           0 :         return 0;
      45             : }
      46             : early_param("initrdmem", early_initrdmem);
      47             : 
      48           0 : static int __init early_initrd(char *p)
      49             : {
      50           0 :         return early_initrdmem(p);
      51             : }
      52             : early_param("initrd", early_initrd);
      53             : 
      54             : static int __init init_linuxrc(struct subprocess_info *info, struct cred *new)
      55             : {
      56             :         ksys_unshare(CLONE_FS | CLONE_FILES);
      57             :         console_on_rootfs();
      58             :         /* move initrd over / and chdir/chroot in initrd root */
      59             :         init_chdir("/root");
      60             :         init_mount(".", "/", NULL, MS_MOVE, NULL);
      61             :         init_chroot(".");
      62             :         ksys_setsid();
      63             :         return 0;
      64             : }
      65             : 
      66             : static void __init handle_initrd(void)
      67             : {
      68             :         struct subprocess_info *info;
      69             :         static char *argv[] = { "linuxrc", NULL, };
      70             :         extern char *envp_init[];
      71             :         int error;
      72             : 
      73             :         pr_warn("using deprecated initrd support, will be removed in 2021.\n");
      74             : 
      75             :         real_root_dev = new_encode_dev(ROOT_DEV);
      76             :         create_dev("/dev/root.old", Root_RAM0);
      77             :         /* mount initrd on rootfs' /root */
      78             :         mount_block_root("/dev/root.old", root_mountflags & ~MS_RDONLY);
      79             :         init_mkdir("/old", 0700);
      80             :         init_chdir("/old");
      81             : 
      82             :         /*
      83             :          * In case that a resume from disk is carried out by linuxrc or one of
      84             :          * its children, we need to tell the freezer not to wait for us.
      85             :          */
      86             :         current->flags |= PF_FREEZER_SKIP;
      87             : 
      88             :         info = call_usermodehelper_setup("/linuxrc", argv, envp_init,
      89             :                                          GFP_KERNEL, init_linuxrc, NULL, NULL);
      90             :         if (!info)
      91             :                 return;
      92             :         call_usermodehelper_exec(info, UMH_WAIT_PROC);
      93             : 
      94             :         current->flags &= ~PF_FREEZER_SKIP;
      95             : 
      96             :         /* move initrd to rootfs' /old */
      97             :         init_mount("..", ".", NULL, MS_MOVE, NULL);
      98             :         /* switch root and cwd back to / of rootfs */
      99             :         init_chroot("..");
     100             : 
     101             :         if (new_decode_dev(real_root_dev) == Root_RAM0) {
     102             :                 init_chdir("/old");
     103             :                 return;
     104             :         }
     105             : 
     106             :         init_chdir("/");
     107             :         ROOT_DEV = new_decode_dev(real_root_dev);
     108             :         mount_root();
     109             : 
     110             :         printk(KERN_NOTICE "Trying to move old root to /initrd ... ");
     111             :         error = init_mount("/old", "/root/initrd", NULL, MS_MOVE, NULL);
     112             :         if (!error)
     113             :                 printk("okay\n");
     114             :         else {
     115             :                 if (error == -ENOENT)
     116             :                         printk("/initrd does not exist. Ignored.\n");
     117             :                 else
     118             :                         printk("failed\n");
     119             :                 printk(KERN_NOTICE "Unmounting old root\n");
     120             :                 init_umount("/old", MNT_DETACH);
     121             :         }
     122             : }
     123             : 
     124           1 : bool __init initrd_load(void)
     125             : {
     126           1 :         if (mount_initrd) {
     127           1 :                 create_dev("/dev/ram", Root_RAM0);
     128             :                 /*
     129             :                  * Load the initrd data into /dev/ram0. Execute it as initrd
     130             :                  * unless /dev/ram0 is supposed to be our actual root device,
     131             :                  * in that case the ram disk is just set up here, and gets
     132             :                  * mounted in the normal path.
     133             :                  */
     134           1 :                 if (rd_load_image("/initrd.image") && ROOT_DEV != Root_RAM0) {
     135             :                         init_unlink("/initrd.image");
     136             :                         handle_initrd();
     137             :                         return true;
     138             :                 }
     139             :         }
     140           1 :         init_unlink("/initrd.image");
     141           1 :         return false;
     142             : }

Generated by: LCOV version 1.14