From d6b2123802d2b7eee8c62cd0ebd73e8636cbb068 Mon Sep 17 00:00:00 2001
From: Al Viro <viro@zeniv.linux.org.uk>
Date: Wed, 10 Oct 2012 19:57:26 -0400
Subject: [PATCH] make sure that we always have a return path from
 kernel_execve()

The only place where kernel_execve() is called without a way to
return to the caller of kernel_thread() callback is kernel_post().
Reorganize kernel_init()/kernel_post() - instead of the former
calling the latter in the end (and getting freed by it), have the
latter *begin* with calling the former (and turn the latter into
kernel_thread() callback, of course).

Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
---
 init/main.c | 13 +++++--------
 1 file changed, 5 insertions(+), 8 deletions(-)

diff --git a/init/main.c b/init/main.c
index b28673087ac00..a490ffecb7b9e 100644
--- a/init/main.c
+++ b/init/main.c
@@ -794,11 +794,11 @@ static void run_init_process(const char *init_filename)
 	kernel_execve(init_filename, argv_init, envp_init);
 }
 
-/* This is a non __init function. Force it to be noinline otherwise gcc
- * makes it inline to init() and it becomes part of init.text section
- */
-static noinline int init_post(void)
+static void __init kernel_init_freeable(void);
+
+static int __ref kernel_init(void *unused)
 {
+	kernel_init_freeable();
 	/* need to finish all async __init code before freeing the memory */
 	async_synchronize_full();
 	free_initmem();
@@ -835,7 +835,7 @@ static noinline int init_post(void)
 	      "See Linux Documentation/init.txt for guidance.");
 }
 
-static int __init kernel_init(void * unused)
+static void __init kernel_init_freeable(void)
 {
 	/*
 	 * Wait until kthreadd is all set-up.
@@ -890,7 +890,4 @@ static int __init kernel_init(void * unused)
 	 * we're essentially up and running. Get rid of the
 	 * initmem segments and start the user-mode stuff..
 	 */
-
-	init_post();
-	return 0;
 }
-- 
GitLab