augmented_syscalls.c (5202B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * Augment syscalls with the contents of the pointer arguments. 4 * 5 * Test it with: 6 * 7 * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null 8 * 9 * It'll catch some openat syscalls related to the dynamic linked and 10 * the last one should be the one for '/etc/passwd'. 11 * 12 * This matches what is marshalled into the raw_syscall:sys_enter payload 13 * expected by the 'perf trace' beautifiers, and can be used by them, that will 14 * check if perf_sample->raw_data is more than what is expected for each 15 * syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the 16 * contents of pointer arguments. 17 */ 18 19#include <stdio.h> 20#include <linux/socket.h> 21 22/* bpf-output associated map */ 23bpf_map(__augmented_syscalls__, PERF_EVENT_ARRAY, int, u32, __NR_CPUS__); 24 25struct syscall_exit_args { 26 unsigned long long common_tp_fields; 27 long syscall_nr; 28 long ret; 29}; 30 31struct augmented_filename { 32 unsigned int size; 33 int reserved; 34 char value[256]; 35}; 36 37#define augmented_filename_syscall(syscall) \ 38struct augmented_enter_##syscall##_args { \ 39 struct syscall_enter_##syscall##_args args; \ 40 struct augmented_filename filename; \ 41}; \ 42int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ 43{ \ 44 struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; \ 45 unsigned int len = sizeof(augmented_args); \ 46 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ 47 augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, \ 48 sizeof(augmented_args.filename.value), \ 49 args->filename_ptr); \ 50 if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) { \ 51 len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size; \ 52 len &= sizeof(augmented_args.filename.value) - 1; \ 53 } \ 54 /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ \ 55 return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ 56 &augmented_args, len); \ 57} \ 58int syscall_exit(syscall)(struct syscall_exit_args *args) \ 59{ \ 60 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \ 61} 62 63struct syscall_enter_openat_args { 64 unsigned long long common_tp_fields; 65 long syscall_nr; 66 long dfd; 67 char *filename_ptr; 68 long flags; 69 long mode; 70}; 71 72augmented_filename_syscall(openat); 73 74struct syscall_enter_open_args { 75 unsigned long long common_tp_fields; 76 long syscall_nr; 77 char *filename_ptr; 78 long flags; 79 long mode; 80}; 81 82augmented_filename_syscall(open); 83 84struct syscall_enter_inotify_add_watch_args { 85 unsigned long long common_tp_fields; 86 long syscall_nr; 87 long fd; 88 char *filename_ptr; 89 long mask; 90}; 91 92augmented_filename_syscall(inotify_add_watch); 93 94struct statbuf; 95 96struct syscall_enter_newstat_args { 97 unsigned long long common_tp_fields; 98 long syscall_nr; 99 char *filename_ptr; 100 struct stat *statbuf; 101}; 102 103augmented_filename_syscall(newstat); 104 105#ifndef _K_SS_MAXSIZE 106#define _K_SS_MAXSIZE 128 107#endif 108 109#define augmented_sockaddr_syscall(syscall) \ 110struct augmented_enter_##syscall##_args { \ 111 struct syscall_enter_##syscall##_args args; \ 112 struct sockaddr_storage addr; \ 113}; \ 114int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args) \ 115{ \ 116 struct augmented_enter_##syscall##_args augmented_args; \ 117 unsigned long addrlen = sizeof(augmented_args.addr); \ 118 probe_read(&augmented_args.args, sizeof(augmented_args.args), args); \ 119/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */ \ 120/* if (addrlen > augmented_args.args.addrlen) */ \ 121/* addrlen = augmented_args.args.addrlen; */ \ 122/* */ \ 123 probe_read(&augmented_args.addr, addrlen, args->addr_ptr); \ 124 /* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */ \ 125 return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, \ 126 &augmented_args, \ 127 sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen);\ 128} \ 129int syscall_exit(syscall)(struct syscall_exit_args *args) \ 130{ \ 131 return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */ \ 132} 133 134struct sockaddr; 135 136struct syscall_enter_bind_args { 137 unsigned long long common_tp_fields; 138 long syscall_nr; 139 long fd; 140 struct sockaddr *addr_ptr; 141 unsigned long addrlen; 142}; 143 144augmented_sockaddr_syscall(bind); 145 146struct syscall_enter_connect_args { 147 unsigned long long common_tp_fields; 148 long syscall_nr; 149 long fd; 150 struct sockaddr *addr_ptr; 151 unsigned long addrlen; 152}; 153 154augmented_sockaddr_syscall(connect); 155 156struct syscall_enter_sendto_args { 157 unsigned long long common_tp_fields; 158 long syscall_nr; 159 long fd; 160 void *buff; 161 long len; 162 unsigned long flags; 163 struct sockaddr *addr_ptr; 164 long addr_len; 165}; 166 167augmented_sockaddr_syscall(sendto); 168 169license(GPL);