Re: sw_perf_event_destroy() oops while fuzzing
2013/4/12 Tommi Rantala : > 2013/4/12 Peter Zijlstra : >> perf_swevent_init() only sets event->destroy() (to >> sw_perf_event_destroy) _after_ it increments the static key thing and >> enqueues (and allocates) the hash list stuff. >> >> Obviously something is funny, but I'm not seeing it. > > Might this help... ? (untested) I can reproduce the bug on my machine with: #include #include #include int main(void) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .size = sizeof(struct perf_event_attr), .config = 0x, }; syscall(__NR_perf_event_open, , getpid(), -1, -1, 0); return 0; } The patch below fixes the oops. I'll send it properly. > diff --git a/kernel/events/core.c b/kernel/events/core.c > index 59412d0..fff6420 100644 > --- a/kernel/events/core.c > +++ b/kernel/events/core.c > @@ -5330,7 +5330,7 @@ static void sw_perf_event_destroy(struct > perf_event *event) > > static int perf_swevent_init(struct perf_event *event) > { > - int event_id = event->attr.config; > + u64 event_id = event->attr.config; > > if (event->attr.type != PERF_TYPE_SOFTWARE) > return -ENOENT; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: sw_perf_event_destroy() oops while fuzzing
2013/4/12 Tommi Rantala tt.rant...@gmail.com: 2013/4/12 Peter Zijlstra a.p.zijls...@chello.nl: perf_swevent_init() only sets event-destroy() (to sw_perf_event_destroy) _after_ it increments the static key thing and enqueues (and allocates) the hash list stuff. Obviously something is funny, but I'm not seeing it. Might this help... ? (untested) I can reproduce the bug on my machine with: #include unistd.h #include sys/syscall.h #include linux/perf_event.h int main(void) { struct perf_event_attr attr = { .type = PERF_TYPE_SOFTWARE, .size = sizeof(struct perf_event_attr), .config = 0x, }; syscall(__NR_perf_event_open, attr, getpid(), -1, -1, 0); return 0; } The patch below fixes the oops. I'll send it properly. diff --git a/kernel/events/core.c b/kernel/events/core.c index 59412d0..fff6420 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5330,7 +5330,7 @@ static void sw_perf_event_destroy(struct perf_event *event) static int perf_swevent_init(struct perf_event *event) { - int event_id = event-attr.config; + u64 event_id = event-attr.config; if (event-attr.type != PERF_TYPE_SOFTWARE) return -ENOENT; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: sw_perf_event_destroy() oops while fuzzing
2013/4/12 Peter Zijlstra : > On Fri, 2013-04-12 at 08:34 +0300, Tommi Rantala wrote: > >> [92759.011005] RIP [] sw_perf_event_destroy+0x30/0x90 > >> [114607.070003] RIP: 0010:[] [] >> sw_perf_event_destroy+0x30/0x90 > >> [114607.070003] RIP [] sw_perf_event_destroy+0x30/0x90 > > Would you have a source line for me that goes with that.. I can't seem > to poke any holes just by looking. It is crashing at: 0x811a7200 <+48>:lock decl -0x7c3c9680(,%r12,4) Matching source line is: static_key_slow_dec(_swevent_enabled[event_id]); -0x7c3c9680 is the address of perf_swevent_enabled[], and %r12 is 0xff4c in the first oops. So it looks like event_id is invalid. (gdb) disassemble sw_perf_event_destroy Dump of assembler code for function sw_perf_event_destroy: 0x811a71d0 <+0>: push %rbp 0x811a71d1 <+1>: mov%rsp,%rbp 0x811a71d4 <+4>: push %r12 0x811a71d6 <+6>: push %rbx 0x811a71d7 <+7>: cmpq $0x0,0x288(%rdi) 0x811a71df <+15>:mov%rdi,%rbx 0x811a71e2 <+18>:mov0xa8(%rdi),%r12 0x811a71e9 <+25>:je 0x811a7200 0x811a71eb <+27>:mov$0x14cd,%esi 0x811a71f0 <+32>:mov$0x829c3e50,%rdi 0x811a71f7 <+39>:callq 0x810f0b10 0x811a71fc <+44>:nopl 0x0(%rax) 0x811a7200 <+48>:lock decl -0x7c3c9680(,%r12,4) 0x811a7209 <+57>:mov0x294(%rbx),%edi 0x811a720f <+63>:cmp$0x,%edi 0x811a7212 <+66>:jne0x811a7220 0x811a7214 <+68>:mov0x127ea5d(%rip),%r12# 0x82425c78 0x811a721b <+75>:mov%edi,%ebx 0x811a721d <+77>:jmp0x811a7237 0x811a721f <+79>:nop 0x811a7220 <+80>:callq 0x811a7170 0x811a7225 <+85>:jmp0x811a7254 0x811a7227 <+87>:nopw 0x0(%rax,%rax,1) 0x811a7230 <+96>:mov%eax,%edi 0x811a7232 <+98>:callq 0x811a7170 0x811a7237 <+103>: add$0x1,%ebx 0x811a723a <+106>: mov$0x40,%esi 0x811a723f <+111>: mov%r12,%rdi 0x811a7242 <+114>: movslq %ebx,%rdx 0x811a7245 <+117>: callq 0x814c63f0 0x811a724a <+122>: cmp0x1c6d9f4(%rip),%eax# 0x82e14c44 0x811a7250 <+128>: mov%eax,%ebx 0x811a7252 <+130>: jl 0x811a7230 0x811a7254 <+132>: pop%rbx 0x811a7255 <+133>: pop%r12 0x811a7257 <+135>: pop%rbp 0x811a7258 <+136>: retq End of assembler dump. (gdb) list *0x811a7200 0x811a7200 is in sw_perf_event_destroy (/home/ttrantal/git/linux/arch/x86/include/asm/atomic.h:107). 102 * 103 * Atomically decrements @v by 1. 104 */ 105 static inline void atomic_dec(atomic_t *v) 106 { 107 asm volatile(LOCK_PREFIX "decl %0" 108 : "+m" (v->counter)); 109 } 110 111 /** (gdb) print _swevent_enabled $2 = (struct static_key (*)[9]) 0x83c36980 > perf_swevent_init() only sets event->destroy() (to > sw_perf_event_destroy) _after_ it increments the static key thing and > enqueues (and allocates) the hash list stuff. > > Obviously something is funny, but I'm not seeing it. Might this help... ? (untested) diff --git a/kernel/events/core.c b/kernel/events/core.c index 59412d0..fff6420 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5330,7 +5330,7 @@ static void sw_perf_event_destroy(struct perf_event *event) static int perf_swevent_init(struct perf_event *event) { - int event_id = event->attr.config; + u64 event_id = event->attr.config; if (event->attr.type != PERF_TYPE_SOFTWARE) return -ENOENT; -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: sw_perf_event_destroy() oops while fuzzing
On Fri, 2013-04-12 at 08:34 +0300, Tommi Rantala wrote: > [92759.011005] RIP [] sw_perf_event_destroy+0x30/0x90 > [114607.070003] RIP: 0010:[] [] > sw_perf_event_destroy+0x30/0x90 > [114607.070003] RIP [] sw_perf_event_destroy+0x30/0x90 Would you have a source line for me that goes with that.. I can't seem to poke any holes just by looking. perf_swevent_init() only sets event->destroy() (to sw_perf_event_destroy) _after_ it increments the static key thing and enqueues (and allocates) the hash list stuff. Obviously something is funny, but I'm not seeing it. -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: sw_perf_event_destroy() oops while fuzzing
On Fri, 2013-04-12 at 08:34 +0300, Tommi Rantala wrote: [92759.011005] RIP [811a7200] sw_perf_event_destroy+0x30/0x90 [114607.070003] RIP: 0010:[811a7200] [811a7200] sw_perf_event_destroy+0x30/0x90 [114607.070003] RIP [811a7200] sw_perf_event_destroy+0x30/0x90 Would you have a source line for me that goes with that.. I can't seem to poke any holes just by looking. perf_swevent_init() only sets event-destroy() (to sw_perf_event_destroy) _after_ it increments the static key thing and enqueues (and allocates) the hash list stuff. Obviously something is funny, but I'm not seeing it. -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
Re: sw_perf_event_destroy() oops while fuzzing
2013/4/12 Peter Zijlstra a.p.zijls...@chello.nl: On Fri, 2013-04-12 at 08:34 +0300, Tommi Rantala wrote: [92759.011005] RIP [811a7200] sw_perf_event_destroy+0x30/0x90 [114607.070003] RIP: 0010:[811a7200] [811a7200] sw_perf_event_destroy+0x30/0x90 [114607.070003] RIP [811a7200] sw_perf_event_destroy+0x30/0x90 Would you have a source line for me that goes with that.. I can't seem to poke any holes just by looking. It is crashing at: 0x811a7200 +48:lock decl -0x7c3c9680(,%r12,4) Matching source line is: static_key_slow_dec(perf_swevent_enabled[event_id]); -0x7c3c9680 is the address of perf_swevent_enabled[], and %r12 is 0xff4c in the first oops. So it looks like event_id is invalid. (gdb) disassemble sw_perf_event_destroy Dump of assembler code for function sw_perf_event_destroy: 0x811a71d0 +0: push %rbp 0x811a71d1 +1: mov%rsp,%rbp 0x811a71d4 +4: push %r12 0x811a71d6 +6: push %rbx 0x811a71d7 +7: cmpq $0x0,0x288(%rdi) 0x811a71df +15:mov%rdi,%rbx 0x811a71e2 +18:mov0xa8(%rdi),%r12 0x811a71e9 +25:je 0x811a7200 sw_perf_event_destroy+48 0x811a71eb +27:mov$0x14cd,%esi 0x811a71f0 +32:mov$0x829c3e50,%rdi 0x811a71f7 +39:callq 0x810f0b10 warn_slowpath_null 0x811a71fc +44:nopl 0x0(%rax) 0x811a7200 +48:lock decl -0x7c3c9680(,%r12,4) 0x811a7209 +57:mov0x294(%rbx),%edi 0x811a720f +63:cmp$0x,%edi 0x811a7212 +66:jne0x811a7220 sw_perf_event_destroy+80 0x811a7214 +68:mov0x127ea5d(%rip),%r12# 0x82425c78 cpu_possible_mask 0x811a721b +75:mov%edi,%ebx 0x811a721d +77:jmp0x811a7237 sw_perf_event_destroy+103 0x811a721f +79:nop 0x811a7220 +80:callq 0x811a7170 swevent_hlist_put_cpu 0x811a7225 +85:jmp0x811a7254 sw_perf_event_destroy+132 0x811a7227 +87:nopw 0x0(%rax,%rax,1) 0x811a7230 +96:mov%eax,%edi 0x811a7232 +98:callq 0x811a7170 swevent_hlist_put_cpu 0x811a7237 +103: add$0x1,%ebx 0x811a723a +106: mov$0x40,%esi 0x811a723f +111: mov%r12,%rdi 0x811a7242 +114: movslq %ebx,%rdx 0x811a7245 +117: callq 0x814c63f0 find_next_bit 0x811a724a +122: cmp0x1c6d9f4(%rip),%eax# 0x82e14c44 nr_cpu_ids 0x811a7250 +128: mov%eax,%ebx 0x811a7252 +130: jl 0x811a7230 sw_perf_event_destroy+96 0x811a7254 +132: pop%rbx 0x811a7255 +133: pop%r12 0x811a7257 +135: pop%rbp 0x811a7258 +136: retq End of assembler dump. (gdb) list *0x811a7200 0x811a7200 is in sw_perf_event_destroy (/home/ttrantal/git/linux/arch/x86/include/asm/atomic.h:107). 102 * 103 * Atomically decrements @v by 1. 104 */ 105 static inline void atomic_dec(atomic_t *v) 106 { 107 asm volatile(LOCK_PREFIX decl %0 108 : +m (v-counter)); 109 } 110 111 /** (gdb) print perf_swevent_enabled $2 = (struct static_key (*)[9]) 0x83c36980 perf_swevent_enabled perf_swevent_init() only sets event-destroy() (to sw_perf_event_destroy) _after_ it increments the static key thing and enqueues (and allocates) the hash list stuff. Obviously something is funny, but I'm not seeing it. Might this help... ? (untested) diff --git a/kernel/events/core.c b/kernel/events/core.c index 59412d0..fff6420 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c @@ -5330,7 +5330,7 @@ static void sw_perf_event_destroy(struct perf_event *event) static int perf_swevent_init(struct perf_event *event) { - int event_id = event-attr.config; + u64 event_id = event-attr.config; if (event-attr.type != PERF_TYPE_SOFTWARE) return -ENOENT; -- To unsubscribe from this list: send the line unsubscribe linux-kernel in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/