Wednesday, May 10, 2017

Exploiting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux kernel via packet sockets

Guest blog post, posted by Andrey Konovalov

Introduction

Lately I’ve been spending some time fuzzing network-related Linux kernel interfaces with syzkaller. Besides cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 recently discovered vulnerability in DCCP sockets, I also found anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one, this time in packet sockets. This post describes how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug was discovered and how we can exploit it to escalate privileges.

The bug itself (CVE-2017-7308) is a signedness issue, which leads to an exploitable heap-out-of-bounds write. It can be triggered by providing specific parameters to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_RX_RING option on an AF_PACKET socket with a TPACKET_V3 ring buffer version enabled. As a result cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following sanity check in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_set_ring() function in net/packet/af_packet.c can be bypassed, which later leads to an out-of-bounds access.

4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     (int)(req->tp_block_size -
4209                           BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
4210                         goto out;

The bug was introduced on Aug 19, 2011 in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 commit f6fb8f10 ("af-packet: TPACKET_V3 flexible buffer implementation") togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TPACKET_V3 implementation. There was an attempt to fix it on Aug 15, 2014 in commit dc808110 ("packet: handle too big packets for PACKET_V3") by adding additional checks, but this was not sufficient, as shown below. The bug was fixed in 2b6867c2 ("net/packet: fix overflow in check for priv area size") on Mar 29, 2017.

The bug affects a kernel if it has AF_PACKET sockets enabled (CONFIG_PACKET=y), which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 case for many Linux kernel distributions. Exploitation requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CAP_NET_RAW privilege to be able to create such sockets. However it's possible to do that from a user namespace if cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are enabled (CONFIG_USER_NS=y) and accessible to unprivileged users.

Since packet sockets are a quite widely used kernel feature, this vulnerability affects a number of popular Linux kernel distributions including Ubuntu and Android. It should be noted, that access to AF_PACKET sockets is expressly disallowed to any untrusted code within Android, although it is available to some privileged components. Updated Ubuntu kernels are already out, Android’s update is scheduled for July.

Syzkaller


The bug was found with syzkaller, a coverage guided syscall fuzzer, and KASAN, a dynamic memory error detector. I’m going to provide some details on how syzkaller works and how to use it for fuzzing some kernel interface in case someone decides to try this.

Let’s start with a quick overview of how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syzkaller fuzzer works. Syzkaller is able to generate random programs (sequences of syscalls) based on manually written template descriptions for each syscall. The fuzzer executes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se programs and collects code coverage for each of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. Using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 coverage information, syzkaller keeps a corpus of programs, which trigger different code paths in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. Whenever a new program triggers a new code path (i.e. gives new coverage), syzkaller adds it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corpus. Besides generating completely new programs, syzkaller is able to mutate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 existing ones from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corpus.

Syzkaller is meant to be used togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with dynamic bug detectors like KASAN (detects memory bugs like out-of-bounds and use-after-frees, available upstream since 4.0), KMSAN (detects uses of uninitialized memory, prototype was just released) or KTSAN (detects data races, prototype is available). The idea is that syzkaller stresses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel and executes various interesting code paths and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 detectors detect and report bugs.

The usual workflow for finding bugs with syzkaller is as follows:
  1. Setup syzkaller and make sure it works. README and wiki provides quite extensive information on how to do that.
  2. Write template descriptions for a particular kernel interface you want to test.
  3. Specify cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syscalls that are used in this interface in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syzkaller config.
  4. Run syzkaller until it finds bugs. Usually this happens quite fast for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 interfaces, that haven’t been tested with it previously.

Syzkaller uses it’s own declarative language to describe syscall templates. Checkout sys/sys.txt for an example or sys/README.md for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 information on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syntax. Here’s an excerpt from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syzkaller descriptions for AF_PACKET sockets that I used to discover cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug:

resource sock_packet[sock]

define ETH_P_ALL_BE htons(ETH_P_ALL)

socket$packet(domain const[AF_PACKET], type flags[packet_socket_type], proto const[ETH_P_ALL_BE]) sock_packet

packet_socket_type = SOCK_RAW, SOCK_DGRAM

setsockopt$packet_rx_ring(fd sock_packet, level const[SOL_PACKET], optname const[PACKET_RX_RING], optval ptr[in, tpacket_req_u], optlen len[optval])
setsockopt$packet_tx_ring(fd sock_packet, level const[SOL_PACKET], optname const[PACKET_TX_RING], optval ptr[in, tpacket_req_u], optlen len[optval])

tpacket_req {
tp_block_size int32
tp_block_nr int32
tp_frame_size int32
tp_frame_nr int32
}

tpacket_req3 {
tp_block_size int32
tp_block_nr int32
tp_frame_size int32
tp_frame_nr int32
tp_retire_blk_tov int32
tp_sizeof_priv int32
tp_feature_req_word int32
}

tpacket_req_u [
req tpacket_req
req3 tpacket_req3
] [varlen]

The syntax is mostly self-explanatory. First, we declare a new type sock_packet. This type is inherited from an existing type sock. That way syzkaller will use syscalls which have arguments of type sock on sock_packet sockets as well.

After that, we declare a new syscall socket$packet. The part before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 $ sign tells syzkaller what syscall it should use, and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 part after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 $ sign is used to differentiate between different kinds of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same syscall. This is particularly useful when dealing with syscalls like ioctl. The socket$packet syscall returns a sock_packet socket.

Then setsockopt$packet_rx_ring and setsockopt$packet_tx_ring are declared. These syscalls set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_RX_RING and PACKET_TX_RING socket options on a sock_packet socket. I’ll talk about cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se options in details below. Both of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tpacket_req_u union as a socket option value. This union has two struct members tpacket_req and tpacket_req3.

Once cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 descriptions are added, syzkaller can be instructed to fuzz packet-related syscalls specifically. This is what I provided in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syzkaller manager config:

"enable_syscalls": [
"socket$packet", "socketpair$packet", "accept$packet", "accept4$packet", "bind$packet", "connect$packet", "sendto$packet", "recvfrom$packet", "getsockname$packet", "getpeername$packet", "listen", "setsockopt", "getsockopt", "syz_emit_ecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rnet"
],

After a few minutes of running syzkaller with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se descriptions I started getting kernel crashes. Here’s one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syzkaller programs that triggered cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mentioned bug:

mmap(&(0x7f0000000000/0xc8f000)=nil, (0xc8f000), 0x3, 0x32, 0xffffffffffffffff, 0x0)
r0 = socket$packet(0x11, 0x3, 0x300)
setsockopt$packet_int(r0, 0x107, 0xa, &(0x7f000061f000)=0x2, 0x4)
setsockopt$packet_rx_ring(r0, 0x107, 0x5, &(0x7f0000c8b000)=@req3={0x10000, 0x3, 0x10000, 0x3, 0x4, 0xfffffffffffffffe, 0x5}, 0x1c)

And here’s one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 KASAN reports. It should be noted, that since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 access is quite far past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block bounds, allocation and deallocation stacks don’t correspond to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflown object.

==================================================================
BUG: KASAN: slab-out-of-bounds in prb_close_block net/packet/af_packet.c:808
Write of size 4 at addr ffff880054b70010 by task syz-executor0/30839

CPU: 0 PID: 30839 Comm: syz-executor0 Not tainted 4.11.0-rc2+ #94
Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
Call Trace:
__dump_stack lib/dump_stack.c:16 [inline]
dump_stack+0x292/0x398 lib/dump_stack.c:52
print_address_description+0x73/0x280 mm/kasan/report.c:246
kasan_report_error mm/kasan/report.c:345 [inline]
kasan_report.part.3+0x21f/0x310 mm/kasan/report.c:368
kasan_report mm/kasan/report.c:393 [inline]
__asan_report_store4_noabort+0x2c/0x30 mm/kasan/report.c:393
prb_close_block net/packet/af_packet.c:808 [inline]
prb_retire_current_block+0x6ed/0x820 net/packet/af_packet.c:970
__packet_lookup_frame_in_block net/packet/af_packet.c:1093 [inline]
packet_current_rx_frame net/packet/af_packet.c:1122 [inline]
tpacket_rcv+0x9c1/0x3750 net/packet/af_packet.c:2236
packet_rcv_fanout+0x527/0x810 net/packet/af_packet.c:1493
deliver_skb net/core/dev.c:1834 [inline]
__netif_receive_skb_core+0x1cff/0x3400 net/core/dev.c:4117
__netif_receive_skb+0x2a/0x170 net/core/dev.c:4244
netif_receive_skb_internal+0x1d6/0x430 net/core/dev.c:4272
netif_receive_skb+0xae/0x3b0 net/core/dev.c:4296
tun_rx_batched.isra.39+0x5e5/0x8c0 drivers/net/tun.c:1155
tun_get_user+0x100d/0x2e20 drivers/net/tun.c:1327
tun_chr_write_iter+0xd8/0x190 drivers/net/tun.c:1353
call_write_iter include/linux/fs.h:1733 [inline]
new_sync_write fs/read_write.c:497 [inline]
__vfs_write+0x483/0x760 fs/read_write.c:510
vfs_write+0x187/0x530 fs/read_write.c:558
SYSC_write fs/read_write.c:605 [inline]
SyS_write+0xfb/0x230 fs/read_write.c:597
entry_SYSCALL_64_fastpath+0x1f/0xc2
RIP: 0033:0x40b031
RSP: 002b:00007faacbc3cb50 EFLAGS: 00000293 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 000000000000002a RCX: 000000000040b031
RDX: 000000000000002a RSI: 0000000020002fd6 RDI: 0000000000000015
RBP: 00000000006e2960 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000708000
R13: 000000000000002a R14: 0000000020002fd6 R15: 0000000000000000

Allocated by task 30534:
save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
save_stack+0x43/0xd0 mm/kasan/kasan.c:513
set_track mm/kasan/kasan.c:525 [inline]
kasan_kmalloc+0xad/0xe0 mm/kasan/kasan.c:617
kasan_slab_alloc+0x12/0x20 mm/kasan/kasan.c:555
slab_post_alloc_hook mm/slab.h:456 [inline]
slab_alloc_node mm/slub.c:2720 [inline]
slab_alloc mm/slub.c:2728 [inline]
kmem_cache_alloc+0x1af/0x250 mm/slub.c:2733
getname_flags+0xcb/0x580 fs/namei.c:137
getname+0x19/0x20 fs/namei.c:208
do_sys_open+0x2ff/0x720 fs/open.c:1045
SYSC_open fs/open.c:1069 [inline]
SyS_open+0x2d/0x40 fs/open.c:1064
entry_SYSCALL_64_fastpath+0x1f/0xc2

Freed by task 30534:
save_stack_trace+0x16/0x20 arch/x86/kernel/stacktrace.c:59
save_stack+0x43/0xd0 mm/kasan/kasan.c:513
set_track mm/kasan/kasan.c:525 [inline]
kasan_slab_free+0x72/0xc0 mm/kasan/kasan.c:590
slab_free_hook mm/slub.c:1358 [inline]
slab_free_freelist_hook mm/slub.c:1381 [inline]
slab_free mm/slub.c:2963 [inline]
kmem_cache_free+0xb5/0x2d0 mm/slub.c:2985
putname+0xee/0x130 fs/namei.c:257
do_sys_open+0x336/0x720 fs/open.c:1060
SYSC_open fs/open.c:1069 [inline]
SyS_open+0x2d/0x40 fs/open.c:1064
entry_SYSCALL_64_fastpath+0x1f/0xc2

Object at ffff880054b70040 belongs to cache names_cache of size 4096
The buggy address belongs to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page:
page:ffffea000152dc00 count:1 mapcount:0 mapping:          (null) index:0x0 compound_mapcount: 0
flags: 0x500000000008100(slab|head)
raw: 0500000000008100 0000000000000000 0000000000000000 0000000100070007
raw: ffffea0001549a20 ffffea0001b3cc20 ffff88003eb44f40 0000000000000000
page dumped because: kasan: bad access detected

Memory state around cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 buggy address:
ffff880054b6ff00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
ffff880054b6ff80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
>ffff880054b70000: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb
                        ^
ffff880054b70080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff880054b70100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================

You can find more details about syzkaller in it’s repository and more details about KASAN in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel documentation. If you decide to try syzkaller or KASAN and run into any troubles drop an email to syzkaller@googlegroups.com or to kasan-dev@googlegroups.com.

Introduction to AF_PACKET sockets


To better understand cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 vulnerability it leads to and how to exploit it, we need to understand what AF_PACKET sockets are and how cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel.

Overview


AF_PACKET sockets allow users to send or receive packets on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 device driver level. This for example lets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to implement cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir own protocol on top of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 physical layer or to sniff packets including Ecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rnet and higher levels protocol headers. To create an AF_PACKET socket a process must have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CAP_NET_RAW capability in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user namespace that governs its network namespace. More details can be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet sockets documentation. It should be noted that if a kernel has unprivileged user namespaces enabled, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n an unprivileged user is able to create packet sockets.

To send and receive packets on a packet socket, a process can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 send and recv syscalls. However, packet sockets provide a way to do this faster by using a ring buffer, that’s shared between cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace. A ring buffer can be created via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_TX_RING and PACKET_RX_RING socket options. The ring buffer can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be mmaped by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet data can cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n be read or written directly to it.

There are a few different variants of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer is handled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. This variant can be chosen by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user by using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_VERSION socket option. The difference between ring buffer versions can be found in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel documentation (search for “TPACKET versions”).

One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 widely known users of AF_PACKET sockets is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tcpdump utility. This is roughly what happens when tcpdump is used to sniff all packets on a particular interface:

# strace tcpdump -i eth0
...
socket(PF_PACKET, SOCK_RAW, 768)        = 3
...
bind(3, {sa_family=AF_PACKET, proto=0x03, if2, pkttype=PACKET_HOST, addr(0)={0, }, 20) = 0
...
setsockopt(3, SOL_PACKET, PACKET_VERSION, [1], 4) = 0
...
setsockopt(3, SOL_PACKET, PACKET_RX_RING, {block_size=131072, block_nr=31, frame_size=65616, frame_nr=31}, 16) = 0
...
mmap(NULL, 4063232, PROT_READ|PROT_WRITE, MAP_SHARED, 3, 0) = 0x7f73a6817000
...

This sequence of syscalls corresponds to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following actions:
  1. A socket(AF_PACKET, SOCK_RAW, htons(ETH_P_ALL)) is created.
  2. The socket is bound to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 eth0 interface.
  3. Ring buffer version is set to TPACKET_V2 via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_VERSION socket option.
  4. A ring buffer is created via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_RX_RING socket option.
  5. The ring buffer is mmapped in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace.

After that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will start putting all packets coming through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 eth0 interface in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer and tcpdump will read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mmapped region in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace.



Ring buffers


Let’s see how to use ring buffers for packet sockets. For consistency all of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel code snippets below will come from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux kernel 4.8. This is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 version cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 latest Ubuntu 16.04.2 kernel is based on.

The existing documentation mostly focuses on TPACKET_V1 and TPACKET_V2 ring buffer versions. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mentioned bug only affects cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 TPACKET_V3 version, I’m going to assume that we deal with that particular version for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 rest of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 post. Also I’m going to mostly focus on PACKET_RX_RING ignoring PACKET_TX_RING.

A ring buffer is a memory region used to store packets. Each packet is stored in a separate frame. Frames are grouped into blocks. In TPACKET_V3 ring buffers frame size is not fixed and can have arbitrary value as long as a frame fits into a block.

To create a TPACKET_V3 ring buffer via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_RX_RING socket option a user must provide cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact parameters for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer. These parameters are passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 setsockopt call via a pointer to a request struct called tpacket_req3, which is defined as:

274 struct tpacket_req3 {
275         unsigned int    tp_block_size;  /* Minimal size of contiguous block */
276         unsigned int    tp_block_nr;    /* Number of blocks */
277         unsigned int    tp_frame_size;  /* Size of frame */
278         unsigned int    tp_frame_nr;    /* Total number of frames */
279         unsigned int    tp_retire_blk_tov; /* timeout in msecs */
280         unsigned int    tp_sizeof_priv; /* offset to private data area */
281         unsigned int    tp_feature_req_word;
282 };

Here’s what each field means in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tpacket_req3 struct:
  1. tp_block_size - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of each block.
  2. tp_block_nr - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of blocks.
  3. tp_frame_size - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of each frame, ignored for TPACKET_V3.
  4. tp_frame_nr - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 number of frames, ignored for TPACKET_V3.
  5. tp_retire_blk_tov - timeout after which a block is retired, even if it’s not fully filled with data (see below).
  6. tp_sizeof_priv - cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of per-block private area. This area can be used by a user to store arbitrary information associated with each block.
  7. tp_feature_req_word - a set of flags (actually just one at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 moment), which allows to enable some additional functionality.

Each block has an associated header, which is stored at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 very beginning of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory area allocated for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block. The block header struct is called tpacket_block_desc and has a block_status field, which indicates whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block is currently being used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel or available to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user. The usual workflow is that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel stores packets into a block until it’s full and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n sets block_status to TP_STATUS_USER. The user cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365n reads required data from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and releases it back to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel by setting block_status to TP_STATUS_KERNEL.

186 struct tpacket_hdr_v1 {
187         __u32   block_status;
188         __u32   num_pkts;
189         __u32   offset_to_first_pkt;
...
233 };
234
235 union tpacket_bd_header_u {
236         struct tpacket_hdr_v1 bh1;
237 };
238
239 struct tpacket_block_desc {
240         __u32 version;
241         __u32 offset_to_priv;
242         union tpacket_bd_header_u hdr;
243 };

Each frame also has an associated header described by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 struct tpacket3_hdr. The tp_next_offset field points to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next frame within cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same block.

162 struct tpacket3_hdr {
163         __u32 tp_next_offset;
...
176 };

When a block is fully filled with data (a new packet doesn’t fit into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 remaining space), it’s closed and released to userspace or “retired” by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user usually wants to see packets as soon as possible, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel can release a block even if it’s not filled with data completely. This is done by setting up a timer that retires current block with a timeout controlled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tp_retire_blk_tov parameter.

There’s also a way so specify per-block private area, which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel won’t touch and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user can use to store any information associated with a block. The size of this area is passed via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tp_sizeof_priv parameter.

If you’d like to better understand how a userspace program can use TPACKET_V3 ring buffer you can read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 example provided in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 documentation (search for “TPACKET_V3 example“).


Implementation of AF_PACKET sockets


Let’s take a quick look at how some of this is implemented in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel.

Struct definitions


Whenever a packet socket is created, an associated packet_sock struct is allocated in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel:

103 struct packet_sock {
...
105         struct sock             sk;
...
108         struct packet_ring_buffer       rx_ring;
109         struct packet_ring_buffer       tx_ring;
...
123         enum tpacket_versions   tp_version;
...
130         int                     (*xmit)(struct sk_buff *skb);
...
132 };

The tp_version field in this struct holds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer version, which in our case is set to TPACKET_V3 by a PACKET_VERSION setsockopt call. The rx_ring and tx_ring fields describe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 receive and transmit ring buffers in case cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y are created via PACKET_RX_RING and PACKET_TX_RING setsockopt calls. These two fields have type packet_ring_buffer, which is defined as:

56 struct packet_ring_buffer {
57         struct pgv              *pg_vec;
...
70         struct tpacket_kbdq_core        prb_bdqc;
71 };

The pg_vec field is a pointer to an array of pgv structs, each of which holds a reference to a block. Blocks are actually allocated separately, not as a one contiguous memory region.

52 struct pgv {
53         char *buffer;
54 };



The prb_bdqc field is of type tpacket_kbdq_core and its fields describe cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current state of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer:

14 struct tpacket_kbdq_core {
...
21         unsigned short  blk_sizeof_priv;
...
36         char            *nxt_offset;
...
49         struct timer_list retire_blk_timer;
50 };

The blk_sizeof_priv fields contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-block private area. The nxt_offset field points inside cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 currently active block and shows where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next packet should be saved. The retire_blk_timer field has type timer_list and describes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 timer which retires current block on timeout.

12 struct timer_list {
...
17         struct hlist_node       entry;
18         unsigned long           expires;
19         void                    (*function)(unsigned long);
20         unsigned long           data;
...
31 };

Ring buffer setup


The kernel uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_setsockopt() function to handle setting socket options for packet sockets. When cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_VERSION socket option is used, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel sets po->tp_version to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided value.

With cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 PACKET_RX_RING socket option a receive ring buffer is created. Internally it’s done by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_set_ring() function. This function does a lot of things, so I’ll just show cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 important parts. First, packet_set_ring() performs a bunch of sanity checks on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 provided ring buffer parameters:

4202                 err = -EINVAL;
4203                 if (unlikely((int)req->tp_block_size <= 0))
4204                         goto out;
4205                 if (unlikely(!PAGE_ALIGNED(req->tp_block_size)))
4206                         goto out;
4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     (int)(req->tp_block_size -
4209                           BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
4210                         goto out;
4211                 if (unlikely(req->tp_frame_size < po->tp_hdrlen +
4212                                         po->tp_reserve))
4213                         goto out;
4214                 if (unlikely(req->tp_frame_size & (TPACKET_ALIGNMENT - 1)))
4215                         goto out;
4216
4217                 rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
4218                 if (unlikely(rb->frames_per_block == 0))
4219                         goto out;
4220                 if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
4221                                         req->tp_frame_nr))
4222                         goto out;

Then, it allocates cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer blocks:

4224                 err = -ENOMEM;
4225                 order = get_order(req->tp_block_size);
4226                 pg_vec = alloc_pg_vec(req, order);
4227                 if (unlikely(!pg_vec))
4228                         goto out;

It should be noted that alloc_pg_vec() uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel page allocator to allocate blocks (we’ll use this in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit):

4104 static char *alloc_one_pg_vec_page(unsigned long order)
4105 {
...
4110         buffer = (char *) __get_free_pages(gfp_flags, order);
4111         if (buffer)
4112                 return buffer;
...
4127 }
4128
4129 static struct pgv *alloc_pg_vec(struct tpacket_req *req, int order)
4130 {
...
4139         for (i = 0; i < block_nr; i++) {
4140                 pg_vec[i].buffer = alloc_one_pg_vec_page(order);
...
4143         }
...
4152 }

Finally, packet_set_ring() calls init_prb_bdqc(), which performs some additional steps to set up a TPACKET_V3 receive ring buffer specifically:

4229                 switch (po->tp_version) {
4230                 case TPACKET_V3:
...
4234                         if (!tx_ring)
4235                                 init_prb_bdqc(po, rb, pg_vec, req_u);
4236                         break;
4237                 default:
4238                         break;
4239                 }

The init_prb_bdqc() function copies provided ring buffer parameters to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prb_bdqc field of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer struct, calculates some ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r parameters based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m, sets up cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block retire timer and calls prb_open_block() to initialize cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first block:

604 static void init_prb_bdqc(struct packet_sock *po,
605                         struct packet_ring_buffer *rb,
606                         struct pgv *pg_vec,
607                         union tpacket_req_u *req_u)
608 {
609         struct tpacket_kbdq_core *p1 = GET_PBDQC_FROM_RB(rb);
610         struct tpacket_block_desc *pbd;
...
616         pbd = (struct tpacket_block_desc *)pg_vec[0].buffer;
617         p1->pkblk_start = pg_vec[0].buffer;
618         p1->kblk_size = req_u->req3.tp_block_size;
...
630         p1->blk_sizeof_priv = req_u->req3.tp_sizeof_priv;
631
632         p1->max_frame_len = p1->kblk_size - BLK_PLUS_PRIV(p1->blk_sizeof_priv);
633         prb_init_ft_ops(p1, req_u);
634         prb_setup_retire_blk_timer(po);
635         prb_open_block(p1, pbd);
636 }

On of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 things that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 prb_open_block() function does is it sets cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nxt_offset field of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tpacket_kbdq_core struct to point right after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-block private area:

841 static void prb_open_block(struct tpacket_kbdq_core *pkc1,
842         struct tpacket_block_desc *pbd1)
843 {
...
862         pkc1->pkblk_start = (char *)pbd1;
863         pkc1->nxt_offset = pkc1->pkblk_start + BLK_PLUS_PRIV(pkc1->blk_sizeof_priv);
...
876 }

Packet reception


Whenever a new packet is received, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel is supposed to save it into cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ring buffer. The key function here is __packet_lookup_frame_in_block(), which does cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following:
  1. Checks whecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 currently active block has enough space for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet.
  2. If yes, saves cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current block and returns.
  3. If no, dispatches cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next block and saves cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re.

1041 static void *__packet_lookup_frame_in_block(struct packet_sock *po,
1042                                             struct sk_buff *skb,
1043                                                 int status,
1044                                             unsigned int len
1045                                             )
1046 {
1047         struct tpacket_kbdq_core *pkc;
1048         struct tpacket_block_desc *pbd;
1049         char *curr, *end;
1050
1051         pkc = GET_PBDQC_FROM_RB(&po->rx_ring);
1052         pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
...
1075         curr = pkc->nxt_offset;
1076         pkc->skb = skb;
1077         end = (char *)pbd + pkc->kblk_size;
1078
1079         /* first try cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current block */
1080         if (curr+TOTAL_PKT_LEN_INCL_ALIGN(len) < end) {
1081                 prb_fill_curr_block(curr, pkc, pbd, len);
1082                 return (void *)curr;
1083         }
1084
1085         /* Ok, close cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current block */
1086         prb_retire_current_block(pkc, po, 0);
1087
1088         /* Now, try to dispatch cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next block */
1089         curr = (char *)prb_dispatch_next_block(pkc, po);
1090         if (curr) {
1091                 pbd = GET_CURR_PBLOCK_DESC_FROM_CORE(pkc);
1092                 prb_fill_curr_block(curr, pkc, pbd, len);
1093                 return (void *)curr;
1094         }
...
1101 }

Vulnerability


Bug


Let’s look closely at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following check from packet_set_ring():

4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     (int)(req->tp_block_size -
4209                           BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
4210                         goto out;

This is supposed to ensure that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 length of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block header togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 per-block private data is not bigger than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block. Which totally makes sense, ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rwise we won’t have enough space in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m let alone cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet data.

However turns out this check can be bypassed. In case req_u->req3.tp_sizeof_priv has cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 higher bit set, casting cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 expression to int results in a big positive value instead of negative. To illustrate this behavior:

A = req->tp_block_size = 4096 = 0x1000
B = req_u->req3.tp_sizeof_priv = (1 << 31) + 4096 = 0x80001000
BLK_PLUS_PRIV(B) = (1 << 31) + 4096 + 48 = 0x80001030
A - BLK_PLUS_PRIV(B) = 0x1000 - 0x80001030 = 0x7fffffd0
(int)0x7fffffd0 = 0x7fffffd0 > 0

Later, when req_u->req3.tp_sizeof_priv is copied to p1->blk_sizeof_priv in init_prb_bdqc() (see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 snippet above), it’s clamped to two lower bytes, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 type of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 latter is unsigned short. So this bug basically allows us to set cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 blk_sizeof_priv of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 tpacket_kbdq_core struct to arbitrary value bypassing all sanity checks.

Consequences


If we search through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 net/packet/af_packet.c source looking for blk_sizeof_priv usage, we’ll find that it’s being used in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two following places.

The first one is in init_prb_bdqc() right after it gets assigned (see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code snippet above) to set max_frame_len. The value of p1->max_frame_len denotes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum size of a frame that can be saved into a block. Since we control p1->blk_sizeof_priv, we can make BLK_PLUS_PRIV(p1->blk_sizeof_priv) bigger than p1->kblk_size. This will result in p1->max_frame_len having a huge value, higher than cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of a block. This allows us to bypass cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size check when a frame is being copied into a block, thus causing a kernel heap out-of-bounds write.

That’s not all. Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r user of blk_sizeof_priv is prb_open_block(), which initializes a block (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 code snippet is above as well). There pkc1->nxt_offset denotes cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address, where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will write a new packet when it’s being received. The kernel doesn’t intend to overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block header and per-block private data, so it makes this address to point right after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m. Since we control blk_sizeof_priv, we can control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lowest two bytes of nxt_offset. This allows us to control offset of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 out-of-bounds write.

To sum up, this bug leads to a kernel heap out-of-bounds write of controlled maximum size and controlled offset up to about 64k bytes. 

Exploitation


Let’s see how we can exploit this vulnerability. I’m going to be targeting x86-64 Ubuntu 16.04.2 with 4.8.0-41-generic kernel version with KASLR, SMEP and SMAP enabled. Ubuntu kernel has user namespaces available to unprivileged users (CONFIG_USER_NS=y and no restrictions on it’s usage), so cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug can be exploited to gain root privileges by an unprivileged user. All of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitation steps below are performed from within a user namespace.

The Linux kernel has support for a few hardening features that make exploitation more difficult. KASLR (Kernel Address Space Layout Randomization) puts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel text at a random offset to make jumping to a particular fixed address useless. SMEP (Supervisor Mode Execution Protection) causes an oops whenever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel tries to execute code from cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace memory and SMAP (Supervisor Mode Access Prevention) does cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same whenever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel tries to access cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace memory directly.

Shaping heap


The idea of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit is to use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap out-of-bounds write to overwrite a function pointer in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory adjacent to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overflown block. For that we need to specifically shape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap, so some object with a triggerable function pointer is placed right after a ring buffer block. I chose cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 already mentioned packet_sock struct to be this object. We need to find a way to make cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel allocate a ring buffer block and a packet_sock struct one next to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r.

As I mentioned above, ring buffer blocks are allocated with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel page allocator (buddy allocator). It allows to allocate blocks of 2^n contiguous memory pages. The allocator keeps a freelist of such block for each n and returns cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 freelist head when a block is requested. If cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 freelist for some n is empty, it finds cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first m > n, for which cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 freelist is not empty and splits it in halves until cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 required size is reached. Therefore, if we start repeatedly allocating blocks of size 2^n, at some point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will start coming from one high order memory block being split and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y will be adjacent each one to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 next.

A packet_sock is allocated via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kmalloc() function by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 slab allocator. The slab allocator is mostly used to allocate objects of a smaller-than-one-page size. It uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page allocator to allocate a big block of memory and splits this block into smaller objects. The big blocks are called slabs, hence cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 name of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocator. A set of slabs togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365ir current state and a set of operations like “allocate an object” and “free an object” is called a cache. The slab allocator creates a set of general purpose caches for objects of size 2^n. Whenever kmalloc(size) is called, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 slab allocator rounds size up to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 nearest power of 2 and uses cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 cache of that size.

Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel uses kmalloc() all cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 time, if we try to allocate an object it will most likely come from one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 slabs already created during previous usage. However, if we start allocating objects of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same size, at some point cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 slab allocator will run out of slabs for this size and will have to allocate anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r one via cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page allocator.

The size of a newly allocated slab depends on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of objects this slab is meant for. The size of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_sock struct is ~1920 and 1024 < 1920 <= 2048, which means that it’ll be rounded to 2048 and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kmalloc-2048 cache will be used. Turns out, for this particular cache cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SLUB allocator (which is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kind of slab allocator used in Ubuntu) uses slabs of size 0x8000. So whenever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 allocator runs out of slabs for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kmalloc-2048 cache, it allocates 0x8000 bytes with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page allocator.

Keeping all that in mind, this is how we can allocate a kmalloc-2048 slab next to a ring buffer block:
  1. Allocate a lot (512 worked for me) of objects of size 2048 to fill currently existing slabs in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kmalloc-2048 cache. To do that we can create a bunch of packet sockets to cause allocation of packet_sock structs.
  2. Allocate a lot (1024 worked for me) page blocks of size 0x8000 to drain cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 page allocator freelists and cause some high-order page block to be split. To do that we can create anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r packet socket and attach a ring buffer with 1024 blocks of size 0x8000.
  3. Create a packet socket and attach a ring buffer with blocks of size 0x8000. The last one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se blocks (I’m using 2 blocks, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 reason is explained below) is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one we’re going to overflow.
  4. Create a bunch of packet sockets to allocate packet_sock structs and cause an allocation of at least one new slab.
This way we can shape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following way:



The exact number of allocations to drain freelists and shape cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 heap cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 way we want might be different for different setups and depend on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 memory usage activity. The numbers above are for a mostly idle Ubuntu machine.

Controlling cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 overwrite


Above I explained that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bug results in a write of a controlled maximum size at a controlled offset out of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 bounds of a ring buffer block. Turns out not only we can control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 maximum size and offset, we can actually control cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exact data (and it’s size) that’s being written. Since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data that’s being stored in a ring buffer block is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet that’s passing through a particular network interface, we can manually send packets with arbitrary content on a raw socket through cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 loopback interface. If we’re doing that in an isolated network namespace no external traffic will interfere.

There are a few caveats though.

First, it seems that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 size of a packet must be at least 14 bytes (12 bytes for two mac addresses and 2 bytes for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Ecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365rType apparently) for it to be passed to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet socket layer. That means that we have to overwrite at least 14 bytes. The data in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet itself can be arbitrary.

Then, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 lowest 3 bits of nxt_offset always have cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of 2 due to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 alignment. That means that we can’t start overwriting at an 8-byte aligned offset.

Besides that, when a packet is being received and saved into a block, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel updates some fields in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and frame headers. If we point nxt_offset to some particular offset we want to overwrite, some data where cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and frames headers end up will probably be corrupted.

Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r issue is that if we make nxt_offset point past cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block end, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first block will be immediately closed when cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first packet is being received, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will (correctly) decide that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s no space left in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first block (see cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 __packet_lookup_frame_in_block() snippet). This is not really an issue, since we can create a ring buffer with 2 blocks. The first one will be closed, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 second one will be overflown.

Executing code


Now, we need to figure out which function pointers to overwrite. There are a few of function pointers fields in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_sock struct, but I ended up using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 following two:
  1. packet_sock->xmit
  2. packet_sock->rx_ring->prb_bdqc->retire_blk_timer->func

The first one is called whenever a user tries to send a packet via a packet socket. The usual way to elevate privileges to root is to execute cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 commit_creds(prepare_kernel_cred(0)) payload in a process context. The xmit pointer is called from a process context, which means we can simply point it to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 executable memory region, which contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload.

To do that we need to put our payload to some executable memory region. One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 possible ways for that is to put cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 payload in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace, eicá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r by mmapping an executable memory page or by just defining a global function within our exploit program. However, SMEP & SMAP will prevent cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel from accessing and executing user memory directly, so we need to deal with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m first.

For that I used cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 retire_blk_timer field (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same field used by Philip Pettersson in his CVE-2016-8655 exploit). It contains a function pointer that’s triggered whenever cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 retire timer times out. During normal packet socket operation, retire_blk_timer->func points to prb_retire_rx_blk_timer_expired() and it’s called with retire_blk_timer->data as an argument, which contains cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 address of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_sock struct. Since we can overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 data field along with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 func field, we get a very nice func(data) primitive.

The state of SMEP & SMAP on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current CPU core is controlled by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 20th and 21st bits of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CR4 register. To disable cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m we should zero out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se two bits. For this we can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 func(data) primitive to call native_write_cr4(X), where X has 20th and 21st bits set to 0. The exact value of X might depend on what ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r CPU features are enabled. On cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 machine where I tested cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 value of CR4 is 0x10407f0 (only cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 SMEP bit is enabled since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CPU has no SMAP support), so I used X = 0x407f0. We can use cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 sched_setaffinity syscall to force cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit program to be executed on one CPU core and thus making sure that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 userspace payload will be executed on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same core as where we disable SMAP & SMEP.

Putting this all togecá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r, here are cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploitation steps:
  1. Figure out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel text address to bypass KASLR (described below).
  2. Pad heap as described above.
  3. Disable SMEP & SMAP.
    1. Allocate a packet_sock after a ring buffer block.
    2. Schedule a block retire timer on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_sock by attaching a receive ring buffer to it.
    3. Overflow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and overwrite retire_blk_timer field. Make retire_blk_timer->func point to native_write_cr4 and make retire_blk_timer->data equal to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 desired CR4 value.
    4. Wait for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 timer to be executed, now we have SMEP & SMAP disabled on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current core.
  4. Get root privileges.
    1. Allocate anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r pair of a packet_sock and a ring buffer block.
    2. Overflow cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and overwrite xmit field. Make xmit point to a commit_creds(prepare_kernel_cred(0)) allocated in userspace.
    3. Send a packet on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 corresponding packet socket, xmit will get triggered and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 current process will obtain root privileges.

The exploit code can be found here.

It should be noted, that when we overwrite cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se two fields in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 packet_sock structs, we’ll end up corrupting some of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fields before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m (cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel will write some values to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 block and frame headers), which can lead to a kernel crash. However, as long as cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365se ocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r fields don’t get used by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel we should be good. I found that one of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fields that caused crashes if we try to close all packet sockets after cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 exploit finished is cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 mclist field, but simply zeroing it out helps.


KASLR bypass


I didn’t bocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r to come up with some elaborate KASLR bypass technique which exploits cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 same bug. Since Ubuntu doesn’t restrict dmesg by default, we can just grep cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel syslog for cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 “Freeing SMP” string, which contains a kernel pointer, that looks suspiciously similar to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel text address:

# Boot #1
$ dmesg | grep 'Freeing SMP'
[    0.012520] Freeing SMP alternatives memory: 32K (ffffffffa58ee000 - ffffffffa58f6000)
$ sudo cat /proc/kallsyms | grep 'T _text'
ffffffffa4800000 T _text

# Boot #2
$ dmesg | grep 'Freeing SMP'
[    0.017487] Freeing SMP alternatives memory: 32K (ffffffff85aee000 - ffffffff85af6000)
$ sudo cat /proc/kallsyms | grep 'T _text'
ffffffff84a00000 T _text

By doing simple math we can calculate cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel text address based on cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 one exposed through dmesg. This way of figuring out cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel text location works only for some time after boot, as syslog only stores a fixed number of lines and starts dropping cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m at some point.

There are a few Linux kernel hardening features that can be used to prevent this kind of information disclosures. The first one is called dmesg_restrict and it restricts cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ability of unprivileged users to read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel syslog. It should be noted, that even with dmesg restricted cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first user on Ubuntu can still read cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 syslog from /var/log/kern.log and /var/log/syslog since he belongs to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 adm group.

Anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r feature is called kptr_restrict and it doesn’t allow unprivileged users to see pointers printed by cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel with cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 %pK format specifier. However in 4.8 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 free_reserved_area() function uses %p, so kptr_restrict doesn’t help in this case. In 4.10 free_reserved_area() was fixed not to print address ranges at all, but cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 change was not backported to older kernels.

Fix


Let’s take a look at cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix. The vulnerable code as it was before cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix is below. Remember that cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 user fully controls both tp_block_size and tp_sizeof_priv.

4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     (int)(req->tp_block_size -
4209                           BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv)) <= 0)
4210                         goto out;

When thinking about a way to fix this, cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 first idea that comes to mind is that we can compare cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 two values as is without that weird conversion to int:

4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     req->tp_block_size <=
4209                           BLK_PLUS_PRIV(req_u->req3.tp_sizeof_priv))
4210                         goto out;

Funny enough, this doesn’t actually help. The reason is that an overflow can happen while evaluating BLK_PLUS_PRIV in case tp_sizeof_priv is close to cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 unsigned int maximum value.

177 #define BLK_PLUS_PRIV(sz_of_priv) \
178         (BLK_HDR_LEN + ALIGN((sz_of_priv), V3_ALIGNMENT))

One of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 ways to fix this overflow is to cast tp_sizeof_priv to uint64 before passing it to BLK_PLUS_PRIV. That’s exactly what I did in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 fix that was sent upstream.

4207                 if (po->tp_version >= TPACKET_V3 &&
4208                     req->tp_block_size <=
4209                           BLK_PLUS_PRIV((u64)req_u->req3.tp_sizeof_priv))
4210                         goto out;

Mitigation


Creating packet socket requires cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 CAP_NET_RAW privilege, which can be acquired by an unprivileged user inside a user namespaces. Unprivileged user namespaces expose a huge kernel attack surface, which resulted in quite a few exploitable vulnerabilities (CVE-2017-7184, CVE-2016-8655, ...). This kind of kernel vulnerabilities can be mitigated by completely disabling user namespaces or disallowing using cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m to unprivileged users.

To disable user namespaces completely you can rebuild your kernel with CONFIG_USER_NS disabled. Restricting user namespaces usage only to privileged users can be done by writing 0 to /proc/sys/kernel/unprivileged_userns_clone in Debian-based kernel. Since version 4.9 cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 upstream kernel has a similar /proc/sys/user/max_user_namespaces setting.

Conclusion


Right now cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 Linux kernel has a huge number of poorly tested (from a security standpoint) interfaces and a lot of cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365m are enabled and exposed to unprivileged users in popular Linux distributions like Ubuntu. This is obviously not good and cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365y need to be tested or restricted.

Syzkaller is an amazing tool that allows to test kernel interfaces via fuzzing. Even adding barebone descriptions for anocá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365r syscall usually uncovers numbers of bugs. We certainly need people writing syscall descriptions and fixing existing ones, since cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365re’s a huge surface that’s still not covered and probably a ton of security bugs buried in cá cược thể thao bet365_cách nạp tiền vào bet365_ đăng ký bet365 kernel. If you decide to contribute, we’ll be glad to see a pull request.

Links


Just a bunch of related links.


Our Linux kernel bug finding tools:

A collection of Linux kernel exploitation materials: https://github.com/xairy/linux-kernel-exploitation