diff mbox series

[for,v6.1,regression] mm, mremap: fix mremap() expanding vma with addr inside vma

Message ID 20221216163227.24648-1-vbabka@suse.cz (mailing list archive)
State New
Headers show
Series [for,v6.1,regression] mm, mremap: fix mremap() expanding vma with addr inside vma | expand

Commit Message

Vlastimil Babka Dec. 16, 2022, 4:32 p.m. UTC
Since 6.1 we have noticed random rpm install failures that were tracked
to mremap() returning -ENOMEM and to commit ca3d76b0aa80 ("mm: add
merging after mremap resize").

The problem occurs when mremap() expands a VMA in place, but using an
starting address that's not vma->vm_start, but somewhere in the middle.
The extension_pgoff calculation introduced by the commit is wrong in
that case, so vma_merge() fails due to pgoffs not being compatible.
Fix the calculation.

By the way it seems that the situations, where rpm now expands a vma
from the middle, were made possible also due to that commit, thanks to
the improved vma merging. Yet it should work just fine, except for the
buggy calculation.

Reported-by: Jiri Slaby <jirislaby@kernel.org>
Link: https://bugzilla.suse.com/show_bug.cgi?id=1206359
Fixes: ca3d76b0aa80 ("mm: add merging after mremap resize")
Signed-off-by: Vlastimil Babka <vbabka@suse.cz>
Cc: Jakub Matěna <matenajakub@gmail.com>
Cc: <stable@vger.kernel.org>
Cc: "Kirill A . Shutemov" <kirill@shutemov.name>
Cc: Liam Howlett <liam.howlett@oracle.com>
Cc: Matthew Wilcox <willy@infradead.org>
Cc: Mel Gorman <mgorman@techsingularity.net>
Cc: Michal Hocko <mhocko@kernel.org>
---
Hi, this fixes a regression in 6.1 so please process ASAP so that stable
6.1.y can get the fix.

 mm/mremap.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

Comments

Thorsten Leemhuis Dec. 23, 2022, 8:08 a.m. UTC | #1
[Note: this mail contains only information for Linux kernel regression
tracking. Mails like these contain '#forregzbot' in the subject to make
then easy to spot and filter out. The author also tried to remove most
or all individuals from the list of recipients to spare them the hassle.]

On 16.12.22 17:32, Vlastimil Babka wrote:
> Since 6.1 we have noticed random rpm install failures that were tracked
> to mremap() returning -ENOMEM and to commit ca3d76b0aa80 ("mm: add
> merging after mremap resize").
> 
> The problem occurs when mremap() expands a VMA in place, but using an
> starting address that's not vma->vm_start, but somewhere in the middle.
> The extension_pgoff calculation introduced by the commit is wrong in
> that case, so vma_merge() fails due to pgoffs not being compatible.
> Fix the calculation.
> 
> By the way it seems that the situations, where rpm now expands a vma
> from the middle, were made possible also due to that commit, thanks to
> the improved vma merging. Yet it should work just fine, except for the
> buggy calculation.
> 
> Reported-by: Jiri Slaby <jirislaby@kernel.org>
> Link: https://bugzilla.suse.com/show_bug.cgi?id=1206359
> Fixes: ca3d76b0aa80 ("mm: add merging after mremap resize")

This is just for the record, the fix will soon land, but I want to have
this in the report I plan to send later.

#regzbot ^introduced ca3d76b0aa80
#regzbot from: Jiri Slaby <jirislaby@kernel.org>
#regzbot title mm: random rpm install failures that were tracked to
mremap() returning -ENOMEM
#regzbot fix mm, mremap: fix mremap() expanding vma with addr inside vma
#regzbot ignore-activity

Ciao, Thorsten (wearing his 'the Linux kernel's regression tracker' hat)

P.S.: As the Linux kernel's regression tracker I deal with a lot of
reports and sometimes miss something important when writing mails like
this. If that's the case here, don't hesitate to tell me in a public
reply, it's in everyone's interest to set the public record straight.
diff mbox series

Patch

diff --git a/mm/mremap.c b/mm/mremap.c
index e465ffe279bb..fe587c5d6591 100644
--- a/mm/mremap.c
+++ b/mm/mremap.c
@@ -1016,7 +1016,8 @@  SYSCALL_DEFINE5(mremap, unsigned long, addr, unsigned long, old_len,
 			long pages = (new_len - old_len) >> PAGE_SHIFT;
 			unsigned long extension_start = addr + old_len;
 			unsigned long extension_end = addr + new_len;
-			pgoff_t extension_pgoff = vma->vm_pgoff + (old_len >> PAGE_SHIFT);
+			pgoff_t extension_pgoff = vma->vm_pgoff +
+				((extension_start - vma->vm_start) >> PAGE_SHIFT);
 
 			if (vma->vm_flags & VM_ACCOUNT) {
 				if (security_vm_enough_memory_mm(mm, pages)) {