cve-2016-3768
Due to the duplicate constraints, arch/arm/mach-msm/perfeventmsmkraitl2.c drivers marks the event as OFF but returns TRUE to perfevent.c which goes ahead and allocates the hwevent and enables it.
Since event is marked OFF, kernel events core will try to enable this event again during next perfeventenable.
Which results in same event enabled on multiple hw_events.
But during the perfrelease, event struct is freed and only one hwevent is released.
This results in dereferencing the invalid pointer and hence the crash.
crash and my kernel log
[ 50.803798] [idhyt] --- call perf_event_open ---
[ 50.806024] [idhyt] --- in perf_event_alloc ---
[ 50.806300] [idhyt] kzalloc event = e9859c00
[ 50.817401] [idhyt] --- in armpmu_add ---
[ 50.817808] [idhyt] event = e9859c00, hwc(hw_perf_event) = e9859cd0, hw_events(pmu_hw_events) = c11a5a68
[ 50.819088] [idhyt] armpmu->get_event_idx = 0
[ 50.819315] [idhyt] c11a5a68->events[0] = e9859c00
[ 50.820089] [idhyt] call perf_event_open return, event_fd = 3, event = e9859c00, hw_perf_event = e9859cd0
[ 50.820505] [idhyt] --- call perf_event_open ---
[ 50.820736] [idhyt] --- in perf_event_alloc ---
[ 50.820966] [idhyt] kzalloc event = e9859800
[ 50.831431] [idhyt] --- in armpmu_add ---
[ 50.831660] [idhyt] event = e9859800, hwc(hw_perf_event) = e98598d0, hw_events(pmu_hw_events) = c11a5a68
[ 50.832072] [idhyt] --- in msm_l2_test_set_ev_constraint ---
[ 50.832478] [idhyt] l2_pmu_constraints.pmu_bitmap = 0x1, bitmap_t = 0x1
[ 50.832710] [idhyt] perf_event = e9859800, set event->state = PERF_EVENT_STATE_OFF, event->attr.constraint_duplicate = 1
[ 50.833125] [idhyt] armpmu->get_event_idx = 1
[ 50.833354] [idhyt] c11a5a68->events[1] = e9859800
[ 50.834114] [idhyt] call perf_event_open return, event_fd = 4, event = e9859800, hw_perf_event = e98598d0
[ 50.834537] [idhyt] ioclt: PERF_EVENT_IOC_ENABLE
[ 50.835412] [idhyt] --- in armpmu_add ---
[ 50.835821] [idhyt] event = e9859800, hwc(hw_perf_event) = e98598d0, hw_events(pmu_hw_events) = c11a5a68
[ 50.836238] [idhyt] --- in msm_l2_test_set_ev_constraint ---
[ 50.836469] [idhyt] l2_pmu_constraints.pmu_bitmap = 0x1, bitmap_t = 0x1
[ 50.836878] [idhyt] perf_event = e9859800, set event->state = PERF_EVENT_STATE_OFF, event->attr.constraint_duplicate = 1
[ 50.837300] [idhyt] armpmu->get_event_idx = 2
[ 50.837530] [idhyt] c11a5a68->events[2] = e9859800
[ 50.837972] [idhyt] --- in perf_release func
[ 50.838202] [idhyt] event = e9859c00, event->state = 1
[ 50.854583] [idhyt] --- in perf_release func
// // release events[1] !!!!!!
[ 50.854763] [idhyt] event = e9859800, event->state = -1
// // open new perf_event !!!!!!
[ 96.572065] [idhyt] --- call perf_event_open ---
[ 96.572112] [idhyt] --- in perf_event_alloc ---
[ 96.572193] [idhyt] kzalloc event = e9859c00
[ 96.572384] [idhyt] --- in perf_init_event ---
[ 96.572673] [idhyt] --- in armpmu_event_init ---
[ 96.573138] [idhyt] --- in armpmu_reserve_hardware ---
[ 96.573578] [idhyt] armpmu->request_pmu_irq
[ 96.573622] [idhyt] --- in krait_l2_handle_irq ---
[ 96.573662] [idhyt] idx = 1
// // dereferencing the invalid pointer and crash!!!!!!
[ 96.573731] [idhyt] event = krait_l2_pmu_hw_events.events[1] = e9859800
[ 96.573771] [idhyt] armpmu_event_update
[ 96.573841] [idhyt] --- in armpmu_event_update ---
[ 96.573881] [idhyt] event = e9859800, event->state = 538976288, hwc(hw_perf_event) = e98598d0, idx = 1
[ 96.573954] Unable to handle kernel paging request at virtual address 202020d8
[ 96.573994] pgd = eb3fc000
[ 96.574063] [202020d8] *pgd=00000000
[ 96.574142] Internal error: Oops: 5 [#1] PREEMPT SMP ARM
[ 96.574184] CPU: 0 Not tainted (3.4.0-geaa8415-dirty #25)
[ 96.574262] PC is at armpmu_event_update+0x64/0x11c
[ 96.574307] LR is at console_unlock+0x2d8/0x330
[ 96.574378] pc : [<c0116bf4>] lr : [<c01ae924>] psr: 20000193
[ 96.574380] sp : ea739b68 ip : ea739a50 fp : ea739b9c
[ 96.574484] r10: e9859928 r9 : e98598d0 r8 : e9859800
[ 96.574524] r7 : 20202020 r6 : 00000001 r5 : 00000000 r4 : 00000000
[ 96.574594] r3 : 20202020 r2 : 9059756f r1 : 60000193 r0 : 0000006d
[ 96.574634] Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment user
[ 96.574705] Control: 10c5787d Table: 337fc06a DAC: 00000015
[ 96.574774]
[ 96.574776] PC: 0xc0116b74:
[ 96.574847] 6b74 ebffff8b eafffff7 00c95cc4 00c95cbc 00c95d04 00c95c98 00c95cd8 e1a0c00d
[ 96.575241] 6b94 e92ddff0 e24cb004 e24dd00c e52de004 e8bd4000 e1a08000 e59f00f0 e1a09001
[ 96.575608] 6bb4 e1a06002 e08f0000 eb28b0fd e59f00e0 e5982030 e1a03009 e58d6000 e1a01008
[ 96.576008] 6bd4 e08f0000 e598702c eb28b0f5 e5983030 e3530000 ba000029 e289a058 e1ba4f9f
[ 96.576376] 6bf4 e59730b8 e1a00006 e12fff33 e3a03000 e1a02000 f57ff05f e1ba0f9f e3a0c000
[ 96.576775] 6c14 e1300004 01310005 01aacf92 e35c0000 1afffff8 f57ff05f e1510005 01500004
[ 96.577145] 6c34 1affffed e1c709d0 e0524004 e0c35005 e288c038 e0000004 e0011005 e1bc4f9f
[ 96.577543] 6c54 e0944000 e0a55001 e1acef94 e33e0000 1afffff9 e289c070 e1bc4f9f e0544000
[ 96.577941]
[ 96.577942] LR: 0xc01ae8a4:
[ 96.578015] e8a4 e2800004 eb00a841 e1a00004 eb26ab59 e595200c e5953004 e1a00004 e1a01006
[ 96.578382] e8c4 e1520003 0a00000d eb26abe5 ebffff17 e3500000 0a00000d e3a03001 e50b3044
[ 96.578784] e8e4 eaffff6e e1a02000 e51b104c e24b0032 ebfffce9 e51b3048 e5932008 eaffffd2
[ 96.579154] e904 eb26abd7 e51b3044 e3530000 1affffee e51b3038 e3530000 0a000000 ebffff2b
[ 96.579553] e924 e24bd028 e89daff0 e7f001f2 e59f0040 e08f0000 e2800004 eb00a81c e24bd028
[ 96.579955] e944 e89daff0 011022d8 00f9d9b8 00f9d948 010030d4 00f9d934 010030bc 00f9d90c
[ 96.580325] e964 00f9d89c fff5179c 00f9d7dc 011020c0 01002f34 01002ea0 e1a0c00d e92ddff0
[ 96.580723] e984 e24cb004 e24dd074 e52de004 e8bd4000 e59f3630 e1a06000 e59f062c e1a05001
[ 96.581121]
cve-2016-0819
attr.disabled = 0;
attr.constraint_duplicate = 1;
fd =syscall(__NR_perf_event_open, &attr, 0, -1, -1, 0);
enable: event->state = PERF_EVENT_STATE_ACTIVE;
ioctl(fd, PERF_EVENT_IOC_DISABLE, 0);
disable: event->state = PERF_EVENT_STATE_OFF
close(fd);
static int perf_release(struct inode *inode, struct file *file)
{
struct perf_event *event = file->private_data;
struct task_struct *owner;
/*
* Event can be in state OFF because of a constraint check.
* Change to ACTIVE so that it gets cleaned up correctly.
*/
if ((event->state == PERF_EVENT_STATE_OFF) &&
event->attr.constraint_duplicate)
event->state = PERF_EVENT_STATE_ACTIVE;
...
}
if (event->attr.constraintduplicate) event->state = PERFEVENTSTATEACTIVE;
static void
event_sched_out(struct perf_event *event,
struct perf_cpu_context *cpuctx,
struct perf_event_context *ctx)
{
u64 tstamp = perf_event_time(event);
u64 delta;
/*
* An event which could not be activated because of
* filter mismatch still needs to have its timings
* maintained, otherwise bogus information is return
* via read() for time_enabled, time_running:
*/
if (event->state == PERF_EVENT_STATE_INACTIVE
&& !event_filter_match(event)) {
delta = tstamp - event->tstamp_stopped;
event->tstamp_running += delta;
event->tstamp_stopped = tstamp;
}
// !! should return, but event->state = PERF_EVENT_STATE_ACTIVE
if (event->state != PERF_EVENT_STATE_ACTIVE)
return;
event->state = PERF_EVENT_STATE_INACTIVE;
if (event->pending_disable) {
event->pending_disable = 0;
event->state = PERF_EVENT_STATE_OFF;
}
event->tstamp_stopped = tstamp;
event->pmu->del(event, 0); // del again, crash !!!
event->oncpu = -1;
...
}
crash backtrace
[11831.615804] [<c0241d00>] (perf_trace_del+0x20/0x4c) from [<c0247f2c>] (event_sched_out+0xb8/0x13c)
[11831.615890] [<c0247f2c>] (event_sched_out+0xb8/0x13c) from [<c024af0c>] (__perf_remove_from_context+0x58/0x94)
[11831.615977] [<c024af0c>] (__perf_remove_from_context+0x58/0x94) from [<c02495fc>] (remote_function+0x5c/0x68)
[11831.616066] [<c02495fc>] (remote_function+0x5c/0x68) from [<c020403c>] (smp_call_function_single+0x1d4/0x228)
[11831.616158] [<c020403c>] (smp_call_function_single+0x1d4/0x228) from [<c0b0e284>] (perf_remove_from_context+0x90/0x170)
[11831.616247] [<c0b0e284>] (perf_remove_from_context+0x90/0x170) from [<c024bdb8>] (perf_event_release_kernel+0x50/0xa0)
[11831.616333] [<c024bdb8>] (perf_event_release_kernel+0x50/0xa0) from [<c024bee8>] (perf_release+0xe0/0x114)
[11831.616424] [<c024bee8>] (perf_release+0xe0/0x114) from [<c0298bfc>] (fput+0xc8/0x244)
[11831.616479] [<c0298bfc>] (fput+0xc8/0x244) from [<c0295ffc>] (filp_close+0x74/0x9c)
[11831.616563] [<c0295ffc>] (filp_close+0x74/0x9c) from [<c02960fc>] (sys_close+0xd8/0x110)
[11831.616651] [<c02960fc>] (sys_close+0xd8/0x110) from [<c0109b00>] (ret_fast_syscall+0x0/0x30)
[11831.616702] Code: e1a03000 e590101c e5900240 e3520000 (e5812000)
cve-2013-2094
struct static_key {
atomic_t enabled;
};
static inline void static_key_slow_inc(struct static_key *key)
{
atomic_inc(&key->enabled);
}
static int perf_swevent_init(struct perf_event *event)
{
int event_id = event->attr.config;
...
// if event_id < 0
if (event_id >= PERF_COUNT_SW_MAX)
return -ENOENT;
if (!event->parent) {
int err;
err = swevent_hlist_get(event);
if (err)
return err;
// could inc op array out of bouds
static_key_slow_inc(&perf_swevent_enabled[event_id]);
event->destroy = sw_perf_event_destroy;
}
return 0;
}
没有评论:
发表评论