1*387f9dfdSAndroid Build Coastguard Worker#!/usr/bin/env python3 2*387f9dfdSAndroid Build Coastguard Worker# Copyright (c) PLUMgrid, Inc. 3*387f9dfdSAndroid Build Coastguard Worker# Licensed under the Apache License, Version 2.0 (the "License") 4*387f9dfdSAndroid Build Coastguard Worker 5*387f9dfdSAndroid Build Coastguard Workerimport bcc 6*387f9dfdSAndroid Build Coastguard Workerimport os 7*387f9dfdSAndroid Build Coastguard Workerimport unittest 8*387f9dfdSAndroid Build Coastguard Workerfrom utils import mayFail, kernel_version_ge 9*387f9dfdSAndroid Build Coastguard Workerimport subprocess 10*387f9dfdSAndroid Build Coastguard Worker 11*387f9dfdSAndroid Build Coastguard Worker 12*387f9dfdSAndroid Build Coastguard Worker@unittest.skipUnless(kernel_version_ge(4,6), "requires kernel >= 4.6") 13*387f9dfdSAndroid Build Coastguard Workerclass TestStackid(unittest.TestCase): 14*387f9dfdSAndroid Build Coastguard Worker @mayFail("This fails on github actions environment, and needs to be fixed") 15*387f9dfdSAndroid Build Coastguard Worker def test_simple(self): 16*387f9dfdSAndroid Build Coastguard Worker b = bcc.BPF(text=b""" 17*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 18*387f9dfdSAndroid Build Coastguard Workerstruct bpf_map; 19*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE(stack_traces, 10240); 20*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stack_entries, int, int); 21*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stub); 22*387f9dfdSAndroid Build Coastguard Workerint kprobe__htab_map_lookup_elem(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { 23*387f9dfdSAndroid Build Coastguard Worker int id = stack_traces.get_stackid(ctx, BPF_F_REUSE_STACKID); 24*387f9dfdSAndroid Build Coastguard Worker if (id < 0) 25*387f9dfdSAndroid Build Coastguard Worker return 0; 26*387f9dfdSAndroid Build Coastguard Worker int key = 1; 27*387f9dfdSAndroid Build Coastguard Worker stack_entries.update(&key, &id); 28*387f9dfdSAndroid Build Coastguard Worker return 0; 29*387f9dfdSAndroid Build Coastguard Worker} 30*387f9dfdSAndroid Build Coastguard Worker""") 31*387f9dfdSAndroid Build Coastguard Worker stub = b[b"stub"] 32*387f9dfdSAndroid Build Coastguard Worker stack_traces = b[b"stack_traces"] 33*387f9dfdSAndroid Build Coastguard Worker stack_entries = b[b"stack_entries"] 34*387f9dfdSAndroid Build Coastguard Worker try: x = stub[stub.Key(1)] 35*387f9dfdSAndroid Build Coastguard Worker except: pass 36*387f9dfdSAndroid Build Coastguard Worker k = stack_entries.Key(1) 37*387f9dfdSAndroid Build Coastguard Worker self.assertIn(k, stack_entries) 38*387f9dfdSAndroid Build Coastguard Worker stackid = stack_entries[k] 39*387f9dfdSAndroid Build Coastguard Worker self.assertIsNotNone(stackid) 40*387f9dfdSAndroid Build Coastguard Worker stack = stack_traces[stackid].ip 41*387f9dfdSAndroid Build Coastguard Worker self.assertEqual(b.ksym(stack[0]), b"htab_map_lookup_elem") 42*387f9dfdSAndroid Build Coastguard Worker 43*387f9dfdSAndroid Build Coastguard Workerdef Get_libc_path(): 44*387f9dfdSAndroid Build Coastguard Worker cmd = 'cat /proc/self/maps | grep libc | awk \'{print $6}\' | uniq' 45*387f9dfdSAndroid Build Coastguard Worker output = subprocess.check_output(cmd, shell=True) 46*387f9dfdSAndroid Build Coastguard Worker if not isinstance(output, str): 47*387f9dfdSAndroid Build Coastguard Worker output = output.decode() 48*387f9dfdSAndroid Build Coastguard Worker return output.split('\n')[0] 49*387f9dfdSAndroid Build Coastguard Worker 50*387f9dfdSAndroid Build Coastguard Worker@unittest.skipUnless(kernel_version_ge(4,17), "requires kernel >= 4.17") 51*387f9dfdSAndroid Build Coastguard Workerclass TestStackBuildid(unittest.TestCase): 52*387f9dfdSAndroid Build Coastguard Worker def test_simple(self): 53*387f9dfdSAndroid Build Coastguard Worker b = bcc.BPF(text=b""" 54*387f9dfdSAndroid Build Coastguard Worker#include <uapi/linux/ptrace.h> 55*387f9dfdSAndroid Build Coastguard Workerstruct bpf_map; 56*387f9dfdSAndroid Build Coastguard WorkerBPF_STACK_TRACE_BUILDID(stack_traces, 10240); 57*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stack_entries, int, int); 58*387f9dfdSAndroid Build Coastguard WorkerBPF_HASH(stub); 59*387f9dfdSAndroid Build Coastguard Workerint kprobe__sys_getuid(struct pt_regs *ctx, struct bpf_map *map, u64 *k) { 60*387f9dfdSAndroid Build Coastguard Worker int id = stack_traces.get_stackid(ctx, BPF_F_USER_STACK); 61*387f9dfdSAndroid Build Coastguard Worker if (id < 0) 62*387f9dfdSAndroid Build Coastguard Worker return 0; 63*387f9dfdSAndroid Build Coastguard Worker int key = 1; 64*387f9dfdSAndroid Build Coastguard Worker stack_entries.update(&key, &id); 65*387f9dfdSAndroid Build Coastguard Worker return 0; 66*387f9dfdSAndroid Build Coastguard Worker} 67*387f9dfdSAndroid Build Coastguard Worker""") 68*387f9dfdSAndroid Build Coastguard Worker os.getuid() 69*387f9dfdSAndroid Build Coastguard Worker stub = b[b"stub"] 70*387f9dfdSAndroid Build Coastguard Worker stack_traces = b[b"stack_traces"] 71*387f9dfdSAndroid Build Coastguard Worker stack_entries = b[b"stack_entries"] 72*387f9dfdSAndroid Build Coastguard Worker b.add_module(Get_libc_path()) 73*387f9dfdSAndroid Build Coastguard Worker try: x = stub[stub.Key(1)] 74*387f9dfdSAndroid Build Coastguard Worker except: pass 75*387f9dfdSAndroid Build Coastguard Worker k = stack_entries.Key(1) 76*387f9dfdSAndroid Build Coastguard Worker self.assertIn(k, stack_entries) 77*387f9dfdSAndroid Build Coastguard Worker stackid = stack_entries[k] 78*387f9dfdSAndroid Build Coastguard Worker self.assertIsNotNone(stackid) 79*387f9dfdSAndroid Build Coastguard Worker stack = stack_traces[stackid] 80*387f9dfdSAndroid Build Coastguard Worker self.assertTrue(b.sym(stack.trace[0], -1).find(b"getuid")!=-1) 81*387f9dfdSAndroid Build Coastguard Worker 82*387f9dfdSAndroid Build Coastguard Workerif __name__ == "__main__": 83*387f9dfdSAndroid Build Coastguard Worker unittest.main() 84