lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  PHC 
Open Source and information security mailing list archives
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [thread-next>] [day] [month] [year] [list]
Date:   Tue, 29 Dec 2020 18:45:29 +0100
From:   Helge Deller <>
To:     Kalesh Singh <>,
        "Kirill A. Shutemov" <>,
        Andrew Morton <>,
        Linus Torvalds <>,,
        James Bottomley <>,
        John David Anglin <>
Subject: [PATCH] mm: fix extend calculation for move_page_tables()

On parisc the kernel fails to start the init process because in
shift_arg_pages() in fs/exec.c, move_page_tables() is called to e.g.
move pages from start addr 0xffeff000 to the new start addr 0xf9ccb000
with a length of 0x1000 bytes, but move_page_tables() instead returns
that it apparently moved 0x57000 bytes. Since the number of bytes is
different than the number of bytes which should have been moved,
shift_arg_pages() aborts with -ENOMEM.

Debugging shows that commit c49dd34018026 ("mm: speedup mremap on
1GB or larger regions") is the culprit.
In this commit, the extent calculation was tried to be optimized, but
got it wrong for this case.
The patch below reverts to the previous way to calculate the extent and
thus fixes the boot problem.

Fixes: c49dd34018026 ("mm: speedup mremap on 1GB or larger regions")
Signed-off-by: Helge Deller <>
Cc: Kalesh Singh <>
Cc: "Kirill A. Shutemov" <>
Cc: Andrew Morton <>


diff --git a/mm/mremap.c b/mm/mremap.c
index c5590afe7165..f554320281cc 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -358,7 +358,9 @@ static unsigned long get_extent(enum pgt_entry entry, unsigned long old_addr,

 	next = (old_addr + size) & mask;
 	/* even if next overflowed, extent below will be ok */
-	extent = (next > old_end) ? old_end - old_addr : next - old_addr;
+	extent = next - old_addr;
+	if (extent > old_end - old_addr)
+		extent = old_end - old_addr;
 	next = (new_addr + size) & mask;
 	if (extent > next - new_addr)
 		extent = next - new_addr;

Powered by blists - more mailing lists