in cli/bpfcov.c [1050:1185]
int run(struct root_args *args)
{
log_info(args, "executing program '%s'\n", args->program[0]);
pid_t pid = fork();
switch (pid)
{
case -1: /* Error */
log_fata(args, "%s\n", strerror(errno));
case 0: /* Child */
if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) < 0)
{
log_fata(args, "%s\n", strerror(errno));
}
execvp(args->program[0], args->program);
log_fata(args, "%s\n", strerror(errno));
}
/* Parent */
waitpid(pid, 0, 0); // sync with PTRACE_TRACEME
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL);
int is_map = 0;
for (;;)
{
/* Enter next system call */
if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1)
{
log_fata(args, "%s\n", strerror(errno));
}
/* Waiting for PID to die */
if (waitpid(pid, 0, 0) == -1)
{
log_fata(args, "%s\n", strerror(errno));
}
/* Gather system call arguments */
struct user_regs_struct regs;
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) == -1)
{
log_fata(args, "%s\n", strerror(errno));
}
/* Mark bpf(BPF_MAP_CREATE, ...) */
const unsigned int sysc = regs.orig_rax;
const unsigned int comm = regs.rdi;
is_map = (sysc == SYS_bpf && comm == BPF_MAP_CREATE);
/* Print a representation of the system call */
log_debu(args,
"%d(%d, %ld, %ld, %ld, %ld, %ld)",
sysc,
comm, (long)regs.rsi, (long)regs.rdx, (long)regs.r10, (long)regs.r8, (long)regs.r9);
/* Run system call and stop on exit */
if (ptrace(PTRACE_SYSCALL, pid, 0, 0) == -1)
{
log_fata(args, "%s\n", strerror(errno));
}
/* Waiting for PID to die */
if (waitpid(pid, 0, 0) == -1)
{
log_fata(args, "%s\n", strerror(errno));
}
/* Get system call result */
if (ptrace(PTRACE_GETREGS, pid, 0, ®s) == -1)
{
if (DEBUG) {
print_log(3, NULL, args, "%s\n", " = ?");
}
if (errno == ESRCH)
{
exit(regs.rdi); // _exit(2) or similar
}
log_fata(args, "%s\n", strerror(errno));
}
/* Print system call result */
long result = regs.rax;
if (DEBUG) {
print_log(3, NULL, args, " = %ld\n", result);
}
/* Pin the bpfcov maps */
if (is_map && result)
{
int pidfd = syscall(SYS_pidfd_open, pid, 0);
if (pidfd < 0)
{
continue;
}
int curfd = syscall(SYS_pidfd_getfd, pidfd, result, 0);
if (curfd < 0)
{
continue;
}
close(pidfd);
struct bpf_map_info map_info = {};
int err;
err = get_map_info(curfd, &map_info);
if (!err && strlen(map_info.name) > 0)
{
log_info(args, "got info about map '%s'\n", map_info.name);
char map_name[BPF_OBJ_NAME_LEN];
strcpy(map_name, map_info.name);
const char *sep = ".";
strtok(map_info.name, sep);
char *suffix = strtok(NULL, sep);
char *pin_path = "";
if (get_pin_path(args, suffix, &pin_path))
{
err = bpf_obj_pin(curfd, pin_path);
if (err)
{
if (errno == EEXIST)
{
log_warn(args, "pin '%s' already exists for map '%s'\n", pin_path, map_name);
continue;
}
log_fata(args, "%s\n", "could not pin map");
}
log_warn(args, "pin map '%s' to '%s'\n", map_name, pin_path);
}
}
}
}
return 0;
}