diff options
Diffstat (limited to 'init')
| -rw-r--r-- | init/Kconfig | 123 | ||||
| -rw-r--r-- | init/do_mounts.c | 6 | ||||
| -rw-r--r-- | init/do_mounts_rd.c | 14 | ||||
| -rw-r--r-- | init/initramfs.c | 3 | ||||
| -rw-r--r-- | init/main.c | 203 | 
5 files changed, 265 insertions, 84 deletions
diff --git a/init/Kconfig b/init/Kconfig index 3ecd8a1178f..9d76b99af1b 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -261,6 +261,16 @@ config POSIX_MQUEUE_SYSCTL  	depends on SYSCTL  	default y +config CROSS_MEMORY_ATTACH +	bool "Enable process_vm_readv/writev syscalls" +	depends on MMU +	default y +	help +	  Enabling this option adds the system calls process_vm_readv and +	  process_vm_writev which allow a process with the correct privileges +	  to directly read from or write to to another process's address space. +	  See the man page for more details. +  config FHANDLE  	bool "open by fhandle syscalls"  	select EXPORTFS @@ -273,6 +283,16 @@ config FHANDLE  	  get renamed. Enables open_by_handle_at(2) and name_to_handle_at(2)  	  syscalls. +config USELIB +	bool "uselib syscall" +	default y +	help +	  This option enables the uselib syscall, a system call used in the +	  dynamic linker from libc5 and earlier.  glibc does not use this +	  system call.  If you intend to run programs built on libc5 or +	  earlier, you may need to enable this syscall.  Current systems +	  running glibc can safely disable this. +  config AUDIT  	bool "Auditing support"  	depends on NET @@ -282,9 +302,12 @@ config AUDIT  	  logging of avc messages output).  Does not do system-call  	  auditing without CONFIG_AUDITSYSCALL. +config HAVE_ARCH_AUDITSYSCALL +	bool +  config AUDITSYSCALL  	bool "Enable system-call auditing support" -	depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH || (ARM && AEABI && !OABI_COMPAT)) +	depends on AUDIT && HAVE_ARCH_AUDITSYSCALL  	default y if SECURITY_SELINUX  	help  	  Enable low-overhead system-call auditing infrastructure that @@ -301,20 +324,6 @@ config AUDIT_TREE  	depends on AUDITSYSCALL  	select FSNOTIFY -config AUDIT_LOGINUID_IMMUTABLE -	bool "Make audit loginuid immutable" -	depends on AUDIT -	help -	  The config option toggles if a task setting its loginuid requires -	  CAP_SYS_AUDITCONTROL or if that task should require no special permissions -	  but should instead only allow setting its loginuid if it was never -	  previously set.  On systems which use systemd or a similar central -	  process to restart login services this should be set to true.  On older -	  systems in which an admin would typically have to directly stop and -	  start processes this should be set to false.  Setting this to true allows -	  one to drop potentially dangerous capabilites from the login tasks, -	  but may not be backwards compatible with older init systems. -  source "kernel/irq/Kconfig"  source "kernel/time/Kconfig" @@ -354,7 +363,8 @@ config VIRT_CPU_ACCOUNTING_NATIVE  config VIRT_CPU_ACCOUNTING_GEN  	bool "Full dynticks CPU time accounting" -	depends on HAVE_CONTEXT_TRACKING && 64BIT +	depends on HAVE_CONTEXT_TRACKING +	depends on HAVE_VIRT_CPU_ACCOUNTING_GEN  	select VIRT_CPU_ACCOUNTING  	select CONTEXT_TRACKING  	help @@ -545,7 +555,7 @@ config CONTEXT_TRACKING_FORCE  	  dynticks subsystem by forcing the context tracking on all  	  CPUs in the system. -	  Say Y only if you're working on the developpement of an +	  Say Y only if you're working on the development of an  	  architecture backend for the context tracking.  	  Say N otherwise, this option brings an overhead that you @@ -822,6 +832,12 @@ config GENERIC_SCHED_CLOCK  config ARCH_SUPPORTS_NUMA_BALANCING  	bool +# +# For architectures that know their GCC __int128 support is sound +# +config ARCH_SUPPORTS_INT128 +	bool +  # For architectures that (ab)use NUMA to represent different memory regions  # all cpu-local but of different latencies, such as SuperH.  # @@ -844,7 +860,7 @@ config NUMA_BALANCING_DEFAULT_ENABLED  	default y  	depends on NUMA_BALANCING  	help -	  If set, autonumic NUMA balancing will be enabled if running on a NUMA +	  If set, automatic NUMA balancing will be enabled if running on a NUMA  	  machine.  config NUMA_BALANCING @@ -855,13 +871,13 @@ config NUMA_BALANCING  	help  	  This option adds support for automatic NUMA aware memory/task placement.  	  The mechanism is quite primitive and is based on migrating memory when -	  it is references to the node the task is running on. +	  it has references to the node the task is running on.  	  This system will be inactive on UMA systems.  menuconfig CGROUPS  	boolean "Control Group support" -	depends on EVENTFD +	select KERNFS  	help  	  This option adds support for grouping sets of processes together, for  	  use with process control subsystems such as Cpusets, CFS, memory @@ -927,7 +943,7 @@ config RESOURCE_COUNTERS  config MEMCG  	bool "Memory Resource Controller for Control Groups"  	depends on RESOURCE_COUNTERS -	select MM_OWNER +	select EVENTFD  	help  	  Provides a memory resource controller that manages both anonymous  	  memory and page cache. (See Documentation/cgroups/memory.txt) @@ -944,9 +960,6 @@ config MEMCG  	  disable memory resource controller and you can avoid overheads.  	  (and lose benefits of memory resource controller) -	  This config option also selects MM_OWNER config option, which -	  could in turn add some fork/exit overhead. -  config MEMCG_SWAP  	bool "Memory Resource Controller Swap Extension"  	depends on MEMCG && SWAP @@ -989,6 +1002,12 @@ config MEMCG_KMEM  	  the kmem extension can use it to guarantee that no group of processes  	  will ever exhaust kernel resources alone. +	  WARNING: Current implementation lacks reclaim support. That means +	  allocation attempts will fail when close to the limit even if there +	  are plenty of kmem available for reclaim. That makes this option +	  unusable in real life so DO NOT SELECT IT unless for development +	  purposes. +  config CGROUP_HUGETLB  	bool "HugeTLB Resource Controller for Control Groups"  	depends on RESOURCE_COUNTERS && HUGETLB_PAGE @@ -1123,8 +1142,6 @@ config IPC_NS  config USER_NS  	bool "User namespace" -	select UIDGID_STRICT_TYPE_CHECKS -  	default n  	help  	  This allows containers, i.e. vservers, to use user namespaces @@ -1156,18 +1173,8 @@ config NET_NS  endif # NAMESPACES -config UIDGID_STRICT_TYPE_CHECKS -	bool "Require conversions between uid/gids and their internal representation" -	default n -	help -	 While the nececessary conversions are being added to all subsystems this option allows -	 the code to continue to build for unconverted subsystems. - -	 Say Y here if you want the strict type checking enabled -  config SCHED_AUTOGROUP  	bool "Automatic process group scheduling" -	select EVENTFD  	select CGROUPS  	select CGROUP_SCHED  	select FAIR_GROUP_SCHED @@ -1178,9 +1185,6 @@ config SCHED_AUTOGROUP  	  desktop applications.  Task group autogeneration is currently based  	  upon task session. -config MM_OWNER -	bool -  config SYSFS_DEPRECATED  	bool "Enable deprecated sysfs features to support old userspace tools"  	depends on SYSFS @@ -1309,6 +1313,26 @@ config UID16  	help  	  This enables the legacy 16-bit UID syscall wrappers. +config SGETMASK_SYSCALL +	bool "sgetmask/ssetmask syscalls support" if EXPERT +	def_bool PARISC || MN10300 || BLACKFIN || M68K || PPC || MIPS || X86 || SPARC || CRIS || MICROBLAZE || SUPERH +	---help--- +	  sys_sgetmask and sys_ssetmask are obsolete system calls +	  no longer supported in libc but still enabled by default in some +	  architectures. + +	  If unsure, leave the default option here. + +config SYSFS_SYSCALL +	bool "Sysfs syscall support" if EXPERT +	default y +	---help--- +	  sys_sysfs is an obsolete system call no longer supported in libc. +	  Note that disabling this option is more secure but might break +	  compatibility with some systems. + +	  If unsure say Y here. +  config SYSCTL_SYSCALL  	bool "Sysctl syscall support" if EXPERT  	depends on PROC_SYSCTL @@ -1406,6 +1430,13 @@ config FUTEX  	  support for "fast userspace mutexes".  The resulting kernel may not  	  run glibc-based applications correctly. +config HAVE_FUTEX_CMPXCHG +	bool +	help +	  Architectures should select this if futex_atomic_cmpxchg_inatomic() +	  is implemented and always working. This removes a couple of runtime +	  checks. +  config EPOLL  	bool "Enable eventpoll support" if EXPERT  	default y @@ -1474,6 +1505,7 @@ config PCI_QUIRKS  config EMBEDDED  	bool "Embedded system" +	option allnoconfig_y  	select EXPERT  	help  	  This option should be enabled if compiling the kernel for @@ -1633,6 +1665,18 @@ config MMAP_ALLOW_UNINITIALIZED  	  See Documentation/nommu-mmap.txt for more information. +config SYSTEM_TRUSTED_KEYRING +	bool "Provide system-wide ring of trusted keys" +	depends on KEYS +	help +	  Provide a system keyring to which trusted keys can be added.  Keys in +	  the keyring are considered to be trusted.  Keys may be added at will +	  by the kernel from compiled-in data and from hardware key stores, but +	  userspace may only add extra keys if those keys can be verified by +	  keys already in the keyring. + +	  Keys in this keyring are used by module signature checking. +  config PROFILING  	bool "Profiling support"  	help @@ -1741,6 +1785,7 @@ config MODULE_SRCVERSION_ALL  config MODULE_SIG  	bool "Module signature verification"  	depends on MODULES +	select SYSTEM_TRUSTED_KEYRING  	select KEYS  	select CRYPTO  	select ASYMMETRIC_KEY_TYPE diff --git a/init/do_mounts.c b/init/do_mounts.c index a51cddc2ff8..82f22885c87 100644 --- a/init/do_mounts.c +++ b/init/do_mounts.c @@ -102,13 +102,13 @@ no_match:  /**   * devt_from_partuuid - looks up the dev_t of a partition by its UUID - * @uuid:	char array containing ascii UUID + * @uuid_str:	char array containing ascii UUID   *   * The function will return the first partition which contains a matching   * UUID value in its partition_meta_info struct.  This does not search   * by filesystem UUIDs.   * - * If @uuid is followed by a "/PARTNROFF=%d", then the number will be + * If @uuid_str is followed by a "/PARTNROFF=%d", then the number will be   * extracted and used as an offset from the partition identified by the UUID.   *   * Returns the matching dev_t on success or 0 on failure. @@ -197,6 +197,8 @@ done:   *	   is a zero-filled hex representation of the 1-based partition number.   *	7) PARTUUID=<UUID>/PARTNROFF=<int> to select a partition in relation to   *	   a partition with a known unique id. + *	8) <major>:<minor> major and minor number of the device separated by + *	   a colon.   *   *	If name doesn't have fall into the categories above, we return (0,0).   *	block_class is used to check if something is a disk name. If the disk diff --git a/init/do_mounts_rd.c b/init/do_mounts_rd.c index 6be2879cca6..a8227022e3a 100644 --- a/init/do_mounts_rd.c +++ b/init/do_mounts_rd.c @@ -13,7 +13,7 @@  #include <linux/minix_fs.h>  #include <linux/ext2_fs.h>  #include <linux/romfs_fs.h> -#include <linux/cramfs_fs.h> +#include <uapi/linux/cramfs_fs.h>  #include <linux/initrd.h>  #include <linux/string.h>  #include <linux/slab.h> @@ -57,6 +57,11 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco);   *	cramfs   *	squashfs   *	gzip + *	bzip2 + *	lzma + *	xz + *	lzo + *	lz4   */  static int __init  identify_ramdisk_image(int fd, int start_block, decompress_fn *decompressor) @@ -342,6 +347,13 @@ static int __init crd_load(int in_fd, int out_fd, decompress_fn deco)  	int result;  	crd_infd = in_fd;  	crd_outfd = out_fd; + +	if (!deco) { +		pr_emerg("Invalid ramdisk decompression routine.  " +			 "Select appropriate config option.\n"); +		panic("Could not decompress initial ramdisk image."); +	} +  	result = deco(NULL, 0, compr_fill, compr_flush, NULL, NULL, error);  	if (decompress_error)  		result = 1; diff --git a/init/initramfs.c b/init/initramfs.c index a67ef9dbda9..a8497fab1c3 100644 --- a/init/initramfs.c +++ b/init/initramfs.c @@ -455,6 +455,7 @@ static char * __init unpack_to_rootfs(char *buf, unsigned len)  		}  		this_header = 0;  		decompress = decompress_method(buf, len, &compress_name); +		pr_debug("Detected %s compressed data\n", compress_name);  		if (decompress) {  			res = decompress(buf, len, NULL, flush_buffer, NULL,  				   &my_inptr, error); @@ -583,7 +584,7 @@ static int __init populate_rootfs(void)  {  	char *err = unpack_to_rootfs(__initramfs_start, __initramfs_size);  	if (err) -		panic(err);	/* Failed to decompress INTERNAL initramfs */ +		panic("%s", err); /* Failed to decompress INTERNAL initramfs */  	if (initrd_start) {  #ifdef CONFIG_BLK_DEV_RAM  		int fd; diff --git a/init/main.c b/init/main.c index af310afbef2..e8ae1fef090 100644 --- a/init/main.c +++ b/init/main.c @@ -76,6 +76,8 @@  #include <linux/elevator.h>  #include <linux/sched_clock.h>  #include <linux/context_tracking.h> +#include <linux/random.h> +#include <linux/list.h>  #include <asm/io.h>  #include <asm/bugs.h> @@ -91,17 +93,11 @@ static int kernel_init(void *);  extern void init_IRQ(void);  extern void fork_init(unsigned long); -extern void mca_init(void); -extern void sbus_init(void);  extern void radix_tree_init(void);  #ifndef CONFIG_DEBUG_RODATA  static inline void mark_rodata_ro(void) { }  #endif -#ifdef CONFIG_TC -extern void tc_init(void); -#endif -  /*   * Debug helper: via this flag we know that we are in 'early bootup code'   * where only the boot processor is running with IRQ disabled.  This means @@ -123,7 +119,6 @@ EXPORT_SYMBOL(system_state);  extern void time_init(void);  /* Default late time init is NULL. archs can override this later. */  void (*__initdata late_time_init)(void); -extern void softirq_init(void);  /* Untouched command line saved by arch-specific code. */  char __initdata boot_command_line[COMMAND_LINE_SIZE]; @@ -131,11 +126,20 @@ char __initdata boot_command_line[COMMAND_LINE_SIZE];  char *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;  static char *execute_command;  static char *ramdisk_execute_command;  /* + * Used to generate warnings if static_key manipulation functions are used + * before jump_label_init is called. + */ +bool static_key_initialized __read_mostly = false; +EXPORT_SYMBOL_GPL(static_key_initialized); + +/*   * If set, this is an indication to the drivers that reset the underlying   * device before going ahead with the initialization otherwise driver might   * rely on the BIOS and skip the reset operation. @@ -200,13 +204,13 @@ EXPORT_SYMBOL(loops_per_jiffy);  static int __init debug_kernel(char *str)  { -	console_loglevel = 10; +	console_loglevel = CONSOLE_LOGLEVEL_DEBUG;  	return 0;  }  static int __init quiet_kernel(char *str)  { -	console_loglevel = 4; +	console_loglevel = CONSOLE_LOGLEVEL_QUIET;  	return 0;  } @@ -249,6 +253,27 @@ static int __init repair_env_string(char *param, char *val, const char *unused)  	return 0;  } +/* Anything after -- gets handed straight to init. */ +static int __init set_init_arg(char *param, char *val, const char *unused) +{ +	unsigned int i; + +	if (panic_later) +		return 0; + +	repair_env_string(param, val, unused); + +	for (i = 0; argv_init[i]; i++) { +		if (i == MAX_INIT_ARGS) { +			panic_later = "init"; +			panic_param = param; +			return 0; +		} +	} +	argv_init[i] = param; +	return 0; +} +  /*   * Unknown boot options get handed to init, unless they look like   * unused parameters (modprobe will find them in /proc/cmdline). @@ -273,7 +298,7 @@ static int __init unknown_bootoption(char *param, char *val, const char *unused)  		unsigned int i;  		for (i = 0; envp_init[i]; i++) {  			if (i == MAX_INIT_ENVS) { -				panic_later = "Too many boot env vars at `%s'"; +				panic_later = "env";  				panic_param = param;  			}  			if (!strncmp(param, envp_init[i], val - param)) @@ -285,7 +310,7 @@ static int __init unknown_bootoption(char *param, char *val, const char *unused)  		unsigned int i;  		for (i = 0; argv_init[i]; i++) {  			if (i == MAX_INIT_ARGS) { -				panic_later = "Too many boot init vars at `%s'"; +				panic_later = "init";  				panic_param = param;  			}  		} @@ -346,8 +371,11 @@ static inline void smp_prepare_cpus(unsigned int maxcpus) { }   */  static void __init setup_command_line(char *command_line)  { -	saved_command_line = alloc_bootmem(strlen (boot_command_line)+1); -	static_command_line = alloc_bootmem(strlen (command_line)+1); +	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);  } @@ -373,7 +401,7 @@ static noinline void __init_refok rest_init(void)  	 * the init task will end up wanting to create kthreads, which, if  	 * we schedule it before we create kthreadd, will OOPS.  	 */ -	kernel_thread(kernel_init, NULL, CLONE_FS | CLONE_SIGHAND); +	kernel_thread(kernel_init, NULL, CLONE_FS);  	numa_default_policy();  	pid = kernel_thread(kthreadd, NULL, CLONE_FS | CLONE_FILES);  	rcu_read_lock(); @@ -466,13 +494,13 @@ static void __init mm_init(void)  	mem_init();  	kmem_cache_init();  	percpu_init_late(); -	pgtable_cache_init(); +	pgtable_init();  	vmalloc_init();  } -asmlinkage void __init start_kernel(void) +asmlinkage __visible void __init start_kernel(void)  { -	char * command_line; +	char * command_line, *after_dashes;  	extern const struct kernel_param __start___param[], __stop___param[];  	/* @@ -501,7 +529,6 @@ asmlinkage void __init start_kernel(void)  	page_address_init();  	pr_notice("%s", linux_banner);  	setup_arch(&command_line); -	mm_init_owner(&init_mm, &init_task);  	mm_init_cpumask(&init_mm);  	setup_command_line(command_line);  	setup_nr_cpu_ids(); @@ -513,9 +540,13 @@ asmlinkage void __init start_kernel(void)  	pr_notice("Kernel command line: %s\n", boot_command_line);  	parse_early_param(); -	parse_args("Booting kernel", static_command_line, __start___param, -		   __stop___param - __start___param, -		   -1, -1, &unknown_bootoption); +	after_dashes = parse_args("Booting kernel", +				  static_command_line, __start___param, +				  __stop___param - __start___param, +				  -1, -1, &unknown_bootoption); +	if (after_dashes) +		parse_args("Setting init args", after_dashes, NULL, 0, -1, -1, +			   set_init_arg);  	jump_label_init(); @@ -574,7 +605,8 @@ asmlinkage void __init start_kernel(void)  	 */  	console_init();  	if (panic_later) -		panic(panic_later, panic_param); +		panic("Too many boot %s vars at `%s'", panic_later, +		      panic_param);  	lockdep_info(); @@ -605,10 +637,15 @@ asmlinkage void __init start_kernel(void)  	calibrate_delay();  	pidmap_init();  	anon_vma_init(); +	acpi_early_init();  #ifdef CONFIG_X86  	if (efi_enabled(EFI_RUNTIME_SERVICES))  		efi_enter_virtual_mode();  #endif +#ifdef CONFIG_X86_ESPFIX64 +	/* Should be run before the first non-init thread is created */ +	init_espfix_bsp(); +#endif  	thread_info_cache_init();  	cred_init();  	fork_init(totalram_pages); @@ -621,9 +658,7 @@ asmlinkage void __init start_kernel(void)  	signals_init();  	/* rootfs populating might need page-writeback */  	page_writeback_init(); -#ifdef CONFIG_PROC_FS  	proc_root_init(); -#endif  	cgroup_init();  	cpuset_init();  	taskstats_init_early(); @@ -631,7 +666,6 @@ asmlinkage void __init start_kernel(void)  	check_bugs(); -	acpi_early_init(); /* before LAPIC and SMP init */  	sfi_init_late();  	if (efi_enabled(EFI_RUNTIME_SERVICES)) { @@ -659,19 +693,83 @@ static void __init do_ctors(void)  bool initcall_debug;  core_param(initcall_debug, initcall_debug, bool, 0644); +#ifdef CONFIG_KALLSYMS +struct blacklist_entry { +	struct list_head next; +	char *buf; +}; + +static __initdata_or_module LIST_HEAD(blacklisted_initcalls); + +static int __init initcall_blacklist(char *str) +{ +	char *str_entry; +	struct blacklist_entry *entry; + +	/* str argument is a comma-separated list of functions */ +	do { +		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); +			strcpy(entry->buf, str_entry); +			list_add(&entry->next, &blacklisted_initcalls); +		} +	} while (str_entry); + +	return 0; +} + +static bool __init_or_module initcall_blacklisted(initcall_t fn) +{ +	struct list_head *tmp; +	struct blacklist_entry *entry; +	char *fn_name; + +	fn_name = kasprintf(GFP_KERNEL, "%pf", fn); +	if (!fn_name) +		return false; + +	list_for_each(tmp, &blacklisted_initcalls) { +		entry = list_entry(tmp, struct blacklist_entry, next); +		if (!strcmp(fn_name, entry->buf)) { +			pr_debug("initcall %s blacklisted\n", fn_name); +			kfree(fn_name); +			return true; +		} +	} + +	kfree(fn_name); +	return false; +} +#else +static int __init initcall_blacklist(char *str) +{ +	pr_warn("initcall_blacklist requires CONFIG_KALLSYMS\n"); +	return 0; +} + +static bool __init_or_module initcall_blacklisted(initcall_t fn) +{ +	return false; +} +#endif +__setup("initcall_blacklist=", initcall_blacklist); +  static int __init_or_module do_one_initcall_debug(initcall_t fn)  {  	ktime_t calltime, delta, rettime;  	unsigned long long duration;  	int ret; -	pr_debug("calling  %pF @ %i\n", fn, task_pid_nr(current)); +	printk(KERN_DEBUG "calling  %pF @ %i\n", fn, task_pid_nr(current));  	calltime = ktime_get();  	ret = fn();  	rettime = ktime_get();  	delta = ktime_sub(rettime, calltime);  	duration = (unsigned long long) ktime_to_ns(delta) >> 10; -	pr_debug("initcall %pF returned %d after %lld usecs\n", +	printk(KERN_DEBUG "initcall %pF returned %d after %lld usecs\n",  		 fn, ret, duration);  	return ret; @@ -683,6 +781,9 @@ int __init_or_module do_one_initcall(initcall_t fn)  	int ret;  	char msgbuf[64]; +	if (initcall_blacklisted(fn)) +		return -EPERM; +  	if (initcall_debug)  		ret = do_one_initcall_debug(fn);  	else @@ -692,7 +793,7 @@ int __init_or_module do_one_initcall(initcall_t fn)  	if (preempt_count() != count) {  		sprintf(msgbuf, "preemption imbalance "); -		preempt_count() = count; +		preempt_count_set(count);  	}  	if (irqs_disabled()) {  		strlcat(msgbuf, "disabled interrupts ", sizeof(msgbuf)); @@ -744,9 +845,9 @@ static void __init do_initcall_level(int level)  	extern const struct kernel_param __start___param[], __stop___param[];  	initcall_t *fn; -	strcpy(static_command_line, saved_command_line); +	strcpy(initcall_command_line, saved_command_line);  	parse_args(initcall_level_names[level], -		   static_command_line, __start___param, +		   initcall_command_line, __start___param,  		   __stop___param - __start___param,  		   level, level,  		   &repair_env_string); @@ -780,6 +881,7 @@ static void __init do_basic_setup(void)  	do_ctors();  	usermodehelper_enable();  	do_initcalls(); +	random_int_secret_init();  }  static void __init do_pre_smp_initcalls(void) @@ -804,15 +906,31 @@ void __init load_default_modules(void)  static int run_init_process(const char *init_filename)  {  	argv_init[0] = init_filename; -	return do_execve(init_filename, +	return do_execve(getname_kernel(init_filename),  		(const char __user *const __user *)argv_init,  		(const char __user *const __user *)envp_init);  } +static int try_to_run_init_process(const char *init_filename) +{ +	int ret; + +	ret = run_init_process(init_filename); + +	if (ret && ret != -ENOENT) { +		pr_err("Starting init: %s exists but couldn't execute it (error %d)\n", +		       init_filename, ret); +	} + +	return ret; +} +  static noinline void __init kernel_init_freeable(void);  static int __ref kernel_init(void *unused)  { +	int ret; +  	kernel_init_freeable();  	/* need to finish all async __init code before freeing the memory */  	async_synchronize_full(); @@ -824,9 +942,11 @@ static int __ref kernel_init(void *unused)  	flush_delayed_fput();  	if (ramdisk_execute_command) { -		if (!run_init_process(ramdisk_execute_command)) +		ret = run_init_process(ramdisk_execute_command); +		if (!ret)  			return 0; -		pr_err("Failed to execute %s\n", ramdisk_execute_command); +		pr_err("Failed to execute %s (error %d)\n", +		       ramdisk_execute_command, ret);  	}  	/* @@ -836,18 +956,19 @@ static int __ref kernel_init(void *unused)  	 * trying to recover a really broken machine.  	 */  	if (execute_command) { -		if (!run_init_process(execute_command)) +		ret = run_init_process(execute_command); +		if (!ret)  			return 0; -		pr_err("Failed to execute %s.  Attempting defaults...\n", -			execute_command); +		pr_err("Failed to execute %s (error %d).  Attempting defaults...\n", +			execute_command, ret);  	} -	if (!run_init_process("/sbin/init") || -	    !run_init_process("/etc/init") || -	    !run_init_process("/bin/init") || -	    !run_init_process("/bin/sh")) +	if (!try_to_run_init_process("/sbin/init") || +	    !try_to_run_init_process("/etc/init") || +	    !try_to_run_init_process("/bin/init") || +	    !try_to_run_init_process("/bin/sh"))  		return 0; -	panic("No init found.  Try passing init= option to kernel. " +	panic("No working init found.  Try passing init= option to kernel. "  	      "See Linux Documentation/init.txt for guidance.");  }  | 
