cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

do_mounts_initrd.c (3964B)


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