Skip to content

Instantly share code, notes, and snippets.

@jld
Created August 5, 2014 22:26
Show Gist options
  • Star 6 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jld/5d292c2c48eb07980562 to your computer and use it in GitHub Desktop.
Save jld/5d292c2c48eb07980562 to your computer and use it in GitHub Desktop.
Example of using a perf_event breakpoint counter to crash on write to a specific location.
#include <fcntl.h>
#include <linux/hw_breakpoint.h>
#include <linux/perf_event.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/syscall.h>
#include <sys/types.h>
#include <unistd.h>
// There's probably a magic ifdef that will make the headers include
// this stuff, but I haven't figured that out yet:
#ifndef F_SETSIG
#define F_SETSIG 10
#endif
#ifndef F_SETOWN_EX
#define F_SETOWN_EX 15
#define F_GETOWN_EX 16
struct f_owner_ex {
int type;
pid_t pid;
};
enum __pid_type {
F_OWNER_TID = 0,
F_OWNER_PID,
F_OWNER_PGRP,
};
#endif
static int perf_event_open(struct perf_event_attr *attr,
pid_t pid, int cpu, int group_fd,
unsigned long flags)
{
return syscall(__NR_perf_event_open,
attr, pid, cpu, group_fd, flags);
}
static pid_t gettid()
{
return syscall(__NR_gettid);
}
/// Actual program starts here:
volatile long stuff[256];
int main()
{
struct perf_event_attr attr;
struct f_owner_ex owner;
int fd, c;
memset(&attr, 0, sizeof(attr));
attr.size = sizeof(attr);
attr.type = PERF_TYPE_BREAKPOINT;
attr.bp_type = HW_BREAKPOINT_W;
attr.bp_addr = (uint64_t)&stuff['X'];
attr.bp_len = sizeof(stuff['X']);
attr.sample_period = 1;
attr.precise_ip = 2; // request synchronous delivery
attr.wakeup_events = 1;
fd = perf_event_open(&attr, 0, -1, -1,
PERF_FLAG_FD_CLOEXEC);
if (fd < 0) {
perror("perf_event_open");
return -1;
}
if (fcntl(fd, F_SETSIG, SIGSEGV) < 0) {
perror("fcntl F_SETSIG");
return 1;
}
owner.type = F_OWNER_TID;
owner.pid = gettid();
if (fcntl(fd, F_SETOWN_EX, &owner) < 0) {
perror("fcntl F_SETOWN_EX");
return 1;
}
if (fcntl(fd, F_SETFL, O_ASYNC) < 0) {
perror("fcntl F_SETFL");
return 1;
}
while ((c = getchar()) != EOF)
stuff[c] = 0;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment