Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tty/vt: avoid high order pages allocation on GIO_UNIMAP ioctl

GIO_UNIMAP can easily result in a high order allocation,
seen 6th order allocation on radeondrmfb:

fbcon: radeondrmfb (fb0) is primary device
Console: switching to colour frame buffer device 160x64
radeon 0000:01:05.0: fb0: radeondrmfb frame buffer device
WARNING: CPU: 0 PID: 78661 at mm/page_alloc.c:3532
__alloc_pages_nodemask+0x1b1/0x600
order 6 >= 3, gfp 0x40d0

The warning is generated by a debug patch.

At the same time it's safe to use kvmalloc() for allocation in
con_get_unimap(), so let's do the substitution.

And do the same for con_set_unimap().

Signed-off-by: Konstantin Khorenko <khorenko@virtuozzo.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Konstantin Khorenko and committed by
Greg Kroah-Hartman
fa2b360f f692f776

+4 -4
+4 -4
drivers/tty/vt/consolemap.c
··· 542 542 if (!ct) 543 543 return 0; 544 544 545 - unilist = memdup_user(list, ct * sizeof(struct unipair)); 545 + unilist = vmemdup_user(list, ct * sizeof(struct unipair)); 546 546 if (IS_ERR(unilist)) 547 547 return PTR_ERR(unilist); 548 548 ··· 641 641 642 642 out_unlock: 643 643 console_unlock(); 644 - kfree(unilist); 644 + kvfree(unilist); 645 645 return err; 646 646 } 647 647 ··· 743 743 struct uni_pagedir *p; 744 744 struct unipair *unilist; 745 745 746 - unilist = kmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL); 746 + unilist = kvmalloc_array(ct, sizeof(struct unipair), GFP_KERNEL); 747 747 if (!unilist) 748 748 return -ENOMEM; 749 749 ··· 775 775 if (copy_to_user(list, unilist, min(ect, ct) * sizeof(struct unipair))) 776 776 ret = -EFAULT; 777 777 put_user(ect, uct); 778 - kfree(unilist); 778 + kvfree(unilist); 779 779 return ret ? ret : (ect <= ct) ? 0 : -ENOMEM; 780 780 } 781 781