All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel
@ 2024-01-26  9:40 oficerovas
  2024-01-26  9:40 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
  2024-01-26  9:40 ` [PATCH 2/2] KVM: use __vcalloc for very large allocations oficerovas
  0 siblings, 2 replies; 7+ messages in thread
From: oficerovas @ 2024-01-26  9:40 UTC (permalink / raw)
  To: oficerovas, linux-kernel, kvm; +Cc: kovalev

From: Alexander Ofitserov <oficerovas@altlinux.org>

Syzkaller hit 'WARNING: kmalloc bug in kvm_arch_prepare_memory_region' bug.

This bug is not a vulnerability and is reproduced only when running with root privileges
for stable 5.10 kernel.

Bug fixed by backported commits in next two patches.

------------[ cut here ]------------
WARNING: CPU: 1 PID: 315 at mm/util.c:618 kvmalloc_node+0x163/0x170 mm/util.c:618
Modules linked in: ide_cd_mod cdrom ide_gd_mod ata_generic pata_acpi ata_piix libata scsi_mod ide_pci_generic ppdev joydev kvm_amd ccp kvm irqbypass crct10dif_pclmul crc32_pclmul crc32c_intel ghash_clmulni_intel aesni_intel crypto_simd bochs_drm cryptd af_packet drm_vram_helper glue_helper drm_ttm_helper ttm psmouse evdev pcspkr drm_kms_helper input_leds piix cec ide_core rc_core intel_agp i2c_piix4 serio_raw intel_gtt parport_pc parport floppy tiny_power_button qemu_fw_cfg button sch_fq_codel drm fuse dm_mod binfmt_misc efi_pstore virtio_rng rng_core ip_tables x_tables autofs4
CPU: 1 PID: 315 Comm: syz-executor319 Not tainted 5.10.198-std-def-alt1 #1
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.16.0-alt1 04/01/2014
RIP: 0010:kvmalloc_node+0x163/0x170 mm/util.c:618
Code: ed 41 81 cd 00 20 01 00 e9 6c ff ff ff e8 f5 f1 d0 ff 81 e5 00 20 00 00 31 ff 89 ee e8 16 ee d0 ff 85 ed 75 cc e8 dd f1 d0 ff <0f> 0b e9 e4 fe ff ff 66 0f 1f 44 00 00 0f 1f 44 00 00 55 48 89 fd
RSP: 0018:ffff8881034c78a0 EFLAGS: 00010293
RAX: 0000000000000000 RBX: 0000000010101640 RCX: ffffffff817bff9a
RDX: ffff8881185e0240 RSI: ffffffff817bffa3 RDI: 0000000000000005
RBP: 0000000000000000 R08: 0000000000000001 R09: ffff8881034c7ac8
R10: 0000000000000000 R11: 0000000000000001 R12: 000000008080b200
R13: 0000000000000000 R14: 00000000ffffffff R15: ffff8881034c7ab0
FS:  00007f4ee2a3d740(0000) GS:ffff888140280000(0000) knlGS:0000000000000000
CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000000020000008 CR3: 0000000130906000 CR4: 0000000000750ee0
PKRU: 55555554
Call Trace:
 kvm_arch_prepare_memory_region+0x141/0x5c0 [kvm]
 kvm_set_memslot+0x522/0x13d0 [kvm]
 __kvm_set_memory_region+0xb32/0xfe0 [kvm]
 kvm_vm_ioctl+0x6b7/0x1cd0 [kvm]
 vfs_ioctl fs/ioctl.c:48 [inline]
 __do_sys_ioctl fs/ioctl.c:753 [inline]
 __se_sys_ioctl fs/ioctl.c:739 [inline]
 __x64_sys_ioctl+0x19f/0x210 fs/ioctl.c:739
 do_syscall_64+0x33/0x40 arch/x86/entry/common.c:46
 entry_SYSCALL_64_after_hwframe+0x62/0xc7
RIP: 0033:0x7f4ee2b3ad49
Code: 00 c3 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 8b 0d ef 70 0d 00 f7 d8 64 89 01 48
RSP: 002b:00007fffa9df3428 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 000056092b108330 RCX: 00007f4ee2b3ad49
RDX: 00000000200000c0 RSI: 000000004020ae46 RDI: 0000000000000004
RBP: 0000000000000000 R08: 000056092b108330 R09: 000056092b108330
R10: 000056092b108330 R11: 0000000000000246 R12: 000056092b108240
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
irq event stamp: 19075
hardirqs last  enabled at (19085): [<ffffffff813489c0>] console_unlock+0xa40/0xca0 kernel/printk/printk.c:2561
hardirqs last disabled at (19092): [<ffffffff81348643>] console_unlock+0x6c3/0xca0 kernel/printk/printk.c:2476
softirqs last  enabled at (19108): [<ffffffff836011d2>] asm_call_irq_on_stack+0x12/0x20
softirqs last disabled at (19101): [<ffffffff836011d2>] asm_call_irq_on_stack+0x12/0x20
---[ end trace c4463afe05024b06 ]---


Syzkaller reproducer:
# {Threaded:false Repeat:false RepeatTimes:0 Procs:1 Slowdown:1 Sandbox: Leak:false NetInjection:false NetDevices:false NetReset:false Cgroups:false BinfmtMisc:false CloseFDs:false KCSAN:false DevlinkPCI:false USB:false VhciInjection:false Wifi:false IEEE802154:false Sysctl:false UseTmpDir:false HandleSegv:false Repro:false Trace:false LegacyOptions:{Collide:false Fault:false FaultCall:0 FaultNth:0}}
r0 = openat$kvm(0xffffffffffffff9c, &(0x7f0000000000), 0x0, 0x0)
connect$pppl2tp(0xffffffffffffffff, &(0x7f00000000c0)=@pppol2tp={0x18, 0x1, {0x0, 0xffffffffffffffff, {0x2, 0x0, @rand_addr=0x64010101}}}, 0x26)
r1 = ioctl$KVM_CREATE_VM(r0, 0xae01, 0x0)
ioctl$KVM_CREATE_DEVICE(r1, 0x4020ae46, &(0x7f00000000c0))


C reproducer:
// autogenerated by syzkaller (https://github.com/google/syzkaller)

#define _GNU_SOURCE 

#include <endian.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>

uint64_t r[2] = {0xffffffffffffffff, 0xffffffffffffffff};

int main(void)
{
		syscall(__NR_mmap, 0x1ffff000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
	syscall(__NR_mmap, 0x20000000ul, 0x1000000ul, 7ul, 0x32ul, -1, 0ul);
	syscall(__NR_mmap, 0x21000000ul, 0x1000ul, 0ul, 0x32ul, -1, 0ul);
				intptr_t res = 0;
memcpy((void*)0x20000000, "/dev/kvm\000", 9);
	res = syscall(__NR_openat, 0xffffffffffffff9cul, 0x20000000ul, 0ul, 0ul);
	if (res != -1)
		r[0] = res;
*(uint16_t*)0x200000c0 = 0x18;
*(uint32_t*)0x200000c2 = 1;
*(uint32_t*)0x200000c6 = 0;
*(uint32_t*)0x200000ca = -1;
*(uint16_t*)0x200000ce = 2;
*(uint16_t*)0x200000d0 = htobe16(0);
*(uint32_t*)0x200000d2 = htobe32(0x64010101);
*(uint16_t*)0x200000de = 0;
*(uint16_t*)0x200000e0 = 0;
*(uint16_t*)0x200000e2 = 0;
*(uint16_t*)0x200000e4 = 0;
	syscall(__NR_connect, -1, 0x200000c0ul, 0x26ul);
	res = syscall(__NR_ioctl, r[0], 0xae01, 0ul);
	if (res != -1)
		r[1] = res;
*(uint32_t*)0x200000c0 = 0;
*(uint32_t*)0x200000c8 = 0;
	syscall(__NR_ioctl, r[1], 0x4020ae46, 0x200000c0ul);
	return 0;
}

[PATCH 1/2] mm: vmalloc: introduce array allocation functions
[PATCH 2/2] KVM: use __vcalloc for very large allocations

-- 
2.42.1

^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] mm: vmalloc: introduce array allocation functions
  2024-01-26  9:40 [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel oficerovas
@ 2024-01-26  9:40 ` oficerovas
  2024-01-26  9:40 ` [PATCH 2/2] KVM: use __vcalloc for very large allocations oficerovas
  1 sibling, 0 replies; 7+ messages in thread
From: oficerovas @ 2024-01-26  9:40 UTC (permalink / raw)
  To: oficerovas, linux-kernel, kvm; +Cc: kovalev

From: Alexander Ofitserov <oficerovas@altlinux.org>

From: Paolo Bonzini <pbonzini@redhat.com>

commit a8749a35c399 ("mm: vmalloc: introduce array allocation functions")

Linux has dozens of occurrences of vmalloc(array_size()) and
vzalloc(array_size()).  Allow to simplify the code by providing
vmalloc_array and vcalloc, as well as the underscored variants that let
the caller specify the GFP flags.

Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
---
 include/linux/vmalloc.h |  5 +++++
 mm/util.c               | 50 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 76dad53a410ac..0fd47f2f39eb0 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
 void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
 		int node, const void *caller);
 
+extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags);
+extern void *vmalloc_array(size_t n, size_t size);
+extern void *__vcalloc(size_t n, size_t size, gfp_t flags);
+extern void *vcalloc(size_t n, size_t size);
+
 extern void vfree(const void *addr);
 extern void vfree_atomic(const void *addr);
 
diff --git a/mm/util.c b/mm/util.c
index 25bfda774f6fd..7fd3c2bb3e4f5 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -686,6 +686,56 @@ static inline void *__page_rmapping(struct page *page)
 	return (void *)mapping;
 }
 
+/**
+ * __vmalloc_array - allocate memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+void *__vmalloc_array(size_t n, size_t size, gfp_t flags)
+{
+	size_t bytes;
+
+	if (unlikely(check_mul_overflow(n, size, &bytes)))
+		return NULL;
+	return __vmalloc(bytes, flags);
+}
+EXPORT_SYMBOL(__vmalloc_array);
+
+/**
+ * vmalloc_array - allocate memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ */
+void *vmalloc_array(size_t n, size_t size)
+{
+	return __vmalloc_array(n, size, GFP_KERNEL);
+}
+EXPORT_SYMBOL(vmalloc_array);
+
+/**
+ * __vcalloc - allocate and zero memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+void *__vcalloc(size_t n, size_t size, gfp_t flags)
+{
+	return __vmalloc_array(n, size, flags | __GFP_ZERO);
+}
+EXPORT_SYMBOL(__vcalloc);
+
+/**
+ * vcalloc - allocate and zero memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ */
+void *vcalloc(size_t n, size_t size)
+{
+	return __vmalloc_array(n, size, GFP_KERNEL | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vcalloc);
+
 /* Neutral page->mapping pointer to address_space or anon_vma or other */
 void *page_rmapping(struct page *page)
 {
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH 2/2] KVM: use __vcalloc for very large allocations
  2024-01-26  9:40 [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel oficerovas
  2024-01-26  9:40 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
@ 2024-01-26  9:40 ` oficerovas
  1 sibling, 0 replies; 7+ messages in thread
From: oficerovas @ 2024-01-26  9:40 UTC (permalink / raw)
  To: oficerovas, linux-kernel, kvm; +Cc: kovalev

From: Alexander Ofitserov <oficerovas@altlinux.org>

From: Paolo Bonzini <pbonzini@redhat.com>

commit 37b2a6510a48 ("KVM: use __vcalloc for very large allocations")

Allocations whose size is related to the memslot size can be arbitrarily
large.  Do not use kvzalloc/kvcalloc, as those are limited to "not crazy"
sizes that fit in 32 bits.

URL: https://lore.kernel.org/lkml/20220711090606.962822924@linuxfoundation.org/
Reviewed-by: David Hildenbrand <david@redhat.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
---
 arch/powerpc/kvm/book3s_hv_uvmem.c | 2 +-
 arch/x86/kvm/mmu/page_track.c      | 2 +-
 arch/x86/kvm/x86.c                 | 4 ++--
 virt/kvm/kvm_main.c                | 4 ++--
 4 files changed, 6 insertions(+), 6 deletions(-)

diff --git a/arch/powerpc/kvm/book3s_hv_uvmem.c b/arch/powerpc/kvm/book3s_hv_uvmem.c
index 3dd58b4ee33e5..5f6b3f80023de 100644
--- a/arch/powerpc/kvm/book3s_hv_uvmem.c
+++ b/arch/powerpc/kvm/book3s_hv_uvmem.c
@@ -250,7 +250,7 @@ int kvmppc_uvmem_slot_init(struct kvm *kvm, const struct kvm_memory_slot *slot)
 	p = kzalloc(sizeof(*p), GFP_KERNEL);
 	if (!p)
 		return -ENOMEM;
-	p->pfns = vzalloc(array_size(slot->npages, sizeof(*p->pfns)));
+	p->pfns = vcalloc(slot->npages, sizeof(*p->pfns));
 	if (!p->pfns) {
 		kfree(p);
 		return -ENOMEM;
diff --git a/arch/x86/kvm/mmu/page_track.c b/arch/x86/kvm/mmu/page_track.c
index 81cf4babbd0b4..3c379335ea477 100644
--- a/arch/x86/kvm/mmu/page_track.c
+++ b/arch/x86/kvm/mmu/page_track.c
@@ -35,7 +35,7 @@ int kvm_page_track_create_memslot(struct kvm_memory_slot *slot,
 
 	for (i = 0; i < KVM_PAGE_TRACK_MAX; i++) {
 		slot->arch.gfn_track[i] =
-			kvcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
+			__vcalloc(npages, sizeof(*slot->arch.gfn_track[i]),
 				 GFP_KERNEL_ACCOUNT);
 		if (!slot->arch.gfn_track[i])
 			goto track_free;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 13e4699a0744f..6c2bf7cd7aec6 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10826,14 +10826,14 @@ static int kvm_alloc_memslot_metadata(struct kvm_memory_slot *slot,
 				      slot->base_gfn, level) + 1;
 
 		slot->arch.rmap[i] =
-			kvcalloc(lpages, sizeof(*slot->arch.rmap[i]),
+			__vcalloc(lpages, sizeof(*slot->arch.rmap[i]),
 				 GFP_KERNEL_ACCOUNT);
 		if (!slot->arch.rmap[i])
 			goto out_free;
 		if (i == 0)
 			continue;
 
-		linfo = kvcalloc(lpages, sizeof(*linfo), GFP_KERNEL_ACCOUNT);
+		linfo = __vcalloc(lpages, sizeof(*linfo), GFP_KERNEL_ACCOUNT);
 		if (!linfo)
 			goto out_free;
 
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 356fd5d1a4285..b7638c3c9eb7d 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -1008,9 +1008,9 @@ static int kvm_vm_release(struct inode *inode, struct file *filp)
  */
 static int kvm_alloc_dirty_bitmap(struct kvm_memory_slot *memslot)
 {
-	unsigned long dirty_bytes = 2 * kvm_dirty_bitmap_bytes(memslot);
+	unsigned long dirty_bytes = kvm_dirty_bitmap_bytes(memslot);
 
-	memslot->dirty_bitmap = kvzalloc(dirty_bytes, GFP_KERNEL_ACCOUNT);
+	memslot->dirty_bitmap = __vcalloc(2, dirty_bytes, GFP_KERNEL_ACCOUNT);
 	if (!memslot->dirty_bitmap)
 		return -ENOMEM;
 
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] mm: vmalloc: introduce array allocation functions
  2024-01-26  9:55 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
  2024-01-26 13:59   ` David Laight
@ 2024-01-27  0:50   ` Greg Kroah-Hartman
  1 sibling, 0 replies; 7+ messages in thread
From: Greg Kroah-Hartman @ 2024-01-27  0:50 UTC (permalink / raw)
  To: oficerovas
  Cc: stable, Paolo Bonzini, Andrew Morton, Michael Ellerman, kovalev,
	nickel, dutyrok, Michal Hocko

On Fri, Jan 26, 2024 at 12:55:13PM +0300, oficerovas@altlinux.org wrote:
> From: Alexander Ofitserov <oficerovas@altlinux.org>
> 
> From: Paolo Bonzini <pbonzini@redhat.com>

Nit, duplicate From: lines :(

I'll fix it up by hand, watch out for that next time please.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 1/2] mm: vmalloc: introduce array allocation functions
  2024-01-26 13:59   ` David Laight
@ 2024-01-26 18:42     ` Paolo Bonzini
  0 siblings, 0 replies; 7+ messages in thread
From: Paolo Bonzini @ 2024-01-26 18:42 UTC (permalink / raw)
  To: David Laight
  Cc: oficerovas, stable, Greg Kroah-Hartman, Andrew Morton,
	Michael Ellerman, kovalev, nickel, dutyrok, Michal Hocko

On Fri, Jan 26, 2024 at 3:00 PM David Laight <David.Laight@aculab.com> wrote:
>
> From: oficerovas@altlinux.org
> > Sent: 26 January 2024 09:55
> >
> > commit a8749a35c399 ("mm: vmalloc: introduce array allocation functions")
> >
> > Linux has dozens of occurrences of vmalloc(array_size()) and
> > vzalloc(array_size()).  Allow to simplify the code by providing
> > vmalloc_array and vcalloc, as well as the underscored variants that let
> > the caller specify the GFP flags.
> >
> > Acked-by: Michal Hocko <mhocko@suse.com>
> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> > Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
> > ---
> >  include/linux/vmalloc.h |  5 +++++
> >  mm/util.c               | 50 +++++++++++++++++++++++++++++++++++++++++
> >  2 files changed, 55 insertions(+)
> >
> > diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
> > index 76dad53a410ac..0fd47f2f39eb0 100644
> > --- a/include/linux/vmalloc.h
> > +++ b/include/linux/vmalloc.h
> > @@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
> >  void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
> >               int node, const void *caller);
> >
> > +extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags);
> > +extern void *vmalloc_array(size_t n, size_t size);
> > +extern void *__vcalloc(size_t n, size_t size, gfp_t flags);
> > +extern void *vcalloc(size_t n, size_t size);
>
> Symbols starting __ should really be ones that are part of the implementation
> and not publicly visible.

This is a patch that already exists in master.

Paolo


^ permalink raw reply	[flat|nested] 7+ messages in thread

* RE: [PATCH 1/2] mm: vmalloc: introduce array allocation functions
  2024-01-26  9:55 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
@ 2024-01-26 13:59   ` David Laight
  2024-01-26 18:42     ` Paolo Bonzini
  2024-01-27  0:50   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 7+ messages in thread
From: David Laight @ 2024-01-26 13:59 UTC (permalink / raw)
  To: 'oficerovas@altlinux.org', stable
  Cc: Paolo Bonzini, Greg Kroah-Hartman, Andrew Morton,
	Michael Ellerman, kovalev, nickel, dutyrok, Michal Hocko

From: oficerovas@altlinux.org
> Sent: 26 January 2024 09:55
> 
> commit a8749a35c399 ("mm: vmalloc: introduce array allocation functions")
> 
> Linux has dozens of occurrences of vmalloc(array_size()) and
> vzalloc(array_size()).  Allow to simplify the code by providing
> vmalloc_array and vcalloc, as well as the underscored variants that let
> the caller specify the GFP flags.
> 
> Acked-by: Michal Hocko <mhocko@suse.com>
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
> ---
>  include/linux/vmalloc.h |  5 +++++
>  mm/util.c               | 50 +++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 55 insertions(+)
> 
> diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
> index 76dad53a410ac..0fd47f2f39eb0 100644
> --- a/include/linux/vmalloc.h
> +++ b/include/linux/vmalloc.h
> @@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
>  void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
>  		int node, const void *caller);
> 
> +extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags);
> +extern void *vmalloc_array(size_t n, size_t size);
> +extern void *__vcalloc(size_t n, size_t size, gfp_t flags);
> +extern void *vcalloc(size_t n, size_t size);

Symbols starting __ should really be ones that are part of the implementation
and not publicly visible.

...
> +/**
> + * __vmalloc_array - allocate memory for a virtually contiguous array.
> + * @n: number of elements.
> + * @size: element size.
> + * @flags: the type of memory to allocate (see kmalloc).
> + */
> +void *__vmalloc_array(size_t n, size_t size, gfp_t flags)
> +{
> +	size_t bytes;
> +
> +	if (unlikely(check_mul_overflow(n, size, &bytes)))
> +		return NULL;
> +	return __vmalloc(bytes, flags);
> +}
> +EXPORT_SYMBOL(__vmalloc_array);
> +
> +/**
> + * vmalloc_array - allocate memory for a virtually contiguous array.
> + * @n: number of elements.
> + * @size: element size.
> + */
> +void *vmalloc_array(size_t n, size_t size)
> +{
> +	return __vmalloc_array(n, size, GFP_KERNEL);
> +}
> +EXPORT_SYMBOL(vmalloc_array);

and that should just be an inline wrapper on the function above.

	David

-
Registered Address Lakeside, Bramley Road, Mount Farm, Milton Keynes, MK1 1PT, UK
Registration No: 1397386 (Wales)


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH 1/2] mm: vmalloc: introduce array allocation functions
  2024-01-26  9:55 [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel oficerovas
@ 2024-01-26  9:55 ` oficerovas
  2024-01-26 13:59   ` David Laight
  2024-01-27  0:50   ` Greg Kroah-Hartman
  0 siblings, 2 replies; 7+ messages in thread
From: oficerovas @ 2024-01-26  9:55 UTC (permalink / raw)
  To: stable
  Cc: Alexander Ofitserov, Paolo Bonzini, Greg Kroah-Hartman,
	Andrew Morton, Michael Ellerman, kovalev, nickel, dutyrok,
	Michal Hocko

From: Alexander Ofitserov <oficerovas@altlinux.org>

From: Paolo Bonzini <pbonzini@redhat.com>

commit a8749a35c399 ("mm: vmalloc: introduce array allocation functions")

Linux has dozens of occurrences of vmalloc(array_size()) and
vzalloc(array_size()).  Allow to simplify the code by providing
vmalloc_array and vcalloc, as well as the underscored variants that let
the caller specify the GFP flags.

Acked-by: Michal Hocko <mhocko@suse.com>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Alexander Ofitserov <oficerovas@altlinux.org>
---
 include/linux/vmalloc.h |  5 +++++
 mm/util.c               | 50 +++++++++++++++++++++++++++++++++++++++++
 2 files changed, 55 insertions(+)

diff --git a/include/linux/vmalloc.h b/include/linux/vmalloc.h
index 76dad53a410ac..0fd47f2f39eb0 100644
--- a/include/linux/vmalloc.h
+++ b/include/linux/vmalloc.h
@@ -112,6 +112,11 @@ extern void *__vmalloc_node_range(unsigned long size, unsigned long align,
 void *__vmalloc_node(unsigned long size, unsigned long align, gfp_t gfp_mask,
 		int node, const void *caller);
 
+extern void *__vmalloc_array(size_t n, size_t size, gfp_t flags);
+extern void *vmalloc_array(size_t n, size_t size);
+extern void *__vcalloc(size_t n, size_t size, gfp_t flags);
+extern void *vcalloc(size_t n, size_t size);
+
 extern void vfree(const void *addr);
 extern void vfree_atomic(const void *addr);
 
diff --git a/mm/util.c b/mm/util.c
index 25bfda774f6fd..7fd3c2bb3e4f5 100644
--- a/mm/util.c
+++ b/mm/util.c
@@ -686,6 +686,56 @@ static inline void *__page_rmapping(struct page *page)
 	return (void *)mapping;
 }
 
+/**
+ * __vmalloc_array - allocate memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+void *__vmalloc_array(size_t n, size_t size, gfp_t flags)
+{
+	size_t bytes;
+
+	if (unlikely(check_mul_overflow(n, size, &bytes)))
+		return NULL;
+	return __vmalloc(bytes, flags);
+}
+EXPORT_SYMBOL(__vmalloc_array);
+
+/**
+ * vmalloc_array - allocate memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ */
+void *vmalloc_array(size_t n, size_t size)
+{
+	return __vmalloc_array(n, size, GFP_KERNEL);
+}
+EXPORT_SYMBOL(vmalloc_array);
+
+/**
+ * __vcalloc - allocate and zero memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ * @flags: the type of memory to allocate (see kmalloc).
+ */
+void *__vcalloc(size_t n, size_t size, gfp_t flags)
+{
+	return __vmalloc_array(n, size, flags | __GFP_ZERO);
+}
+EXPORT_SYMBOL(__vcalloc);
+
+/**
+ * vcalloc - allocate and zero memory for a virtually contiguous array.
+ * @n: number of elements.
+ * @size: element size.
+ */
+void *vcalloc(size_t n, size_t size)
+{
+	return __vmalloc_array(n, size, GFP_KERNEL | __GFP_ZERO);
+}
+EXPORT_SYMBOL(vcalloc);
+
 /* Neutral page->mapping pointer to address_space or anon_vma or other */
 void *page_rmapping(struct page *page)
 {
-- 
2.42.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2024-01-27  0:50 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-01-26  9:40 [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel oficerovas
2024-01-26  9:40 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
2024-01-26  9:40 ` [PATCH 2/2] KVM: use __vcalloc for very large allocations oficerovas
2024-01-26  9:55 [PATCH 0/2] kvm: fix kmalloc bug in kvm_arch_prepare_memory_region on 5.10 stable kernel oficerovas
2024-01-26  9:55 ` [PATCH 1/2] mm: vmalloc: introduce array allocation functions oficerovas
2024-01-26 13:59   ` David Laight
2024-01-26 18:42     ` Paolo Bonzini
2024-01-27  0:50   ` Greg Kroah-Hartman

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.