From 102a0743326a03cd1a1202ceda21e175b7d3575c Mon Sep 17 00:00:00 2001 From: hc <hc@nodka.com> Date: Tue, 20 Feb 2024 01:20:52 +0000 Subject: [PATCH] add new system file --- kernel/init/main.c | 544 +++++++++++++++++++++++++++++++++++++++++++----------- 1 files changed, 433 insertions(+), 111 deletions(-) diff --git a/kernel/init/main.c b/kernel/init/main.c index 6091067..02d6bfb 100644 --- a/kernel/init/main.c +++ b/kernel/init/main.c @@ -1,3 +1,4 @@ +// SPDX-License-Identifier: GPL-2.0-only /* * linux/init/main.c * @@ -25,18 +26,21 @@ #include <linux/ioport.h> #include <linux/init.h> #include <linux/initrd.h> -#include <linux/bootmem.h> +#include <linux/memblock.h> #include <linux/acpi.h> +#include <linux/bootconfig.h> #include <linux/console.h> #include <linux/nmi.h> #include <linux/percpu.h> #include <linux/kmod.h> +#include <linux/kprobes.h> #include <linux/vmalloc.h> #include <linux/kernel_stat.h> #include <linux/start_kernel.h> #include <linux/security.h> #include <linux/smp.h> #include <linux/profile.h> +#include <linux/kfence.h> #include <linux/rcupdate.h> #include <linux/moduleparam.h> #include <linux/kallsyms.h> @@ -61,8 +65,9 @@ #include <linux/debugobjects.h> #include <linux/lockdep.h> #include <linux/kmemleak.h> +#include <linux/padata.h> #include <linux/pid_namespace.h> -#include <linux/device.h> +#include <linux/device/driver.h> #include <linux/kthread.h> #include <linux/sched.h> #include <linux/sched/init.h> @@ -91,16 +96,19 @@ #include <linux/cache.h> #include <linux/rodata_test.h> #include <linux/jump_label.h> -#include <linux/mem_encrypt.h> +#include <linux/kcsan.h> +#include <linux/init_syscalls.h> +#include <linux/stackdepot.h> #include <asm/io.h> -#include <asm/bugs.h> #include <asm/setup.h> #include <asm/sections.h> #include <asm/cacheflush.h> #define CREATE_TRACE_POINTS #include <trace/events/initcall.h> + +#include <kunit/test.h> static int kernel_init(void *); @@ -133,14 +141,24 @@ char __initdata boot_command_line[COMMAND_LINE_SIZE]; /* Untouched saved command line (eg. for /proc) */ char *saved_command_line; -EXPORT_SYMBOL_GPL(saved_command_line); /* Command line for parameter parsing */ static char *static_command_line; -/* Command line for per-initcall parameter parsing */ -static char *initcall_command_line; +/* Untouched extra command line */ +static char *extra_command_line; +/* Extra init arguments */ +static char *extra_init_args; + +#ifdef CONFIG_BOOT_CONFIG +/* Is bootconfig on command line? */ +static bool bootconfig_found; +static bool initargs_found; +#else +# define bootconfig_found false +# define initargs_found false +#endif static char *execute_command; -static char *ramdisk_execute_command; +static char *ramdisk_execute_command = "/init"; /* * Used to generate warnings if static_key manipulation functions are used @@ -245,9 +263,223 @@ early_param("loglevel", loglevel); -/* Change NUL term back to "=", to make "param" the whole string. */ -static int __init repair_env_string(char *param, char *val, +#ifdef CONFIG_BLK_DEV_INITRD +static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) +{ + u32 size, csum; + char *data; + u32 *hdr; + int i; + + if (!initrd_end) + return NULL; + + data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; + /* + * Since Grub may align the size of initrd to 4, we must + * check the preceding 3 bytes as well. + */ + for (i = 0; i < 4; i++) { + if (!memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN)) + goto found; + data--; + } + return NULL; + +found: + hdr = (u32 *)(data - 8); + size = le32_to_cpu(hdr[0]); + csum = le32_to_cpu(hdr[1]); + + data = ((void *)hdr) - size; + if ((unsigned long)data < initrd_start) { + pr_err("bootconfig size %d is greater than initrd size %ld\n", + size, initrd_end - initrd_start); + return NULL; + } + + /* Remove bootconfig from initramfs/initrd */ + initrd_end = (unsigned long)data; + if (_size) + *_size = size; + if (_csum) + *_csum = csum; + + return data; +} +#else +static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) +{ + return NULL; +} +#endif + +#ifdef CONFIG_BOOT_CONFIG + +static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata; + +#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0) + +static int __init xbc_snprint_cmdline(char *buf, size_t size, + struct xbc_node *root) +{ + struct xbc_node *knode, *vnode; + char *end = buf + size; + const char *val; + int ret; + + xbc_node_for_each_key_value(root, knode, val) { + ret = xbc_node_compose_key_after(root, knode, + xbc_namebuf, XBC_KEYLEN_MAX); + if (ret < 0) + return ret; + + vnode = xbc_node_get_child(knode); + if (!vnode) { + ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf); + if (ret < 0) + return ret; + buf += ret; + continue; + } + xbc_array_for_each_value(vnode, val) { + ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ", + xbc_namebuf, val); + if (ret < 0) + return ret; + buf += ret; + } + } + + return buf - (end - size); +} +#undef rest + +/* Make an extra command line under given key word */ +static char * __init xbc_make_cmdline(const char *key) +{ + struct xbc_node *root; + char *new_cmdline; + int ret, len = 0; + + root = xbc_find_node(key); + if (!root) + return NULL; + + /* Count required buffer size */ + len = xbc_snprint_cmdline(NULL, 0, root); + if (len <= 0) + return NULL; + + new_cmdline = memblock_alloc(len + 1, SMP_CACHE_BYTES); + if (!new_cmdline) { + pr_err("Failed to allocate memory for extra kernel cmdline.\n"); + return NULL; + } + + ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); + if (ret < 0 || ret > len) { + pr_err("Failed to print extra kernel cmdline.\n"); + memblock_free(__pa(new_cmdline), len + 1); + return NULL; + } + + return new_cmdline; +} + +static int __init bootconfig_params(char *param, char *val, const char *unused, void *arg) +{ + if (strcmp(param, "bootconfig") == 0) { + bootconfig_found = true; + } + return 0; +} + +static void __init setup_boot_config(const char *cmdline) +{ + static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; + const char *msg; + int pos; + u32 size, csum; + char *data, *copy, *err; + int ret; + + /* Cut out the bootconfig data even if we have no bootconfig option */ + data = get_boot_config_from_initrd(&size, &csum); + + strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); + err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL, + bootconfig_params); + + if (IS_ERR(err) || !bootconfig_found) + return; + + /* parse_args() stops at '--' and returns an address */ + if (err) + initargs_found = true; + + if (!data) { + pr_err("'bootconfig' found on command line, but no bootconfig found\n"); + return; + } + + if (size >= XBC_DATA_MAX) { + pr_err("bootconfig size %d greater than max size %d\n", + size, XBC_DATA_MAX); + return; + } + + if (xbc_calc_checksum(data, size) != csum) { + pr_err("bootconfig checksum failed\n"); + return; + } + + copy = memblock_alloc(size + 1, SMP_CACHE_BYTES); + if (!copy) { + pr_err("Failed to allocate memory for bootconfig\n"); + return; + } + + memcpy(copy, data, size); + copy[size] = '\0'; + + ret = xbc_init(copy, &msg, &pos); + if (ret < 0) { + if (pos < 0) + pr_err("Failed to init bootconfig: %s.\n", msg); + else + pr_err("Failed to parse bootconfig: %s at %d.\n", + msg, pos); + } else { + pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret); + /* keys starting with "kernel." are passed via cmdline */ + extra_command_line = xbc_make_cmdline("kernel"); + /* Also, "init." keys are init arguments */ + extra_init_args = xbc_make_cmdline("init"); + } + return; +} + +#else + +static void __init setup_boot_config(const char *cmdline) +{ + /* Remove bootconfig data from initrd */ + get_boot_config_from_initrd(NULL, NULL); +} + +static int __init warn_bootconfig(char *str) +{ + pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n"); + return 0; +} +early_param("bootconfig", warn_bootconfig); + +#endif + +/* Change NUL term back to "=", to make "param" the whole string. */ +static void __init repair_env_string(char *param, char *val) { if (val) { /* param=val or param="val"? */ @@ -256,11 +488,9 @@ else if (val == param+strlen(param)+2) { val[-2] = '='; memmove(val-1, val, strlen(val)+1); - val--; } else BUG(); } - return 0; } /* Anything after -- gets handed straight to init. */ @@ -272,7 +502,7 @@ if (panic_later) return 0; - repair_env_string(param, val, unused, NULL); + repair_env_string(param, val); for (i = 0; argv_init[i]; i++) { if (i == MAX_INIT_ARGS) { @@ -292,14 +522,16 @@ static int __init unknown_bootoption(char *param, char *val, const char *unused, void *arg) { - repair_env_string(param, val, unused, NULL); + size_t len = strlen(param); + + repair_env_string(param, val); /* Handle obsolete-style parameters */ if (obsolete_checksetup(param)) return 0; /* Unused module parameter. */ - if (strchr(param, '.') && (!val || strchr(param, '.') < val)) + if (strnchr(param, len, '.')) return 0; if (panic_later) @@ -313,7 +545,7 @@ panic_later = "env"; panic_param = param; } - if (!strncmp(param, envp_init[i], val - param)) + if (!strncmp(param, envp_init[i], len+1)) break; } envp_init[i] = param; @@ -374,13 +606,51 @@ */ static void __init setup_command_line(char *command_line) { - saved_command_line = - memblock_virt_alloc(strlen(boot_command_line) + 1, 0); - initcall_command_line = - memblock_virt_alloc(strlen(boot_command_line) + 1, 0); - static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0); - strcpy(saved_command_line, boot_command_line); - strcpy(static_command_line, command_line); + size_t len, xlen = 0, ilen = 0; + + if (extra_command_line) + xlen = strlen(extra_command_line); + if (extra_init_args) + ilen = strlen(extra_init_args) + 4; /* for " -- " */ + + len = xlen + strlen(boot_command_line) + 1; + + saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES); + if (!saved_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen); + + static_command_line = memblock_alloc(len, SMP_CACHE_BYTES); + if (!static_command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + if (xlen) { + /* + * We have to put extra_command_line before boot command + * lines because there could be dashes (separator of init + * command line) in the command lines. + */ + strcpy(saved_command_line, extra_command_line); + strcpy(static_command_line, extra_command_line); + } + strcpy(saved_command_line + xlen, boot_command_line); + strcpy(static_command_line + xlen, command_line); + + if (ilen) { + /* + * Append supplemental init boot args to saved_command_line + * so that user can check what command line options passed + * to init. + */ + len = strlen(saved_command_line); + if (initargs_found) { + saved_command_line[len++] = ' '; + } else { + strcpy(saved_command_line + len, " -- "); + len += 4; + } + + strcpy(saved_command_line + len, extra_init_args); + } } /* @@ -394,7 +664,7 @@ static __initdata DECLARE_COMPLETION(kthreadd_done); -static noinline void __ref rest_init(void) +noinline void __ref rest_init(void) { struct task_struct *tsk; int pid; @@ -424,7 +694,7 @@ /* * Enable might_sleep() and smp_processor_id() checks. - * They cannot be enabled earlier because with CONFIG_PREEMPT=y + * They cannot be enabled earlier because with CONFIG_PREEMPTION=y * kernel_thread() would trigger might_sleep() splats. With * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled * already, but it's stuck on the kthreadd_done completion. @@ -494,7 +764,9 @@ } #endif -void __init __weak mem_encrypt_init(void) { } +void __init __weak poking_init(void) { } + +void __init __weak pgtable_cache_init(void) { } bool initcall_debug; core_param(initcall_debug, initcall_debug, bool, 0644); @@ -542,19 +814,32 @@ * bigger than MAX_ORDER unless SPARSEMEM. */ page_ext_init_flatmem(); + init_mem_debugging_and_hardening(); + kfence_alloc_pool(); report_meminit(); + stack_depot_init(); mem_init(); + /* page_owner must be initialized after buddy is ready */ + page_ext_init_flatmem_late(); kmem_cache_init(); + kmemleak_init(); pgtable_init(); + debug_objects_mem_init(); vmalloc_init(); ioremap_huge_init(); /* Should be run before the first non-init thread is created */ init_espfix_bsp(); /* Should be run after espfix64 is set up. */ pti_init(); + mm_cache_init(); } -asmlinkage __visible void __init start_kernel(void) +void __init __weak arch_call_rest_init(void) +{ + rest_init(); +} + +asmlinkage __visible void __init __no_sanitize_address start_kernel(void) { char *command_line; char *after_dashes; @@ -575,12 +860,12 @@ boot_cpu_init(); page_address_init(); pr_notice("%s", linux_banner); + early_security_init(); setup_arch(&command_line); - mm_init_cpumask(&init_mm); + setup_boot_config(command_line); setup_command_line(command_line); setup_nr_cpu_ids(); setup_per_cpu_areas(); - softirq_early_init(); smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ boot_cpu_hotplug_init(); @@ -589,10 +874,10 @@ #ifdef CONFIG_ARCH_ROCKCHIP { - const char *s = boot_command_line; - const char *e = &boot_command_line[strlen(boot_command_line)]; + const char *s = saved_command_line; + const char *e = &saved_command_line[strlen(saved_command_line)]; int n = - pr_notice("Kernel command line: %s\n", boot_command_line); + pr_notice("Kernel command line: %s\n", saved_command_line); n -= strlen("Kernel command line: "); s += n; /* command line maybe too long to print one time */ @@ -602,7 +887,7 @@ } } #else - pr_notice("Kernel command line: %s\n", boot_command_line); + pr_notice("Kernel command line: %s\n", saved_command_line); #endif /* parameters may set static keys */ jump_label_init(); @@ -614,6 +899,9 @@ if (!IS_ERR_OR_NULL(after_dashes)) parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, NULL, set_init_arg); + if (extra_init_args) + parse_args("Setting extra init args", extra_init_args, + NULL, 0, -1, -1, NULL, set_init_arg); /* * These use large bootmem allocations and must precede @@ -624,7 +912,7 @@ sort_main_extable(); trap_init(); mm_init(); - + poking_init(); ftrace_init(); /* trace_printk can be enabled here */ @@ -636,11 +924,7 @@ * time - but meanwhile we still have a functioning scheduler. */ sched_init(); - /* - * Disable preemption - early bootup scheduling is extremely - * fragile until we cpu_idle() for the first time. - */ - preempt_disable(); + if (WARN(!irqs_disabled(), "Interrupts were enabled *very* early, fixing it\n")) local_irq_disable(); @@ -677,21 +961,19 @@ hrtimers_init(); softirq_init(); timekeeping_init(); + kfence_init(); + time_init(); /* * For best initial stack canary entropy, prepare it after: * - setup_arch() for any UEFI RNG entropy and boot cmdline access - * - timekeeping_init() for ktime entropy used in rand_initialize() - * - rand_initialize() to get any arch-specific entropy like RDRAND - * - add_latent_entropy() to get any latent entropy - * - adding command line entropy + * - timekeeping_init() for ktime entropy used in random_init() + * - time_init() for making random_get_entropy() work on some platforms + * - random_init() to initialize the RNG from from early entropy sources */ - rand_initialize(); - add_latent_entropy(); - add_device_randomness(command_line, strlen(command_line)); + random_init(command_line); boot_init_stack_canary(); - time_init(); perf_event_init(); profile_init(); call_function_init(); @@ -721,14 +1003,6 @@ */ locking_selftest(); - /* - * This needs to be called before any devices perform DMA - * operations that might use the SWIOTLB bounce buffers. It will - * mark the bounce buffers as decrypted so that their usage will - * not cause "plain-text" data to be decrypted when accessed. - */ - mem_encrypt_init(); - #ifdef CONFIG_BLK_DEV_INITRD if (initrd_start && !initrd_below_start_ok && page_to_pfn(virt_to_page((void *)initrd_start)) < min_low_pfn) { @@ -738,8 +1012,6 @@ initrd_start = 0; } #endif - kmemleak_init(); - debug_objects_mem_init(); setup_per_cpu_pageset(); numa_policy_init(); acpi_early_init(); @@ -747,6 +1019,9 @@ late_time_init(); sched_clock_init(); calibrate_delay(); + + arch_cpu_finalize_init(); + pid_idr_init(); anon_vma_init(); #ifdef CONFIG_X86 @@ -773,18 +1048,13 @@ taskstats_init_early(); delayacct_init(); - check_bugs(); - acpi_subsystem_init(); arch_post_acpi_subsys_init(); sfi_init_late(); - - if (efi_enabled(EFI_RUNTIME_SERVICES)) { - efi_free_boot_services(); - } + kcsan_init(); /* Do the rest non-__init'ed, we're now alive */ - rest_init(); + arch_call_rest_init(); prevent_tail_call_optimization(); } @@ -818,14 +1088,22 @@ str_entry = strsep(&str, ","); if (str_entry) { pr_debug("blacklisting initcall %s\n", str_entry); - entry = alloc_bootmem(sizeof(*entry)); - entry->buf = alloc_bootmem(strlen(str_entry) + 1); + entry = memblock_alloc(sizeof(*entry), + SMP_CACHE_BYTES); + if (!entry) + panic("%s: Failed to allocate %zu bytes\n", + __func__, sizeof(*entry)); + entry->buf = memblock_alloc(strlen(str_entry) + 1, + SMP_CACHE_BYTES); + if (!entry->buf) + panic("%s: Failed to allocate %zu bytes\n", + __func__, strlen(str_entry) + 1); strcpy(entry->buf, str_entry); list_add(&entry->next, &blacklisted_initcalls); } } while (str_entry); - return 0; + return 1; } static bool __init_or_module initcall_blacklisted(initcall_t fn) @@ -874,7 +1152,7 @@ { ktime_t *calltime = (ktime_t *)data; - printk(KERN_DEBUG "calling %pF @ %i\n", fn, task_pid_nr(current)); + printk(KERN_DEBUG "calling %pS @ %i\n", fn, task_pid_nr(current)); *calltime = ktime_get(); } @@ -888,7 +1166,7 @@ rettime = ktime_get(); delta = ktime_sub(rettime, *calltime); duration = (unsigned long long) ktime_to_ns(delta) >> 10; - printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n", + printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n", fn, ret, duration); } @@ -945,7 +1223,7 @@ strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); local_irq_enable(); } - WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf); + WARN(msgbuf[0], "initcall %pS returned with %s\n", fn, msgbuf); add_latent_entropy(); return ret; @@ -976,7 +1254,7 @@ }; /* Keep these in sync with initcalls in include/linux/init.h */ -static char *initcall_level_names[] __initdata = { +static const char *initcall_level_names[] __initdata = { "pure", "core", "postcore", @@ -986,6 +1264,12 @@ "device", "late", }; + +static int __init ignore_unknown_bootoption(char *param, char *val, + const char *unused, void *arg) +{ + return 0; +} #ifdef CONFIG_INITCALL_ASYNC extern initcall_entry_t __initcall0s_start[]; @@ -1164,16 +1448,15 @@ } #endif /* CONFIG_INITCALL_ASYNC */ -static void __init do_initcall_level(int level) +static void __init do_initcall_level(int level, char *command_line) { initcall_entry_t *fn; - strcpy(initcall_command_line, saved_command_line); parse_args(initcall_level_names[level], - initcall_command_line, __start___param, + command_line, __start___param, __stop___param - __start___param, level, level, - NULL, &repair_env_string); + NULL, ignore_unknown_bootoption); trace_initcall_level(initcall_level_names[level]); @@ -1190,13 +1473,24 @@ static void __init do_initcalls(void) { int level; + size_t len = strlen(saved_command_line) + 1; + char *command_line; #ifdef CONFIG_INITCALL_ASYNC initcall_init_workers(); #endif - for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) - do_initcall_level(level); + command_line = kzalloc(len, GFP_KERNEL); + if (!command_line) + panic("%s: Failed to allocate %zu bytes\n", __func__, len); + + for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) { + /* Parser modifies command_line, restore it each time */ + strcpy(command_line, saved_command_line); + do_initcall_level(level, command_line); + } + + kfree(command_line); #ifdef CONFIG_INITCALL_ASYNC initcall_free_works(); @@ -1213,7 +1507,6 @@ static void __init do_basic_setup(void) { cpuset_init_smp(); - shmem_init(); driver_init(); init_irq_proc(); do_ctors(); @@ -1230,24 +1523,19 @@ do_one_initcall(initcall_from_entry(fn)); } -/* - * This function requests modules which should be loaded by default and is - * called twice right after initrd is mounted and right before init is - * exec'd. If such modules are on either initrd or rootfs, they will be - * loaded before control is passed to userland. - */ -void __init load_default_modules(void) -{ - load_default_elevator_module(); -} - static int run_init_process(const char *init_filename) { + const char *const *p; + argv_init[0] = init_filename; pr_info("Run %s as init process\n", init_filename); - return do_execve(getname_kernel(init_filename), - (const char __user *const __user *)argv_init, - (const char __user *const __user *)envp_init); + pr_debug(" with arguments:\n"); + for (p = argv_init; *p; p++) + pr_debug(" %s\n", *p); + pr_debug(" with environment:\n"); + for (p = envp_init; *p; p++) + pr_debug(" %s\n", *p); + return kernel_execve(init_filename, argv_init, envp_init); } static int try_to_run_init_process(const char *init_filename) @@ -1270,7 +1558,9 @@ bool rodata_enabled __ro_after_init = true; static int __init set_debug_rodata(char *str) { - return strtobool(str, &rodata_enabled); + if (strtobool(str, &rodata_enabled)) + pr_warn("Invalid option string for rodata: '%s'\n", str); + return 1; } __setup("rodata=", set_debug_rodata); #endif @@ -1280,16 +1570,21 @@ { if (rodata_enabled) { /* - * load_module() results in W+X mappings, which are cleaned up - * with call_rcu_sched(). Let's make sure that queued work is + * load_module() results in W+X mappings, which are cleaned + * up with call_rcu(). Let's make sure that queued work is * flushed so that we don't hit false positives looking for * insecure pages which are W+X. */ - rcu_barrier_sched(); + rcu_barrier(); mark_rodata_ro(); rodata_test(); } else pr_info("Kernel memory protection disabled.\n"); +} +#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX) +static inline void mark_readonly(void) +{ + pr_warn("Kernel memory protection not selected by kernel config.\n"); } #else static inline void mark_readonly(void) @@ -1298,6 +1593,11 @@ } #endif +void __weak free_initmem(void) +{ + free_initmem_default(POISON_FREE_INITMEM); +} + static int __ref kernel_init(void *unused) { int ret; @@ -1305,8 +1605,9 @@ kernel_init_freeable(); /* need to finish all async __init code before freeing the memory */ async_synchronize_full(); + kprobe_free_init_mem(); ftrace_free_init_mem(); - jump_label_invalidate_initmem(); + kgdb_free_init_mem(); free_initmem(); mark_readonly(); @@ -1320,6 +1621,8 @@ numa_default_policy(); rcu_end_inkernel_boot(); + + do_sysctl_args(); if (ramdisk_execute_command) { ret = run_init_process(ramdisk_execute_command); @@ -1342,6 +1645,16 @@ panic("Requested init %s failed (error %d).", execute_command, ret); } + + if (CONFIG_DEFAULT_INIT[0] != '\0') { + ret = run_init_process(CONFIG_DEFAULT_INIT); + if (ret) + pr_err("Default init %s failed (error %d)\n", + CONFIG_DEFAULT_INIT, ret); + else + return 0; + } + if (!try_to_run_init_process("/sbin/init") || !try_to_run_init_process("/etc/init") || !try_to_run_init_process("/bin/init") || @@ -1350,6 +1663,21 @@ panic("No working init found. Try passing init= option to kernel. " "See Linux Documentation/admin-guide/init.rst for guidance."); +} + +/* Open /dev/console, for stdin/stdout/stderr, this should never fail */ +void __init console_on_rootfs(void) +{ + struct file *file = filp_open("/dev/console", O_RDWR, 0); + + if (IS_ERR(file)) { + pr_err("Warning: unable to open an initial console.\n"); + return; + } + init_dup(file); + init_dup(file); + init_dup(file); + fput(file); } static noinline void __init kernel_init_freeable(void) @@ -1375,42 +1703,37 @@ init_mm_internals(); + rcu_init_tasks_generic(); do_pre_smp_initcalls(); lockup_detector_init(); smp_init(); sched_init_smp(); -#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT - kthread_run(defer_free_bootmem, NULL, "defer_mem"); +#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP) + kthread_run(defer_free_memblock, NULL, "defer_mem"); #endif + padata_init(); page_alloc_init_late(); /* Initialize page ext after all struct pages are initialized. */ page_ext_init(); do_basic_setup(); + kunit_run_all_tests(); + #if IS_BUILTIN(CONFIG_INITRD_ASYNC) async_synchronize_full(); #endif - /* Open the /dev/console on the rootfs, this should never fail */ - if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) - pr_err("Warning: unable to open an initial console.\n"); + console_on_rootfs(); - (void) ksys_dup(0); - (void) ksys_dup(0); /* * check if there is an early userspace init. If yes, let it do all * the work */ - - if (!ramdisk_execute_command) - ramdisk_execute_command = "/init"; - - if (ksys_access((const char __user *) - ramdisk_execute_command, 0) != 0) { + if (init_eaccess(ramdisk_execute_command) != 0) { ramdisk_execute_command = NULL; prepare_namespace(); } @@ -1425,5 +1748,4 @@ */ integrity_load_keys(); - load_default_modules(); } -- Gitblit v1.6.2