1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# killsnoop Trace signals issued by the kill() syscall. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: killsnoop [-h] [-x] [-p PID] [-T PID] [-s SIGNAL] 8*387f9dfdSAndroid Build Coastguard Worker# 9*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg. 10*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# 20-Sep-2015 Brendan Gregg Created this. 13*387f9dfdSAndroid Build Coastguard Worker# 19-Feb-2016 Allan McAleavy migrated to BPF_PERF_OUTPUT 14*387f9dfdSAndroid Build Coastguard Worker 15*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 16*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 17*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import ArgString, printb 18*387f9dfdSAndroid Build Coastguard Workerimport argparse 19*387f9dfdSAndroid Build Coastguard Workerfrom time import strftime 20*387f9dfdSAndroid Build Coastguard Worker 21*387f9dfdSAndroid Build Coastguard Worker# arguments 22*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 23*387f9dfdSAndroid Build Coastguard Worker ./killsnoop # trace all kill() signals 24*387f9dfdSAndroid Build Coastguard Worker ./killsnoop -x # only show failed kills 25*387f9dfdSAndroid Build Coastguard Worker ./killsnoop -p 181 # only trace PID 181 26*387f9dfdSAndroid Build Coastguard Worker ./killsnoop -T 189 # only trace target PID 189 27*387f9dfdSAndroid Build Coastguard Worker ./killsnoop -s 9 # only trace signal 9 28*387f9dfdSAndroid Build Coastguard Worker""" 29*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 30*387f9dfdSAndroid Build Coastguard Worker description="Trace signals issued by the kill() syscall", 31*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 32*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 33*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--failed", action="store_true", 34*387f9dfdSAndroid Build Coastguard Worker help="only show failed kill syscalls") 35*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 36*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only which is the sender of signal") 37*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--tpid", 38*387f9dfdSAndroid Build Coastguard Worker help="trace this target PID only which is the receiver of signal") 39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-s", "--signal", 40*387f9dfdSAndroid Build Coastguard Worker help="trace this signal only") 41*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 42*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 43*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 44*387f9dfdSAndroid Build Coastguard Workerdebug = 0 45*387f9dfdSAndroid Build Coastguard Worker 46*387f9dfdSAndroid Build Coastguard Worker# define BPF program 47*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 48*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 49*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 50*387f9dfdSAndroid Build Coastguard Worker 51*387f9dfdSAndroid Build Coastguard Workerstruct val_t { 52*387f9dfdSAndroid Build Coastguard Worker u32 pid; 53*387f9dfdSAndroid Build Coastguard Worker int sig; 54*387f9dfdSAndroid Build Coastguard Worker int tpid; 55*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 56*387f9dfdSAndroid Build Coastguard Worker}; 57*387f9dfdSAndroid Build Coastguard Worker 58*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 59*387f9dfdSAndroid Build Coastguard Worker u32 pid; 60*387f9dfdSAndroid Build Coastguard Worker int tpid; 61*387f9dfdSAndroid Build Coastguard Worker int sig; 62*387f9dfdSAndroid Build Coastguard Worker int ret; 63*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 64*387f9dfdSAndroid Build Coastguard Worker}; 65*387f9dfdSAndroid Build Coastguard Worker 66*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infotmp, u32, struct val_t); 67*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 68*387f9dfdSAndroid Build Coastguard Worker 69*387f9dfdSAndroid Build Coastguard Workerint syscall__kill(struct pt_regs *ctx, int tpid, int sig) 70*387f9dfdSAndroid Build Coastguard Worker{ 71*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 72*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 73*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 74*387f9dfdSAndroid Build Coastguard Worker 75*387f9dfdSAndroid Build Coastguard Worker TPID_FILTER 76*387f9dfdSAndroid Build Coastguard Worker PID_FILTER 77*387f9dfdSAndroid Build Coastguard Worker SIGNAL_FILTER 78*387f9dfdSAndroid Build Coastguard Worker 79*387f9dfdSAndroid Build Coastguard Worker struct val_t val = {.pid = pid}; 80*387f9dfdSAndroid Build Coastguard Worker if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) { 81*387f9dfdSAndroid Build Coastguard Worker val.tpid = tpid; 82*387f9dfdSAndroid Build Coastguard Worker val.sig = sig; 83*387f9dfdSAndroid Build Coastguard Worker infotmp.update(&tid, &val); 84*387f9dfdSAndroid Build Coastguard Worker } 85*387f9dfdSAndroid Build Coastguard Worker 86*387f9dfdSAndroid Build Coastguard Worker return 0; 87*387f9dfdSAndroid Build Coastguard Worker}; 88*387f9dfdSAndroid Build Coastguard Worker 89*387f9dfdSAndroid Build Coastguard Workerint do_ret_sys_kill(struct pt_regs *ctx) 90*387f9dfdSAndroid Build Coastguard Worker{ 91*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 92*387f9dfdSAndroid Build Coastguard Worker struct val_t *valp; 93*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 94*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 95*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 96*387f9dfdSAndroid Build Coastguard Worker 97*387f9dfdSAndroid Build Coastguard Worker valp = infotmp.lookup(&tid); 98*387f9dfdSAndroid Build Coastguard Worker if (valp == 0) { 99*387f9dfdSAndroid Build Coastguard Worker // missed entry 100*387f9dfdSAndroid Build Coastguard Worker return 0; 101*387f9dfdSAndroid Build Coastguard Worker } 102*387f9dfdSAndroid Build Coastguard Worker 103*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm); 104*387f9dfdSAndroid Build Coastguard Worker data.pid = pid; 105*387f9dfdSAndroid Build Coastguard Worker data.tpid = valp->tpid; 106*387f9dfdSAndroid Build Coastguard Worker data.ret = PT_REGS_RC(ctx); 107*387f9dfdSAndroid Build Coastguard Worker data.sig = valp->sig; 108*387f9dfdSAndroid Build Coastguard Worker 109*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 110*387f9dfdSAndroid Build Coastguard Worker infotmp.delete(&tid); 111*387f9dfdSAndroid Build Coastguard Worker 112*387f9dfdSAndroid Build Coastguard Worker return 0; 113*387f9dfdSAndroid Build Coastguard Worker} 114*387f9dfdSAndroid Build Coastguard Worker""" 115*387f9dfdSAndroid Build Coastguard Worker 116*387f9dfdSAndroid Build Coastguard Workerif args.tpid: 117*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('TPID_FILTER', 118*387f9dfdSAndroid Build Coastguard Worker 'if (tpid != %s) { return 0; }' % args.tpid) 119*387f9dfdSAndroid Build Coastguard Workerelse: 120*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('TPID_FILTER', '') 121*387f9dfdSAndroid Build Coastguard Worker 122*387f9dfdSAndroid Build Coastguard Workerif args.pid: 123*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('PID_FILTER', 124*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 125*387f9dfdSAndroid Build Coastguard Workerelse: 126*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('PID_FILTER', '') 127*387f9dfdSAndroid Build Coastguard Worker 128*387f9dfdSAndroid Build Coastguard Workerif args.signal: 129*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('SIGNAL_FILTER', 130*387f9dfdSAndroid Build Coastguard Worker 'if (sig != %s) { return 0; }' % args.signal) 131*387f9dfdSAndroid Build Coastguard Workerelse: 132*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('SIGNAL_FILTER', '') 133*387f9dfdSAndroid Build Coastguard Worker 134*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf: 135*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 136*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 137*387f9dfdSAndroid Build Coastguard Worker exit() 138*387f9dfdSAndroid Build Coastguard Worker 139*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 140*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 141*387f9dfdSAndroid Build Coastguard Workerkill_fnname = b.get_syscall_fnname("kill") 142*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event=kill_fnname, fn_name="syscall__kill") 143*387f9dfdSAndroid Build Coastguard Workerb.attach_kretprobe(event=kill_fnname, fn_name="do_ret_sys_kill") 144*387f9dfdSAndroid Build Coastguard Worker 145*387f9dfdSAndroid Build Coastguard Worker# detect the length of PID column 146*387f9dfdSAndroid Build Coastguard Workerpid_bytes = 6 147*387f9dfdSAndroid Build Coastguard Workertry: 148*387f9dfdSAndroid Build Coastguard Worker with open("/proc/sys/kernel/pid_max", 'r') as f: 149*387f9dfdSAndroid Build Coastguard Worker pid_bytes = len(f.read().strip()) + 1 150*387f9dfdSAndroid Build Coastguard Worker f.close() 151*387f9dfdSAndroid Build Coastguard Workerexcept: 152*387f9dfdSAndroid Build Coastguard Worker pass # not fatal error, just use the default value 153*387f9dfdSAndroid Build Coastguard Worker 154*387f9dfdSAndroid Build Coastguard Worker# header 155*387f9dfdSAndroid Build Coastguard Workerprint("%-9s %-*s %-16s %-4s %-*s %s" % ( 156*387f9dfdSAndroid Build Coastguard Worker "TIME", pid_bytes, "PID", "COMM", "SIG", pid_bytes, "TPID", "RESULT")) 157*387f9dfdSAndroid Build Coastguard Worker 158*387f9dfdSAndroid Build Coastguard Worker# process event 159*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size): 160*387f9dfdSAndroid Build Coastguard Worker event = b["events"].event(data) 161*387f9dfdSAndroid Build Coastguard Worker 162*387f9dfdSAndroid Build Coastguard Worker if (args.failed and (event.ret >= 0)): 163*387f9dfdSAndroid Build Coastguard Worker return 164*387f9dfdSAndroid Build Coastguard Worker 165*387f9dfdSAndroid Build Coastguard Worker printb(b"%-9s %-*d %-16s %-4d %-*d %d" % (strftime("%H:%M:%S").encode('ascii'), 166*387f9dfdSAndroid Build Coastguard Worker pid_bytes, event.pid, event.comm, event.sig, pid_bytes, event.tpid, event.ret)) 167*387f9dfdSAndroid Build Coastguard Worker 168*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event 169*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event) 170*387f9dfdSAndroid Build Coastguard Workerwhile 1: 171*387f9dfdSAndroid Build Coastguard Worker try: 172*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 173*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 174*387f9dfdSAndroid Build Coastguard Worker exit() 175