1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python 2*387f9dfdSAndroid Build Coastguard Worker# 3*387f9dfdSAndroid Build Coastguard Worker# mountsnoop Trace mount() and umount syscalls. 4*387f9dfdSAndroid Build Coastguard Worker# For Linux, uses BCC, eBPF. Embedded C. 5*387f9dfdSAndroid Build Coastguard Worker# 6*387f9dfdSAndroid Build Coastguard Worker# USAGE: mountsnoop [-h] 7*387f9dfdSAndroid Build Coastguard Worker# 8*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) 2016 Facebook, Inc. 9*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 10*387f9dfdSAndroid Build Coastguard Worker# 11*387f9dfdSAndroid Build Coastguard Worker# 14-Oct-2016 Omar Sandoval Created this. 12*387f9dfdSAndroid Build Coastguard Worker 13*387f9dfdSAndroid Build Coastguard Workerfrom __future__ import print_function 14*387f9dfdSAndroid Build Coastguard Workerimport argparse 15*387f9dfdSAndroid Build Coastguard Workerimport bcc 16*387f9dfdSAndroid Build Coastguard Workerfrom bcc.containers import filter_by_containers 17*387f9dfdSAndroid Build Coastguard Workerimport ctypes 18*387f9dfdSAndroid Build Coastguard Workerimport errno 19*387f9dfdSAndroid Build Coastguard Workerimport functools 20*387f9dfdSAndroid Build Coastguard Workerimport sys 21*387f9dfdSAndroid Build Coastguard Worker 22*387f9dfdSAndroid Build Coastguard Worker 23*387f9dfdSAndroid Build Coastguard Workerbpf_text = r""" 24*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 25*387f9dfdSAndroid Build Coastguard Worker#include <linux/sched.h> 26*387f9dfdSAndroid Build Coastguard Worker 27*387f9dfdSAndroid Build Coastguard Worker#include <linux/nsproxy.h> 28*387f9dfdSAndroid Build Coastguard Worker#include <linux/ns_common.h> 29*387f9dfdSAndroid Build Coastguard Worker 30*387f9dfdSAndroid Build Coastguard Worker/* 31*387f9dfdSAndroid Build Coastguard Worker * XXX: struct mnt_namespace is defined in fs/mount.h, which is private to the 32*387f9dfdSAndroid Build Coastguard Worker * VFS and not installed in any kernel-devel packages. So, let's duplicate the 33*387f9dfdSAndroid Build Coastguard Worker * important part of the definition. There are actually more members in the 34*387f9dfdSAndroid Build Coastguard Worker * real struct, but we don't need them, and they're more likely to change. 35*387f9dfdSAndroid Build Coastguard Worker * 36*387f9dfdSAndroid Build Coastguard Worker * To add support for --selector option, we need to call filter_by_containers(). 37*387f9dfdSAndroid Build Coastguard Worker * But this function adds code which defines struct mnt_namespace. 38*387f9dfdSAndroid Build Coastguard Worker * To avoid having this structure twice, we define MNT_NAMESPACE_DEFINED in 39*387f9dfdSAndroid Build Coastguard Worker * filter_by_containers(), then here we check if macro is already defined before 40*387f9dfdSAndroid Build Coastguard Worker * adding struct definition. 41*387f9dfdSAndroid Build Coastguard Worker */ 42*387f9dfdSAndroid Build Coastguard Worker#ifndef MNT_NAMESPACE_DEFINED 43*387f9dfdSAndroid Build Coastguard Workerstruct mnt_namespace { 44*387f9dfdSAndroid Build Coastguard Worker // This field was removed in https://github.com/torvalds/linux/commit/1a7b8969e664d6af328f00fe6eb7aabd61a71d13 45*387f9dfdSAndroid Build Coastguard Worker #if LINUX_VERSION_CODE < KERNEL_VERSION(5, 11, 0) 46*387f9dfdSAndroid Build Coastguard Worker atomic_t count; 47*387f9dfdSAndroid Build Coastguard Worker #endif 48*387f9dfdSAndroid Build Coastguard Worker struct ns_common ns; 49*387f9dfdSAndroid Build Coastguard Worker}; 50*387f9dfdSAndroid Build Coastguard Worker#endif /* !MNT_NAMESPACE_DEFINED */ 51*387f9dfdSAndroid Build Coastguard Worker 52*387f9dfdSAndroid Build Coastguard Worker/* 53*387f9dfdSAndroid Build Coastguard Worker * XXX: this could really use first-class string support in BPF. target is a 54*387f9dfdSAndroid Build Coastguard Worker * NUL-terminated path up to PATH_MAX in length. source and type are 55*387f9dfdSAndroid Build Coastguard Worker * NUL-terminated strings up to PAGE_SIZE in length. data is a weird case: it's 56*387f9dfdSAndroid Build Coastguard Worker * almost always a NUL-terminated string, but for some filesystems (e.g., older 57*387f9dfdSAndroid Build Coastguard Worker * NFS variants), it's a binary structure with plenty of NUL bytes, so the 58*387f9dfdSAndroid Build Coastguard Worker * kernel always copies up to PAGE_SIZE bytes, stopping when it hits a fault. 59*387f9dfdSAndroid Build Coastguard Worker * 60*387f9dfdSAndroid Build Coastguard Worker * The best we can do with the existing BPF helpers is to copy as much of each 61*387f9dfdSAndroid Build Coastguard Worker * argument as we can. Our stack space is limited, and we need to leave some 62*387f9dfdSAndroid Build Coastguard Worker * headroom for the rest of the function, so this should be a decent value. 63*387f9dfdSAndroid Build Coastguard Worker */ 64*387f9dfdSAndroid Build Coastguard Worker#define MAX_STR_LEN 412 65*387f9dfdSAndroid Build Coastguard Worker 66*387f9dfdSAndroid Build Coastguard Workerenum event_type { 67*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT, 68*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_SOURCE, 69*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_TARGET, 70*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_TYPE, 71*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_DATA, 72*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_RET, 73*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT, 74*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT_TARGET, 75*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT_RET, 76*387f9dfdSAndroid Build Coastguard Worker}; 77*387f9dfdSAndroid Build Coastguard Worker 78*387f9dfdSAndroid Build Coastguard Workerstruct data_t { 79*387f9dfdSAndroid Build Coastguard Worker enum event_type type; 80*387f9dfdSAndroid Build Coastguard Worker pid_t pid, tgid; 81*387f9dfdSAndroid Build Coastguard Worker union { 82*387f9dfdSAndroid Build Coastguard Worker /* EVENT_MOUNT, EVENT_UMOUNT */ 83*387f9dfdSAndroid Build Coastguard Worker struct { 84*387f9dfdSAndroid Build Coastguard Worker /* current->nsproxy->mnt_ns->ns.inum */ 85*387f9dfdSAndroid Build Coastguard Worker unsigned int mnt_ns; 86*387f9dfdSAndroid Build Coastguard Worker char comm[TASK_COMM_LEN]; 87*387f9dfdSAndroid Build Coastguard Worker char pcomm[TASK_COMM_LEN]; 88*387f9dfdSAndroid Build Coastguard Worker pid_t ppid; 89*387f9dfdSAndroid Build Coastguard Worker unsigned long flags; 90*387f9dfdSAndroid Build Coastguard Worker } enter; 91*387f9dfdSAndroid Build Coastguard Worker /* 92*387f9dfdSAndroid Build Coastguard Worker * EVENT_MOUNT_SOURCE, EVENT_MOUNT_TARGET, EVENT_MOUNT_TYPE, 93*387f9dfdSAndroid Build Coastguard Worker * EVENT_MOUNT_DATA, EVENT_UMOUNT_TARGET 94*387f9dfdSAndroid Build Coastguard Worker */ 95*387f9dfdSAndroid Build Coastguard Worker char str[MAX_STR_LEN]; 96*387f9dfdSAndroid Build Coastguard Worker /* EVENT_MOUNT_RET, EVENT_UMOUNT_RET */ 97*387f9dfdSAndroid Build Coastguard Worker int retval; 98*387f9dfdSAndroid Build Coastguard Worker }; 99*387f9dfdSAndroid Build Coastguard Worker}; 100*387f9dfdSAndroid Build Coastguard Worker 101*387f9dfdSAndroid Build Coastguard WorkerBPF_PERF_OUTPUT(events); 102*387f9dfdSAndroid Build Coastguard Worker 103*387f9dfdSAndroid Build Coastguard Workerint syscall__mount(struct pt_regs *ctx, char __user *source, 104*387f9dfdSAndroid Build Coastguard Worker char __user *target, char __user *type, 105*387f9dfdSAndroid Build Coastguard Worker unsigned long flags, char __user *data) 106*387f9dfdSAndroid Build Coastguard Worker{ 107*387f9dfdSAndroid Build Coastguard Worker struct data_t event = {}; 108*387f9dfdSAndroid Build Coastguard Worker struct task_struct *task; 109*387f9dfdSAndroid Build Coastguard Worker struct nsproxy *nsproxy; 110*387f9dfdSAndroid Build Coastguard Worker struct mnt_namespace *mnt_ns; 111*387f9dfdSAndroid Build Coastguard Worker 112*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 113*387f9dfdSAndroid Build Coastguard Worker return 0; 114*387f9dfdSAndroid Build Coastguard Worker } 115*387f9dfdSAndroid Build Coastguard Worker 116*387f9dfdSAndroid Build Coastguard Worker event.pid = bpf_get_current_pid_tgid() & 0xffffffff; 117*387f9dfdSAndroid Build Coastguard Worker event.tgid = bpf_get_current_pid_tgid() >> 32; 118*387f9dfdSAndroid Build Coastguard Worker 119*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT; 120*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm)); 121*387f9dfdSAndroid Build Coastguard Worker event.enter.flags = flags; 122*387f9dfdSAndroid Build Coastguard Worker task = (struct task_struct *)bpf_get_current_task(); 123*387f9dfdSAndroid Build Coastguard Worker event.enter.ppid = task->real_parent->tgid; 124*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel_str(&event.enter.pcomm, TASK_COMM_LEN, task->real_parent->comm); 125*387f9dfdSAndroid Build Coastguard Worker nsproxy = task->nsproxy; 126*387f9dfdSAndroid Build Coastguard Worker mnt_ns = nsproxy->mnt_ns; 127*387f9dfdSAndroid Build Coastguard Worker event.enter.mnt_ns = mnt_ns->ns.inum; 128*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 129*387f9dfdSAndroid Build Coastguard Worker 130*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT_SOURCE; 131*387f9dfdSAndroid Build Coastguard Worker __builtin_memset(event.str, 0, sizeof(event.str)); 132*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(event.str, sizeof(event.str), source); 133*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 134*387f9dfdSAndroid Build Coastguard Worker 135*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT_TARGET; 136*387f9dfdSAndroid Build Coastguard Worker __builtin_memset(event.str, 0, sizeof(event.str)); 137*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(event.str, sizeof(event.str), target); 138*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 139*387f9dfdSAndroid Build Coastguard Worker 140*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT_TYPE; 141*387f9dfdSAndroid Build Coastguard Worker __builtin_memset(event.str, 0, sizeof(event.str)); 142*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(event.str, sizeof(event.str), type); 143*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 144*387f9dfdSAndroid Build Coastguard Worker 145*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT_DATA; 146*387f9dfdSAndroid Build Coastguard Worker __builtin_memset(event.str, 0, sizeof(event.str)); 147*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(event.str, sizeof(event.str), data); 148*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 149*387f9dfdSAndroid Build Coastguard Worker 150*387f9dfdSAndroid Build Coastguard Worker return 0; 151*387f9dfdSAndroid Build Coastguard Worker} 152*387f9dfdSAndroid Build Coastguard Worker 153*387f9dfdSAndroid Build Coastguard Workerint do_ret_sys_mount(struct pt_regs *ctx) 154*387f9dfdSAndroid Build Coastguard Worker{ 155*387f9dfdSAndroid Build Coastguard Worker struct data_t event = {}; 156*387f9dfdSAndroid Build Coastguard Worker 157*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_MOUNT_RET; 158*387f9dfdSAndroid Build Coastguard Worker event.pid = bpf_get_current_pid_tgid() & 0xffffffff; 159*387f9dfdSAndroid Build Coastguard Worker event.tgid = bpf_get_current_pid_tgid() >> 32; 160*387f9dfdSAndroid Build Coastguard Worker event.retval = PT_REGS_RC(ctx); 161*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 162*387f9dfdSAndroid Build Coastguard Worker 163*387f9dfdSAndroid Build Coastguard Worker return 0; 164*387f9dfdSAndroid Build Coastguard Worker} 165*387f9dfdSAndroid Build Coastguard Worker 166*387f9dfdSAndroid Build Coastguard Workerint syscall__umount(struct pt_regs *ctx, char __user *target, int flags) 167*387f9dfdSAndroid Build Coastguard Worker{ 168*387f9dfdSAndroid Build Coastguard Worker struct data_t event = {}; 169*387f9dfdSAndroid Build Coastguard Worker struct task_struct *task; 170*387f9dfdSAndroid Build Coastguard Worker struct nsproxy *nsproxy; 171*387f9dfdSAndroid Build Coastguard Worker struct mnt_namespace *mnt_ns; 172*387f9dfdSAndroid Build Coastguard Worker 173*387f9dfdSAndroid Build Coastguard Worker if (container_should_be_filtered()) { 174*387f9dfdSAndroid Build Coastguard Worker return 0; 175*387f9dfdSAndroid Build Coastguard Worker } 176*387f9dfdSAndroid Build Coastguard Worker 177*387f9dfdSAndroid Build Coastguard Worker event.pid = bpf_get_current_pid_tgid() & 0xffffffff; 178*387f9dfdSAndroid Build Coastguard Worker event.tgid = bpf_get_current_pid_tgid() >> 32; 179*387f9dfdSAndroid Build Coastguard Worker 180*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_UMOUNT; 181*387f9dfdSAndroid Build Coastguard Worker bpf_get_current_comm(event.enter.comm, sizeof(event.enter.comm)); 182*387f9dfdSAndroid Build Coastguard Worker event.enter.flags = flags; 183*387f9dfdSAndroid Build Coastguard Worker task = (struct task_struct *)bpf_get_current_task(); 184*387f9dfdSAndroid Build Coastguard Worker event.enter.ppid = task->real_parent->tgid; 185*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_kernel_str(&event.enter.pcomm, TASK_COMM_LEN, task->real_parent->comm); 186*387f9dfdSAndroid Build Coastguard Worker nsproxy = task->nsproxy; 187*387f9dfdSAndroid Build Coastguard Worker mnt_ns = nsproxy->mnt_ns; 188*387f9dfdSAndroid Build Coastguard Worker event.enter.mnt_ns = mnt_ns->ns.inum; 189*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 190*387f9dfdSAndroid Build Coastguard Worker 191*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_UMOUNT_TARGET; 192*387f9dfdSAndroid Build Coastguard Worker __builtin_memset(event.str, 0, sizeof(event.str)); 193*387f9dfdSAndroid Build Coastguard Worker bpf_probe_read_user(event.str, sizeof(event.str), target); 194*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 195*387f9dfdSAndroid Build Coastguard Worker 196*387f9dfdSAndroid Build Coastguard Worker return 0; 197*387f9dfdSAndroid Build Coastguard Worker} 198*387f9dfdSAndroid Build Coastguard Worker 199*387f9dfdSAndroid Build Coastguard Workerint do_ret_sys_umount(struct pt_regs *ctx) 200*387f9dfdSAndroid Build Coastguard Worker{ 201*387f9dfdSAndroid Build Coastguard Worker struct data_t event = {}; 202*387f9dfdSAndroid Build Coastguard Worker 203*387f9dfdSAndroid Build Coastguard Worker event.type = EVENT_UMOUNT_RET; 204*387f9dfdSAndroid Build Coastguard Worker event.pid = bpf_get_current_pid_tgid() & 0xffffffff; 205*387f9dfdSAndroid Build Coastguard Worker event.tgid = bpf_get_current_pid_tgid() >> 32; 206*387f9dfdSAndroid Build Coastguard Worker event.retval = PT_REGS_RC(ctx); 207*387f9dfdSAndroid Build Coastguard Worker events.perf_submit(ctx, &event, sizeof(event)); 208*387f9dfdSAndroid Build Coastguard Worker 209*387f9dfdSAndroid Build Coastguard Worker return 0; 210*387f9dfdSAndroid Build Coastguard Worker} 211*387f9dfdSAndroid Build Coastguard Worker""" 212*387f9dfdSAndroid Build Coastguard Worker 213*387f9dfdSAndroid Build Coastguard Worker# sys/mount.h 214*387f9dfdSAndroid Build Coastguard WorkerMS_MGC_VAL = 0xc0ed0000 215*387f9dfdSAndroid Build Coastguard WorkerMS_MGC_MSK = 0xffff0000 216*387f9dfdSAndroid Build Coastguard WorkerMOUNT_FLAGS = [ 217*387f9dfdSAndroid Build Coastguard Worker ('MS_RDONLY', 1), 218*387f9dfdSAndroid Build Coastguard Worker ('MS_NOSUID', 2), 219*387f9dfdSAndroid Build Coastguard Worker ('MS_NODEV', 4), 220*387f9dfdSAndroid Build Coastguard Worker ('MS_NOEXEC', 8), 221*387f9dfdSAndroid Build Coastguard Worker ('MS_SYNCHRONOUS', 16), 222*387f9dfdSAndroid Build Coastguard Worker ('MS_REMOUNT', 32), 223*387f9dfdSAndroid Build Coastguard Worker ('MS_MANDLOCK', 64), 224*387f9dfdSAndroid Build Coastguard Worker ('MS_DIRSYNC', 128), 225*387f9dfdSAndroid Build Coastguard Worker ('MS_NOATIME', 1024), 226*387f9dfdSAndroid Build Coastguard Worker ('MS_NODIRATIME', 2048), 227*387f9dfdSAndroid Build Coastguard Worker ('MS_BIND', 4096), 228*387f9dfdSAndroid Build Coastguard Worker ('MS_MOVE', 8192), 229*387f9dfdSAndroid Build Coastguard Worker ('MS_REC', 16384), 230*387f9dfdSAndroid Build Coastguard Worker ('MS_SILENT', 32768), 231*387f9dfdSAndroid Build Coastguard Worker ('MS_POSIXACL', 1 << 16), 232*387f9dfdSAndroid Build Coastguard Worker ('MS_UNBINDABLE', 1 << 17), 233*387f9dfdSAndroid Build Coastguard Worker ('MS_PRIVATE', 1 << 18), 234*387f9dfdSAndroid Build Coastguard Worker ('MS_SLAVE', 1 << 19), 235*387f9dfdSAndroid Build Coastguard Worker ('MS_SHARED', 1 << 20), 236*387f9dfdSAndroid Build Coastguard Worker ('MS_RELATIME', 1 << 21), 237*387f9dfdSAndroid Build Coastguard Worker ('MS_KERNMOUNT', 1 << 22), 238*387f9dfdSAndroid Build Coastguard Worker ('MS_I_VERSION', 1 << 23), 239*387f9dfdSAndroid Build Coastguard Worker ('MS_STRICTATIME', 1 << 24), 240*387f9dfdSAndroid Build Coastguard Worker ('MS_LAZYTIME', 1 << 25), 241*387f9dfdSAndroid Build Coastguard Worker ('MS_ACTIVE', 1 << 30), 242*387f9dfdSAndroid Build Coastguard Worker ('MS_NOUSER', 1 << 31), 243*387f9dfdSAndroid Build Coastguard Worker] 244*387f9dfdSAndroid Build Coastguard WorkerUMOUNT_FLAGS = [ 245*387f9dfdSAndroid Build Coastguard Worker ('MNT_FORCE', 1), 246*387f9dfdSAndroid Build Coastguard Worker ('MNT_DETACH', 2), 247*387f9dfdSAndroid Build Coastguard Worker ('MNT_EXPIRE', 4), 248*387f9dfdSAndroid Build Coastguard Worker ('UMOUNT_NOFOLLOW', 8), 249*387f9dfdSAndroid Build Coastguard Worker] 250*387f9dfdSAndroid Build Coastguard Worker 251*387f9dfdSAndroid Build Coastguard Worker 252*387f9dfdSAndroid Build Coastguard WorkerTASK_COMM_LEN = 16 # linux/sched.h 253*387f9dfdSAndroid Build Coastguard WorkerMAX_STR_LEN = 412 254*387f9dfdSAndroid Build Coastguard Worker 255*387f9dfdSAndroid Build Coastguard Worker 256*387f9dfdSAndroid Build Coastguard Workerclass EventType(object): 257*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT = 0 258*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_SOURCE = 1 259*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_TARGET = 2 260*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_TYPE = 3 261*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_DATA = 4 262*387f9dfdSAndroid Build Coastguard Worker EVENT_MOUNT_RET = 5 263*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT = 6 264*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT_TARGET = 7 265*387f9dfdSAndroid Build Coastguard Worker EVENT_UMOUNT_RET = 8 266*387f9dfdSAndroid Build Coastguard Worker 267*387f9dfdSAndroid Build Coastguard Worker 268*387f9dfdSAndroid Build Coastguard Workerclass EnterData(ctypes.Structure): 269*387f9dfdSAndroid Build Coastguard Worker _fields_ = [ 270*387f9dfdSAndroid Build Coastguard Worker ('mnt_ns', ctypes.c_uint), 271*387f9dfdSAndroid Build Coastguard Worker ('comm', ctypes.c_char * TASK_COMM_LEN), 272*387f9dfdSAndroid Build Coastguard Worker ('pcomm', ctypes.c_char * TASK_COMM_LEN), 273*387f9dfdSAndroid Build Coastguard Worker ('ppid', ctypes.c_uint), 274*387f9dfdSAndroid Build Coastguard Worker ('flags', ctypes.c_ulong), 275*387f9dfdSAndroid Build Coastguard Worker ] 276*387f9dfdSAndroid Build Coastguard Worker 277*387f9dfdSAndroid Build Coastguard Worker 278*387f9dfdSAndroid Build Coastguard Workerclass DataUnion(ctypes.Union): 279*387f9dfdSAndroid Build Coastguard Worker _fields_ = [ 280*387f9dfdSAndroid Build Coastguard Worker ('enter', EnterData), 281*387f9dfdSAndroid Build Coastguard Worker ('str', ctypes.c_char * MAX_STR_LEN), 282*387f9dfdSAndroid Build Coastguard Worker ('retval', ctypes.c_int), 283*387f9dfdSAndroid Build Coastguard Worker ] 284*387f9dfdSAndroid Build Coastguard Worker 285*387f9dfdSAndroid Build Coastguard Worker 286*387f9dfdSAndroid Build Coastguard Workerclass Event(ctypes.Structure): 287*387f9dfdSAndroid Build Coastguard Worker _fields_ = [ 288*387f9dfdSAndroid Build Coastguard Worker ('type', ctypes.c_uint), 289*387f9dfdSAndroid Build Coastguard Worker ('pid', ctypes.c_uint), 290*387f9dfdSAndroid Build Coastguard Worker ('tgid', ctypes.c_uint), 291*387f9dfdSAndroid Build Coastguard Worker ('union', DataUnion), 292*387f9dfdSAndroid Build Coastguard Worker ] 293*387f9dfdSAndroid Build Coastguard Worker 294*387f9dfdSAndroid Build Coastguard Worker 295*387f9dfdSAndroid Build Coastguard Workerdef _decode_flags(flags, flag_list): 296*387f9dfdSAndroid Build Coastguard Worker str_flags = [] 297*387f9dfdSAndroid Build Coastguard Worker for flag, bit in flag_list: 298*387f9dfdSAndroid Build Coastguard Worker if flags & bit: 299*387f9dfdSAndroid Build Coastguard Worker str_flags.append(flag) 300*387f9dfdSAndroid Build Coastguard Worker flags &= ~bit 301*387f9dfdSAndroid Build Coastguard Worker if flags or not str_flags: 302*387f9dfdSAndroid Build Coastguard Worker str_flags.append('0x{:x}'.format(flags)) 303*387f9dfdSAndroid Build Coastguard Worker return str_flags 304*387f9dfdSAndroid Build Coastguard Worker 305*387f9dfdSAndroid Build Coastguard Worker 306*387f9dfdSAndroid Build Coastguard Workerdef decode_flags(flags, flag_list): 307*387f9dfdSAndroid Build Coastguard Worker return '|'.join(_decode_flags(flags, flag_list)) 308*387f9dfdSAndroid Build Coastguard Worker 309*387f9dfdSAndroid Build Coastguard Worker 310*387f9dfdSAndroid Build Coastguard Workerdef decode_mount_flags(flags): 311*387f9dfdSAndroid Build Coastguard Worker str_flags = [] 312*387f9dfdSAndroid Build Coastguard Worker if flags & MS_MGC_MSK == MS_MGC_VAL: 313*387f9dfdSAndroid Build Coastguard Worker flags &= ~MS_MGC_MSK 314*387f9dfdSAndroid Build Coastguard Worker str_flags.append('MS_MGC_VAL') 315*387f9dfdSAndroid Build Coastguard Worker str_flags.extend(_decode_flags(flags, MOUNT_FLAGS)) 316*387f9dfdSAndroid Build Coastguard Worker return '|'.join(str_flags) 317*387f9dfdSAndroid Build Coastguard Worker 318*387f9dfdSAndroid Build Coastguard Worker 319*387f9dfdSAndroid Build Coastguard Workerdef decode_umount_flags(flags): 320*387f9dfdSAndroid Build Coastguard Worker return decode_flags(flags, UMOUNT_FLAGS) 321*387f9dfdSAndroid Build Coastguard Worker 322*387f9dfdSAndroid Build Coastguard Worker 323*387f9dfdSAndroid Build Coastguard Workerdef decode_errno(retval): 324*387f9dfdSAndroid Build Coastguard Worker try: 325*387f9dfdSAndroid Build Coastguard Worker return '-' + errno.errorcode[-retval] 326*387f9dfdSAndroid Build Coastguard Worker except KeyError: 327*387f9dfdSAndroid Build Coastguard Worker return str(retval) 328*387f9dfdSAndroid Build Coastguard Worker 329*387f9dfdSAndroid Build Coastguard Worker 330*387f9dfdSAndroid Build Coastguard Worker_escape_chars = { 331*387f9dfdSAndroid Build Coastguard Worker ord('\a'): '\\a', 332*387f9dfdSAndroid Build Coastguard Worker ord('\b'): '\\b', 333*387f9dfdSAndroid Build Coastguard Worker ord('\t'): '\\t', 334*387f9dfdSAndroid Build Coastguard Worker ord('\n'): '\\n', 335*387f9dfdSAndroid Build Coastguard Worker ord('\v'): '\\v', 336*387f9dfdSAndroid Build Coastguard Worker ord('\f'): '\\f', 337*387f9dfdSAndroid Build Coastguard Worker ord('\r'): '\\r', 338*387f9dfdSAndroid Build Coastguard Worker ord('"'): '\\"', 339*387f9dfdSAndroid Build Coastguard Worker ord('\\'): '\\\\', 340*387f9dfdSAndroid Build Coastguard Worker} 341*387f9dfdSAndroid Build Coastguard Worker 342*387f9dfdSAndroid Build Coastguard Worker 343*387f9dfdSAndroid Build Coastguard Workerdef escape_character(c): 344*387f9dfdSAndroid Build Coastguard Worker try: 345*387f9dfdSAndroid Build Coastguard Worker return _escape_chars[c] 346*387f9dfdSAndroid Build Coastguard Worker except KeyError: 347*387f9dfdSAndroid Build Coastguard Worker if 0x20 <= c <= 0x7e: 348*387f9dfdSAndroid Build Coastguard Worker return chr(c) 349*387f9dfdSAndroid Build Coastguard Worker else: 350*387f9dfdSAndroid Build Coastguard Worker return '\\x{:02x}'.format(c) 351*387f9dfdSAndroid Build Coastguard Worker 352*387f9dfdSAndroid Build Coastguard Worker 353*387f9dfdSAndroid Build Coastguard Workerif sys.version_info.major < 3: 354*387f9dfdSAndroid Build Coastguard Worker def decode_mount_string(s): 355*387f9dfdSAndroid Build Coastguard Worker return '"{}"'.format(''.join(escape_character(ord(c)) for c in s)) 356*387f9dfdSAndroid Build Coastguard Workerelse: 357*387f9dfdSAndroid Build Coastguard Worker def decode_mount_string(s): 358*387f9dfdSAndroid Build Coastguard Worker return '"{}"'.format(''.join(escape_character(c) for c in s)) 359*387f9dfdSAndroid Build Coastguard Worker 360*387f9dfdSAndroid Build Coastguard Worker 361*387f9dfdSAndroid Build Coastguard Workerdef print_event(mounts, umounts, parent, cpu, data, size): 362*387f9dfdSAndroid Build Coastguard Worker event = ctypes.cast(data, ctypes.POINTER(Event)).contents 363*387f9dfdSAndroid Build Coastguard Worker 364*387f9dfdSAndroid Build Coastguard Worker try: 365*387f9dfdSAndroid Build Coastguard Worker if event.type == EventType.EVENT_MOUNT: 366*387f9dfdSAndroid Build Coastguard Worker mounts[event.pid] = { 367*387f9dfdSAndroid Build Coastguard Worker 'pid': event.pid, 368*387f9dfdSAndroid Build Coastguard Worker 'tgid': event.tgid, 369*387f9dfdSAndroid Build Coastguard Worker 'mnt_ns': event.union.enter.mnt_ns, 370*387f9dfdSAndroid Build Coastguard Worker 'comm': event.union.enter.comm, 371*387f9dfdSAndroid Build Coastguard Worker 'flags': event.union.enter.flags, 372*387f9dfdSAndroid Build Coastguard Worker 'ppid': event.union.enter.ppid, 373*387f9dfdSAndroid Build Coastguard Worker 'pcomm': event.union.enter.pcomm, 374*387f9dfdSAndroid Build Coastguard Worker } 375*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_MOUNT_SOURCE: 376*387f9dfdSAndroid Build Coastguard Worker mounts[event.pid]['source'] = event.union.str 377*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_MOUNT_TARGET: 378*387f9dfdSAndroid Build Coastguard Worker mounts[event.pid]['target'] = event.union.str 379*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_MOUNT_TYPE: 380*387f9dfdSAndroid Build Coastguard Worker mounts[event.pid]['type'] = event.union.str 381*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_MOUNT_DATA: 382*387f9dfdSAndroid Build Coastguard Worker # XXX: data is not always a NUL-terminated string 383*387f9dfdSAndroid Build Coastguard Worker mounts[event.pid]['data'] = event.union.str 384*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_UMOUNT: 385*387f9dfdSAndroid Build Coastguard Worker umounts[event.pid] = { 386*387f9dfdSAndroid Build Coastguard Worker 'pid': event.pid, 387*387f9dfdSAndroid Build Coastguard Worker 'tgid': event.tgid, 388*387f9dfdSAndroid Build Coastguard Worker 'mnt_ns': event.union.enter.mnt_ns, 389*387f9dfdSAndroid Build Coastguard Worker 'comm': event.union.enter.comm, 390*387f9dfdSAndroid Build Coastguard Worker 'flags': event.union.enter.flags, 391*387f9dfdSAndroid Build Coastguard Worker 'ppid': event.union.enter.ppid, 392*387f9dfdSAndroid Build Coastguard Worker 'pcomm': event.union.enter.pcomm, 393*387f9dfdSAndroid Build Coastguard Worker } 394*387f9dfdSAndroid Build Coastguard Worker elif event.type == EventType.EVENT_UMOUNT_TARGET: 395*387f9dfdSAndroid Build Coastguard Worker umounts[event.pid]['target'] = event.union.str 396*387f9dfdSAndroid Build Coastguard Worker elif (event.type == EventType.EVENT_MOUNT_RET or 397*387f9dfdSAndroid Build Coastguard Worker event.type == EventType.EVENT_UMOUNT_RET): 398*387f9dfdSAndroid Build Coastguard Worker if event.type == EventType.EVENT_MOUNT_RET: 399*387f9dfdSAndroid Build Coastguard Worker syscall = mounts.pop(event.pid) 400*387f9dfdSAndroid Build Coastguard Worker call = ('mount({source}, {target}, {type}, {flags}, {data}) ' + 401*387f9dfdSAndroid Build Coastguard Worker '= {retval}').format( 402*387f9dfdSAndroid Build Coastguard Worker source=decode_mount_string(syscall['source']), 403*387f9dfdSAndroid Build Coastguard Worker target=decode_mount_string(syscall['target']), 404*387f9dfdSAndroid Build Coastguard Worker type=decode_mount_string(syscall['type']), 405*387f9dfdSAndroid Build Coastguard Worker flags=decode_mount_flags(syscall['flags']), 406*387f9dfdSAndroid Build Coastguard Worker data=decode_mount_string(syscall['data']), 407*387f9dfdSAndroid Build Coastguard Worker retval=decode_errno(event.union.retval)) 408*387f9dfdSAndroid Build Coastguard Worker else: 409*387f9dfdSAndroid Build Coastguard Worker syscall = umounts.pop(event.pid) 410*387f9dfdSAndroid Build Coastguard Worker call = 'umount({target}, {flags}) = {retval}'.format( 411*387f9dfdSAndroid Build Coastguard Worker target=decode_mount_string(syscall['target']), 412*387f9dfdSAndroid Build Coastguard Worker flags=decode_umount_flags(syscall['flags']), 413*387f9dfdSAndroid Build Coastguard Worker retval=decode_errno(event.union.retval)) 414*387f9dfdSAndroid Build Coastguard Worker if parent: 415*387f9dfdSAndroid Build Coastguard Worker print('{:16} {:<7} {:<7} {:16} {:<7} {:<11} {}'.format( 416*387f9dfdSAndroid Build Coastguard Worker syscall['comm'].decode('utf-8', 'replace'), syscall['tgid'], 417*387f9dfdSAndroid Build Coastguard Worker syscall['pid'], syscall['pcomm'].decode('utf-8', 'replace'), 418*387f9dfdSAndroid Build Coastguard Worker syscall['ppid'], syscall['mnt_ns'], call)) 419*387f9dfdSAndroid Build Coastguard Worker else: 420*387f9dfdSAndroid Build Coastguard Worker print('{:16} {:<7} {:<7} {:<11} {}'.format( 421*387f9dfdSAndroid Build Coastguard Worker syscall['comm'].decode('utf-8', 'replace'), syscall['tgid'], 422*387f9dfdSAndroid Build Coastguard Worker syscall['pid'], syscall['mnt_ns'], call)) 423*387f9dfdSAndroid Build Coastguard Worker sys.stdout.flush() 424*387f9dfdSAndroid Build Coastguard Worker except KeyError: 425*387f9dfdSAndroid Build Coastguard Worker # This might happen if we lost an event. 426*387f9dfdSAndroid Build Coastguard Worker pass 427*387f9dfdSAndroid Build Coastguard Worker 428*387f9dfdSAndroid Build Coastguard Worker 429*387f9dfdSAndroid Build Coastguard Workerdef main(): 430*387f9dfdSAndroid Build Coastguard Worker parser = argparse.ArgumentParser( 431*387f9dfdSAndroid Build Coastguard Worker description='trace mount() and umount() syscalls' 432*387f9dfdSAndroid Build Coastguard Worker ) 433*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--ebpf", action="store_true", 434*387f9dfdSAndroid Build Coastguard Worker help=argparse.SUPPRESS) 435*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("-P", "--parent_process", action="store_true", 436*387f9dfdSAndroid Build Coastguard Worker help="also snoop the parent process") 437*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--cgroupmap", 438*387f9dfdSAndroid Build Coastguard Worker help="trace cgroups in this BPF map only") 439*387f9dfdSAndroid Build Coastguard Worker parser.add_argument("--mntnsmap", 440*387f9dfdSAndroid Build Coastguard Worker help="trace mount namespaces in this BPF map only") 441*387f9dfdSAndroid Build Coastguard Worker args = parser.parse_args() 442*387f9dfdSAndroid Build Coastguard Worker 443*387f9dfdSAndroid Build Coastguard Worker mounts = {} 444*387f9dfdSAndroid Build Coastguard Worker umounts = {} 445*387f9dfdSAndroid Build Coastguard Worker global bpf_text 446*387f9dfdSAndroid Build Coastguard Worker bpf_text = filter_by_containers(args) + bpf_text 447*387f9dfdSAndroid Build Coastguard Worker if args.ebpf: 448*387f9dfdSAndroid Build Coastguard Worker print(bpf_text) 449*387f9dfdSAndroid Build Coastguard Worker exit() 450*387f9dfdSAndroid Build Coastguard Worker b = bcc.BPF(text=bpf_text) 451*387f9dfdSAndroid Build Coastguard Worker mount_fnname = b.get_syscall_fnname("mount") 452*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=mount_fnname, fn_name="syscall__mount") 453*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event=mount_fnname, fn_name="do_ret_sys_mount") 454*387f9dfdSAndroid Build Coastguard Worker umount_fnname = b.get_syscall_fnname("umount") 455*387f9dfdSAndroid Build Coastguard Worker b.attach_kprobe(event=umount_fnname, fn_name="syscall__umount") 456*387f9dfdSAndroid Build Coastguard Worker b.attach_kretprobe(event=umount_fnname, fn_name="do_ret_sys_umount") 457*387f9dfdSAndroid Build Coastguard Worker b['events'].open_perf_buffer( 458*387f9dfdSAndroid Build Coastguard Worker functools.partial(print_event, mounts, umounts, args.parent_process)) 459*387f9dfdSAndroid Build Coastguard Worker 460*387f9dfdSAndroid Build Coastguard Worker if args.parent_process: 461*387f9dfdSAndroid Build Coastguard Worker print('{:16} {:<7} {:<7} {:16} {:<7} {:<11} {}'.format( 462*387f9dfdSAndroid Build Coastguard Worker 'COMM', 'PID', 'TID', 'PCOMM', 'PPID', 'MNT_NS', 'CALL')) 463*387f9dfdSAndroid Build Coastguard Worker else: 464*387f9dfdSAndroid Build Coastguard Worker print('{:16} {:<7} {:<7} {:<11} {}'.format( 465*387f9dfdSAndroid Build Coastguard Worker 'COMM', 'PID', 'TID', 'MNT_NS', 'CALL')) 466*387f9dfdSAndroid Build Coastguard Worker 467*387f9dfdSAndroid Build Coastguard Worker while True: 468*387f9dfdSAndroid Build Coastguard Worker try: 469*387f9dfdSAndroid Build Coastguard Worker b.perf_buffer_poll() 470*387f9dfdSAndroid Build Coastguard Worker except KeyboardInterrupt: 471*387f9dfdSAndroid Build Coastguard Worker exit() 472*387f9dfdSAndroid Build Coastguard Worker 473*387f9dfdSAndroid Build Coastguard Worker 474*387f9dfdSAndroid Build Coastguard Worker 475*387f9dfdSAndroid Build Coastguard Workerif __name__ == '__main__': 476*387f9dfdSAndroid Build Coastguard Worker main() 477