Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tracing: Display some syscall arrays as strings

Some of the system calls that read a fixed length of memory from the user
space address are not arrays but strings. Take a bit away from the nb_args
field in the syscall meta data to use as a flag to denote that the system
call's user_arg_size is being used as a string. The nb_args should never
be more than 6, so 7 bits is plenty to hold that number. When the
user_arg_is_str flag that, when set, will display the data array from the
user space address as a string and not an array.

This will allow the output to look like this:

sys_sethostname(name: 0x5584310eb2a0 "debian", len: 6)

Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Takaya Saeki <takayas@google.com>
Cc: Tom Zanussi <zanussi@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Ian Rogers <irogers@google.com>
Cc: Douglas Raillard <douglas.raillard@arm.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Jiri Olsa <jolsa@kernel.org>
Cc: Adrian Hunter <adrian.hunter@intel.com>
Cc: Ingo Molnar <mingo@redhat.com>
Link: https://lore.kernel.org/20251028231147.930550359@kernel.org
Signed-off-by: Steven Rostedt (Google) <rostedt@goodmis.org>

+22 -4
+3 -1
include/trace/syscall.h
··· 16 16 * @name: name of the syscall 17 17 * @syscall_nr: number of the syscall 18 18 * @nb_args: number of parameters it takes 19 + * @user_arg_is_str: set if the arg for @user_arg_size is a string 19 20 * @user_arg_size: holds @arg that has size of the user space to read 20 21 * @user_mask: mask of @args that will read user space 21 22 * @types: list of types as strings ··· 28 27 struct syscall_metadata { 29 28 const char *name; 30 29 int syscall_nr; 31 - u8 nb_args; 30 + u8 nb_args:7; 31 + u8 user_arg_is_str:1; 32 32 s8 user_arg_size; 33 33 short user_mask; 34 34 const char **types;
+19 -3
kernel/trace/trace_syscalls.c
··· 184 184 ptr = (void *)ent + (val & 0xffff); 185 185 len = val >> 16; 186 186 187 - if (entry->user_arg_size < 0) { 187 + if (entry->user_arg_size < 0 || entry->user_arg_is_str) { 188 188 trace_seq_printf(s, " \"%.*s\"", len, ptr); 189 189 continue; 190 190 } ··· 249 249 static int __init 250 250 __set_enter_print_fmt(struct syscall_metadata *entry, char *buf, int len) 251 251 { 252 + bool is_string = entry->user_arg_is_str; 252 253 int i; 253 254 int pos = 0; 254 255 ··· 267 266 continue; 268 267 269 268 /* Add the format for the user space string or array */ 270 - if (entry->user_arg_size < 0) 269 + if (entry->user_arg_size < 0 || is_string) 271 270 pos += snprintf(buf + pos, LEN_OR_ZERO, " \\\"%%s\\\""); 272 271 else 273 272 pos += snprintf(buf + pos, LEN_OR_ZERO, " (%%s)"); ··· 280 279 if (!(BIT(i) & entry->user_mask)) 281 280 continue; 282 281 /* The user space data for arg has name __<arg>_val */ 283 - if (entry->user_arg_size < 0) { 282 + if (entry->user_arg_size < 0 || is_string) { 284 283 pos += snprintf(buf + pos, LEN_OR_ZERO, ", __get_str(__%s_val)", 285 284 entry->args[i]); 286 285 } else { ··· 782 781 sys_data->user_mask = BIT(1); 783 782 sys_data->user_arg_size = 2; 784 783 break; 784 + /* user arg 0 with size arg at 1 as string */ 785 + case __NR_setdomainname: 786 + case __NR_sethostname: 787 + sys_data->user_mask = BIT(0); 788 + sys_data->user_arg_size = 1; 789 + sys_data->user_arg_is_str = 1; 790 + break; 791 + #ifdef __NR_kexec_file_load 792 + /* user arg 4 with size arg at 3 as string */ 793 + case __NR_kexec_file_load: 794 + sys_data->user_mask = BIT(4); 795 + sys_data->user_arg_size = 3; 796 + sys_data->user_arg_is_str = 1; 797 + break; 798 + #endif 785 799 /* user arg at position 0 */ 786 800 #ifdef __NR_access 787 801 case __NR_access: