You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
133 lines
3.0 KiB
133 lines
3.0 KiB
7 months ago
|
/*
|
||
|
* RandomRead Monitor random number read events.
|
||
|
* For Linux, uses BCC, eBPF. Embedded C.
|
||
|
*
|
||
|
* Basic example of BCC Tracepoint and perf buffer.
|
||
|
*
|
||
|
* USAGE: RandomRead
|
||
|
*
|
||
|
* Copyright (c) Facebook, Inc.
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License")
|
||
|
*/
|
||
|
|
||
|
#include <signal.h>
|
||
|
#include <iostream>
|
||
|
|
||
|
#include "BPF.h"
|
||
|
|
||
|
const std::string BPF_PROGRAM = R"(
|
||
|
#include <linux/sched.h>
|
||
|
#include <uapi/linux/ptrace.h>
|
||
|
|
||
|
#ifndef CGROUP_FILTER
|
||
|
#define CGROUP_FILTER 0
|
||
|
#endif
|
||
|
|
||
|
struct urandom_read_args {
|
||
|
// See /sys/kernel/debug/tracing/events/random/urandom_read/format
|
||
|
uint64_t common__unused;
|
||
|
int got_bits;
|
||
|
int pool_left;
|
||
|
int input_left;
|
||
|
};
|
||
|
|
||
|
struct event_t {
|
||
|
int pid;
|
||
|
char comm[16];
|
||
|
int cpu;
|
||
|
int got_bits;
|
||
|
};
|
||
|
|
||
|
BPF_PERF_OUTPUT(events);
|
||
|
BPF_CGROUP_ARRAY(cgroup, 1);
|
||
|
|
||
|
int on_urandom_read(struct urandom_read_args* attr) {
|
||
|
if (CGROUP_FILTER && (cgroup.check_current_task(0) != 1))
|
||
|
return 0;
|
||
|
|
||
|
struct event_t event = {};
|
||
|
event.pid = bpf_get_current_pid_tgid();
|
||
|
bpf_get_current_comm(&event.comm, sizeof(event.comm));
|
||
|
event.cpu = bpf_get_smp_processor_id();
|
||
|
event.got_bits = attr->got_bits;
|
||
|
|
||
|
events.perf_submit(attr, &event, sizeof(event));
|
||
|
return 0;
|
||
|
}
|
||
|
)";
|
||
|
|
||
|
// Define the same struct to use in user space.
|
||
|
struct event_t {
|
||
|
int pid;
|
||
|
char comm[16];
|
||
|
int cpu;
|
||
|
int got_bits;
|
||
|
};
|
||
|
|
||
|
void handle_output(void* cb_cookie, void* data, int data_size) {
|
||
|
auto event = static_cast<event_t*>(data);
|
||
|
std::cout << "PID: " << event->pid << " (" << event->comm << ") on CPU "
|
||
|
<< event->cpu << " read " << event->got_bits << " bits"
|
||
|
<< std::endl;
|
||
|
}
|
||
|
|
||
|
ebpf::BPF* bpf;
|
||
|
|
||
|
void signal_handler(int s) {
|
||
|
std::cerr << "Terminating..." << std::endl;
|
||
|
delete bpf;
|
||
|
exit(0);
|
||
|
}
|
||
|
|
||
|
int main(int argc, char** argv) {
|
||
|
if (argc != 1 && argc != 2) {
|
||
|
std::cerr << "USAGE: RandomRead [cgroup2_path]" << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
std::vector<std::string> cflags = {};
|
||
|
if (argc == 2)
|
||
|
cflags.emplace_back("-DCGROUP_FILTER=1");
|
||
|
|
||
|
bpf = new ebpf::BPF();
|
||
|
auto init_res = bpf->init(BPF_PROGRAM, cflags, {});
|
||
|
if (init_res.code() != 0) {
|
||
|
std::cerr << init_res.msg() << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
if (argc == 2) {
|
||
|
auto cgroup_array = bpf->get_cgroup_array("cgroup");
|
||
|
auto update_res = cgroup_array.update_value(0, argv[1]);
|
||
|
if (update_res.code() != 0) {
|
||
|
std::cerr << update_res.msg() << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
auto attach_res =
|
||
|
bpf->attach_tracepoint("random:urandom_read", "on_urandom_read");
|
||
|
if (attach_res.code() != 0) {
|
||
|
std::cerr << attach_res.msg() << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
auto open_res = bpf->open_perf_buffer("events", &handle_output);
|
||
|
if (open_res.code() != 0) {
|
||
|
std::cerr << open_res.msg() << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
// done with all initial work, free bcc memory
|
||
|
if (bpf->free_bcc_memory()) {
|
||
|
std::cerr << "Failed to free llvm/clang memory" << std::endl;
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
signal(SIGINT, signal_handler);
|
||
|
std::cout << "Started tracing, hit Ctrl-C to terminate." << std::endl;
|
||
|
while (true)
|
||
|
bpf->poll_perf_buffer("events");
|
||
|
|
||
|
return 0;
|
||
|
}
|