augmented_syscalls.c 3.8 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
// SPDX-License-Identifier: GPL-2.0
/*
 * Augment the openat syscall with the contents of the filename pointer argument.
 *
 * Test it with:
 *
 * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
 *
 * It'll catch some openat syscalls related to the dynamic linked and
 * the last one should be the one for '/etc/passwd'.
 *
 * This matches what is marshalled into the raw_syscall:sys_enter payload
 * expected by the 'perf trace' beautifiers, and can be used by them unmodified,
 * which will be done as that feature is implemented in the next csets, for now
 * it will appear in a dump done by the default tracepoint handler in 'perf trace',
 * that uses bpf_output__fprintf() to just dump those contents, as done with
 * the bpf-output event associated with the __bpf_output__ map declared in
 * tools/perf/include/bpf/stdio.h.
 */

#include <stdio.h>
22
#include <linux/socket.h>
23 24 25 26 27 28 29 30

struct bpf_map SEC("maps") __augmented_syscalls__ = {
       .type = BPF_MAP_TYPE_PERF_EVENT_ARRAY,
       .key_size = sizeof(int),
       .value_size = sizeof(u32),
       .max_entries = __NR_CPUS__,
};

31 32 33 34 35 36
struct augmented_filename {
	int	size;
	int	reserved;
	char	value[256];
};

37
#define augmented_filename_syscall_enter(syscall)						\
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
struct augmented_enter_##syscall##_args {			 				\
	struct syscall_enter_##syscall##_args	args;				 		\
	struct augmented_filename		filename;				 	\
};												\
int syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)				\
{												\
	struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; 	\
	probe_read(&augmented_args.args, sizeof(augmented_args.args), args);			\
	augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, 		\
						      sizeof(augmented_args.filename.value), 	\
						      args->filename_ptr); 			\
	perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, 			\
			  &augmented_args, 							\
			  (sizeof(augmented_args) - sizeof(augmented_args.filename.value) +	\
			   augmented_args.filename.size));					\
	return 0;										\
}

56 57 58 59 60 61 62 63 64
struct syscall_enter_openat_args {
	unsigned long long common_tp_fields;
	long		   syscall_nr;
	long		   dfd;
	char		   *filename_ptr;
	long		   flags;
	long		   mode;
};

65
augmented_filename_syscall_enter(openat);
66

67 68 69 70 71 72 73 74
struct syscall_enter_open_args {
	unsigned long long common_tp_fields;
	long		   syscall_nr;
	char		   *filename_ptr;
	long		   flags;
	long		   mode;
};

75
augmented_filename_syscall_enter(open);
76

77 78 79 80
struct syscall_enter_inotify_add_watch_args {
	unsigned long long common_tp_fields;
	long		   syscall_nr;
	long		   fd;
81
	char		   *filename_ptr;
82 83 84
	long		   mask;
};

85
augmented_filename_syscall_enter(inotify_add_watch);
86

87 88 89 90 91 92 93 94 95 96 97
struct statbuf;

struct syscall_enter_newstat_args {
	unsigned long long common_tp_fields;
	long		   syscall_nr;
	char		   *filename_ptr;
	struct stat	   *statbuf;
};

augmented_filename_syscall_enter(newstat);

98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128
struct sockaddr;

struct syscall_enter_connect_args {
	unsigned long long common_tp_fields;
	long		   syscall_nr;
	long		   fd;
	struct sockaddr	   *addr_ptr;
	unsigned long	   addrlen;
};

struct augmented_enter_connect_args {
	struct syscall_enter_connect_args args;
	struct sockaddr_storage		  addr;
};

int syscall_enter(connect)(struct syscall_enter_connect_args *args)
{
	struct augmented_enter_connect_args augmented_args;
	unsigned long addrlen = sizeof(augmented_args.addr);

	probe_read(&augmented_args.args, sizeof(augmented_args.args), args);
#ifdef FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK
	if (addrlen > augmented_args.args.addrlen)
		addrlen = augmented_args.args.addrlen;
#endif
	probe_read(&augmented_args.addr, addrlen, args->addr_ptr); 
	perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, &augmented_args, 
			  sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen);
	return 0;
}

129
license(GPL);