PROBLEM: syzkaller found / reduced C repro for non-fatal unchecked MSR access error

From: Esme
Date: Thu Jan 10 2019 - 18:21:57 EST


Attached is a fairly small C repro I did not see any references to this possible flaw (unchecked MSR access) in relation to __NR_perf_event_open

Attached is the config directly extracted from proc. This is the call stack in relation to the MSR access error (5.0.0-rc1+), I get a very similar stack running this test case on a stock Ubuntu "4.18.0-11-generic" (pasted after this one).
-- Esme

[ 70.228744] unchecked MSR access error: WRMSR to 0xc0010000 (tried to write 0x0000020000130076) at rIP: 0xffffffff812dde28 (native_write_msr+0x8/0x30)
[ 70.231712] Call Trace:
[ 70.232229] x86_pmu_disable_event+0xaf/0xf0
[ 70.233104] x86_pmu_stop+0x9e/0x2a0
[ 70.233855] x86_pmu_del+0xf3/0x4d0
[ 70.234575] event_sched_out.isra.99+0x48b/0xf70
[ 70.235532] ? perf_swevent_init+0x620/0x620
[ 70.236460] ? alloc_set_pte+0x131d/0x1dc0
[ 70.237353] ? pvclock_read_flags+0x160/0x160
[ 70.238298] ? event_function+0x1f6/0x490
[ 70.239163] ? kvm_sched_clock_read+0x18/0x30
[ 70.240073] ? sched_clock+0x31/0x50
[ 70.240819] ? sched_clock_cpu+0x26/0x180
[ 70.241662] ? rwlock_bug.part.2+0x90/0x90
[ 70.242520] __perf_remove_from_context+0x8b/0x440
[ 70.243521] event_function+0x301/0x490
[ 70.244318] ? unclone_ctx+0x170/0x170
[ 70.245116] remote_function+0x138/0x1c0
[ 70.245931] generic_exec_single+0x37c/0x620
[ 70.246813] ? perf_cgroup_attach+0xf0/0xf0
[ 70.247710] ? smp_call_on_cpu+0x580/0x580
[ 70.248537] ? lock_release+0xaf0/0xaf0
[ 70.249319] ? check_same_owner+0x350/0x350
[ 70.250176] smp_call_function_single+0x364/0x620
[ 70.251129] ? kasan_check_write+0x14/0x20
[ 70.251972] ? perf_cgroup_attach+0xf0/0xf0
[ 70.252824] ? generic_exec_single+0x620/0x620
[ 70.253724] ? find_held_lock+0x36/0x1d0
[ 70.254536] ? graph_lock+0x270/0x270
[ 70.255301] task_function_call+0x182/0x280
[ 70.256154] ? perf_event_addr_filters_exec+0x2e0/0x2e0
[ 70.257239] ? unclone_ctx+0x170/0x170
[ 70.258023] event_function_call+0x305/0x620
[ 70.258920] ? event_sched_out.isra.99+0xf70/0xf70
[ 70.259946] ? task_function_call+0x280/0x280
[ 70.260846] ? event_sched_out.isra.99+0xf70/0xf70
[ 70.261856] ? __perf_cgroup_move+0x180/0x180
[ 70.262755] ? __lock_is_held+0xb4/0x140
[ 70.263575] perf_remove_from_context+0xb2/0x1f0
[ 70.264506] perf_event_release_kernel+0x293/0x1090
[ 70.265504] ? find_held_lock+0x36/0x1d0
[ 70.266328] ? put_event+0x60/0x60
[ 70.267079] ? mark_held_locks+0x130/0x130
[ 70.267943] ? __fd_install+0x2b4/0x8a0
[ 70.268766] ? kasan_check_read+0x11/0x20
[ 70.269607] ? do_raw_spin_unlock+0xa7/0x340
[ 70.270494] ? do_raw_spin_trylock+0x280/0x280
[ 70.271395] ? add_mm_counter_fast+0xf0/0xf0
[ 70.272306] ? locks_remove_posix+0x489/0x870
[ 70.273214] ? vfs_lock_file+0x110/0x110
[ 70.274033] ? fsnotify+0x505/0xf50
[ 70.274773] ? vmf_insert_mixed_mkwrite+0x40/0x40
[ 70.275738] ? __sanitizer_cov_trace_const_cmp8+0x18/0x20
[ 70.276850] ? locks_remove_file+0x3db/0x5a0
[ 70.277769] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[ 70.278895] ? ima_file_free+0x13d/0x670
[ 70.279701] ? fsnotify_first_mark+0x360/0x360
[ 70.280613] ? ima_file_check+0x150/0x150
[ 70.281446] ? fsnotify+0xf50/0xf50
[ 70.282168] ? perf_event_release_kernel+0x1090/0x1090
[ 70.283192] perf_release+0x37/0x50
[ 70.283912] __fput+0x383/0xa80
[ 70.284565] ? get_max_files+0x20/0x20
[ 70.285327] ? trace_hardirqs_on+0xce/0x310
[ 70.286191] ? kasan_check_read+0x11/0x20
[ 70.287039] ? task_work_run+0x1af/0x2a0
[ 70.287845] ? __bpf_trace_preemptirq_template+0x30/0x30
[ 70.288922] ? filp_close+0x1cb/0x260
[ 70.289678] ____fput+0x1a/0x20
[ 70.290342] task_work_run+0x1df/0x2a0
[ 70.291146] ? task_work_cancel+0x250/0x250
[ 70.292005] ? copy_fd_bitmaps+0x210/0x210
[ 70.292859] ? do_syscall_64+0x9a/0x820
[ 70.293658] exit_to_usermode_loop+0x328/0x390
[ 70.294567] ? syscall_trace_enter+0x1270/0x1270
[ 70.295524] ? __sanitizer_cov_trace_const_cmp4+0x16/0x20
[ 70.296664] do_syscall_64+0x6ba/0x820
[ 70.297493] ? entry_SYSCALL_64_after_hwframe+0x3e/0xbe
[ 70.298559] ? syscall_return_slowpath+0x630/0x630
[ 70.299529] ? trace_hardirqs_off_thunk+0x1a/0x1c
[ 70.300498] ? trace_hardirqs_on_caller+0x300/0x300
[ 70.301504] ? prepare_exit_to_usermode+0x291/0x3d0
[ 70.302515] ? trace_hardirqs_off_thunk+0x1a/0x1c
[ 70.303493] entry_SYSCALL_64_after_hwframe+0x49/0xbe
[ 70.304537] RIP: 0033:0x7f74d08f7cf0
[ 70.305302] Code: 00 64 c7 00 0d 00 00 00 b8 ff ff ff ff eb 90 b8 ff ff ff ff eb 89 0f 1f 40 00 83 3d 19 2a 2c 00 00 75 10 b8 03 00 00 00 0f 05 <48> 3d 01 f0 ff ff 73 31 c3 48 83 ec 08 e8 be 95 04
[ 70.309076] RSP: 002b:00007ffdf26dfe18 EFLAGS: 00000246 ORIG_RAX: 0000000000000003
[ 70.310626] RAX: 0000000000000000 RBX: 0000000000000000 RCX: 00007f74d08f7cf0
[ 70.312105] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000003
[ 70.313569] RBP: 00007ffdf26dfe30 R08: 0000000000000000 R09: 00007ffdf26dfe60
[ 70.314998] R10: 0000000000000692 R11: 0000000000000246 R12: 000055d75a0e3a70
[ 70.316448] R13: 00007ffdf26dff50 R14: 0000000000000000 R15: 0000000000000000
[ 70.361490]
[ 70.361945] ======================================================


****** The following is from the aforementioned Ubuntu binary kernel 4.18.0-11.

[ 256.601373] unchecked MSR access error: WRMSR to 0xc0010000 (tried to write 0x0000020000130076) at rIP: 0xffffffffb9c6de28 (native_write_msr+0x8/0x30)
[ 256.601377] Call Trace:
[ 256.601384] x86_pmu_disable_event+0x1c/0x20
[ 256.601389] x86_pmu_stop+0x40/0xa0
[ 256.601394] x86_pmu_del+0x5a/0x150
[ 256.601399] event_sched_out.isra.106+0x86/0x170
[ 256.601403] group_sched_out.part.108+0x5d/0xe0
[ 256.601407] ctx_sched_out+0x149/0x220
[ 256.601411] task_ctx_sched_out+0x20/0x30
[ 256.601415] __perf_event_task_sched_out+0x191/0x440
[ 256.601419] ? pick_next_task_fair+0x4e7/0x610
[ 256.601425] ? smp_call_function_single+0xc3/0xf0
[ 256.601431] __schedule+0x5fe/0x840
[ 256.601435] preempt_schedule_common+0xe/0x20
[ 256.601439] _cond_resched+0x22/0x30
[ 256.601442] mutex_lock+0x12/0x30
[ 256.601447] __do_sys_perf_event_open+0x46f/0xef0
[ 256.601453] __x64_sys_perf_event_open+0x20/0x30
[ 256.601457] do_syscall_64+0x5a/0x110
[ 256.601461] entry_SYSCALL_64_after_hwframe+0x44/0xa9
[ 256.601465] RIP: 0033:0x7f1864ecc219
[ 256.601467] 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 47 fc 0c 00 f7 d8 64 89 01 48
[ 256.601526] RSP: 002b:00007ffcc36e86f8 EFLAGS: 00000206 ORIG_RAX: 000000000000012a
[ 256.601530] RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f1864ecc219
[ 256.601532] RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000020000300
[ 256.601534] RBP: 00007ffcc36e8700 R08: 0000000000000000 R09: 00007ffcc36e8730
[ 256.601536] R10: 00000000ffffffff R11: 0000000000000206 R12: 000055f7aa664170
[ 256.601538] R13: 00007ffcc36e8820 R14: 0000000000000000 R15: 0000000000000000


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

#define _GNU_SOURCE

#include <dirent.h>
#include <endian.h>
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/prctl.h>
#include <sys/stat.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <time.h>
#include <unistd.h>

unsigned long long procid;

static void sleep_ms(uint64_t ms)
{
usleep(ms * 1000);
}

static uint64_t current_time_ms(void)
{
struct timespec ts;
if (clock_gettime(CLOCK_MONOTONIC, &ts))
exit(1);
return (uint64_t)ts.tv_sec * 1000 + (uint64_t)ts.tv_nsec / 1000000;
}

#define BITMASK(bf_off,bf_len) (((1ull << (bf_len)) - 1) << (bf_off))
#define STORE_BY_BITMASK(type,htobe,addr,val,bf_off,bf_len) *(type*)(addr) = htobe((htobe(*(type*)(addr)) & ~BITMASK((bf_off), (bf_len))) | (((type)(val) << (bf_off)) & BITMASK((bf_off), (bf_len))))

static void kill_and_wait(int pid, int* status)
{
kill(-pid, SIGKILL);
kill(pid, SIGKILL);
int i;
for (i = 0; i < 100; i++) {
if (waitpid(-1, status, WNOHANG | __WALL) == pid)
return;
usleep(1000);
}
DIR* dir = opendir("/sys/fs/fuse/connections");
if (dir) {
for (;;) {
struct dirent* ent = readdir(dir);
if (!ent)
break;
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0)
continue;
char abort[300];
snprintf(abort, sizeof(abort), "/sys/fs/fuse/connections/%s/abort", ent->d_name);
int fd = open(abort, O_WRONLY);
if (fd == -1) {
continue;
}
if (write(fd, abort, 1) < 0) {
}
close(fd);
}
closedir(dir);
} else {
}
while (waitpid(-1, status, __WALL) != pid) {
}
}

#define SYZ_HAVE_SETUP_TEST 1
static void setup_test()
{
prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0);
setpgrp();
}

#define SYZ_HAVE_RESET_TEST 1
static void reset_test()
{
int fd;
for (fd = 3; fd < 30; fd++)
close(fd);
}

static void execute_one(void);

#define WAIT_FLAGS __WALL

static void loop(void)
{
int iter;
for (iter = 0;; iter++) {
int pid = fork();
if (pid < 0)
exit(1);
if (pid == 0) {
setup_test();
execute_one();
reset_test();
exit(0);
}
int status = 0;
uint64_t start = current_time_ms();
for (;;) {
if (waitpid(-1, &status, WNOHANG | WAIT_FLAGS) == pid)
break;
sleep_ms(1);
if (current_time_ms() - start < 5 * 1000)
continue;
kill_and_wait(pid, &status);
break;
}
}
}

void execute_one(void)
{
*(uint32_t*)0x20000300 = 0;
*(uint32_t*)0x20000304 = 0x70;
*(uint8_t*)0x20000308 = 0;
*(uint8_t*)0x20000309 = 0;
*(uint8_t*)0x2000030a = 0;
*(uint8_t*)0x2000030b = 0;
*(uint32_t*)0x2000030c = 0;
*(uint64_t*)0x20000310 = 0x4000;
*(uint64_t*)0x20000318 = 0x22;
*(uint64_t*)0x20000320 = 0;
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 0, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 1, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 2, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 3, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 4, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 5, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 6, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 7, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 8, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 9, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 10, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 11, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 12, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 13, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 14, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 15, 2);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 17, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 18, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 19, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 3, 20, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 21, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 22, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 23, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 24, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 25, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 26, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0x80000, 27, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 28, 1);
STORE_BY_BITMASK(uint64_t, , 0x20000328, 0, 29, 35);
*(uint32_t*)0x20000330 = 0;
*(uint32_t*)0x20000334 = 0;
*(uint64_t*)0x20000338 = 0;
*(uint64_t*)0x20000340 = 0;
*(uint64_t*)0x20000348 = 0;
*(uint64_t*)0x20000350 = 0;
*(uint32_t*)0x20000358 = 0;
*(uint32_t*)0x2000035c = 0;
*(uint64_t*)0x20000360 = 0;
*(uint32_t*)0x20000368 = 0;
*(uint16_t*)0x2000036c = 0;
*(uint16_t*)0x2000036e = 0;
syscall(__NR_perf_event_open, 0x20000300, 0, 0, -1, 0);

}
int main(void)
{
syscall(__NR_mmap, 0x20000000, 0x1000000, 3, 0x32, -1, 0);
for (procid = 0; procid < 8; procid++) {
if (fork() == 0) {
loop();
}
}
sleep(1000000);
return 0;
}

Attachment: proc.config
Description: Binary data