HARDENED_USERCOPY will BUG on multiple slub objects coalesced into an sk_buff fragment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hello,

Here's a rare issue I reproduce on 4.12.10 (centos config): full log sample below.
An innocent process (dhcpclient) is about to receive a datagram, but during skb_copy_datagram_iter() usercopy triggers a BUG in:
usercopy.c:check_heap_object() -> slub.c:__check_heap_object(), because the sk_buff fragment being copied crosses the 64-byte slub object boundary.

Example __check_heap_object() context:
  n=128    << usually 128, sometimes 192.
  object_size=64
  s->size=64
  page_address(page)=0xffff880233f7c000
  ptr=0xffff880233f7c540

My take on the root cause:
  When adding data to an skb, new data is appended to the current fragment if the new chunk immediately follows the last one: by simply increasing the frag->size, skb_frag_size_add().
  See include/linux/skbuff.h:skb_can_coalesce() callers.
  This happens very frequently for kmem_cache objects (slub/slab) with intensive kernel level TCP traffic, and produces sk_buff fragments that span multiple kmem_cache objects.
  However, if the same happens to receive data intended for user space, usercopy triggers a BUG.
  This is quite rare but possible: fails after 5-60min of network traffic (needs some unfortunate timing, e.g. only on QEMU, without CONFIG_SLUB_DEBUG_ON etc).
  I used an instrumentation that counts coalesced chunks in the fragment, in order to confirm that the failing fragment was legally constructed from multiple slub objects.

On 4.17.0.rc3:
  I could not reproduce the issue with the latest kernel, but the changes in usercopy.c and slub.c since 4.12 do not address the issue.
  Moreover, it would be quite hard to do without effectively disabling the heap protection.
  However, looking at the recent changes in include/linux/sk_buff.h I see skb_zcopy() that yields negative skb_can_coalesce() and may have masked the problem.

Please, let me know what do you think?
4.12.10 is the centos official kernel with CONFIG_HARDENED_USERCOPY enabled: if the problem is real we better have an erratum for it. 

Regards,
Anton Eidelman


[ 655.602500] usercopy: kernel memory exposure attempt detected from ffff88022a31aa00 (kmalloc-64) (192 bytes)
[ 655.604254] ----------[ cut here ]----------
[ 655.604877] kernel BUG at mm/usercopy.c:72!
[ 655.606302] invalid opcode: 0000 1 SMP
[ 655.618390] CPU: 3 PID: 2335 Comm: dhclient Tainted: G O 4.12.10-1.el7.elrepo.x86_64 #1
[ 655.619666] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1ubuntu1 04/01/2014
[ 655.620926] task: ffff880229ab2d80 task.stack: ffffc90001198000
[ 655.621786] RIP: 0010:__check_object_size+0x74/0x190
[ 655.622489] RSP: 0018:ffffc9000119bbb8 EFLAGS: 00010246
[ 655.623236] RAX: 0000000000000060 RBX: ffff88022a31aa00 RCX: 0000000000000000
[ 655.624234] RDX: 0000000000000000 RSI: ffff88023fcce108 RDI: ffff88023fcce108
[ 655.625237] RBP: ffffc9000119bbd8 R08: 00000000fffffffe R09: 0000000000000271
[ 655.626248] R10: 0000000000000005 R11: 0000000000000270 R12: 00000000000000c0
[ 655.627256] R13: ffff88022a31aac0 R14: 0000000000000001 R15: 00000000000000c0
[ 655.628268] FS: 00007fb54413b880(0000) GS:ffff88023fcc0000(0000) knlGS:0000000000000000
[ 655.629561] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 655.630289] CR2: 00007fb5439dc5c0 CR3: 000000023211d000 CR4: 00000000003406e0
[ 655.631268] DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000
[ 655.632281] DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400
[ 655.633318] Call Trace:
[ 655.633696] copy_page_to_iter_iovec+0x9c/0x180
[ 655.634351] copy_page_to_iter+0x22/0x160
[ 655.634943] skb_copy_datagram_iter+0x157/0x260
[ 655.635604] packet_recvmsg+0xcb/0x460
[ 655.636156] ? selinux_socket_recvmsg+0x17/0x20
[ 655.636816] sock_recvmsg+0x3d/0x50
[ 655.637330] ___sys_recvmsg+0xd7/0x1f0
[ 655.637892] ? kvm_clock_get_cycles+0x1e/0x20
[ 655.638533] ? ktime_get_ts64+0x49/0xf0
[ 655.639101] ? _copy_to_user+0x26/0x40
[ 655.639657] __sys_recvmsg+0x51/0x90
[ 655.640184] SyS_recvmsg+0x12/0x20
[ 655.640696] entry_SYSCALL_64_fastpath+0x1a/0xa5
--------------------------------------------------------------------------------------------------------------------------------------------


[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Bugtraq]     [Linux OMAP]     [Linux MIPS]     [eCos]     [Asterisk Internet PBX]     [Linux API]

  Powered by Linux