From 7de7de7ca0ae0fc70515ee3154af33af75edae2c Mon Sep 17 00:00:00 2001
From: Linus Torvalds <torvalds@linux-foundation.org>
Date: Sun, 15 Dec 2019 19:50:23 -0800
Subject: [PATCH] Fix root mounting with no mount options
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

The "trivial conversion" in commit cccaa5e33525 ("init: use do_mount()
instead of ksys_mount()") was totally broken, since it didn't handle the
case of a NULL mount data pointer.  And while I had "tested" it (and
presumably Dominik had too) that bug was hidden by me having options.

Cc: Dominik Brodowski <linux@dominikbrodowski.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Reported-by: Ondřej Jirman <megi@xff.cz>
Reported-by: Guenter Roeck <linux@roeck-us.net>
Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org>
Reported-and-tested-by: Borislav Petkov <bp@suse.de>
Tested-by: Chris Clayton <chris2553@googlemail.com>
Tested-by: Eric Biggers <ebiggers@kernel.org>
Tested-by: Geert Uytterhoeven <geert@linux-m68k.org>
Tested-by: Guido Günther <agx@sigxcpu.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
 init/do_mounts.c | 23 +++++++++++++----------
 1 file changed, 13 insertions(+), 10 deletions(-)

diff --git a/init/do_mounts.c b/init/do_mounts.c
index f55cbd9cb8183f..0ae9cc22f2ae25 100644
--- a/init/do_mounts.c
+++ b/init/do_mounts.c
@@ -391,17 +391,19 @@ static int __init do_mount_root(const char *name, const char *fs,
 				 const int flags, const void *data)
 {
 	struct super_block *s;
-	char *data_page;
-	struct page *p;
+	struct page *p = NULL;
+	char *data_page = NULL;
 	int ret;
 
-	/* do_mount() requires a full page as fifth argument */
-	p = alloc_page(GFP_KERNEL);
-	if (!p)
-		return -ENOMEM;
-
-	data_page = page_address(p);
-	strncpy(data_page, data, PAGE_SIZE - 1);
+	if (data) {
+		/* do_mount() requires a full page as fifth argument */
+		p = alloc_page(GFP_KERNEL);
+		if (!p)
+			return -ENOMEM;
+		data_page = page_address(p);
+		/* zero-pad. do_mount() will make sure it's terminated */
+		strncpy(data_page, data, PAGE_SIZE);
+	}
 
 	ret = do_mount(name, "/root", fs, flags, data_page);
 	if (ret)
@@ -417,7 +419,8 @@ static int __init do_mount_root(const char *name, const char *fs,
 	       MAJOR(ROOT_DEV), MINOR(ROOT_DEV));
 
 out:
-	put_page(p);
+	if (p)
+		put_page(p);
 	return ret;
 }
 
-- 
GitLab