18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Augment syscalls with the contents of the pointer arguments.
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Test it with:
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci * perf trace -e tools/perf/examples/bpf/augmented_syscalls.c cat /etc/passwd > /dev/null
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * It'll catch some openat syscalls related to the dynamic linked and
108c2ecf20Sopenharmony_ci * the last one should be the one for '/etc/passwd'.
118c2ecf20Sopenharmony_ci *
128c2ecf20Sopenharmony_ci * This matches what is marshalled into the raw_syscall:sys_enter payload
138c2ecf20Sopenharmony_ci * expected by the 'perf trace' beautifiers, and can be used by them, that will
148c2ecf20Sopenharmony_ci * check if perf_sample->raw_data is more than what is expected for each
158c2ecf20Sopenharmony_ci * syscalls:sys_{enter,exit}_SYSCALL tracepoint, uing the extra data as the
168c2ecf20Sopenharmony_ci * contents of pointer arguments.
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <stdio.h>
208c2ecf20Sopenharmony_ci#include <linux/socket.h>
218c2ecf20Sopenharmony_ci
228c2ecf20Sopenharmony_ci/* bpf-output associated map */
238c2ecf20Sopenharmony_cibpf_map(__augmented_syscalls__, PERF_EVENT_ARRAY, int, u32, __NR_CPUS__);
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_cistruct syscall_exit_args {
268c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
278c2ecf20Sopenharmony_ci	long		   syscall_nr;
288c2ecf20Sopenharmony_ci	long		   ret;
298c2ecf20Sopenharmony_ci};
308c2ecf20Sopenharmony_ci
318c2ecf20Sopenharmony_cistruct augmented_filename {
328c2ecf20Sopenharmony_ci	unsigned int	size;
338c2ecf20Sopenharmony_ci	int		reserved;
348c2ecf20Sopenharmony_ci	char		value[256];
358c2ecf20Sopenharmony_ci};
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci#define augmented_filename_syscall(syscall)							\
388c2ecf20Sopenharmony_cistruct augmented_enter_##syscall##_args {			 				\
398c2ecf20Sopenharmony_ci	struct syscall_enter_##syscall##_args	args;				 		\
408c2ecf20Sopenharmony_ci	struct augmented_filename		filename;				 	\
418c2ecf20Sopenharmony_ci};												\
428c2ecf20Sopenharmony_ciint syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)				\
438c2ecf20Sopenharmony_ci{												\
448c2ecf20Sopenharmony_ci	struct augmented_enter_##syscall##_args augmented_args = { .filename.reserved = 0, }; 	\
458c2ecf20Sopenharmony_ci	unsigned int len = sizeof(augmented_args);						\
468c2ecf20Sopenharmony_ci	probe_read(&augmented_args.args, sizeof(augmented_args.args), args);			\
478c2ecf20Sopenharmony_ci	augmented_args.filename.size = probe_read_str(&augmented_args.filename.value, 		\
488c2ecf20Sopenharmony_ci						      sizeof(augmented_args.filename.value), 	\
498c2ecf20Sopenharmony_ci						      args->filename_ptr); 			\
508c2ecf20Sopenharmony_ci	if (augmented_args.filename.size < sizeof(augmented_args.filename.value)) {		\
518c2ecf20Sopenharmony_ci		len -= sizeof(augmented_args.filename.value) - augmented_args.filename.size;	\
528c2ecf20Sopenharmony_ci		len &= sizeof(augmented_args.filename.value) - 1;				\
538c2ecf20Sopenharmony_ci	}											\
548c2ecf20Sopenharmony_ci	/* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */	\
558c2ecf20Sopenharmony_ci	return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, 		\
568c2ecf20Sopenharmony_ci				 &augmented_args, len);						\
578c2ecf20Sopenharmony_ci}												\
588c2ecf20Sopenharmony_ciint syscall_exit(syscall)(struct syscall_exit_args *args)					\
598c2ecf20Sopenharmony_ci{												\
608c2ecf20Sopenharmony_ci       return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */	\
618c2ecf20Sopenharmony_ci}
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_cistruct syscall_enter_openat_args {
648c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
658c2ecf20Sopenharmony_ci	long		   syscall_nr;
668c2ecf20Sopenharmony_ci	long		   dfd;
678c2ecf20Sopenharmony_ci	char		   *filename_ptr;
688c2ecf20Sopenharmony_ci	long		   flags;
698c2ecf20Sopenharmony_ci	long		   mode;
708c2ecf20Sopenharmony_ci};
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ciaugmented_filename_syscall(openat);
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_cistruct syscall_enter_open_args {
758c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
768c2ecf20Sopenharmony_ci	long		   syscall_nr;
778c2ecf20Sopenharmony_ci	char		   *filename_ptr;
788c2ecf20Sopenharmony_ci	long		   flags;
798c2ecf20Sopenharmony_ci	long		   mode;
808c2ecf20Sopenharmony_ci};
818c2ecf20Sopenharmony_ci
828c2ecf20Sopenharmony_ciaugmented_filename_syscall(open);
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_cistruct syscall_enter_inotify_add_watch_args {
858c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
868c2ecf20Sopenharmony_ci	long		   syscall_nr;
878c2ecf20Sopenharmony_ci	long		   fd;
888c2ecf20Sopenharmony_ci	char		   *filename_ptr;
898c2ecf20Sopenharmony_ci	long		   mask;
908c2ecf20Sopenharmony_ci};
918c2ecf20Sopenharmony_ci
928c2ecf20Sopenharmony_ciaugmented_filename_syscall(inotify_add_watch);
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistruct statbuf;
958c2ecf20Sopenharmony_ci
968c2ecf20Sopenharmony_cistruct syscall_enter_newstat_args {
978c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
988c2ecf20Sopenharmony_ci	long		   syscall_nr;
998c2ecf20Sopenharmony_ci	char		   *filename_ptr;
1008c2ecf20Sopenharmony_ci	struct stat	   *statbuf;
1018c2ecf20Sopenharmony_ci};
1028c2ecf20Sopenharmony_ci
1038c2ecf20Sopenharmony_ciaugmented_filename_syscall(newstat);
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_ci#ifndef _K_SS_MAXSIZE
1068c2ecf20Sopenharmony_ci#define _K_SS_MAXSIZE 128
1078c2ecf20Sopenharmony_ci#endif
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci#define augmented_sockaddr_syscall(syscall)						\
1108c2ecf20Sopenharmony_cistruct augmented_enter_##syscall##_args {			 				\
1118c2ecf20Sopenharmony_ci	struct syscall_enter_##syscall##_args	args;				 		\
1128c2ecf20Sopenharmony_ci	struct sockaddr_storage			addr;						\
1138c2ecf20Sopenharmony_ci};												\
1148c2ecf20Sopenharmony_ciint syscall_enter(syscall)(struct syscall_enter_##syscall##_args *args)				\
1158c2ecf20Sopenharmony_ci{												\
1168c2ecf20Sopenharmony_ci	struct augmented_enter_##syscall##_args augmented_args;				 	\
1178c2ecf20Sopenharmony_ci	unsigned long addrlen = sizeof(augmented_args.addr);					\
1188c2ecf20Sopenharmony_ci	probe_read(&augmented_args.args, sizeof(augmented_args.args), args);			\
1198c2ecf20Sopenharmony_ci/* FIXME_CLANG_OPTIMIZATION_THAT_ACCESSES_USER_CONTROLLED_ADDRLEN_DESPITE_THIS_CHECK */		\
1208c2ecf20Sopenharmony_ci/*	if (addrlen > augmented_args.args.addrlen)				     */		\
1218c2ecf20Sopenharmony_ci/*		addrlen = augmented_args.args.addrlen;				     */		\
1228c2ecf20Sopenharmony_ci/*										     */		\
1238c2ecf20Sopenharmony_ci	probe_read(&augmented_args.addr, addrlen, args->addr_ptr); 				\
1248c2ecf20Sopenharmony_ci	/* If perf_event_output fails, return non-zero so that it gets recorded unaugmented */	\
1258c2ecf20Sopenharmony_ci	return perf_event_output(args, &__augmented_syscalls__, BPF_F_CURRENT_CPU, 		\
1268c2ecf20Sopenharmony_ci				 &augmented_args, 						\
1278c2ecf20Sopenharmony_ci				sizeof(augmented_args) - sizeof(augmented_args.addr) + addrlen);\
1288c2ecf20Sopenharmony_ci}												\
1298c2ecf20Sopenharmony_ciint syscall_exit(syscall)(struct syscall_exit_args *args)					\
1308c2ecf20Sopenharmony_ci{												\
1318c2ecf20Sopenharmony_ci       return 1; /* 0 as soon as we start copying data returned by the kernel, e.g. 'read' */	\
1328c2ecf20Sopenharmony_ci}
1338c2ecf20Sopenharmony_ci
1348c2ecf20Sopenharmony_cistruct sockaddr;
1358c2ecf20Sopenharmony_ci
1368c2ecf20Sopenharmony_cistruct syscall_enter_bind_args {
1378c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
1388c2ecf20Sopenharmony_ci	long		   syscall_nr;
1398c2ecf20Sopenharmony_ci	long		   fd;
1408c2ecf20Sopenharmony_ci	struct sockaddr	   *addr_ptr;
1418c2ecf20Sopenharmony_ci	unsigned long	   addrlen;
1428c2ecf20Sopenharmony_ci};
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ciaugmented_sockaddr_syscall(bind);
1458c2ecf20Sopenharmony_ci
1468c2ecf20Sopenharmony_cistruct syscall_enter_connect_args {
1478c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
1488c2ecf20Sopenharmony_ci	long		   syscall_nr;
1498c2ecf20Sopenharmony_ci	long		   fd;
1508c2ecf20Sopenharmony_ci	struct sockaddr	   *addr_ptr;
1518c2ecf20Sopenharmony_ci	unsigned long	   addrlen;
1528c2ecf20Sopenharmony_ci};
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ciaugmented_sockaddr_syscall(connect);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_cistruct syscall_enter_sendto_args {
1578c2ecf20Sopenharmony_ci	unsigned long long common_tp_fields;
1588c2ecf20Sopenharmony_ci	long		   syscall_nr;
1598c2ecf20Sopenharmony_ci	long		   fd;
1608c2ecf20Sopenharmony_ci	void		   *buff;
1618c2ecf20Sopenharmony_ci	long		   len;
1628c2ecf20Sopenharmony_ci	unsigned long	   flags;
1638c2ecf20Sopenharmony_ci	struct sockaddr	   *addr_ptr;
1648c2ecf20Sopenharmony_ci	long		   addr_len;
1658c2ecf20Sopenharmony_ci};
1668c2ecf20Sopenharmony_ci
1678c2ecf20Sopenharmony_ciaugmented_sockaddr_syscall(sendto);
1688c2ecf20Sopenharmony_ci
1698c2ecf20Sopenharmony_cilicense(GPL);
170