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# opensnoop Trace open() syscalls. 5*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 6*387f9dfdSAndroid Build Coastguard Worker# 7*387f9dfdSAndroid Build Coastguard Worker# USAGE: opensnoop [-h] [-T] [-U] [-x] [-p PID] [-t TID] 8*387f9dfdSAndroid Build Coastguard Worker# [--cgroupmap CGROUPMAP] [--mntnsmap MNTNSMAP] [-u UID] 9*387f9dfdSAndroid Build Coastguard Worker# [-d DURATION] [-n NAME] [-F] [-e] [-f FLAG_FILTER] 10*387f9dfdSAndroid Build Coastguard Worker# [-b BUFFER_PAGES] 11*387f9dfdSAndroid Build Coastguard Worker# 12*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2015 Brendan Gregg. 13*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 14*387f9dfdSAndroid Build Coastguard Worker# 15*387f9dfdSAndroid Build Coastguard Worker# 17-Sep-2015 Brendan Gregg Created this. 16*387f9dfdSAndroid Build Coastguard Worker# 29-Apr-2016 Allan McAleavy Updated for BPF_PERF_OUTPUT. 17*387f9dfdSAndroid Build Coastguard Worker# 08-Oct-2016 Dina Goldshtein Support filtering by PID and TID. 18*387f9dfdSAndroid Build Coastguard Worker# 28-Dec-2018 Tim Douglas Print flags argument, enable filtering 19*387f9dfdSAndroid Build Coastguard Worker# 06-Jan-2019 Takuma Kume Support filtering by UID 20*387f9dfdSAndroid Build Coastguard Worker# 21-Aug-2022 Rocky Xing Support showing full path for an open file. 21*387f9dfdSAndroid Build Coastguard Worker# 06-Sep-2022 Rocky Xing Support setting size of the perf ring buffer. 22*387f9dfdSAndroid Build Coastguard Worker 23*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 24*387f9dfdSAndroid Build Coastguard Workerfrom bcc import ArgString, BPF 25*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers 26*387f9dfdSAndroid Build Coastguard Workerfrom bcc.utils import printb 27*387f9dfdSAndroid Build Coastguard Workerimport argparse 28*387f9dfdSAndroid Build Coastguard Workerfrom collections import defaultdict 29*387f9dfdSAndroid Build Coastguard Workerfrom datetime import datetime, timedelta 30*387f9dfdSAndroid Build Coastguard Workerimport os 31*387f9dfdSAndroid Build Coastguard Worker 32*387f9dfdSAndroid Build Coastguard Worker# arguments 33*387f9dfdSAndroid Build Coastguard Workerexamples = """examples: 34*387f9dfdSAndroid Build Coastguard Worker ./opensnoop # trace all open() syscalls 35*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -T # include timestamps 36*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -U # include UID 37*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -x # only show failed opens 38*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -p 181 # only trace PID 181 39*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -t 123 # only trace TID 123 40*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -u 1000 # only trace UID 1000 41*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -d 10 # trace for 10 seconds only 42*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -n main # only print process names containing "main" 43*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -e # show extended fields 44*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -f O_WRONLY -f O_RDWR # only print calls for writing 45*387f9dfdSAndroid Build Coastguard Worker ./opensnoop -F # show full path for an open file with relative path 46*387f9dfdSAndroid Build Coastguard Worker ./opensnoop --cgroupmap mappath # only trace cgroups in this BPF map 47*387f9dfdSAndroid Build Coastguard Worker ./opensnoop --mntnsmap mappath # only trace mount namespaces in the map 48*387f9dfdSAndroid Build Coastguard Worker""" 49*387f9dfdSAndroid Build Coastguard Workerparser = argparse.ArgumentParser( 50*387f9dfdSAndroid Build Coastguard Worker description="Trace open() syscalls", 51*387f9dfdSAndroid Build Coastguard Worker formatter_class=argparse.RawDescriptionHelpFormatter, 52*387f9dfdSAndroid Build Coastguard Worker epilog=examples) 53*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-T", "--timestamp", action="store_true", 54*387f9dfdSAndroid Build Coastguard Worker help="include timestamp on output") 55*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-U", "--print-uid", action="store_true", 56*387f9dfdSAndroid Build Coastguard Worker help="print UID column") 57*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-x", "--failed", action="store_true", 58*387f9dfdSAndroid Build Coastguard Worker help="only show failed opens") 59*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-p", "--pid", 60*387f9dfdSAndroid Build Coastguard Worker help="trace this PID only") 61*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-t", "--tid", 62*387f9dfdSAndroid Build Coastguard Worker help="trace this TID only") 63*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--cgroupmap", 64*387f9dfdSAndroid Build Coastguard Worker help="trace cgroups in this BPF map only") 65*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--mntnsmap", 66*387f9dfdSAndroid Build Coastguard Worker help="trace mount namespaces in this BPF map only") 67*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-u", "--uid", 68*387f9dfdSAndroid Build Coastguard Worker help="trace this UID only") 69*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-d", "--duration", 70*387f9dfdSAndroid Build Coastguard Worker help="total duration of trace in seconds") 71*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-n", "--name", 72*387f9dfdSAndroid Build Coastguard Worker type=ArgString, 73*387f9dfdSAndroid Build Coastguard Worker help="only print process names containing this name") 74*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("--ebpf", action="store_true", 75*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 76*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-e", "--extended_fields", action="store_true", 77*387f9dfdSAndroid Build Coastguard Worker help="show extended fields") 78*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-f", "--flag_filter", action="append", 79*387f9dfdSAndroid Build Coastguard Worker help="filter on flags argument (e.g., O_WRONLY)") 80*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-F", "--full-path", action="store_true", 81*387f9dfdSAndroid Build Coastguard Worker help="show full path for an open file with relative path") 82*387f9dfdSAndroid Build Coastguard Workerparser.add_argument("-b", "--buffer-pages", type=int, default=64, 83*387f9dfdSAndroid Build Coastguard Worker help="size of the perf ring buffer " 84*387f9dfdSAndroid Build Coastguard Worker "(must be a power of two number of pages and defaults to 64)") 85*387f9dfdSAndroid Build Coastguard Workerargs = parser.parse_args() 86*387f9dfdSAndroid Build Coastguard Workerdebug = 0 87*387f9dfdSAndroid Build Coastguard Workerif args.duration: 88*387f9dfdSAndroid Build Coastguard Worker args.duration = timedelta(seconds=int(args.duration)) 89*387f9dfdSAndroid Build Coastguard Workerflag_filter_mask = 0 90*387f9dfdSAndroid Build Coastguard Workerfor flag in args.flag_filter or []: 91*387f9dfdSAndroid Build Coastguard Worker if not flag.startswith('O_'): 92*387f9dfdSAndroid Build Coastguard Worker exit("Bad flag: %s" % flag) 93*387f9dfdSAndroid Build Coastguard Worker try: 94*387f9dfdSAndroid Build Coastguard Worker flag_filter_mask |= getattr(os, flag) 95*387f9dfdSAndroid Build Coastguard Worker except AttributeError: 96*387f9dfdSAndroid Build Coastguard Worker exit("Bad flag: %s" % flag) 97*387f9dfdSAndroid Build Coastguard Worker 98*387f9dfdSAndroid Build Coastguard Worker# define BPF program 99*387f9dfdSAndroid Build Coastguard Workerbpf_text = """ 100*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 101*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/limits.h> 102*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 103*387f9dfdSAndroid Build Coastguard Worker#ifdef FULLPATH 104*387f9dfdSAndroid Build Coastguard Worker#include <linux/fs_struct.h> 105*387f9dfdSAndroid Build Coastguard Worker#include <linux/dcache.h> 106*387f9dfdSAndroid Build Coastguard Worker 107*387f9dfdSAndroid Build Coastguard Worker#define MAX_ENTRIES 32 108*387f9dfdSAndroid Build Coastguard Worker 109*387f9dfdSAndroid Build Coastguard Workerenum event_type { 110*387f9dfdSAndroid Build Coastguard Worker EVENT_ENTRY, 111*387f9dfdSAndroid Build Coastguard Worker EVENT_END, 112*387f9dfdSAndroid Build Coastguard Worker}; 113*387f9dfdSAndroid Build Coastguard Worker#endif 114*387f9dfdSAndroid Build Coastguard Worker 115*387f9dfdSAndroid Build Coastguard Workerstruct val_t { 116*387f9dfdSAndroid Build Coastguard Worker u64 id; 117*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 118*387f9dfdSAndroid Build Coastguard Worker const char *fname; 119*387f9dfdSAndroid Build Coastguard Worker int flags; // EXTENDED_STRUCT_MEMBER 120*387f9dfdSAndroid Build Coastguard Worker}; 121*387f9dfdSAndroid Build Coastguard Worker 122*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 123*387f9dfdSAndroid Build Coastguard Worker u64 id; 124*387f9dfdSAndroid Build Coastguard Worker u64 ts; 125*387f9dfdSAndroid Build Coastguard Worker u32 uid; 126*387f9dfdSAndroid Build Coastguard Worker int ret; 127*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 128*387f9dfdSAndroid Build Coastguard Worker#ifdef FULLPATH 129*387f9dfdSAndroid Build Coastguard Worker enum event_type type; 130*387f9dfdSAndroid Build Coastguard Worker#endif 131*387f9dfdSAndroid Build Coastguard Worker char name[NAME_MAX]; 132*387f9dfdSAndroid Build Coastguard Worker int flags; // EXTENDED_STRUCT_MEMBER 133*387f9dfdSAndroid Build Coastguard Worker}; 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 136*387f9dfdSAndroid Build Coastguard Worker""" 137*387f9dfdSAndroid Build Coastguard Worker 138*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe = """ 139*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(infotmp, u64, struct val_t); 140*387f9dfdSAndroid Build Coastguard Worker 141*387f9dfdSAndroid Build Coastguard Workerint trace_return(struct pt_regs *ctx) 142*387f9dfdSAndroid Build Coastguard Worker{ 143*387f9dfdSAndroid Build Coastguard Worker u64 id = bpf_get_current_pid_tgid(); 144*387f9dfdSAndroid Build Coastguard Worker struct val_t *valp; 145*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 146*387f9dfdSAndroid Build Coastguard Worker 147*387f9dfdSAndroid Build Coastguard Worker u64 tsp = bpf_ktime_get_ns(); 148*387f9dfdSAndroid Build Coastguard Worker 149*387f9dfdSAndroid Build Coastguard Worker valp = infotmp.lookup(&id); 150*387f9dfdSAndroid Build Coastguard Worker if (valp == 0) { 151*387f9dfdSAndroid Build Coastguard Worker // missed entry 152*387f9dfdSAndroid Build Coastguard Worker return 0; 153*387f9dfdSAndroid Build Coastguard Worker } 154*387f9dfdSAndroid Build Coastguard Worker 155*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.comm, sizeof(data.comm), valp->comm); 156*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user_str(&data.name, sizeof(data.name), (void *)valp->fname); 157*387f9dfdSAndroid Build Coastguard Worker data.id = valp->id; 158*387f9dfdSAndroid Build Coastguard Worker data.ts = tsp / 1000; 159*387f9dfdSAndroid Build Coastguard Worker data.uid = bpf_get_current_uid_gid(); 160*387f9dfdSAndroid Build Coastguard Worker data.flags = valp->flags; // EXTENDED_STRUCT_MEMBER 161*387f9dfdSAndroid Build Coastguard Worker data.ret = PT_REGS_RC(ctx); 162*387f9dfdSAndroid Build Coastguard Worker 163*387f9dfdSAndroid Build Coastguard Worker SUBMIT_DATA 164*387f9dfdSAndroid Build Coastguard Worker 165*387f9dfdSAndroid Build Coastguard Worker infotmp.delete(&id); 166*387f9dfdSAndroid Build Coastguard Worker 167*387f9dfdSAndroid Build Coastguard Worker return 0; 168*387f9dfdSAndroid Build Coastguard Worker} 169*387f9dfdSAndroid Build Coastguard Worker""" 170*387f9dfdSAndroid Build Coastguard Worker 171*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_open = """ 172*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_open(struct pt_regs *ctx, const char __user *filename, int flags) 173*387f9dfdSAndroid Build Coastguard Worker{ 174*387f9dfdSAndroid Build Coastguard Worker""" 175*387f9dfdSAndroid Build Coastguard Worker 176*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_openat = """ 177*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_openat(struct pt_regs *ctx, int dfd, const char __user *filename, int flags) 178*387f9dfdSAndroid Build Coastguard Worker{ 179*387f9dfdSAndroid Build Coastguard Worker""" 180*387f9dfdSAndroid Build Coastguard Worker 181*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_header_openat2 = """ 182*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/openat2.h> 183*387f9dfdSAndroid Build Coastguard Workerint syscall__trace_entry_openat2(struct pt_regs *ctx, int dfd, const char __user *filename, struct open_how *how) 184*387f9dfdSAndroid Build Coastguard Worker{ 185*387f9dfdSAndroid Build Coastguard Worker int flags = how->flags; 186*387f9dfdSAndroid Build Coastguard Worker""" 187*387f9dfdSAndroid Build Coastguard Worker 188*387f9dfdSAndroid Build Coastguard Workerbpf_text_kprobe_body = """ 189*387f9dfdSAndroid Build Coastguard Worker struct val_t val = {}; 190*387f9dfdSAndroid Build Coastguard Worker u64 id = bpf_get_current_pid_tgid(); 191*387f9dfdSAndroid Build Coastguard Worker u32 pid = id >> 32; // PID is higher part 192*387f9dfdSAndroid Build Coastguard Worker u32 tid = id; // Cast and get the lower part 193*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 194*387f9dfdSAndroid Build Coastguard Worker 195*387f9dfdSAndroid Build Coastguard Worker PID_TID_FILTER 196*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 197*387f9dfdSAndroid Build Coastguard Worker FLAGS_FILTER 198*387f9dfdSAndroid Build Coastguard Worker 199*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 200*387f9dfdSAndroid Build Coastguard Worker return 0; 201*387f9dfdSAndroid Build Coastguard Worker } 202*387f9dfdSAndroid Build Coastguard Worker 203*387f9dfdSAndroid Build Coastguard Worker if (bpf_get_current_comm(&val.comm, sizeof(val.comm)) == 0) { 204*387f9dfdSAndroid Build Coastguard Worker val.id = id; 205*387f9dfdSAndroid Build Coastguard Worker val.fname = filename; 206*387f9dfdSAndroid Build Coastguard Worker val.flags = flags; // EXTENDED_STRUCT_MEMBER 207*387f9dfdSAndroid Build Coastguard Worker infotmp.update(&id, &val); 208*387f9dfdSAndroid Build Coastguard Worker } 209*387f9dfdSAndroid Build Coastguard Worker 210*387f9dfdSAndroid Build Coastguard Worker return 0; 211*387f9dfdSAndroid Build Coastguard Worker}; 212*387f9dfdSAndroid Build Coastguard Worker""" 213*387f9dfdSAndroid Build Coastguard Worker 214*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_open = """ 215*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) 216*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) 217*387f9dfdSAndroid Build Coastguard Worker{ 218*387f9dfdSAndroid Build Coastguard Worker const char __user *filename = (char *)PT_REGS_PARM1(regs); 219*387f9dfdSAndroid Build Coastguard Worker int flags = PT_REGS_PARM2(regs); 220*387f9dfdSAndroid Build Coastguard Worker#else 221*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, const char __user *filename, int flags, int ret) 222*387f9dfdSAndroid Build Coastguard Worker{ 223*387f9dfdSAndroid Build Coastguard Worker#endif 224*387f9dfdSAndroid Build Coastguard Worker""" 225*387f9dfdSAndroid Build Coastguard Worker 226*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_openat = """ 227*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) 228*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) 229*387f9dfdSAndroid Build Coastguard Worker{ 230*387f9dfdSAndroid Build Coastguard Worker int dfd = PT_REGS_PARM1(regs); 231*387f9dfdSAndroid Build Coastguard Worker const char __user *filename = (char *)PT_REGS_PARM2(regs); 232*387f9dfdSAndroid Build Coastguard Worker int flags = PT_REGS_PARM3(regs); 233*387f9dfdSAndroid Build Coastguard Worker#else 234*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, int flags, int ret) 235*387f9dfdSAndroid Build Coastguard Worker{ 236*387f9dfdSAndroid Build Coastguard Worker#endif 237*387f9dfdSAndroid Build Coastguard Worker""" 238*387f9dfdSAndroid Build Coastguard Worker 239*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_header_openat2 = """ 240*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/openat2.h> 241*387f9dfdSAndroid Build Coastguard Worker#if defined(CONFIG_ARCH_HAS_SYSCALL_WRAPPER) && !defined(__s390x__) 242*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, struct pt_regs *regs, int ret) 243*387f9dfdSAndroid Build Coastguard Worker{ 244*387f9dfdSAndroid Build Coastguard Worker int dfd = PT_REGS_PARM1(regs); 245*387f9dfdSAndroid Build Coastguard Worker const char __user *filename = (char *)PT_REGS_PARM2(regs); 246*387f9dfdSAndroid Build Coastguard Worker struct open_how __user how; 247*387f9dfdSAndroid Build Coastguard Worker int flags; 248*387f9dfdSAndroid Build Coastguard Worker 249*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(&how, sizeof(struct open_how), (struct open_how*)PT_REGS_PARM3(regs)); 250*387f9dfdSAndroid Build Coastguard Worker flags = how.flags; 251*387f9dfdSAndroid Build Coastguard Worker#else 252*387f9dfdSAndroid Build Coastguard WorkerKRETFUNC_PROBE(FNNAME, int dfd, const char __user *filename, struct open_how __user *how, int ret) 253*387f9dfdSAndroid Build Coastguard Worker{ 254*387f9dfdSAndroid Build Coastguard Worker int flags = how->flags; 255*387f9dfdSAndroid Build Coastguard Worker#endif 256*387f9dfdSAndroid Build Coastguard Worker""" 257*387f9dfdSAndroid Build Coastguard Worker 258*387f9dfdSAndroid Build Coastguard Workerbpf_text_kfunc_body = """ 259*387f9dfdSAndroid Build Coastguard Worker u64 id = bpf_get_current_pid_tgid(); 260*387f9dfdSAndroid Build Coastguard Worker u32 pid = id >> 32; // PID is higher part 261*387f9dfdSAndroid Build Coastguard Worker u32 tid = id; // Cast and get the lower part 262*387f9dfdSAndroid Build Coastguard Worker u32 uid = bpf_get_current_uid_gid(); 263*387f9dfdSAndroid Build Coastguard Worker 264*387f9dfdSAndroid Build Coastguard Worker PID_TID_FILTER 265*387f9dfdSAndroid Build Coastguard Worker UID_FILTER 266*387f9dfdSAndroid Build Coastguard Worker FLAGS_FILTER 267*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 268*387f9dfdSAndroid Build Coastguard Worker return 0; 269*387f9dfdSAndroid Build Coastguard Worker } 270*387f9dfdSAndroid Build Coastguard Worker 271*387f9dfdSAndroid Build Coastguard Worker struct data_t data = {}; 272*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(&data.comm, sizeof(data.comm)); 273*387f9dfdSAndroid Build Coastguard Worker 274*387f9dfdSAndroid Build Coastguard Worker u64 tsp = bpf_ktime_get_ns(); 275*387f9dfdSAndroid Build Coastguard Worker 276*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user_str(&data.name, sizeof(data.name), (void *)filename); 277*387f9dfdSAndroid Build Coastguard Worker data.id = id; 278*387f9dfdSAndroid Build Coastguard Worker data.ts = tsp / 1000; 279*387f9dfdSAndroid Build Coastguard Worker data.uid = bpf_get_current_uid_gid(); 280*387f9dfdSAndroid Build Coastguard Worker data.flags = flags; // EXTENDED_STRUCT_MEMBER 281*387f9dfdSAndroid Build Coastguard Worker data.ret = ret; 282*387f9dfdSAndroid Build Coastguard Worker 283*387f9dfdSAndroid Build Coastguard Worker SUBMIT_DATA 284*387f9dfdSAndroid Build Coastguard Worker 285*387f9dfdSAndroid Build Coastguard Worker return 0; 286*387f9dfdSAndroid Build Coastguard Worker} 287*387f9dfdSAndroid Build Coastguard Worker""" 288*387f9dfdSAndroid Build Coastguard Worker 289*387f9dfdSAndroid Build Coastguard Workerb = BPF(text='') 290*387f9dfdSAndroid Build Coastguard Worker# open and openat are always in place since 2.6.16 291*387f9dfdSAndroid Build Coastguard Workerfnname_open = b.get_syscall_prefix().decode() + 'open' 292*387f9dfdSAndroid Build Coastguard Workerfnname_openat = b.get_syscall_prefix().decode() + 'openat' 293*387f9dfdSAndroid Build Coastguard Workerfnname_openat2 = b.get_syscall_prefix().decode() + 'openat2' 294*387f9dfdSAndroid Build Coastguard Workerif b.ksymname(fnname_openat2) == -1: 295*387f9dfdSAndroid Build Coastguard Worker fnname_openat2 = None 296*387f9dfdSAndroid Build Coastguard Worker 297*387f9dfdSAndroid Build Coastguard Workerif args.full_path: 298*387f9dfdSAndroid Build Coastguard Worker bpf_text = "#define FULLPATH\n" + bpf_text 299*387f9dfdSAndroid Build Coastguard Worker 300*387f9dfdSAndroid Build Coastguard Workeris_support_kfunc = BPF.support_kfunc() 301*387f9dfdSAndroid Build Coastguard Workerif is_support_kfunc: 302*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_header_open.replace('FNNAME', fnname_open) 303*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_body 304*387f9dfdSAndroid Build Coastguard Worker 305*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_header_openat.replace('FNNAME', fnname_openat) 306*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_body 307*387f9dfdSAndroid Build Coastguard Worker 308*387f9dfdSAndroid Build Coastguard Worker if fnname_openat2: 309*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_header_openat2.replace('FNNAME', fnname_openat2) 310*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kfunc_body 311*387f9dfdSAndroid Build Coastguard Workerelse: 312*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe 313*387f9dfdSAndroid Build Coastguard Worker 314*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_header_open 315*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_body 316*387f9dfdSAndroid Build Coastguard Worker 317*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_header_openat 318*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_body 319*387f9dfdSAndroid Build Coastguard Worker 320*387f9dfdSAndroid Build Coastguard Worker if fnname_openat2: 321*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_header_openat2 322*387f9dfdSAndroid Build Coastguard Worker bpf_text += bpf_text_kprobe_body 323*387f9dfdSAndroid Build Coastguard Worker 324*387f9dfdSAndroid Build Coastguard Workerif args.tid: # TID trumps PID 325*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('PID_TID_FILTER', 326*387f9dfdSAndroid Build Coastguard Worker 'if (tid != %s) { return 0; }' % args.tid) 327*387f9dfdSAndroid Build Coastguard Workerelif args.pid: 328*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('PID_TID_FILTER', 329*387f9dfdSAndroid Build Coastguard Worker 'if (pid != %s) { return 0; }' % args.pid) 330*387f9dfdSAndroid Build Coastguard Workerelse: 331*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('PID_TID_FILTER', '') 332*387f9dfdSAndroid Build Coastguard Workerif args.uid: 333*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('UID_FILTER', 334*387f9dfdSAndroid Build Coastguard Worker 'if (uid != %s) { return 0; }' % args.uid) 335*387f9dfdSAndroid Build Coastguard Workerelse: 336*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('UID_FILTER', '') 337*387f9dfdSAndroid Build Coastguard Workerbpf_text = filter_by_containers(args) + bpf_text 338*387f9dfdSAndroid Build Coastguard Workerif args.flag_filter: 339*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FLAGS_FILTER', 340*387f9dfdSAndroid Build Coastguard Worker 'if (!(flags & %d)) { return 0; }' % flag_filter_mask) 341*387f9dfdSAndroid Build Coastguard Workerelse: 342*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('FLAGS_FILTER', '') 343*387f9dfdSAndroid Build Coastguard Workerif not (args.extended_fields or args.flag_filter): 344*387f9dfdSAndroid Build Coastguard Worker bpf_text = '\n'.join(x for x in bpf_text.split('\n') 345*387f9dfdSAndroid Build Coastguard Worker if 'EXTENDED_STRUCT_MEMBER' not in x) 346*387f9dfdSAndroid Build Coastguard Worker 347*387f9dfdSAndroid Build Coastguard Workerif args.full_path: 348*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('SUBMIT_DATA', """ 349*387f9dfdSAndroid Build Coastguard Worker data.type = EVENT_ENTRY; 350*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 351*387f9dfdSAndroid Build Coastguard Worker 352*387f9dfdSAndroid Build Coastguard Worker if (data.name[0] != '/') { // relative path 353*387f9dfdSAndroid Build Coastguard Worker struct task_struct *task; 354*387f9dfdSAndroid Build Coastguard Worker struct dentry *dentry; 355*387f9dfdSAndroid Build Coastguard Worker int i; 356*387f9dfdSAndroid Build Coastguard Worker 357*387f9dfdSAndroid Build Coastguard Worker task = (struct task_struct *)bpf_get_current_task_btf(); 358*387f9dfdSAndroid Build Coastguard Worker dentry = task->fs->pwd.dentry; 359*387f9dfdSAndroid Build Coastguard Worker 360*387f9dfdSAndroid Build Coastguard Worker for (i = 1; i < MAX_ENTRIES; i++) { 361*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel(&data.name, sizeof(data.name), (void *)dentry->d_name.name); 362*387f9dfdSAndroid Build Coastguard Worker data.type = EVENT_ENTRY; 363*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 364*387f9dfdSAndroid Build Coastguard Worker 365*387f9dfdSAndroid Build Coastguard Worker if (dentry == dentry->d_parent) { // root directory 366*387f9dfdSAndroid Build Coastguard Worker break; 367*387f9dfdSAndroid Build Coastguard Worker } 368*387f9dfdSAndroid Build Coastguard Worker 369*387f9dfdSAndroid Build Coastguard Worker dentry = dentry->d_parent; 370*387f9dfdSAndroid Build Coastguard Worker } 371*387f9dfdSAndroid Build Coastguard Worker } 372*387f9dfdSAndroid Build Coastguard Worker 373*387f9dfdSAndroid Build Coastguard Worker data.type = EVENT_END; 374*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 375*387f9dfdSAndroid Build Coastguard Worker """) 376*387f9dfdSAndroid Build Coastguard Workerelse: 377*387f9dfdSAndroid Build Coastguard Worker bpf_text = bpf_text.replace('SUBMIT_DATA', """ 378*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &data, sizeof(data)); 379*387f9dfdSAndroid Build Coastguard Worker """) 380*387f9dfdSAndroid Build Coastguard Worker 381*387f9dfdSAndroid Build Coastguard Workerif debug or args.ebpf: 382*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 383*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 384*387f9dfdSAndroid Build Coastguard Worker exit() 385*387f9dfdSAndroid Build Coastguard Worker 386*387f9dfdSAndroid Build Coastguard Worker# initialize BPF 387*387f9dfdSAndroid Build Coastguard Workerb = BPF(text=bpf_text) 388*387f9dfdSAndroid Build Coastguard Workerif not is_support_kfunc: 389*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=fnname_open, fn_name="syscall__trace_entry_open") 390*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event=fnname_open, fn_name="trace_return") 391*387f9dfdSAndroid Build Coastguard Worker 392*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=fnname_openat, fn_name="syscall__trace_entry_openat") 393*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event=fnname_openat, fn_name="trace_return") 394*387f9dfdSAndroid Build Coastguard Worker 395*387f9dfdSAndroid Build Coastguard Worker if fnname_openat2: 396*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=fnname_openat2, fn_name="syscall__trace_entry_openat2") 397*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event=fnname_openat2, fn_name="trace_return") 398*387f9dfdSAndroid Build Coastguard Worker 399*387f9dfdSAndroid Build Coastguard Workerinitial_ts = 0 400*387f9dfdSAndroid Build Coastguard Worker 401*387f9dfdSAndroid Build Coastguard Worker# header 402*387f9dfdSAndroid Build Coastguard Workerif args.timestamp: 403*387f9dfdSAndroid Build Coastguard Worker print("%-14s" % ("TIME(s)"), end="") 404*387f9dfdSAndroid Build Coastguard Workerif args.print_uid: 405*387f9dfdSAndroid Build Coastguard Worker print("%-6s" % ("UID"), end="") 406*387f9dfdSAndroid Build Coastguard Workerprint("%-6s %-16s %4s %3s " % 407*387f9dfdSAndroid Build Coastguard Worker ("TID" if args.tid else "PID", "COMM", "FD", "ERR"), end="") 408*387f9dfdSAndroid Build Coastguard Workerif args.extended_fields: 409*387f9dfdSAndroid Build Coastguard Worker print("%-9s" % ("FLAGS"), end="") 410*387f9dfdSAndroid Build Coastguard Workerprint("PATH") 411*387f9dfdSAndroid Build Coastguard Worker 412*387f9dfdSAndroid Build Coastguard Workerclass EventType(object): 413*387f9dfdSAndroid Build Coastguard Worker EVENT_ENTRY = 0 414*387f9dfdSAndroid Build Coastguard Worker EVENT_END = 1 415*387f9dfdSAndroid Build Coastguard Worker 416*387f9dfdSAndroid Build Coastguard Workerentries = defaultdict(list) 417*387f9dfdSAndroid Build Coastguard Worker 418*387f9dfdSAndroid Build Coastguard Worker# process event 419*387f9dfdSAndroid Build Coastguard Workerdef print_event(cpu, data, size): 420*387f9dfdSAndroid Build Coastguard Worker event = b["events"].event(data) 421*387f9dfdSAndroid Build Coastguard Worker global initial_ts 422*387f9dfdSAndroid Build Coastguard Worker 423*387f9dfdSAndroid Build Coastguard Worker if not args.full_path or event.type == EventType.EVENT_END: 424*387f9dfdSAndroid Build Coastguard Worker skip = False 425*387f9dfdSAndroid Build Coastguard Worker 426*387f9dfdSAndroid Build Coastguard Worker # split return value into FD and errno columns 427*387f9dfdSAndroid Build Coastguard Worker if event.ret >= 0: 428*387f9dfdSAndroid Build Coastguard Worker fd_s = event.ret 429*387f9dfdSAndroid Build Coastguard Worker err = 0 430*387f9dfdSAndroid Build Coastguard Worker else: 431*387f9dfdSAndroid Build Coastguard Worker fd_s = -1 432*387f9dfdSAndroid Build Coastguard Worker err = - event.ret 433*387f9dfdSAndroid Build Coastguard Worker 434*387f9dfdSAndroid Build Coastguard Worker if not initial_ts: 435*387f9dfdSAndroid Build Coastguard Worker initial_ts = event.ts 436*387f9dfdSAndroid Build Coastguard Worker 437*387f9dfdSAndroid Build Coastguard Worker if args.failed and (event.ret >= 0): 438*387f9dfdSAndroid Build Coastguard Worker skip = True 439*387f9dfdSAndroid Build Coastguard Worker 440*387f9dfdSAndroid Build Coastguard Worker if args.name and bytes(args.name) not in event.comm: 441*387f9dfdSAndroid Build Coastguard Worker skip = True 442*387f9dfdSAndroid Build Coastguard Worker 443*387f9dfdSAndroid Build Coastguard Worker if not skip: 444*387f9dfdSAndroid Build Coastguard Worker if args.timestamp: 445*387f9dfdSAndroid Build Coastguard Worker delta = event.ts - initial_ts 446*387f9dfdSAndroid Build Coastguard Worker printb(b"%-14.9f" % (float(delta) / 1000000), nl="") 447*387f9dfdSAndroid Build Coastguard Worker 448*387f9dfdSAndroid Build Coastguard Worker if args.print_uid: 449*387f9dfdSAndroid Build Coastguard Worker printb(b"%-6d" % event.uid, nl="") 450*387f9dfdSAndroid Build Coastguard Worker 451*387f9dfdSAndroid Build Coastguard Worker printb(b"%-6d %-16s %4d %3d " % 452*387f9dfdSAndroid Build Coastguard Worker (event.id & 0xffffffff if args.tid else event.id >> 32, 453*387f9dfdSAndroid Build Coastguard Worker event.comm, fd_s, err), nl="") 454*387f9dfdSAndroid Build Coastguard Worker 455*387f9dfdSAndroid Build Coastguard Worker if args.extended_fields: 456*387f9dfdSAndroid Build Coastguard Worker printb(b"%08o " % event.flags, nl="") 457*387f9dfdSAndroid Build Coastguard Worker 458*387f9dfdSAndroid Build Coastguard Worker if not args.full_path: 459*387f9dfdSAndroid Build Coastguard Worker printb(b"%s" % event.name) 460*387f9dfdSAndroid Build Coastguard Worker else: 461*387f9dfdSAndroid Build Coastguard Worker paths = entries[event.id] 462*387f9dfdSAndroid Build Coastguard Worker paths.reverse() 463*387f9dfdSAndroid Build Coastguard Worker printb(b"%s" % os.path.join(*paths)) 464*387f9dfdSAndroid Build Coastguard Worker 465*387f9dfdSAndroid Build Coastguard Worker if args.full_path: 466*387f9dfdSAndroid Build Coastguard Worker try: 467*387f9dfdSAndroid Build Coastguard Worker del(entries[event.id]) 468*387f9dfdSAndroid Build Coastguard Worker except Exception: 469*387f9dfdSAndroid Build Coastguard Worker pass 470*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_ENTRY: 471*387f9dfdSAndroid Build Coastguard Worker entries[event.id].append(event.name) 472*387f9dfdSAndroid Build Coastguard Worker 473*387f9dfdSAndroid Build Coastguard Worker# loop with callback to print_event 474*387f9dfdSAndroid Build Coastguard Workerb["events"].open_perf_buffer(print_event, page_cnt=args.buffer_pages) 475*387f9dfdSAndroid Build Coastguard Workerstart_time = datetime.now() 476*387f9dfdSAndroid Build Coastguard Workerwhile not args.duration or datetime.now() - start_time < args.duration: 477*387f9dfdSAndroid Build Coastguard Worker try: 478*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 479*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 480*387f9dfdSAndroid Build Coastguard Worker exit() 481