Linux Audio

Check our new training course

Loading...
Note: File does not exist in v6.2.
  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);