Re: perf,arm -- another (different) fuzzer oops

From: Vince Weaver
Date: Wed Aug 07 2013 - 21:57:36 EST


On Wed, 7 Aug 2013, Stephen Boyd wrote:

> Is config some really big value? It looks like config (or more
> specifically event->attr.config) is ecececec which is larger than 9
> (PERF_COUNT_HW_MAX). I'm fairly certain r4 is event->attr.type
> (PERF_TYPE_HARDWARE) and so we're out of bounds on that array access in
> armpmu_map_hw_event(). Does the below patch fix that?

Yes, it was big values in attr.config. I managed to bisect down to a
simple test case, which is attached. Oddly the test case has two events
before the oops happens; I should double check to make sure both are
really necessary.

I'll try this patch and see if it fixes things, thanks.

Vince

/* log_to_code output from ./new_oops.bisect15 */
/* by Vince Weaver <vincent.weaver _at_ maine.edu */

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>
#include <sys/mman.h>
#include <sys/syscall.h>
#include <sys/ioctl.h>
#include <sys/prctl.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>

int fd[1024];
struct perf_event_attr pe[1024];
char *mmap_result[1024];
#define MAX_READ_SIZE 65536
static long long data[MAX_READ_SIZE];

int forked_pid;

int perf_event_open(struct perf_event_attr *hw_event_uptr,
pid_t pid, int cpu, int group_fd, unsigned long flags) {

return syscall(__NR_perf_event_open,hw_event_uptr, pid, cpu,
group_fd, flags);
}

int main(int argc, char **argv) {
/* 1 */

memset(&pe[0],0,sizeof(struct perf_event_attr));
pe[0].type=PERF_TYPE_HARDWARE;
pe[0].config=0x2cc61006;
pe[0].sample_type=0; /* 0 */
pe[0].read_format=PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_TOTAL_TIME_RUNNING|PERF_FORMAT_GROUP; /* b */
pe[0].disabled=1;
pe[0].exclusive=1;
pe[0].exclude_idle=1;
pe[0].comm=1;
pe[0].inherit_stat=1;
pe[0].enable_on_exec=1;
pe[0].precise_ip=0; /* arbitrary skid */
pe[0].mmap_data=1;
pe[0].sample_id_all=1;
pe[0].exclude_host=1;
pe[0].exclude_guest=1;
pe[0].wakeup_events=2147483647;
pe[0].bp_type=HW_BREAKPOINT_EMPTY;
pe[0].branch_sample_type=2147483648ULL;

fd[0]=perf_event_open(&pe[0],0,0,-1,PERF_FLAG_FD_NO_GROUP /*1*/ );

/* 2 */

memset(&pe[1],0,sizeof(struct perf_event_attr));
pe[1].type=PERF_TYPE_RAW;
pe[1].size=80;
pe[1].config=0xb6c8ad99;
pe[1].sample_type=0; /* 0 */
pe[1].read_format=PERF_FORMAT_TOTAL_TIME_ENABLED|PERF_FORMAT_ID|0x80000010ULL; /* 80000015 */
pe[1].inherit=1;
pe[1].exclude_user=1;
pe[1].exclude_hv=1;
pe[1].mmap=1;
pe[1].inherit_stat=1;
pe[1].task=1;
pe[1].precise_ip=3; /* must have zero skid */
pe[1].sample_id_all=1;
pe[1].exclude_guest=1;
pe[1].wakeup_events=0;
pe[1].bp_type=HW_BREAKPOINT_EMPTY;

fd[1]=perf_event_open(&pe[1],0,0,-1,PERF_FLAG_FD_NO_GROUP /*1*/ );

/* Replayed 2 syscalls */
return 0;
}