.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * linux/init/main.c |
---|
3 | 4 | * |
---|
.. | .. |
---|
25 | 26 | #include <linux/ioport.h> |
---|
26 | 27 | #include <linux/init.h> |
---|
27 | 28 | #include <linux/initrd.h> |
---|
28 | | -#include <linux/bootmem.h> |
---|
| 29 | +#include <linux/memblock.h> |
---|
29 | 30 | #include <linux/acpi.h> |
---|
| 31 | +#include <linux/bootconfig.h> |
---|
30 | 32 | #include <linux/console.h> |
---|
31 | 33 | #include <linux/nmi.h> |
---|
32 | 34 | #include <linux/percpu.h> |
---|
33 | 35 | #include <linux/kmod.h> |
---|
| 36 | +#include <linux/kprobes.h> |
---|
34 | 37 | #include <linux/vmalloc.h> |
---|
35 | 38 | #include <linux/kernel_stat.h> |
---|
36 | 39 | #include <linux/start_kernel.h> |
---|
37 | 40 | #include <linux/security.h> |
---|
38 | 41 | #include <linux/smp.h> |
---|
39 | 42 | #include <linux/profile.h> |
---|
| 43 | +#include <linux/kfence.h> |
---|
40 | 44 | #include <linux/rcupdate.h> |
---|
41 | 45 | #include <linux/moduleparam.h> |
---|
42 | 46 | #include <linux/kallsyms.h> |
---|
.. | .. |
---|
61 | 65 | #include <linux/debugobjects.h> |
---|
62 | 66 | #include <linux/lockdep.h> |
---|
63 | 67 | #include <linux/kmemleak.h> |
---|
| 68 | +#include <linux/padata.h> |
---|
64 | 69 | #include <linux/pid_namespace.h> |
---|
65 | | -#include <linux/device.h> |
---|
| 70 | +#include <linux/device/driver.h> |
---|
66 | 71 | #include <linux/kthread.h> |
---|
67 | 72 | #include <linux/sched.h> |
---|
68 | 73 | #include <linux/sched/init.h> |
---|
.. | .. |
---|
92 | 97 | #include <linux/rodata_test.h> |
---|
93 | 98 | #include <linux/jump_label.h> |
---|
94 | 99 | #include <linux/mem_encrypt.h> |
---|
| 100 | +#include <linux/kcsan.h> |
---|
| 101 | +#include <linux/init_syscalls.h> |
---|
| 102 | +#include <linux/stackdepot.h> |
---|
95 | 103 | |
---|
96 | 104 | #include <asm/io.h> |
---|
97 | 105 | #include <asm/bugs.h> |
---|
.. | .. |
---|
101 | 109 | |
---|
102 | 110 | #define CREATE_TRACE_POINTS |
---|
103 | 111 | #include <trace/events/initcall.h> |
---|
| 112 | + |
---|
| 113 | +#include <kunit/test.h> |
---|
104 | 114 | |
---|
105 | 115 | static int kernel_init(void *); |
---|
106 | 116 | |
---|
.. | .. |
---|
133 | 143 | char __initdata boot_command_line[COMMAND_LINE_SIZE]; |
---|
134 | 144 | /* Untouched saved command line (eg. for /proc) */ |
---|
135 | 145 | char *saved_command_line; |
---|
136 | | -EXPORT_SYMBOL_GPL(saved_command_line); |
---|
137 | 146 | /* Command line for parameter parsing */ |
---|
138 | 147 | static char *static_command_line; |
---|
139 | | -/* Command line for per-initcall parameter parsing */ |
---|
140 | | -static char *initcall_command_line; |
---|
| 148 | +/* Untouched extra command line */ |
---|
| 149 | +static char *extra_command_line; |
---|
| 150 | +/* Extra init arguments */ |
---|
| 151 | +static char *extra_init_args; |
---|
| 152 | + |
---|
| 153 | +#ifdef CONFIG_BOOT_CONFIG |
---|
| 154 | +/* Is bootconfig on command line? */ |
---|
| 155 | +static bool bootconfig_found; |
---|
| 156 | +static bool initargs_found; |
---|
| 157 | +#else |
---|
| 158 | +# define bootconfig_found false |
---|
| 159 | +# define initargs_found false |
---|
| 160 | +#endif |
---|
141 | 161 | |
---|
142 | 162 | static char *execute_command; |
---|
143 | | -static char *ramdisk_execute_command; |
---|
| 163 | +static char *ramdisk_execute_command = "/init"; |
---|
144 | 164 | |
---|
145 | 165 | /* |
---|
146 | 166 | * Used to generate warnings if static_key manipulation functions are used |
---|
.. | .. |
---|
245 | 265 | |
---|
246 | 266 | early_param("loglevel", loglevel); |
---|
247 | 267 | |
---|
248 | | -/* Change NUL term back to "=", to make "param" the whole string. */ |
---|
249 | | -static int __init repair_env_string(char *param, char *val, |
---|
| 268 | +#ifdef CONFIG_BLK_DEV_INITRD |
---|
| 269 | +static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) |
---|
| 270 | +{ |
---|
| 271 | + u32 size, csum; |
---|
| 272 | + char *data; |
---|
| 273 | + u32 *hdr; |
---|
| 274 | + int i; |
---|
| 275 | + |
---|
| 276 | + if (!initrd_end) |
---|
| 277 | + return NULL; |
---|
| 278 | + |
---|
| 279 | + data = (char *)initrd_end - BOOTCONFIG_MAGIC_LEN; |
---|
| 280 | + /* |
---|
| 281 | + * Since Grub may align the size of initrd to 4, we must |
---|
| 282 | + * check the preceding 3 bytes as well. |
---|
| 283 | + */ |
---|
| 284 | + for (i = 0; i < 4; i++) { |
---|
| 285 | + if (!memcmp(data, BOOTCONFIG_MAGIC, BOOTCONFIG_MAGIC_LEN)) |
---|
| 286 | + goto found; |
---|
| 287 | + data--; |
---|
| 288 | + } |
---|
| 289 | + return NULL; |
---|
| 290 | + |
---|
| 291 | +found: |
---|
| 292 | + hdr = (u32 *)(data - 8); |
---|
| 293 | + size = le32_to_cpu(hdr[0]); |
---|
| 294 | + csum = le32_to_cpu(hdr[1]); |
---|
| 295 | + |
---|
| 296 | + data = ((void *)hdr) - size; |
---|
| 297 | + if ((unsigned long)data < initrd_start) { |
---|
| 298 | + pr_err("bootconfig size %d is greater than initrd size %ld\n", |
---|
| 299 | + size, initrd_end - initrd_start); |
---|
| 300 | + return NULL; |
---|
| 301 | + } |
---|
| 302 | + |
---|
| 303 | + /* Remove bootconfig from initramfs/initrd */ |
---|
| 304 | + initrd_end = (unsigned long)data; |
---|
| 305 | + if (_size) |
---|
| 306 | + *_size = size; |
---|
| 307 | + if (_csum) |
---|
| 308 | + *_csum = csum; |
---|
| 309 | + |
---|
| 310 | + return data; |
---|
| 311 | +} |
---|
| 312 | +#else |
---|
| 313 | +static void * __init get_boot_config_from_initrd(u32 *_size, u32 *_csum) |
---|
| 314 | +{ |
---|
| 315 | + return NULL; |
---|
| 316 | +} |
---|
| 317 | +#endif |
---|
| 318 | + |
---|
| 319 | +#ifdef CONFIG_BOOT_CONFIG |
---|
| 320 | + |
---|
| 321 | +static char xbc_namebuf[XBC_KEYLEN_MAX] __initdata; |
---|
| 322 | + |
---|
| 323 | +#define rest(dst, end) ((end) > (dst) ? (end) - (dst) : 0) |
---|
| 324 | + |
---|
| 325 | +static int __init xbc_snprint_cmdline(char *buf, size_t size, |
---|
| 326 | + struct xbc_node *root) |
---|
| 327 | +{ |
---|
| 328 | + struct xbc_node *knode, *vnode; |
---|
| 329 | + char *end = buf + size; |
---|
| 330 | + const char *val; |
---|
| 331 | + int ret; |
---|
| 332 | + |
---|
| 333 | + xbc_node_for_each_key_value(root, knode, val) { |
---|
| 334 | + ret = xbc_node_compose_key_after(root, knode, |
---|
| 335 | + xbc_namebuf, XBC_KEYLEN_MAX); |
---|
| 336 | + if (ret < 0) |
---|
| 337 | + return ret; |
---|
| 338 | + |
---|
| 339 | + vnode = xbc_node_get_child(knode); |
---|
| 340 | + if (!vnode) { |
---|
| 341 | + ret = snprintf(buf, rest(buf, end), "%s ", xbc_namebuf); |
---|
| 342 | + if (ret < 0) |
---|
| 343 | + return ret; |
---|
| 344 | + buf += ret; |
---|
| 345 | + continue; |
---|
| 346 | + } |
---|
| 347 | + xbc_array_for_each_value(vnode, val) { |
---|
| 348 | + ret = snprintf(buf, rest(buf, end), "%s=\"%s\" ", |
---|
| 349 | + xbc_namebuf, val); |
---|
| 350 | + if (ret < 0) |
---|
| 351 | + return ret; |
---|
| 352 | + buf += ret; |
---|
| 353 | + } |
---|
| 354 | + } |
---|
| 355 | + |
---|
| 356 | + return buf - (end - size); |
---|
| 357 | +} |
---|
| 358 | +#undef rest |
---|
| 359 | + |
---|
| 360 | +/* Make an extra command line under given key word */ |
---|
| 361 | +static char * __init xbc_make_cmdline(const char *key) |
---|
| 362 | +{ |
---|
| 363 | + struct xbc_node *root; |
---|
| 364 | + char *new_cmdline; |
---|
| 365 | + int ret, len = 0; |
---|
| 366 | + |
---|
| 367 | + root = xbc_find_node(key); |
---|
| 368 | + if (!root) |
---|
| 369 | + return NULL; |
---|
| 370 | + |
---|
| 371 | + /* Count required buffer size */ |
---|
| 372 | + len = xbc_snprint_cmdline(NULL, 0, root); |
---|
| 373 | + if (len <= 0) |
---|
| 374 | + return NULL; |
---|
| 375 | + |
---|
| 376 | + new_cmdline = memblock_alloc(len + 1, SMP_CACHE_BYTES); |
---|
| 377 | + if (!new_cmdline) { |
---|
| 378 | + pr_err("Failed to allocate memory for extra kernel cmdline.\n"); |
---|
| 379 | + return NULL; |
---|
| 380 | + } |
---|
| 381 | + |
---|
| 382 | + ret = xbc_snprint_cmdline(new_cmdline, len + 1, root); |
---|
| 383 | + if (ret < 0 || ret > len) { |
---|
| 384 | + pr_err("Failed to print extra kernel cmdline.\n"); |
---|
| 385 | + memblock_free(__pa(new_cmdline), len + 1); |
---|
| 386 | + return NULL; |
---|
| 387 | + } |
---|
| 388 | + |
---|
| 389 | + return new_cmdline; |
---|
| 390 | +} |
---|
| 391 | + |
---|
| 392 | +static int __init bootconfig_params(char *param, char *val, |
---|
250 | 393 | const char *unused, void *arg) |
---|
| 394 | +{ |
---|
| 395 | + if (strcmp(param, "bootconfig") == 0) { |
---|
| 396 | + bootconfig_found = true; |
---|
| 397 | + } |
---|
| 398 | + return 0; |
---|
| 399 | +} |
---|
| 400 | + |
---|
| 401 | +static void __init setup_boot_config(const char *cmdline) |
---|
| 402 | +{ |
---|
| 403 | + static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata; |
---|
| 404 | + const char *msg; |
---|
| 405 | + int pos; |
---|
| 406 | + u32 size, csum; |
---|
| 407 | + char *data, *copy, *err; |
---|
| 408 | + int ret; |
---|
| 409 | + |
---|
| 410 | + /* Cut out the bootconfig data even if we have no bootconfig option */ |
---|
| 411 | + data = get_boot_config_from_initrd(&size, &csum); |
---|
| 412 | + |
---|
| 413 | + strlcpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE); |
---|
| 414 | + err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL, |
---|
| 415 | + bootconfig_params); |
---|
| 416 | + |
---|
| 417 | + if (IS_ERR(err) || !bootconfig_found) |
---|
| 418 | + return; |
---|
| 419 | + |
---|
| 420 | + /* parse_args() stops at '--' and returns an address */ |
---|
| 421 | + if (err) |
---|
| 422 | + initargs_found = true; |
---|
| 423 | + |
---|
| 424 | + if (!data) { |
---|
| 425 | + pr_err("'bootconfig' found on command line, but no bootconfig found\n"); |
---|
| 426 | + return; |
---|
| 427 | + } |
---|
| 428 | + |
---|
| 429 | + if (size >= XBC_DATA_MAX) { |
---|
| 430 | + pr_err("bootconfig size %d greater than max size %d\n", |
---|
| 431 | + size, XBC_DATA_MAX); |
---|
| 432 | + return; |
---|
| 433 | + } |
---|
| 434 | + |
---|
| 435 | + if (xbc_calc_checksum(data, size) != csum) { |
---|
| 436 | + pr_err("bootconfig checksum failed\n"); |
---|
| 437 | + return; |
---|
| 438 | + } |
---|
| 439 | + |
---|
| 440 | + copy = memblock_alloc(size + 1, SMP_CACHE_BYTES); |
---|
| 441 | + if (!copy) { |
---|
| 442 | + pr_err("Failed to allocate memory for bootconfig\n"); |
---|
| 443 | + return; |
---|
| 444 | + } |
---|
| 445 | + |
---|
| 446 | + memcpy(copy, data, size); |
---|
| 447 | + copy[size] = '\0'; |
---|
| 448 | + |
---|
| 449 | + ret = xbc_init(copy, &msg, &pos); |
---|
| 450 | + if (ret < 0) { |
---|
| 451 | + if (pos < 0) |
---|
| 452 | + pr_err("Failed to init bootconfig: %s.\n", msg); |
---|
| 453 | + else |
---|
| 454 | + pr_err("Failed to parse bootconfig: %s at %d.\n", |
---|
| 455 | + msg, pos); |
---|
| 456 | + } else { |
---|
| 457 | + pr_info("Load bootconfig: %d bytes %d nodes\n", size, ret); |
---|
| 458 | + /* keys starting with "kernel." are passed via cmdline */ |
---|
| 459 | + extra_command_line = xbc_make_cmdline("kernel"); |
---|
| 460 | + /* Also, "init." keys are init arguments */ |
---|
| 461 | + extra_init_args = xbc_make_cmdline("init"); |
---|
| 462 | + } |
---|
| 463 | + return; |
---|
| 464 | +} |
---|
| 465 | + |
---|
| 466 | +#else |
---|
| 467 | + |
---|
| 468 | +static void __init setup_boot_config(const char *cmdline) |
---|
| 469 | +{ |
---|
| 470 | + /* Remove bootconfig data from initrd */ |
---|
| 471 | + get_boot_config_from_initrd(NULL, NULL); |
---|
| 472 | +} |
---|
| 473 | + |
---|
| 474 | +static int __init warn_bootconfig(char *str) |
---|
| 475 | +{ |
---|
| 476 | + pr_warn("WARNING: 'bootconfig' found on the kernel command line but CONFIG_BOOT_CONFIG is not set.\n"); |
---|
| 477 | + return 0; |
---|
| 478 | +} |
---|
| 479 | +early_param("bootconfig", warn_bootconfig); |
---|
| 480 | + |
---|
| 481 | +#endif |
---|
| 482 | + |
---|
| 483 | +/* Change NUL term back to "=", to make "param" the whole string. */ |
---|
| 484 | +static void __init repair_env_string(char *param, char *val) |
---|
251 | 485 | { |
---|
252 | 486 | if (val) { |
---|
253 | 487 | /* param=val or param="val"? */ |
---|
.. | .. |
---|
256 | 490 | else if (val == param+strlen(param)+2) { |
---|
257 | 491 | val[-2] = '='; |
---|
258 | 492 | memmove(val-1, val, strlen(val)+1); |
---|
259 | | - val--; |
---|
260 | 493 | } else |
---|
261 | 494 | BUG(); |
---|
262 | 495 | } |
---|
263 | | - return 0; |
---|
264 | 496 | } |
---|
265 | 497 | |
---|
266 | 498 | /* Anything after -- gets handed straight to init. */ |
---|
.. | .. |
---|
272 | 504 | if (panic_later) |
---|
273 | 505 | return 0; |
---|
274 | 506 | |
---|
275 | | - repair_env_string(param, val, unused, NULL); |
---|
| 507 | + repair_env_string(param, val); |
---|
276 | 508 | |
---|
277 | 509 | for (i = 0; argv_init[i]; i++) { |
---|
278 | 510 | if (i == MAX_INIT_ARGS) { |
---|
.. | .. |
---|
292 | 524 | static int __init unknown_bootoption(char *param, char *val, |
---|
293 | 525 | const char *unused, void *arg) |
---|
294 | 526 | { |
---|
295 | | - repair_env_string(param, val, unused, NULL); |
---|
| 527 | + size_t len = strlen(param); |
---|
| 528 | + |
---|
| 529 | + repair_env_string(param, val); |
---|
296 | 530 | |
---|
297 | 531 | /* Handle obsolete-style parameters */ |
---|
298 | 532 | if (obsolete_checksetup(param)) |
---|
299 | 533 | return 0; |
---|
300 | 534 | |
---|
301 | 535 | /* Unused module parameter. */ |
---|
302 | | - if (strchr(param, '.') && (!val || strchr(param, '.') < val)) |
---|
| 536 | + if (strnchr(param, len, '.')) |
---|
303 | 537 | return 0; |
---|
304 | 538 | |
---|
305 | 539 | if (panic_later) |
---|
.. | .. |
---|
313 | 547 | panic_later = "env"; |
---|
314 | 548 | panic_param = param; |
---|
315 | 549 | } |
---|
316 | | - if (!strncmp(param, envp_init[i], val - param)) |
---|
| 550 | + if (!strncmp(param, envp_init[i], len+1)) |
---|
317 | 551 | break; |
---|
318 | 552 | } |
---|
319 | 553 | envp_init[i] = param; |
---|
.. | .. |
---|
374 | 608 | */ |
---|
375 | 609 | static void __init setup_command_line(char *command_line) |
---|
376 | 610 | { |
---|
377 | | - saved_command_line = |
---|
378 | | - memblock_virt_alloc(strlen(boot_command_line) + 1, 0); |
---|
379 | | - initcall_command_line = |
---|
380 | | - memblock_virt_alloc(strlen(boot_command_line) + 1, 0); |
---|
381 | | - static_command_line = memblock_virt_alloc(strlen(command_line) + 1, 0); |
---|
382 | | - strcpy(saved_command_line, boot_command_line); |
---|
383 | | - strcpy(static_command_line, command_line); |
---|
| 611 | + size_t len, xlen = 0, ilen = 0; |
---|
| 612 | + |
---|
| 613 | + if (extra_command_line) |
---|
| 614 | + xlen = strlen(extra_command_line); |
---|
| 615 | + if (extra_init_args) |
---|
| 616 | + ilen = strlen(extra_init_args) + 4; /* for " -- " */ |
---|
| 617 | + |
---|
| 618 | + len = xlen + strlen(boot_command_line) + 1; |
---|
| 619 | + |
---|
| 620 | + saved_command_line = memblock_alloc(len + ilen, SMP_CACHE_BYTES); |
---|
| 621 | + if (!saved_command_line) |
---|
| 622 | + panic("%s: Failed to allocate %zu bytes\n", __func__, len + ilen); |
---|
| 623 | + |
---|
| 624 | + static_command_line = memblock_alloc(len, SMP_CACHE_BYTES); |
---|
| 625 | + if (!static_command_line) |
---|
| 626 | + panic("%s: Failed to allocate %zu bytes\n", __func__, len); |
---|
| 627 | + |
---|
| 628 | + if (xlen) { |
---|
| 629 | + /* |
---|
| 630 | + * We have to put extra_command_line before boot command |
---|
| 631 | + * lines because there could be dashes (separator of init |
---|
| 632 | + * command line) in the command lines. |
---|
| 633 | + */ |
---|
| 634 | + strcpy(saved_command_line, extra_command_line); |
---|
| 635 | + strcpy(static_command_line, extra_command_line); |
---|
| 636 | + } |
---|
| 637 | + strcpy(saved_command_line + xlen, boot_command_line); |
---|
| 638 | + strcpy(static_command_line + xlen, command_line); |
---|
| 639 | + |
---|
| 640 | + if (ilen) { |
---|
| 641 | + /* |
---|
| 642 | + * Append supplemental init boot args to saved_command_line |
---|
| 643 | + * so that user can check what command line options passed |
---|
| 644 | + * to init. |
---|
| 645 | + */ |
---|
| 646 | + len = strlen(saved_command_line); |
---|
| 647 | + if (initargs_found) { |
---|
| 648 | + saved_command_line[len++] = ' '; |
---|
| 649 | + } else { |
---|
| 650 | + strcpy(saved_command_line + len, " -- "); |
---|
| 651 | + len += 4; |
---|
| 652 | + } |
---|
| 653 | + |
---|
| 654 | + strcpy(saved_command_line + len, extra_init_args); |
---|
| 655 | + } |
---|
384 | 656 | } |
---|
385 | 657 | |
---|
386 | 658 | /* |
---|
.. | .. |
---|
394 | 666 | |
---|
395 | 667 | static __initdata DECLARE_COMPLETION(kthreadd_done); |
---|
396 | 668 | |
---|
397 | | -static noinline void __ref rest_init(void) |
---|
| 669 | +noinline void __ref rest_init(void) |
---|
398 | 670 | { |
---|
399 | 671 | struct task_struct *tsk; |
---|
400 | 672 | int pid; |
---|
.. | .. |
---|
424 | 696 | |
---|
425 | 697 | /* |
---|
426 | 698 | * Enable might_sleep() and smp_processor_id() checks. |
---|
427 | | - * They cannot be enabled earlier because with CONFIG_PREEMPT=y |
---|
| 699 | + * They cannot be enabled earlier because with CONFIG_PREEMPTION=y |
---|
428 | 700 | * kernel_thread() would trigger might_sleep() splats. With |
---|
429 | 701 | * CONFIG_PREEMPT_VOLUNTARY=y the init task might have scheduled |
---|
430 | 702 | * already, but it's stuck on the kthreadd_done completion. |
---|
.. | .. |
---|
496 | 768 | |
---|
497 | 769 | void __init __weak mem_encrypt_init(void) { } |
---|
498 | 770 | |
---|
| 771 | +void __init __weak poking_init(void) { } |
---|
| 772 | + |
---|
| 773 | +void __init __weak pgtable_cache_init(void) { } |
---|
| 774 | + |
---|
499 | 775 | bool initcall_debug; |
---|
500 | 776 | core_param(initcall_debug, initcall_debug, bool, 0644); |
---|
501 | 777 | |
---|
.. | .. |
---|
542 | 818 | * bigger than MAX_ORDER unless SPARSEMEM. |
---|
543 | 819 | */ |
---|
544 | 820 | page_ext_init_flatmem(); |
---|
| 821 | + init_mem_debugging_and_hardening(); |
---|
| 822 | + kfence_alloc_pool(); |
---|
545 | 823 | report_meminit(); |
---|
| 824 | + stack_depot_init(); |
---|
546 | 825 | mem_init(); |
---|
| 826 | + /* page_owner must be initialized after buddy is ready */ |
---|
| 827 | + page_ext_init_flatmem_late(); |
---|
547 | 828 | kmem_cache_init(); |
---|
| 829 | + kmemleak_init(); |
---|
548 | 830 | pgtable_init(); |
---|
| 831 | + debug_objects_mem_init(); |
---|
549 | 832 | vmalloc_init(); |
---|
550 | 833 | ioremap_huge_init(); |
---|
551 | 834 | /* Should be run before the first non-init thread is created */ |
---|
.. | .. |
---|
554 | 837 | pti_init(); |
---|
555 | 838 | } |
---|
556 | 839 | |
---|
557 | | -asmlinkage __visible void __init start_kernel(void) |
---|
| 840 | +void __init __weak arch_call_rest_init(void) |
---|
| 841 | +{ |
---|
| 842 | + rest_init(); |
---|
| 843 | +} |
---|
| 844 | + |
---|
| 845 | +asmlinkage __visible void __init __no_sanitize_address start_kernel(void) |
---|
558 | 846 | { |
---|
559 | 847 | char *command_line; |
---|
560 | 848 | char *after_dashes; |
---|
.. | .. |
---|
575 | 863 | boot_cpu_init(); |
---|
576 | 864 | page_address_init(); |
---|
577 | 865 | pr_notice("%s", linux_banner); |
---|
| 866 | + early_security_init(); |
---|
578 | 867 | setup_arch(&command_line); |
---|
579 | | - mm_init_cpumask(&init_mm); |
---|
| 868 | + setup_boot_config(command_line); |
---|
580 | 869 | setup_command_line(command_line); |
---|
581 | 870 | setup_nr_cpu_ids(); |
---|
582 | 871 | setup_per_cpu_areas(); |
---|
583 | | - softirq_early_init(); |
---|
584 | 872 | smp_prepare_boot_cpu(); /* arch-specific boot-cpu hooks */ |
---|
585 | 873 | boot_cpu_hotplug_init(); |
---|
586 | 874 | |
---|
.. | .. |
---|
589 | 877 | |
---|
590 | 878 | #ifdef CONFIG_ARCH_ROCKCHIP |
---|
591 | 879 | { |
---|
592 | | - const char *s = boot_command_line; |
---|
593 | | - const char *e = &boot_command_line[strlen(boot_command_line)]; |
---|
| 880 | + const char *s = saved_command_line; |
---|
| 881 | + const char *e = &saved_command_line[strlen(saved_command_line)]; |
---|
594 | 882 | int n = |
---|
595 | | - pr_notice("Kernel command line: %s\n", boot_command_line); |
---|
| 883 | + pr_notice("Kernel command line: %s\n", saved_command_line); |
---|
596 | 884 | n -= strlen("Kernel command line: "); |
---|
597 | 885 | s += n; |
---|
598 | 886 | /* command line maybe too long to print one time */ |
---|
.. | .. |
---|
602 | 890 | } |
---|
603 | 891 | } |
---|
604 | 892 | #else |
---|
605 | | - pr_notice("Kernel command line: %s\n", boot_command_line); |
---|
| 893 | + pr_notice("Kernel command line: %s\n", saved_command_line); |
---|
606 | 894 | #endif |
---|
607 | 895 | /* parameters may set static keys */ |
---|
608 | 896 | jump_label_init(); |
---|
.. | .. |
---|
614 | 902 | if (!IS_ERR_OR_NULL(after_dashes)) |
---|
615 | 903 | parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, |
---|
616 | 904 | NULL, set_init_arg); |
---|
| 905 | + if (extra_init_args) |
---|
| 906 | + parse_args("Setting extra init args", extra_init_args, |
---|
| 907 | + NULL, 0, -1, -1, NULL, set_init_arg); |
---|
617 | 908 | |
---|
618 | 909 | /* |
---|
619 | 910 | * These use large bootmem allocations and must precede |
---|
.. | .. |
---|
636 | 927 | * time - but meanwhile we still have a functioning scheduler. |
---|
637 | 928 | */ |
---|
638 | 929 | sched_init(); |
---|
639 | | - /* |
---|
640 | | - * Disable preemption - early bootup scheduling is extremely |
---|
641 | | - * fragile until we cpu_idle() for the first time. |
---|
642 | | - */ |
---|
643 | | - preempt_disable(); |
---|
| 930 | + |
---|
644 | 931 | if (WARN(!irqs_disabled(), |
---|
645 | 932 | "Interrupts were enabled *very* early, fixing it\n")) |
---|
646 | 933 | local_irq_disable(); |
---|
.. | .. |
---|
677 | 964 | hrtimers_init(); |
---|
678 | 965 | softirq_init(); |
---|
679 | 966 | timekeeping_init(); |
---|
| 967 | + kfence_init(); |
---|
| 968 | + time_init(); |
---|
680 | 969 | |
---|
681 | 970 | /* |
---|
682 | 971 | * For best initial stack canary entropy, prepare it after: |
---|
683 | 972 | * - setup_arch() for any UEFI RNG entropy and boot cmdline access |
---|
684 | | - * - timekeeping_init() for ktime entropy used in rand_initialize() |
---|
685 | | - * - rand_initialize() to get any arch-specific entropy like RDRAND |
---|
686 | | - * - add_latent_entropy() to get any latent entropy |
---|
687 | | - * - adding command line entropy |
---|
| 973 | + * - timekeeping_init() for ktime entropy used in random_init() |
---|
| 974 | + * - time_init() for making random_get_entropy() work on some platforms |
---|
| 975 | + * - random_init() to initialize the RNG from from early entropy sources |
---|
688 | 976 | */ |
---|
689 | | - rand_initialize(); |
---|
690 | | - add_latent_entropy(); |
---|
691 | | - add_device_randomness(command_line, strlen(command_line)); |
---|
| 977 | + random_init(command_line); |
---|
692 | 978 | boot_init_stack_canary(); |
---|
693 | 979 | |
---|
694 | | - time_init(); |
---|
695 | 980 | perf_event_init(); |
---|
696 | 981 | profile_init(); |
---|
697 | 982 | call_function_init(); |
---|
.. | .. |
---|
738 | 1023 | initrd_start = 0; |
---|
739 | 1024 | } |
---|
740 | 1025 | #endif |
---|
741 | | - kmemleak_init(); |
---|
742 | | - debug_objects_mem_init(); |
---|
743 | 1026 | setup_per_cpu_pageset(); |
---|
744 | 1027 | numa_policy_init(); |
---|
745 | 1028 | acpi_early_init(); |
---|
.. | .. |
---|
773 | 1056 | taskstats_init_early(); |
---|
774 | 1057 | delayacct_init(); |
---|
775 | 1058 | |
---|
| 1059 | + poking_init(); |
---|
776 | 1060 | check_bugs(); |
---|
777 | 1061 | |
---|
778 | 1062 | acpi_subsystem_init(); |
---|
779 | 1063 | arch_post_acpi_subsys_init(); |
---|
780 | 1064 | sfi_init_late(); |
---|
781 | | - |
---|
782 | | - if (efi_enabled(EFI_RUNTIME_SERVICES)) { |
---|
783 | | - efi_free_boot_services(); |
---|
784 | | - } |
---|
| 1065 | + kcsan_init(); |
---|
785 | 1066 | |
---|
786 | 1067 | /* Do the rest non-__init'ed, we're now alive */ |
---|
787 | | - rest_init(); |
---|
| 1068 | + arch_call_rest_init(); |
---|
788 | 1069 | |
---|
789 | 1070 | prevent_tail_call_optimization(); |
---|
790 | 1071 | } |
---|
.. | .. |
---|
818 | 1099 | str_entry = strsep(&str, ","); |
---|
819 | 1100 | if (str_entry) { |
---|
820 | 1101 | pr_debug("blacklisting initcall %s\n", str_entry); |
---|
821 | | - entry = alloc_bootmem(sizeof(*entry)); |
---|
822 | | - entry->buf = alloc_bootmem(strlen(str_entry) + 1); |
---|
| 1102 | + entry = memblock_alloc(sizeof(*entry), |
---|
| 1103 | + SMP_CACHE_BYTES); |
---|
| 1104 | + if (!entry) |
---|
| 1105 | + panic("%s: Failed to allocate %zu bytes\n", |
---|
| 1106 | + __func__, sizeof(*entry)); |
---|
| 1107 | + entry->buf = memblock_alloc(strlen(str_entry) + 1, |
---|
| 1108 | + SMP_CACHE_BYTES); |
---|
| 1109 | + if (!entry->buf) |
---|
| 1110 | + panic("%s: Failed to allocate %zu bytes\n", |
---|
| 1111 | + __func__, strlen(str_entry) + 1); |
---|
823 | 1112 | strcpy(entry->buf, str_entry); |
---|
824 | 1113 | list_add(&entry->next, &blacklisted_initcalls); |
---|
825 | 1114 | } |
---|
826 | 1115 | } while (str_entry); |
---|
827 | 1116 | |
---|
828 | | - return 0; |
---|
| 1117 | + return 1; |
---|
829 | 1118 | } |
---|
830 | 1119 | |
---|
831 | 1120 | static bool __init_or_module initcall_blacklisted(initcall_t fn) |
---|
.. | .. |
---|
874 | 1163 | { |
---|
875 | 1164 | ktime_t *calltime = (ktime_t *)data; |
---|
876 | 1165 | |
---|
877 | | - printk(KERN_DEBUG "calling %pF @ %i\n", fn, task_pid_nr(current)); |
---|
| 1166 | + printk(KERN_DEBUG "calling %pS @ %i\n", fn, task_pid_nr(current)); |
---|
878 | 1167 | *calltime = ktime_get(); |
---|
879 | 1168 | } |
---|
880 | 1169 | |
---|
.. | .. |
---|
888 | 1177 | rettime = ktime_get(); |
---|
889 | 1178 | delta = ktime_sub(rettime, *calltime); |
---|
890 | 1179 | duration = (unsigned long long) ktime_to_ns(delta) >> 10; |
---|
891 | | - printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n", |
---|
| 1180 | + printk(KERN_DEBUG "initcall %pS returned %d after %lld usecs\n", |
---|
892 | 1181 | fn, ret, duration); |
---|
893 | 1182 | } |
---|
894 | 1183 | |
---|
.. | .. |
---|
945 | 1234 | strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); |
---|
946 | 1235 | local_irq_enable(); |
---|
947 | 1236 | } |
---|
948 | | - WARN(msgbuf[0], "initcall %pF returned with %s\n", fn, msgbuf); |
---|
| 1237 | + WARN(msgbuf[0], "initcall %pS returned with %s\n", fn, msgbuf); |
---|
949 | 1238 | |
---|
950 | 1239 | add_latent_entropy(); |
---|
951 | 1240 | return ret; |
---|
.. | .. |
---|
976 | 1265 | }; |
---|
977 | 1266 | |
---|
978 | 1267 | /* Keep these in sync with initcalls in include/linux/init.h */ |
---|
979 | | -static char *initcall_level_names[] __initdata = { |
---|
| 1268 | +static const char *initcall_level_names[] __initdata = { |
---|
980 | 1269 | "pure", |
---|
981 | 1270 | "core", |
---|
982 | 1271 | "postcore", |
---|
.. | .. |
---|
986 | 1275 | "device", |
---|
987 | 1276 | "late", |
---|
988 | 1277 | }; |
---|
| 1278 | + |
---|
| 1279 | +static int __init ignore_unknown_bootoption(char *param, char *val, |
---|
| 1280 | + const char *unused, void *arg) |
---|
| 1281 | +{ |
---|
| 1282 | + return 0; |
---|
| 1283 | +} |
---|
989 | 1284 | |
---|
990 | 1285 | #ifdef CONFIG_INITCALL_ASYNC |
---|
991 | 1286 | extern initcall_entry_t __initcall0s_start[]; |
---|
.. | .. |
---|
1164 | 1459 | } |
---|
1165 | 1460 | #endif /* CONFIG_INITCALL_ASYNC */ |
---|
1166 | 1461 | |
---|
1167 | | -static void __init do_initcall_level(int level) |
---|
| 1462 | +static void __init do_initcall_level(int level, char *command_line) |
---|
1168 | 1463 | { |
---|
1169 | 1464 | initcall_entry_t *fn; |
---|
1170 | 1465 | |
---|
1171 | | - strcpy(initcall_command_line, saved_command_line); |
---|
1172 | 1466 | parse_args(initcall_level_names[level], |
---|
1173 | | - initcall_command_line, __start___param, |
---|
| 1467 | + command_line, __start___param, |
---|
1174 | 1468 | __stop___param - __start___param, |
---|
1175 | 1469 | level, level, |
---|
1176 | | - NULL, &repair_env_string); |
---|
| 1470 | + NULL, ignore_unknown_bootoption); |
---|
1177 | 1471 | |
---|
1178 | 1472 | trace_initcall_level(initcall_level_names[level]); |
---|
1179 | 1473 | |
---|
.. | .. |
---|
1190 | 1484 | static void __init do_initcalls(void) |
---|
1191 | 1485 | { |
---|
1192 | 1486 | int level; |
---|
| 1487 | + size_t len = strlen(saved_command_line) + 1; |
---|
| 1488 | + char *command_line; |
---|
1193 | 1489 | |
---|
1194 | 1490 | #ifdef CONFIG_INITCALL_ASYNC |
---|
1195 | 1491 | initcall_init_workers(); |
---|
1196 | 1492 | #endif |
---|
1197 | 1493 | |
---|
1198 | | - for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) |
---|
1199 | | - do_initcall_level(level); |
---|
| 1494 | + command_line = kzalloc(len, GFP_KERNEL); |
---|
| 1495 | + if (!command_line) |
---|
| 1496 | + panic("%s: Failed to allocate %zu bytes\n", __func__, len); |
---|
| 1497 | + |
---|
| 1498 | + for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++) { |
---|
| 1499 | + /* Parser modifies command_line, restore it each time */ |
---|
| 1500 | + strcpy(command_line, saved_command_line); |
---|
| 1501 | + do_initcall_level(level, command_line); |
---|
| 1502 | + } |
---|
| 1503 | + |
---|
| 1504 | + kfree(command_line); |
---|
1200 | 1505 | |
---|
1201 | 1506 | #ifdef CONFIG_INITCALL_ASYNC |
---|
1202 | 1507 | initcall_free_works(); |
---|
.. | .. |
---|
1213 | 1518 | static void __init do_basic_setup(void) |
---|
1214 | 1519 | { |
---|
1215 | 1520 | cpuset_init_smp(); |
---|
1216 | | - shmem_init(); |
---|
1217 | 1521 | driver_init(); |
---|
1218 | 1522 | init_irq_proc(); |
---|
1219 | 1523 | do_ctors(); |
---|
.. | .. |
---|
1230 | 1534 | do_one_initcall(initcall_from_entry(fn)); |
---|
1231 | 1535 | } |
---|
1232 | 1536 | |
---|
1233 | | -/* |
---|
1234 | | - * This function requests modules which should be loaded by default and is |
---|
1235 | | - * called twice right after initrd is mounted and right before init is |
---|
1236 | | - * exec'd. If such modules are on either initrd or rootfs, they will be |
---|
1237 | | - * loaded before control is passed to userland. |
---|
1238 | | - */ |
---|
1239 | | -void __init load_default_modules(void) |
---|
1240 | | -{ |
---|
1241 | | - load_default_elevator_module(); |
---|
1242 | | -} |
---|
1243 | | - |
---|
1244 | 1537 | static int run_init_process(const char *init_filename) |
---|
1245 | 1538 | { |
---|
| 1539 | + const char *const *p; |
---|
| 1540 | + |
---|
1246 | 1541 | argv_init[0] = init_filename; |
---|
1247 | 1542 | pr_info("Run %s as init process\n", init_filename); |
---|
1248 | | - return do_execve(getname_kernel(init_filename), |
---|
1249 | | - (const char __user *const __user *)argv_init, |
---|
1250 | | - (const char __user *const __user *)envp_init); |
---|
| 1543 | + pr_debug(" with arguments:\n"); |
---|
| 1544 | + for (p = argv_init; *p; p++) |
---|
| 1545 | + pr_debug(" %s\n", *p); |
---|
| 1546 | + pr_debug(" with environment:\n"); |
---|
| 1547 | + for (p = envp_init; *p; p++) |
---|
| 1548 | + pr_debug(" %s\n", *p); |
---|
| 1549 | + return kernel_execve(init_filename, argv_init, envp_init); |
---|
1251 | 1550 | } |
---|
1252 | 1551 | |
---|
1253 | 1552 | static int try_to_run_init_process(const char *init_filename) |
---|
.. | .. |
---|
1270 | 1569 | bool rodata_enabled __ro_after_init = true; |
---|
1271 | 1570 | static int __init set_debug_rodata(char *str) |
---|
1272 | 1571 | { |
---|
1273 | | - return strtobool(str, &rodata_enabled); |
---|
| 1572 | + if (strtobool(str, &rodata_enabled)) |
---|
| 1573 | + pr_warn("Invalid option string for rodata: '%s'\n", str); |
---|
| 1574 | + return 1; |
---|
1274 | 1575 | } |
---|
1275 | 1576 | __setup("rodata=", set_debug_rodata); |
---|
1276 | 1577 | #endif |
---|
.. | .. |
---|
1280 | 1581 | { |
---|
1281 | 1582 | if (rodata_enabled) { |
---|
1282 | 1583 | /* |
---|
1283 | | - * load_module() results in W+X mappings, which are cleaned up |
---|
1284 | | - * with call_rcu_sched(). Let's make sure that queued work is |
---|
| 1584 | + * load_module() results in W+X mappings, which are cleaned |
---|
| 1585 | + * up with call_rcu(). Let's make sure that queued work is |
---|
1285 | 1586 | * flushed so that we don't hit false positives looking for |
---|
1286 | 1587 | * insecure pages which are W+X. |
---|
1287 | 1588 | */ |
---|
1288 | | - rcu_barrier_sched(); |
---|
| 1589 | + rcu_barrier(); |
---|
1289 | 1590 | mark_rodata_ro(); |
---|
1290 | 1591 | rodata_test(); |
---|
1291 | 1592 | } else |
---|
1292 | 1593 | pr_info("Kernel memory protection disabled.\n"); |
---|
| 1594 | +} |
---|
| 1595 | +#elif defined(CONFIG_ARCH_HAS_STRICT_KERNEL_RWX) |
---|
| 1596 | +static inline void mark_readonly(void) |
---|
| 1597 | +{ |
---|
| 1598 | + pr_warn("Kernel memory protection not selected by kernel config.\n"); |
---|
1293 | 1599 | } |
---|
1294 | 1600 | #else |
---|
1295 | 1601 | static inline void mark_readonly(void) |
---|
.. | .. |
---|
1298 | 1604 | } |
---|
1299 | 1605 | #endif |
---|
1300 | 1606 | |
---|
| 1607 | +void __weak free_initmem(void) |
---|
| 1608 | +{ |
---|
| 1609 | + free_initmem_default(POISON_FREE_INITMEM); |
---|
| 1610 | +} |
---|
| 1611 | + |
---|
1301 | 1612 | static int __ref kernel_init(void *unused) |
---|
1302 | 1613 | { |
---|
1303 | 1614 | int ret; |
---|
.. | .. |
---|
1305 | 1616 | kernel_init_freeable(); |
---|
1306 | 1617 | /* need to finish all async __init code before freeing the memory */ |
---|
1307 | 1618 | async_synchronize_full(); |
---|
| 1619 | + kprobe_free_init_mem(); |
---|
1308 | 1620 | ftrace_free_init_mem(); |
---|
1309 | | - jump_label_invalidate_initmem(); |
---|
| 1621 | + kgdb_free_init_mem(); |
---|
1310 | 1622 | free_initmem(); |
---|
1311 | 1623 | mark_readonly(); |
---|
1312 | 1624 | |
---|
.. | .. |
---|
1320 | 1632 | numa_default_policy(); |
---|
1321 | 1633 | |
---|
1322 | 1634 | rcu_end_inkernel_boot(); |
---|
| 1635 | + |
---|
| 1636 | + do_sysctl_args(); |
---|
1323 | 1637 | |
---|
1324 | 1638 | if (ramdisk_execute_command) { |
---|
1325 | 1639 | ret = run_init_process(ramdisk_execute_command); |
---|
.. | .. |
---|
1342 | 1656 | panic("Requested init %s failed (error %d).", |
---|
1343 | 1657 | execute_command, ret); |
---|
1344 | 1658 | } |
---|
| 1659 | + |
---|
| 1660 | + if (CONFIG_DEFAULT_INIT[0] != '\0') { |
---|
| 1661 | + ret = run_init_process(CONFIG_DEFAULT_INIT); |
---|
| 1662 | + if (ret) |
---|
| 1663 | + pr_err("Default init %s failed (error %d)\n", |
---|
| 1664 | + CONFIG_DEFAULT_INIT, ret); |
---|
| 1665 | + else |
---|
| 1666 | + return 0; |
---|
| 1667 | + } |
---|
| 1668 | + |
---|
1345 | 1669 | if (!try_to_run_init_process("/sbin/init") || |
---|
1346 | 1670 | !try_to_run_init_process("/etc/init") || |
---|
1347 | 1671 | !try_to_run_init_process("/bin/init") || |
---|
.. | .. |
---|
1350 | 1674 | |
---|
1351 | 1675 | panic("No working init found. Try passing init= option to kernel. " |
---|
1352 | 1676 | "See Linux Documentation/admin-guide/init.rst for guidance."); |
---|
| 1677 | +} |
---|
| 1678 | + |
---|
| 1679 | +/* Open /dev/console, for stdin/stdout/stderr, this should never fail */ |
---|
| 1680 | +void __init console_on_rootfs(void) |
---|
| 1681 | +{ |
---|
| 1682 | + struct file *file = filp_open("/dev/console", O_RDWR, 0); |
---|
| 1683 | + |
---|
| 1684 | + if (IS_ERR(file)) { |
---|
| 1685 | + pr_err("Warning: unable to open an initial console.\n"); |
---|
| 1686 | + return; |
---|
| 1687 | + } |
---|
| 1688 | + init_dup(file); |
---|
| 1689 | + init_dup(file); |
---|
| 1690 | + init_dup(file); |
---|
| 1691 | + fput(file); |
---|
1353 | 1692 | } |
---|
1354 | 1693 | |
---|
1355 | 1694 | static noinline void __init kernel_init_freeable(void) |
---|
.. | .. |
---|
1375 | 1714 | |
---|
1376 | 1715 | init_mm_internals(); |
---|
1377 | 1716 | |
---|
| 1717 | + rcu_init_tasks_generic(); |
---|
1378 | 1718 | do_pre_smp_initcalls(); |
---|
1379 | 1719 | lockup_detector_init(); |
---|
1380 | 1720 | |
---|
1381 | 1721 | smp_init(); |
---|
1382 | 1722 | sched_init_smp(); |
---|
1383 | 1723 | |
---|
1384 | | -#ifdef CONFIG_ROCKCHIP_THUNDER_BOOT |
---|
1385 | | - kthread_run(defer_free_bootmem, NULL, "defer_mem"); |
---|
| 1724 | +#if defined(CONFIG_ROCKCHIP_THUNDER_BOOT) && defined(CONFIG_SMP) |
---|
| 1725 | + kthread_run(defer_free_memblock, NULL, "defer_mem"); |
---|
1386 | 1726 | #endif |
---|
1387 | 1727 | |
---|
| 1728 | + padata_init(); |
---|
1388 | 1729 | page_alloc_init_late(); |
---|
1389 | 1730 | /* Initialize page ext after all struct pages are initialized. */ |
---|
1390 | 1731 | page_ext_init(); |
---|
1391 | 1732 | |
---|
1392 | 1733 | do_basic_setup(); |
---|
1393 | 1734 | |
---|
| 1735 | + kunit_run_all_tests(); |
---|
| 1736 | + |
---|
1394 | 1737 | #if IS_BUILTIN(CONFIG_INITRD_ASYNC) |
---|
1395 | 1738 | async_synchronize_full(); |
---|
1396 | 1739 | #endif |
---|
1397 | 1740 | |
---|
1398 | | - /* Open the /dev/console on the rootfs, this should never fail */ |
---|
1399 | | - if (ksys_open((const char __user *) "/dev/console", O_RDWR, 0) < 0) |
---|
1400 | | - pr_err("Warning: unable to open an initial console.\n"); |
---|
| 1741 | + console_on_rootfs(); |
---|
1401 | 1742 | |
---|
1402 | | - (void) ksys_dup(0); |
---|
1403 | | - (void) ksys_dup(0); |
---|
1404 | 1743 | /* |
---|
1405 | 1744 | * check if there is an early userspace init. If yes, let it do all |
---|
1406 | 1745 | * the work |
---|
1407 | 1746 | */ |
---|
1408 | | - |
---|
1409 | | - if (!ramdisk_execute_command) |
---|
1410 | | - ramdisk_execute_command = "/init"; |
---|
1411 | | - |
---|
1412 | | - if (ksys_access((const char __user *) |
---|
1413 | | - ramdisk_execute_command, 0) != 0) { |
---|
| 1747 | + if (init_eaccess(ramdisk_execute_command) != 0) { |
---|
1414 | 1748 | ramdisk_execute_command = NULL; |
---|
1415 | 1749 | prepare_namespace(); |
---|
1416 | 1750 | } |
---|
.. | .. |
---|
1425 | 1759 | */ |
---|
1426 | 1760 | |
---|
1427 | 1761 | integrity_load_keys(); |
---|
1428 | | - load_default_modules(); |
---|
1429 | 1762 | } |
---|