1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# sslsniff Captures data on read/recv or write/send functions of OpenSSL, 4*387f9dfdSAndroid Build Coastguard Worker# GnuTLS and NSS 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: sslsniff.py [-h] [-p PID] [-u UID] [-x] [-c COMM] [-o] [-g] [-n] [-d] 8*387f9dfdSAndroid Build Coastguard Worker# [--hexdump] [--max-buffer-size SIZE] [-l] [--handshake] 9*387f9dfdSAndroid Build Coastguard Worker# 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# 12-Aug-2016 Adrian Lopez Created this. 13*387f9dfdSAndroid Build Coastguard Worker# 13-Aug-2016 Mark Drayton Fix SSL_Read 14*387f9dfdSAndroid Build Coastguard Worker# 17-Aug-2016 Adrian Lopez Capture GnuTLS and add options 15*387f9dfdSAndroid Build Coastguard Worker# 16*387f9dfdSAndroid Build Coastguard Worker 17*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 18*387f9dfdSAndroid Build Coastguard Workerfrom bcc import BPF 19*387f9dfdSAndroid Build Coastguard Workerimport argparse 20*387f9dfdSAndroid Build Coastguard Workerimport binascii 21*387f9dfdSAndroid Build Coastguard Workerimport textwrap 22*387f9dfdSAndroid Build Coastguard Workerimport os.path 23*387f9dfdSAndroid Build Coastguard Worker 24*387f9dfdSAndroid Build Coastguard Worker# arguments 25*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 26*387f9dfdSAndroid Build Coastguard Worker ./sslsniff # sniff OpenSSL and GnuTLS functions 27*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -p 181 # sniff PID 181 only 28*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -u 1000 # sniff only UID 1000 29*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -c curl # sniff curl command only 30*387f9dfdSAndroid Build Coastguard Worker ./sslsniff --no-openssl # don't show OpenSSL calls 31*387f9dfdSAndroid Build Coastguard Worker ./sslsniff --no-gnutls # don't show GnuTLS calls 32*387f9dfdSAndroid Build Coastguard Worker ./sslsniff --no-nss # don't show NSS calls 33*387f9dfdSAndroid Build Coastguard Worker ./sslsniff --hexdump # show data as hex instead of trying to decode it as UTF-8 34*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -x # show process UID and TID 35*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -l # show function latency 36*387f9dfdSAndroid Build Coastguard Worker ./sslsniff -l --handshake # show SSL handshake latency 37*387f9dfdSAndroid Build Coastguard Worker ./sslsniff --extra-lib openssl:/path/libssl.so.1.1 # sniff extra library 38*387f9dfdSAndroid Build Coastguard Worker""" 39*387f9dfdSAndroid Build Coastguard Worker 40*387f9dfdSAndroid Build Coastguard Worker 41*387f9dfdSAndroid Build Coastguard Workerdef ssllib_type(input_str): 42*387f9dfdSAndroid Build Coastguard Worker valid_types = frozenset(['openssl', 'gnutls', 'nss']) 43*387f9dfdSAndroid Build Coastguard Worker 44*387f9dfdSAndroid Build Coastguard Worker try: 45*387f9dfdSAndroid Build Coastguard Worker lib_type, lib_path = input_str.split(':', 1) 46*387f9dfdSAndroid Build Coastguard Worker except ValueError: 47*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("Invalid SSL library param: %r" % input_str) 48*387f9dfdSAndroid Build Coastguard Worker 49*387f9dfdSAndroid Build Coastguard Worker if lib_type not in valid_types: 50*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("Invalid SSL library type: %r" % lib_type) 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker if not os.path.isfile(lib_path): 53*387f9dfdSAndroid Build Coastguard Worker raise argparse.ArgumentTypeError("Invalid library path: %r" % lib_path) 54*387f9dfdSAndroid Build Coastguard Worker 55*387f9dfdSAndroid Build Coastguard Worker return lib_type, lib_path 56*387f9dfdSAndroid Build Coastguard Worker 57*387f9dfdSAndroid Build Coastguard Worker 58*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 59*387f9dfdSAndroid Build Coastguard Worker description="Sniff SSL data", 60*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 61*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 62*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", type=int, help="sniff this PID only.") 63*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-u", "--uid", type=int, default=None, 64*387f9dfdSAndroid Build Coastguard Worker help="sniff this UID only.") 65*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--extra", action="store_true", 66*387f9dfdSAndroid Build Coastguard Worker help="show extra fields (UID, TID)") 67*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-c", "--comm", 68*387f9dfdSAndroid Build Coastguard Worker help="sniff only commands matching string.") 69*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-o", "--no-openssl", action="store_false", dest="openssl", 70*387f9dfdSAndroid Build Coastguard Worker help="do not show OpenSSL calls.") 71*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-g", "--no-gnutls", action="store_false", dest="gnutls", 72*387f9dfdSAndroid Build Coastguard Worker help="do not show GnuTLS calls.") 73*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-n", "--no-nss", action="store_false", dest="nss", 74*387f9dfdSAndroid Build Coastguard Worker help="do not show NSS calls.") 75*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('-d', '--debug', dest='debug', action='count', default=0, 76*387f9dfdSAndroid Build Coastguard Worker help='debug mode.') 77*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 78*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 79*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--hexdump", action="store_true", dest="hexdump", 80*387f9dfdSAndroid Build Coastguard Worker help="show data as hexdump instead of trying to decode it as UTF-8") 81*387f9dfdSAndroid Build Coastguard Workerparser.add_argument('--max-buffer-size', type=int, default=8192, 82*387f9dfdSAndroid Build Coastguard Worker help='Size of captured buffer') 83*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-l", "--latency", action="store_true", 84*387f9dfdSAndroid Build Coastguard Worker help="show function latency") 85*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--handshake", action="store_true", 86*387f9dfdSAndroid Build Coastguard Worker help="show SSL handshake latency, enabled only if latency option is on.") 87*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--extra-lib", type=ssllib_type, action='append', 88*387f9dfdSAndroid Build Coastguard Worker help="Intercept calls from extra library (format: lib_type:lib_path)") 89*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 90*387f9dfdSAndroid Build Coastguard Worker 91*387f9dfdSAndroid Build Coastguard Worker 92*387f9dfdSAndroid Build Coastguard Workerprog = """ 93*387f9dfdSAndroid Build Coastguard Worker#include <linux/ptrace.h> 94*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> /* For TASK_COMM_LEN */ 95*387f9dfdSAndroid Build Coastguard Worker 96*387f9dfdSAndroid Build Coastguard Worker#define MAX_BUF_SIZE __MAX_BUF_SIZE__ 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Workerstruct probe_SSL_data_t { 99*387f9dfdSAndroid Build Coastguard Worker u64 timestamp_ns; 100*387f9dfdSAndroid Build Coastguard Worker u64 delta_ns; 101*387f9dfdSAndroid Build Coastguard Worker u32 pid; 102*387f9dfdSAndroid Build Coastguard Worker u32 tid; 103*387f9dfdSAndroid Build Coastguard Worker u32 uid; 104*387f9dfdSAndroid Build Coastguard Worker u32 len; 105*387f9dfdSAndroid Build Coastguard Worker int buf_filled; 106*387f9dfdSAndroid Build Coastguard Worker int rw; 107*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 108*387f9dfdSAndroid Build Coastguard Worker u8 buf[MAX_BUF_SIZE]; 109*387f9dfdSAndroid Build Coastguard Worker}; 110*387f9dfdSAndroid Build Coastguard Worker 111*387f9dfdSAndroid Build Coastguard Worker#define BASE_EVENT_SIZE ((size_t)(&((struct probe_SSL_data_t*)0)->buf)) 112*387f9dfdSAndroid Build Coastguard Worker#define EVENT_SIZE(X) (BASE_EVENT_SIZE + ((size_t)(X))) 113*387f9dfdSAndroid Build Coastguard Worker 114*387f9dfdSAndroid Build Coastguard WorkerBPF_PERCPU_ARRAY(ssl_data, struct probe_SSL_data_t, 1); 115*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(perf_SSL_rw); 116*387f9dfdSAndroid Build Coastguard Worker 117*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(start_ns, u32); 118*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(bufs, u32, u64); 119*387f9dfdSAndroid Build Coastguard Worker 120*387f9dfdSAndroid Build Coastguard Workerint probe_SSL_rw_enter(struct pt_regs *ctx, void *ssl, void *buf, int num) { 121*387f9dfdSAndroid Build Coastguard Worker int ret; 122*387f9dfdSAndroid Build Coastguard Worker u32 zero = 0; 123*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 124*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 125*387f9dfdSAndroid Build Coastguard Worker u32 tid = pid_tgid; 126*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 127*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 128*387f9dfdSAndroid Build Coastguard Worker 129*387f9dfdSAndroid Build Coastguard Worker PID_FILTER 130*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 131*387f9dfdSAndroid Build Coastguard Worker 132*387f9dfdSAndroid Build Coastguard Worker bufs.update(&tid, (u64*)&buf); 133*387f9dfdSAndroid Build Coastguard Worker start_ns.update(&tid, &ts); 134*387f9dfdSAndroid Build Coastguard Worker return 0; 135*387f9dfdSAndroid Build Coastguard Worker} 136*387f9dfdSAndroid Build Coastguard Worker 137*387f9dfdSAndroid Build Coastguard Workerstatic int SSL_exit(struct pt_regs *ctx, int rw) { 138*387f9dfdSAndroid Build Coastguard Worker int ret; 139*387f9dfdSAndroid Build Coastguard Worker u32 zero = 0; 140*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 141*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 142*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 143*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 144*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 145*387f9dfdSAndroid Build Coastguard Worker 146*387f9dfdSAndroid Build Coastguard Worker PID_FILTER 147*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 148*387f9dfdSAndroid Build Coastguard Worker 149*387f9dfdSAndroid Build Coastguard Worker u64 *bufp = bufs.lookup(&tid); 150*387f9dfdSAndroid Build Coastguard Worker if (bufp == 0) 151*387f9dfdSAndroid Build Coastguard Worker return 0; 152*387f9dfdSAndroid Build Coastguard Worker 153*387f9dfdSAndroid Build Coastguard Worker u64 *tsp = start_ns.lookup(&tid); 154*387f9dfdSAndroid Build Coastguard Worker if (tsp == 0) 155*387f9dfdSAndroid Build Coastguard Worker return 0; 156*387f9dfdSAndroid Build Coastguard Worker 157*387f9dfdSAndroid Build Coastguard Worker int len = PT_REGS_RC(ctx); 158*387f9dfdSAndroid Build Coastguard Worker if (len <= 0) // no data 159*387f9dfdSAndroid Build Coastguard Worker return 0; 160*387f9dfdSAndroid Build Coastguard Worker 161*387f9dfdSAndroid Build Coastguard Worker struct probe_SSL_data_t *data = ssl_data.lookup(&zero); 162*387f9dfdSAndroid Build Coastguard Worker if (!data) 163*387f9dfdSAndroid Build Coastguard Worker return 0; 164*387f9dfdSAndroid Build Coastguard Worker 165*387f9dfdSAndroid Build Coastguard Worker data->timestamp_ns = ts; 166*387f9dfdSAndroid Build Coastguard Worker data->delta_ns = ts - *tsp; 167*387f9dfdSAndroid Build Coastguard Worker data->pid = pid; 168*387f9dfdSAndroid Build Coastguard Worker data->tid = tid; 169*387f9dfdSAndroid Build Coastguard Worker data->uid = uid; 170*387f9dfdSAndroid Build Coastguard Worker data->len = (u32)len; 171*387f9dfdSAndroid Build Coastguard Worker data->buf_filled = 0; 172*387f9dfdSAndroid Build Coastguard Worker data->rw = rw; 173*387f9dfdSAndroid Build Coastguard Worker u32 buf_copy_size = min((size_t)MAX_BUF_SIZE, (size_t)len); 174*387f9dfdSAndroid Build Coastguard Worker 175*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data->comm, sizeof(data->comm)); 176*387f9dfdSAndroid Build Coastguard Worker 177*387f9dfdSAndroid Build Coastguard Worker if (bufp != 0) 178*387f9dfdSAndroid Build Coastguard Worker ret = bpf_probe_read_user(&data->buf, buf_copy_size, (char *)*bufp); 179*387f9dfdSAndroid Build Coastguard Worker 180*387f9dfdSAndroid Build Coastguard Worker bufs.delete(&tid); 181*387f9dfdSAndroid Build Coastguard Worker start_ns.delete(&tid); 182*387f9dfdSAndroid Build Coastguard Worker 183*387f9dfdSAndroid Build Coastguard Worker if (!ret) 184*387f9dfdSAndroid Build Coastguard Worker data->buf_filled = 1; 185*387f9dfdSAndroid Build Coastguard Worker else 186*387f9dfdSAndroid Build Coastguard Worker buf_copy_size = 0; 187*387f9dfdSAndroid Build Coastguard Worker 188*387f9dfdSAndroid Build Coastguard Worker perf_SSL_rw.perf_submit(ctx, data, EVENT_SIZE(buf_copy_size)); 189*387f9dfdSAndroid Build Coastguard Worker return 0; 190*387f9dfdSAndroid Build Coastguard Worker} 191*387f9dfdSAndroid Build Coastguard Worker 192*387f9dfdSAndroid Build Coastguard Workerint probe_SSL_read_exit(struct pt_regs *ctx) { 193*387f9dfdSAndroid Build Coastguard Worker return (SSL_exit(ctx, 0)); 194*387f9dfdSAndroid Build Coastguard Worker} 195*387f9dfdSAndroid Build Coastguard Worker 196*387f9dfdSAndroid Build Coastguard Workerint probe_SSL_write_exit(struct pt_regs *ctx) { 197*387f9dfdSAndroid Build Coastguard Worker return (SSL_exit(ctx, 1)); 198*387f9dfdSAndroid Build Coastguard Worker} 199*387f9dfdSAndroid Build Coastguard Worker 200*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(perf_SSL_do_handshake); 201*387f9dfdSAndroid Build Coastguard Worker 202*387f9dfdSAndroid Build Coastguard Workerint probe_SSL_do_handshake_enter(struct pt_regs *ctx, void *ssl) { 203*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 204*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 205*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 206*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 207*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 208*387f9dfdSAndroid Build Coastguard Worker 209*387f9dfdSAndroid Build Coastguard Worker PID_FILTER 210*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 211*387f9dfdSAndroid Build Coastguard Worker 212*387f9dfdSAndroid Build Coastguard Worker start_ns.update(&tid, &ts); 213*387f9dfdSAndroid Build Coastguard Worker return 0; 214*387f9dfdSAndroid Build Coastguard Worker} 215*387f9dfdSAndroid Build Coastguard Worker 216*387f9dfdSAndroid Build Coastguard Workerint probe_SSL_do_handshake_exit(struct pt_regs *ctx) { 217*387f9dfdSAndroid Build Coastguard Worker u32 zero = 0; 218*387f9dfdSAndroid Build Coastguard Worker u64 pid_tgid = bpf_get_current_pid_tgid(); 219*387f9dfdSAndroid Build Coastguard Worker u32 pid = pid_tgid >> 32; 220*387f9dfdSAndroid Build Coastguard Worker u32 tid = (u32)pid_tgid; 221*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 222*387f9dfdSAndroid Build Coastguard Worker u64 ts = bpf_ktime_get_ns(); 223*387f9dfdSAndroid Build Coastguard Worker int ret; 224*387f9dfdSAndroid Build Coastguard Worker 225*387f9dfdSAndroid Build Coastguard Worker PID_FILTER 226*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 227*387f9dfdSAndroid Build Coastguard Worker 228*387f9dfdSAndroid Build Coastguard Worker u64 *tsp = start_ns.lookup(&tid); 229*387f9dfdSAndroid Build Coastguard Worker if (tsp == 0) 230*387f9dfdSAndroid Build Coastguard Worker return 0; 231*387f9dfdSAndroid Build Coastguard Worker 232*387f9dfdSAndroid Build Coastguard Worker ret = PT_REGS_RC(ctx); 233*387f9dfdSAndroid Build Coastguard Worker if (ret <= 0) // handshake failed 234*387f9dfdSAndroid Build Coastguard Worker return 0; 235*387f9dfdSAndroid Build Coastguard Worker 236*387f9dfdSAndroid Build Coastguard Worker struct probe_SSL_data_t *data = ssl_data.lookup(&zero); 237*387f9dfdSAndroid Build Coastguard Worker if (!data) 238*387f9dfdSAndroid Build Coastguard Worker return 0; 239*387f9dfdSAndroid Build Coastguard Worker 240*387f9dfdSAndroid Build Coastguard Worker data->timestamp_ns = ts; 241*387f9dfdSAndroid Build Coastguard Worker data->delta_ns = ts - *tsp; 242*387f9dfdSAndroid Build Coastguard Worker data->pid = pid; 243*387f9dfdSAndroid Build Coastguard Worker data->tid = tid; 244*387f9dfdSAndroid Build Coastguard Worker data->uid = uid; 245*387f9dfdSAndroid Build Coastguard Worker data->len = ret; 246*387f9dfdSAndroid Build Coastguard Worker data->buf_filled = 0; 247*387f9dfdSAndroid Build Coastguard Worker data->rw = 2; 248*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data->comm, sizeof(data->comm)); 249*387f9dfdSAndroid Build Coastguard Worker start_ns.delete(&tid); 250*387f9dfdSAndroid Build Coastguard Worker 251*387f9dfdSAndroid Build Coastguard Worker perf_SSL_do_handshake.perf_submit(ctx, data, EVENT_SIZE(0)); 252*387f9dfdSAndroid Build Coastguard Worker return 0; 253*387f9dfdSAndroid Build Coastguard Worker} 254*387f9dfdSAndroid Build Coastguard Worker""" 255*387f9dfdSAndroid Build Coastguard Worker 256*387f9dfdSAndroid Build Coastguard Workerif args.pid: 257*387f9dfdSAndroid Build Coastguard Worker prog = prog.replace('PID_FILTER', 'if (pid != %d) { return 0; }' % args.pid) 258*387f9dfdSAndroid Build Coastguard Workerelse: 259*387f9dfdSAndroid Build Coastguard Worker prog = prog.replace('PID_FILTER', '') 260*387f9dfdSAndroid Build Coastguard Worker 261*387f9dfdSAndroid Build Coastguard Workerif args.uid is not None: 262*387f9dfdSAndroid Build Coastguard Worker prog = prog.replace('UID_FILTER', 'if (uid != %d) { return 0; }' % args.uid) 263*387f9dfdSAndroid Build Coastguard Workerelse: 264*387f9dfdSAndroid Build Coastguard Worker prog = prog.replace('UID_FILTER', '') 265*387f9dfdSAndroid Build Coastguard Worker 266*387f9dfdSAndroid Build Coastguard Workerprog = prog.replace('__MAX_BUF_SIZE__', str(args.max_buffer_size)) 267*387f9dfdSAndroid Build Coastguard Worker 268*387f9dfdSAndroid Build Coastguard Workerif args.debug or args.ebpf: 269*387f9dfdSAndroid Build Coastguard Worker print(prog) 270*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 271*387f9dfdSAndroid Build Coastguard Worker exit() 272*387f9dfdSAndroid Build Coastguard Worker 273*387f9dfdSAndroid Build Coastguard Worker 274*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=prog) 275*387f9dfdSAndroid Build Coastguard Worker 276*387f9dfdSAndroid Build Coastguard Worker# It looks like SSL_read's arguments aren't available in a return probe so you 277*387f9dfdSAndroid Build Coastguard Worker# need to stash the buffer address in a map on the function entry and read it 278*387f9dfdSAndroid Build Coastguard Worker# on its exit (Mark Drayton) 279*387f9dfdSAndroid Build Coastguard Worker# 280*387f9dfdSAndroid Build Coastguard Workerdef attach_openssl(lib): 281*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="SSL_write", 282*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 283*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="SSL_write", 284*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_write_exit", pid=args.pid or -1) 285*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="SSL_read", 286*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 287*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="SSL_read", 288*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_read_exit", pid=args.pid or -1) 289*387f9dfdSAndroid Build Coastguard Worker if args.latency and args.handshake: 290*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name="ssl", sym="SSL_do_handshake", 291*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_do_handshake_enter", pid=args.pid or -1) 292*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name="ssl", sym="SSL_do_handshake", 293*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_do_handshake_exit", pid=args.pid or -1) 294*387f9dfdSAndroid Build Coastguard Worker 295*387f9dfdSAndroid Build Coastguard Workerdef attach_gnutls(lib): 296*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="gnutls_record_send", 297*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 298*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="gnutls_record_send", 299*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_write_exit", pid=args.pid or -1) 300*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="gnutls_record_recv", 301*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 302*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="gnutls_record_recv", 303*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_read_exit", pid=args.pid or -1) 304*387f9dfdSAndroid Build Coastguard Worker 305*387f9dfdSAndroid Build Coastguard Workerdef attach_nss(lib): 306*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="PR_Write", 307*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 308*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="PR_Write", 309*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_write_exit", pid=args.pid or -1) 310*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="PR_Send", 311*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 312*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="PR_Send", 313*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_write_exit", pid=args.pid or -1) 314*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="PR_Read", 315*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 316*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="PR_Read", 317*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_read_exit", pid=args.pid or -1) 318*387f9dfdSAndroid Build Coastguard Worker b.attach_uprobe(name=lib, sym="PR_Recv", 319*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_rw_enter", pid=args.pid or -1) 320*387f9dfdSAndroid Build Coastguard Worker b.attach_uretprobe(name=lib, sym="PR_Recv", 321*387f9dfdSAndroid Build Coastguard Worker fn_name="probe_SSL_read_exit", pid=args.pid or -1) 322*387f9dfdSAndroid Build Coastguard Worker 323*387f9dfdSAndroid Build Coastguard Worker 324*387f9dfdSAndroid Build Coastguard WorkerLIB_TRACERS = { 325*387f9dfdSAndroid Build Coastguard Worker "openssl": attach_openssl, 326*387f9dfdSAndroid Build Coastguard Worker "gnutls": attach_gnutls, 327*387f9dfdSAndroid Build Coastguard Worker "nss": attach_nss, 328*387f9dfdSAndroid Build Coastguard Worker} 329*387f9dfdSAndroid Build Coastguard Worker 330*387f9dfdSAndroid Build Coastguard Worker 331*387f9dfdSAndroid Build Coastguard Workerif args.openssl: 332*387f9dfdSAndroid Build Coastguard Worker attach_openssl("ssl") 333*387f9dfdSAndroid Build Coastguard Workerif args.gnutls: 334*387f9dfdSAndroid Build Coastguard Worker attach_gnutls("gnutls") 335*387f9dfdSAndroid Build Coastguard Workerif args.nss: 336*387f9dfdSAndroid Build Coastguard Worker attach_nss("nspr4") 337*387f9dfdSAndroid Build Coastguard Worker 338*387f9dfdSAndroid Build Coastguard Worker 339*387f9dfdSAndroid Build Coastguard Workerif args.extra_lib: 340*387f9dfdSAndroid Build Coastguard Worker for lib_type, lib_path in args.extra_lib: 341*387f9dfdSAndroid Build Coastguard Worker LIB_TRACERS[lib_type](lib_path) 342*387f9dfdSAndroid Build Coastguard Worker 343*387f9dfdSAndroid Build Coastguard Worker# define output data structure in Python 344*387f9dfdSAndroid Build Coastguard Worker 345*387f9dfdSAndroid Build Coastguard Worker 346*387f9dfdSAndroid Build Coastguard Worker# header 347*387f9dfdSAndroid Build Coastguard Workerheader = "%-12s %-18s %-16s %-7s %-7s" % ("FUNC", "TIME(s)", "COMM", "PID", "LEN") 348*387f9dfdSAndroid Build Coastguard Worker 349*387f9dfdSAndroid Build Coastguard Workerif args.extra: 350*387f9dfdSAndroid Build Coastguard Worker header += " %-7s %-7s" % ("UID", "TID") 351*387f9dfdSAndroid Build Coastguard Worker 352*387f9dfdSAndroid Build Coastguard Workerif args.latency: 353*387f9dfdSAndroid Build Coastguard Worker header += " %-7s" % ("LAT(ms)") 354*387f9dfdSAndroid Build Coastguard Worker 355*387f9dfdSAndroid Build Coastguard Workerprint(header) 356*387f9dfdSAndroid Build Coastguard Worker# process event 357*387f9dfdSAndroid Build Coastguard Workerstart = 0 358*387f9dfdSAndroid Build Coastguard Worker 359*387f9dfdSAndroid Build Coastguard Workerdef print_event_rw(cpu, data, size): 360*387f9dfdSAndroid Build Coastguard Worker print_event(cpu, data, size, "perf_SSL_rw") 361*387f9dfdSAndroid Build Coastguard Worker 362*387f9dfdSAndroid Build Coastguard Workerdef print_event_handshake(cpu, data, size): 363*387f9dfdSAndroid Build Coastguard Worker print_event(cpu, data, size, "perf_SSL_do_handshake") 364*387f9dfdSAndroid Build Coastguard Worker 365*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size, evt): 366*387f9dfdSAndroid Build Coastguard Worker global start 367*387f9dfdSAndroid Build Coastguard Worker event = b[evt].event(data) 368*387f9dfdSAndroid Build Coastguard Worker if event.len <= args.max_buffer_size: 369*387f9dfdSAndroid Build Coastguard Worker buf_size = event.len 370*387f9dfdSAndroid Build Coastguard Worker else: 371*387f9dfdSAndroid Build Coastguard Worker buf_size = args.max_buffer_size 372*387f9dfdSAndroid Build Coastguard Worker 373*387f9dfdSAndroid Build Coastguard Worker if event.buf_filled == 1: 374*387f9dfdSAndroid Build Coastguard Worker buf = bytearray(event.buf[:buf_size]) 375*387f9dfdSAndroid Build Coastguard Worker else: 376*387f9dfdSAndroid Build Coastguard Worker buf_size = 0 377*387f9dfdSAndroid Build Coastguard Worker buf = b"" 378*387f9dfdSAndroid Build Coastguard Worker 379*387f9dfdSAndroid Build Coastguard Worker # Filter events by command 380*387f9dfdSAndroid Build Coastguard Worker if args.comm: 381*387f9dfdSAndroid Build Coastguard Worker if not args.comm == event.comm.decode('utf-8', 'replace'): 382*387f9dfdSAndroid Build Coastguard Worker return 383*387f9dfdSAndroid Build Coastguard Worker 384*387f9dfdSAndroid Build Coastguard Worker if start == 0: 385*387f9dfdSAndroid Build Coastguard Worker start = event.timestamp_ns 386*387f9dfdSAndroid Build Coastguard Worker time_s = (float(event.timestamp_ns - start)) / 1000000000 387*387f9dfdSAndroid Build Coastguard Worker 388*387f9dfdSAndroid Build Coastguard Worker lat_str = "%.3f" % (event.delta_ns / 1000000) if event.delta_ns else "N/A" 389*387f9dfdSAndroid Build Coastguard Worker 390*387f9dfdSAndroid Build Coastguard Worker s_mark = "-" * 5 + " DATA " + "-" * 5 391*387f9dfdSAndroid Build Coastguard Worker 392*387f9dfdSAndroid Build Coastguard Worker e_mark = "-" * 5 + " END DATA " + "-" * 5 393*387f9dfdSAndroid Build Coastguard Worker 394*387f9dfdSAndroid Build Coastguard Worker truncated_bytes = event.len - buf_size 395*387f9dfdSAndroid Build Coastguard Worker if truncated_bytes > 0: 396*387f9dfdSAndroid Build Coastguard Worker e_mark = "-" * 5 + " END DATA (TRUNCATED, " + str(truncated_bytes) + \ 397*387f9dfdSAndroid Build Coastguard Worker " bytes lost) " + "-" * 5 398*387f9dfdSAndroid Build Coastguard Worker 399*387f9dfdSAndroid Build Coastguard Worker base_fmt = "%(func)-12s %(time)-18.9f %(comm)-16s %(pid)-7d %(len)-6d" 400*387f9dfdSAndroid Build Coastguard Worker 401*387f9dfdSAndroid Build Coastguard Worker if args.extra: 402*387f9dfdSAndroid Build Coastguard Worker base_fmt += " %(uid)-7d %(tid)-7d" 403*387f9dfdSAndroid Build Coastguard Worker 404*387f9dfdSAndroid Build Coastguard Worker if args.latency: 405*387f9dfdSAndroid Build Coastguard Worker base_fmt += " %(lat)-7s" 406*387f9dfdSAndroid Build Coastguard Worker 407*387f9dfdSAndroid Build Coastguard Worker fmt = ''.join([base_fmt, "\n%(begin)s\n%(data)s\n%(end)s\n\n"]) 408*387f9dfdSAndroid Build Coastguard Worker if args.hexdump: 409*387f9dfdSAndroid Build Coastguard Worker unwrapped_data = binascii.hexlify(buf) 410*387f9dfdSAndroid Build Coastguard Worker data = textwrap.fill(unwrapped_data.decode('utf-8', 'replace'), width=32) 411*387f9dfdSAndroid Build Coastguard Worker else: 412*387f9dfdSAndroid Build Coastguard Worker data = buf.decode('utf-8', 'replace') 413*387f9dfdSAndroid Build Coastguard Worker 414*387f9dfdSAndroid Build Coastguard Worker rw_event = { 415*387f9dfdSAndroid Build Coastguard Worker 0: "READ/RECV", 416*387f9dfdSAndroid Build Coastguard Worker 1: "WRITE/SEND", 417*387f9dfdSAndroid Build Coastguard Worker 2: "HANDSHAKE" 418*387f9dfdSAndroid Build Coastguard Worker } 419*387f9dfdSAndroid Build Coastguard Worker 420*387f9dfdSAndroid Build Coastguard Worker fmt_data = { 421*387f9dfdSAndroid Build Coastguard Worker 'func': rw_event[event.rw], 422*387f9dfdSAndroid Build Coastguard Worker 'time': time_s, 423*387f9dfdSAndroid Build Coastguard Worker 'lat': lat_str, 424*387f9dfdSAndroid Build Coastguard Worker 'comm': event.comm.decode('utf-8', 'replace'), 425*387f9dfdSAndroid Build Coastguard Worker 'pid': event.pid, 426*387f9dfdSAndroid Build Coastguard Worker 'tid': event.tid, 427*387f9dfdSAndroid Build Coastguard Worker 'uid': event.uid, 428*387f9dfdSAndroid Build Coastguard Worker 'len': event.len, 429*387f9dfdSAndroid Build Coastguard Worker 'begin': s_mark, 430*387f9dfdSAndroid Build Coastguard Worker 'end': e_mark, 431*387f9dfdSAndroid Build Coastguard Worker 'data': data 432*387f9dfdSAndroid Build Coastguard Worker } 433*387f9dfdSAndroid Build Coastguard Worker 434*387f9dfdSAndroid Build Coastguard Worker # use base_fmt if no buf filled 435*387f9dfdSAndroid Build Coastguard Worker if buf_size == 0: 436*387f9dfdSAndroid Build Coastguard Worker print(base_fmt % fmt_data) 437*387f9dfdSAndroid Build Coastguard Worker else: 438*387f9dfdSAndroid Build Coastguard Worker print(fmt % fmt_data) 439*387f9dfdSAndroid Build Coastguard Worker 440*387f9dfdSAndroid Build Coastguard Workerb["perf_SSL_rw"].open_perf_buffer(print_event_rw) 441*387f9dfdSAndroid Build Coastguard Workerb["perf_SSL_do_handshake"].open_perf_buffer(print_event_handshake) 442*387f9dfdSAndroid Build Coastguard Workerwhile 1: 443*387f9dfdSAndroid Build Coastguard Worker try: 444*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 445*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 446*387f9dfdSAndroid Build Coastguard Worker exit() 447