* Re: [Bug 210023] New: Crash when allocating > 2 TB memory
[not found] <bug-210023-27@https.bugzilla.kernel.org/>
@ 2020-11-04 0:27 ` Andrew Morton
2020-11-04 0:47 ` Matthew Wilcox
2020-11-04 13:55 ` Hsin-Hui Wu
0 siblings, 2 replies; 5+ messages in thread
From: Andrew Morton @ 2020-11-04 0:27 UTC (permalink / raw)
To: hsinhuiwu; +Cc: bugzilla-daemon, linux-mm
(switched to email. Please respond via emailed reply-to-all, not via the
bugzilla web interface).
On Tue, 03 Nov 2020 18:50:07 +0000 bugzilla-daemon@bugzilla.kernel.org wrote:
> https://bugzilla.kernel.org/show_bug.cgi?id=210023
>
> Bug ID: 210023
> Summary: Crash when allocating > 2 TB memory
> Product: Memory Management
> Version: 2.5
> Kernel Version: 3.10.0-957.27.2.el7.x86_64
> Hardware: All
> OS: Linux
> Tree: Mainline
> Status: NEW
> Severity: blocking
> Priority: P1
> Component: Slab Allocator
> Assignee: akpm@linux-foundation.org
> Reporter: hsinhuiwu@gmail.com
> Regression: No
>
> With a machine with 3 TB (more than 2 TB memory). If you use vmalloc to
> allocate > 2 TB memory, the array_size below will be overflowed.
How was this observed?
Is there any know userspace operation which causes the kernel to try to
vmalloc such a large hunk of memory?
> The array_size is an unsigned int and can only be used to allocate less than 2
> TB memory. If you pass 2*1028*1028*1024*1024 = 2 * 2^40 in the argument of
> vmalloc. The array_size will become 2*2^31 = 2^32. The 2^32 cannot be store
> with a 32 bit integer.
>
> The fix is to change the type of array_size to unsigned long.
>
> vmalloc.c
>
> 1762 void *vmalloc(unsigned long size)
> 1763 {
> 1764 return __vmalloc_node_flags(size, NUMA_NO_NODE,
> 1765 GFP_KERNEL | __GFP_HIGHMEM);
> 1766 }
OK, thanks. Against current mainline your proposed change would look
like this, yes?
--- a/mm/vmalloc.c~a
+++ a/mm/vmalloc.c
@@ -2461,9 +2461,11 @@ static void *__vmalloc_area_node(struct
{
const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
unsigned int nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
- unsigned int array_size = nr_pages * sizeof(struct page *), i;
+ unsigned long array_size
+ unsigned int i;
struct page **pages;
+ array_size = (unsigned long)nr_pages * sizeof(struct page *);
gfp_mask |= __GFP_NOWARN;
if (!(gfp_mask & (GFP_DMA | GFP_DMA32)))
gfp_mask |= __GFP_HIGHMEM;
_
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Bug 210023] New: Crash when allocating > 2 TB memory
2020-11-04 0:27 ` [Bug 210023] New: Crash when allocating > 2 TB memory Andrew Morton
@ 2020-11-04 0:47 ` Matthew Wilcox
2020-11-04 13:55 ` Hsin-Hui Wu
1 sibling, 0 replies; 5+ messages in thread
From: Matthew Wilcox @ 2020-11-04 0:47 UTC (permalink / raw)
To: Andrew Morton; +Cc: hsinhuiwu, bugzilla-daemon, linux-mm
On Tue, Nov 03, 2020 at 04:27:40PM -0800, Andrew Morton wrote:
> const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) | __GFP_ZERO;
> unsigned int nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
> - unsigned int array_size = nr_pages * sizeof(struct page *), i;
> + unsigned long array_size
> + unsigned int i;
> struct page **pages;
>
> + array_size = (unsigned long)nr_pages * sizeof(struct page *);
This is only pushing the problem out ~5 years. If somebody tries
to allocate a 16TB area, 16TB / 4kB is 4GB and nr_pages overflows.
That's only 3 doublings of RAM away.
I think we need to change vm_struct's nr_pages from an unsigned int to
an unsigned long. It won't take up any more room because it's sandwiched
between a pointer and a phys_addr_t.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Bug 210023] New: Crash when allocating > 2 TB memory
2020-11-04 0:27 ` [Bug 210023] New: Crash when allocating > 2 TB memory Andrew Morton
2020-11-04 0:47 ` Matthew Wilcox
@ 2020-11-04 13:55 ` Hsin-Hui Wu
2020-11-04 18:19 ` Andrew Morton
1 sibling, 1 reply; 5+ messages in thread
From: Hsin-Hui Wu @ 2020-11-04 13:55 UTC (permalink / raw)
To: Andrew Morton; +Cc: bugzilla-daemon, linux-mm
[-- Attachment #1: Type: text/plain, Size: 3370 bytes --]
> With a machine with 3 TB (more than 2 TB memory). If you use vmalloc to
> allocate > 2 TB memory, the array_size below will be overflowed.
How was this observed?
Is there any know userspace operation which causes the kernel to try to
vmalloc such a large hunk of memory?
[Frank] The Dell PowerEdge R740/R940 can have up to 3TB/6TB memory.
installed. Our application requires reserve consecutive memory in the kernel
space and protected from userspace programs.
----------------------------------------------------------------------------------------------------
OK, thanks. Against current mainline your proposed change would look
like this, yes?
[Frank] Yes. This will support up to less than 16 TB. If you want to support
more than 16 TB, we need to expand nr_pages to unsigned long as
Matthew pointed out.
Will it be possible to add this to kernel 3.10.0-957.27.2.el7.x86_64?
Thanks,
Frank
On Tue, Nov 3, 2020 at 7:27 PM Andrew Morton <akpm@linux-foundation.org>
wrote:
> (switched to email. Please respond via emailed reply-to-all, not via the
> bugzilla web interface).
>
> On Tue, 03 Nov 2020 18:50:07 +0000 bugzilla-daemon@bugzilla.kernel.org
> wrote:
>
> > https://bugzilla.kernel.org/show_bug.cgi?id=210023
> >
> > Bug ID: 210023
> > Summary: Crash when allocating > 2 TB memory
> > Product: Memory Management
> > Version: 2.5
> > Kernel Version: 3.10.0-957.27.2.el7.x86_64
> > Hardware: All
> > OS: Linux
> > Tree: Mainline
> > Status: NEW
> > Severity: blocking
> > Priority: P1
> > Component: Slab Allocator
> > Assignee: akpm@linux-foundation.org
> > Reporter: hsinhuiwu@gmail.com
> > Regression: No
> >
> > With a machine with 3 TB (more than 2 TB memory). If you use vmalloc to
> > allocate > 2 TB memory, the array_size below will be overflowed.
>
> How was this observed?
>
> Is there any know userspace operation which causes the kernel to try to
> vmalloc such a large hunk of memory?
>
> > The array_size is an unsigned int and can only be used to allocate less
> than 2
> > TB memory. If you pass 2*1028*1028*1024*1024 = 2 * 2^40 in the argument
> of
> > vmalloc. The array_size will become 2*2^31 = 2^32. The 2^32 cannot be
> store
> > with a 32 bit integer.
> >
> > The fix is to change the type of array_size to unsigned long.
> >
> > vmalloc.c
> >
> > 1762 void *vmalloc(unsigned long size)
> > 1763 {
> > 1764 return __vmalloc_node_flags(size, NUMA_NO_NODE,
> > 1765 GFP_KERNEL | __GFP_HIGHMEM);
> > 1766 }
>
> OK, thanks. Against current mainline your proposed change would look
> like this, yes?
>
> --- a/mm/vmalloc.c~a
> +++ a/mm/vmalloc.c
> @@ -2461,9 +2461,11 @@ static void *__vmalloc_area_node(struct
> {
> const gfp_t nested_gfp = (gfp_mask & GFP_RECLAIM_MASK) |
> __GFP_ZERO;
> unsigned int nr_pages = get_vm_area_size(area) >> PAGE_SHIFT;
> - unsigned int array_size = nr_pages * sizeof(struct page *), i;
> + unsigned long array_size
> + unsigned int i;
> struct page **pages;
>
> + array_size = (unsigned long)nr_pages * sizeof(struct page *);
> gfp_mask |= __GFP_NOWARN;
> if (!(gfp_mask & (GFP_DMA | GFP_DMA32)))
> gfp_mask |= __GFP_HIGHMEM;
> _
>
>
[-- Attachment #2: Type: text/html, Size: 4788 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Bug 210023] New: Crash when allocating > 2 TB memory
2020-11-04 13:55 ` Hsin-Hui Wu
@ 2020-11-04 18:19 ` Andrew Morton
[not found] ` <CANpob6LY6oXqTG0GTJk-Z9qJtp9kpCCdoDAsbOJgTA8QfPCe2Q@mail.gmail.com>
0 siblings, 1 reply; 5+ messages in thread
From: Andrew Morton @ 2020-11-04 18:19 UTC (permalink / raw)
To: Hsin-Hui Wu; +Cc: bugzilla-daemon, linux-mm
On Wed, 4 Nov 2020 08:55:11 -0500 Hsin-Hui Wu <hsinhuiwu@gmail.com> wrote:
> > With a machine with 3 TB (more than 2 TB memory). If you use vmalloc to
> > allocate > 2 TB memory, the array_size below will be overflowed.
>
> How was this observed?
>
> Is there any know userspace operation which causes the kernel to try to
> vmalloc such a large hunk of memory?
>
> [Frank] The Dell PowerEdge R740/R940 can have up to 3TB/6TB memory.
> installed. Our application requires reserve consecutive memory in the kernel
> space and protected from userspace programs.
Did this require custom kernel changes? If not, precisely which system
calls were used to cause this allocation attempt?
> ----------------------------------------------------------------------------------------------------
> OK, thanks. Against current mainline your proposed change would look
> like this, yes?
>
> [Frank] Yes. This will support up to less than 16 TB. If you want to support
> more than 16 TB, we need to expand nr_pages to unsigned long as
> Matthew pointed out.
>
> Will it be possible to add this to kernel 3.10.0-957.27.2.el7.x86_64?
That is up to Red Hat to decide.
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [Bug 210023] New: Crash when allocating > 2 TB memory
[not found] ` <20201104163822.95df9ee4e42ad5ec45852a19@linux-foundation.org>
@ 2020-11-05 3:52 ` Hsin-Hui Wu
0 siblings, 0 replies; 5+ messages in thread
From: Hsin-Hui Wu @ 2020-11-05 3:52 UTC (permalink / raw)
To: Andrew Morton; +Cc: bugzilla-daemon, linux-mm
[-- Attachment #1: Type: text/plain, Size: 1943 bytes --]
We don't use userspace program to allocate memory. We use kernel module to
do so.
Here is the sample kernel program you can use to test on a machine that has
more than 2 TB memory.
Use "insmod memtest.ko mb=2100000" to allocate more than 2 TB memory.
Use "rmmod memtest" to free the memory.
memtest.c
=============================================================
#include <linux/version.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/mm.h>
#include <linux/vmalloc.h>
#ifdef MODVERSIONS
#include <linux/modversions.h>
#endif
#include <asm/io.h>
static char *mem_ptr;
MODULE_LICENSE("GPL");
int mb = 0;
MODULE_PARM_DESC(mb, "alloc MB memory");
module_param(mb, int, S_IWUSR | S_IRUGO);
static int __init memtest_init(void) {
mem_ptr = NULL;
if (mb > 0) {
unsigned long alloc_len;
alloc_len = mb * 1024 * 1024;
mem_ptr = vmalloc(alloc_len);
if (mem_ptr) {
printk("memtest: vmalloc for size %u MB.\n", mb);
} else {
printk("memtest: failed to vmalloc for bytes %u MB.\n", mb);
}
} else {
printk("memtest len_MB\n");
}
return(0);
}
static void __exit memtest_exit(void) {
if (mem_ptr) {
vfree(mem_ptr);
printk("memtest: vfree for size %u MB.\n", mb);
mem_ptr = NULL;
}
}
module_init(memtest_init);
module_exit(memtest_exit);
On Wed, Nov 4, 2020 at 7:38 PM Andrew Morton <akpm@linux-foundation.org>
wrote:
> On Wed, 4 Nov 2020 15:53:36 -0500 Hsin-Hui Wu <hsinhuiwu@gmail.com> wrote:
>
> > Did this require custom kernel changes? If not, precisely which system
> > calls were used to cause this allocation attempt?
> >
> > [Frank] No. vmalloc().
> >
>
> vmalloc() is not a system call.
>
> Please fully describe how vmalloc() came to be called with such a large
> request size. Fully. Are you able to provide example userspace code?
>
>
[-- Attachment #2: Type: text/html, Size: 2803 bytes --]
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2020-11-05 3:52 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
[not found] <bug-210023-27@https.bugzilla.kernel.org/>
2020-11-04 0:27 ` [Bug 210023] New: Crash when allocating > 2 TB memory Andrew Morton
2020-11-04 0:47 ` Matthew Wilcox
2020-11-04 13:55 ` Hsin-Hui Wu
2020-11-04 18:19 ` Andrew Morton
[not found] ` <CANpob6LY6oXqTG0GTJk-Z9qJtp9kpCCdoDAsbOJgTA8QfPCe2Q@mail.gmail.com>
[not found] ` <20201104163822.95df9ee4e42ad5ec45852a19@linux-foundation.org>
2020-11-05 3:52 ` Hsin-Hui Wu
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).