1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/python 2*387f9dfdSAndroid Build Coastguard Worker# @lint-avoid-python-3-compatibility-imports 3*387f9dfdSAndroid Build Coastguard Worker# 4*387f9dfdSAndroid Build Coastguard Worker# undump Dump UNIX socket packets. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# USAGE: undump [-h] [-t] [-p PID] 7*387f9dfdSAndroid Build Coastguard Worker# 8*387f9dfdSAndroid Build Coastguard Worker# This uses dynamic tracing of kernel functions, and will need to be updated 9*387f9dfdSAndroid Build Coastguard Worker# to match kernel changes. 10*387f9dfdSAndroid Build Coastguard Worker# 11*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2021 Rong Tao. 12*387f9dfdSAndroid Build Coastguard Worker# Licensed under the GPL License, Version 2.0 13*387f9dfdSAndroid Build Coastguard Worker# 14*387f9dfdSAndroid Build Coastguard Worker# 27-Aug-2021 Rong Tao Created this. 15*387f9dfdSAndroid Build Coastguard Worker# 17-Sep-2021 Rong Tao Simplify according to chenhengqi's suggestion 16*387f9dfdSAndroid Build Coastguard Worker# https://github.com/iovisor/bcc/pull/3615 17*387f9dfdSAndroid Build Coastguard Worker# 18*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 19*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 20*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers 21*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import printb 22*387f9dfdSAndroid Build Coastguard Workerimport argparse 23*387f9dfdSAndroid Build Coastguard Workerfrom socket import inet_ntop, ntohs, AF_INET, AF_INET6 24*387f9dfdSAndroid Build Coastguard Workerfrom struct import pack 25*387f9dfdSAndroid Build Coastguard Workerfrom time import sleep 26*387f9dfdSAndroid Build Coastguard Workerfrom datetime import datetime 27*387f9dfdSAndroid Build Coastguard Workerimport sys 28*387f9dfdSAndroid Build Coastguard Worker 29*387f9dfdSAndroid Build Coastguard Worker# arguments 30*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 31*387f9dfdSAndroid Build Coastguard Worker ./undump # trace/dump all UNIX packets 32*387f9dfdSAndroid Build Coastguard Worker ./undump -p 181 # only trace/dump PID 181 33*387f9dfdSAndroid Build Coastguard Worker""" 34*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 35*387f9dfdSAndroid Build Coastguard Worker description="Dump UNIX socket packets", 36*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 37*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 38*387f9dfdSAndroid Build Coastguard Worker 39*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 40*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 41*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 42*387f9dfdSAndroid Build Coastguard Worker 43*387f9dfdSAndroid Build Coastguard Worker# define BPF program 44*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 45*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 46*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 47*387f9dfdSAndroid Build Coastguard Worker#include <bcc/proto.h> 48*387f9dfdSAndroid Build Coastguard Worker#include <linux/aio.h> 49*387f9dfdSAndroid Build Coastguard Worker#include <linux/socket.h> 50*387f9dfdSAndroid Build Coastguard Worker#include <linux/net.h> 51*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs.h> 52*387f9dfdSAndroid Build Coastguard Worker#include <linux/mount.h> 53*387f9dfdSAndroid Build Coastguard Worker#include <linux/module.h> 54*387f9dfdSAndroid Build Coastguard Worker#include <net/sock.h> 55*387f9dfdSAndroid Build Coastguard Worker#include <net/af_unix.h> 56*387f9dfdSAndroid Build Coastguard Worker 57*387f9dfdSAndroid Build Coastguard Worker#define MAX_PKT 512 58*387f9dfdSAndroid Build Coastguard Workerstruct recv_data_t { 59*387f9dfdSAndroid Build Coastguard Worker u32 recv_len; 60*387f9dfdSAndroid Build Coastguard Worker u8 pkt[MAX_PKT]; 61*387f9dfdSAndroid Build Coastguard Worker}; 62*387f9dfdSAndroid Build Coastguard Worker 63*387f9dfdSAndroid Build Coastguard Worker// single element per-cpu array to hold the current event off the stack 64*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(unix_data, struct recv_data_t, 1); 65*387f9dfdSAndroid Build Coastguard Worker 66*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(unix_recv_events); 67*387f9dfdSAndroid Build Coastguard Worker 68*387f9dfdSAndroid Build Coastguard Workerint trace_unix_stream_read_actor(struct pt_regs *ctx) 69*387f9dfdSAndroid Build Coastguard Worker{ 70*387f9dfdSAndroid Build Coastguard Worker u32 zero = 0; 71*387f9dfdSAndroid Build Coastguard Worker int ret = PT_REGS_RC(ctx); 72*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 73*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 74*387f9dfdSAndroid Build Coastguard Worker u32 tid = pid_tgid; 75*387f9dfdSAndroid Build Coastguard Worker 76*387f9dfdSAndroid Build Coastguard Worker FILTER_PID 77*387f9dfdSAndroid Build Coastguard Worker 78*387f9dfdSAndroid Build Coastguard Worker struct sk_buff *skb = (struct sk_buff *)PT_REGS_PARM1(ctx); 79*387f9dfdSAndroid Build Coastguard Worker 80*387f9dfdSAndroid Build Coastguard Worker struct recv_data_t *data = unix_data.lookup(&zero); 81*387f9dfdSAndroid Build Coastguard Worker if (!data) 82*387f9dfdSAndroid Build Coastguard Worker return 0; 83*387f9dfdSAndroid Build Coastguard Worker 84*387f9dfdSAndroid Build Coastguard Worker unsigned int data_len = skb->len; 85*387f9dfdSAndroid Build Coastguard Worker if(data_len > MAX_PKT) 86*387f9dfdSAndroid Build Coastguard Worker return 0; 87*387f9dfdSAndroid Build Coastguard Worker 88*387f9dfdSAndroid Build Coastguard Worker void *iodata = (void *)skb->data; 89*387f9dfdSAndroid Build Coastguard Worker data->recv_len = data_len; 90*387f9dfdSAndroid Build Coastguard Worker 91*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read(data->pkt, data_len, iodata); 92*387f9dfdSAndroid Build Coastguard Worker unix_recv_events.perf_submit(ctx, data, data_len+sizeof(u32)); 93*387f9dfdSAndroid Build Coastguard Worker 94*387f9dfdSAndroid Build Coastguard Worker return 0; 95*387f9dfdSAndroid Build Coastguard Worker} 96*387f9dfdSAndroid Build Coastguard Worker""" 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Workerif args.pid: 99*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FILTER_PID', 100*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 101*387f9dfdSAndroid Build Coastguard Worker 102*387f9dfdSAndroid Build Coastguard Workerbpf_text = bpf_text.replace('FILTER_PID', '') 103*387f9dfdSAndroid Build Coastguard Worker 104*387f9dfdSAndroid Build Coastguard Worker# process event 105*387f9dfdSAndroid Build Coastguard Workerdef print_recv_pkg(cpu, data, size): 106*387f9dfdSAndroid Build Coastguard Worker event = b["unix_recv_events"].event(data) 107*387f9dfdSAndroid Build Coastguard Worker if args.pid: 108*387f9dfdSAndroid Build Coastguard Worker print("PID \033[1;31m%s\033[m " % args.pid, end="") 109*387f9dfdSAndroid Build Coastguard Worker print("Recv \033[1;31m%d\033[m bytes" % event.recv_len) 110*387f9dfdSAndroid Build Coastguard Worker 111*387f9dfdSAndroid Build Coastguard Worker print(" ", end="") 112*387f9dfdSAndroid Build Coastguard Worker for i in range(0, event.recv_len): 113*387f9dfdSAndroid Build Coastguard Worker print("%02x " % event.pkt[i], end="") 114*387f9dfdSAndroid Build Coastguard Worker sys.stdout.flush() 115*387f9dfdSAndroid Build Coastguard Worker if (i+1)%16 == 0: 116*387f9dfdSAndroid Build Coastguard Worker print("") 117*387f9dfdSAndroid Build Coastguard Worker print(" ", end="") 118*387f9dfdSAndroid Build Coastguard Worker print("") 119*387f9dfdSAndroid Build Coastguard Worker 120*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 121*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 122*387f9dfdSAndroid Build Coastguard Workerb.attach_kprobe(event="unix_stream_read_actor", fn_name="trace_unix_stream_read_actor") 123*387f9dfdSAndroid Build Coastguard Worker 124*387f9dfdSAndroid Build Coastguard Workerif args.pid: 125*387f9dfdSAndroid Build Coastguard Worker print("Tracing \033[1;31mPID=%s\033[m UNIX socket packets ... Hit Ctrl-C to end" % args.pid) 126*387f9dfdSAndroid Build Coastguard Workerelse: 127*387f9dfdSAndroid Build Coastguard Worker print("Tracing UNIX socket packets ... Hit Ctrl-C to end") 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Workerstart_ts = 0 130*387f9dfdSAndroid Build Coastguard Worker 131*387f9dfdSAndroid Build Coastguard Worker# read events 132*387f9dfdSAndroid Build Coastguard Workerb["unix_recv_events"].open_perf_buffer(print_recv_pkg) 133*387f9dfdSAndroid Build Coastguard Worker 134*387f9dfdSAndroid Build Coastguard Workerwhile True: 135*387f9dfdSAndroid Build Coastguard Worker try: 136*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 137*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 138*387f9dfdSAndroid Build Coastguard Worker exit() 139