1/*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2022 Dmitry Chagin <dchagin@FreeBSD.org>
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 *    notice, this list of conditions and the following disclaimer in the
13 *    documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 */
27
28#include <sys/param.h>
29#include <sys/uio.h>
30#include <sys/ktrace.h>
31#include <err.h>
32#include <errno.h>
33#include <stddef.h>
34#include <stdlib.h>
35#include <string.h>
36#include <sysdecode.h>
37
38#include "kdump.h"
39
40#ifdef __amd64__
41#include <amd64/linux/linux.h>
42#include <amd64/linux32/linux32_syscall.h>
43#elif __aarch64__
44#include <arm64/linux/linux.h>
45#elif __i386__
46#include <i386/linux/linux.h>
47#endif
48
49#include <compat/linux/linux.h>
50#include <compat/linux/linux_file.h>
51
52static void
53print_linux_signal(int signo)
54{
55	const char *signame;
56
57	signame = sysdecode_linux_signal(signo);
58	if (signame != NULL)
59		printf("%s", signame);
60	else
61		printf("SIG %d", signo);
62}
63
64void
65ktrsyscall_linux(struct ktr_syscall *ktr, register_t **resip,
66    int *resnarg, char *resc)
67{
68	int narg = ktr->ktr_narg;
69	register_t *ip, *first;
70	int quad_align, quad_slots;
71	char c;
72
73	ip = first = &ktr->ktr_args[0];
74	c = *resc;
75	quad_align = 0;
76	quad_slots = 1;
77	switch (ktr->ktr_code) {
78	case LINUX_SYS_linux_faccessat:
79	case LINUX_SYS_linux_fchmodat:
80	case LINUX_SYS_linux_fchownat:
81#ifdef LINUX_SYS_linux_newfstatat
82	case LINUX_SYS_linux_newfstatat:
83#endif
84#ifdef LINUX_SYS_linux_fstatat64
85	case LINUX_SYS_linux_fstatat64:
86#endif
87#ifdef LINUX_SYS_linux_futimesat
88	case LINUX_SYS_linux_futimesat:
89#endif
90	case LINUX_SYS_linux_linkat:
91	case LINUX_SYS_linux_mkdirat:
92	case LINUX_SYS_linux_mknodat:
93	case LINUX_SYS_linux_openat:
94	case LINUX_SYS_linux_readlinkat:
95	case LINUX_SYS_linux_renameat:
96	case LINUX_SYS_linux_unlinkat:
97	case LINUX_SYS_linux_utimensat:
98		putchar('(');
99		print_integer_arg_valid(sysdecode_atfd, *ip);
100		c = ',';
101		ip++;
102		narg--;
103		break;
104	}
105	switch (ktr->ktr_code) {
106#ifdef LINUX_SYS_linux_access
107	case LINUX_SYS_linux_access:
108#endif
109	case LINUX_SYS_linux_faccessat:
110		print_number(ip, narg, c);
111		putchar(',');
112		print_mask_arg(sysdecode_access_mode, *ip);
113		ip++;
114		narg--;
115		break;
116#ifdef LINUX_SYS_linux_chmod
117	case LINUX_SYS_linux_chmod:
118#endif
119	case LINUX_SYS_linux_fchmodat:
120		print_number(ip, narg, c);
121		putchar(',');
122		decode_filemode(*ip);
123		ip++;
124		narg--;
125		break;
126	case LINUX_SYS_linux_mknodat:
127		print_number(ip, narg, c);
128		putchar(',');
129		decode_filemode(*ip);
130		ip++;
131		narg--;
132		break;
133#ifdef LINUX_SYS_linux_mkdir
134	case LINUX_SYS_linux_mkdir:
135#endif
136	case LINUX_SYS_linux_mkdirat:
137		print_number(ip, narg, c);
138		putchar(',');
139		decode_filemode(*ip);
140		ip++;
141		narg--;
142		break;
143	case LINUX_SYS_linux_linkat:
144	case LINUX_SYS_linux_renameat:
145	case LINUX_SYS_linux_symlinkat:
146		print_number(ip, narg, c);
147		putchar(',');
148		print_integer_arg_valid(sysdecode_atfd, *ip);
149		ip++;
150		narg--;
151		print_number(ip, narg, c);
152		break;
153	case LINUX_SYS_linux_fchownat:
154		print_number(ip, narg, c);
155		print_number(ip, narg, c);
156		print_number(ip, narg, c);
157		break;
158#ifdef LINUX_SYS_linux_newfstatat
159	case LINUX_SYS_linux_newfstatat:
160#endif
161#ifdef LINUX_SYS_linux_fstatat64
162	case LINUX_SYS_linux_fstatat64:
163#endif
164	case LINUX_SYS_linux_utimensat:
165		print_number(ip, narg, c);
166		print_number(ip, narg, c);
167		break;
168	case LINUX_SYS_linux_unlinkat:
169		print_number(ip, narg, c);
170		break;
171	case LINUX_SYS_linux_clock_gettime:
172	case LINUX_SYS_linux_clock_settime:
173	case LINUX_SYS_linux_clock_getres:
174	case LINUX_SYS_linux_timer_create:
175		putchar('(');
176		sysdecode_linux_clockid(stdout, *ip);
177		c = ',';
178		ip++;
179		narg--;
180		break;
181	case LINUX_SYS_linux_clock_nanosleep:
182		putchar('(');
183		sysdecode_linux_clockid(stdout, *ip);
184		putchar(',');
185		ip++;
186		narg--;
187		print_mask_arg0(sysdecode_linux_clock_flags, *ip);
188		c = ',';
189		ip++;
190		narg--;
191		break;
192	case LINUX_SYS_linux_clone:
193		putchar('(');
194		print_mask_arg(sysdecode_linux_clone_flags, *ip);
195		ip++;
196		narg--;
197		c = ',';
198		break;
199	case LINUX_SYS_linux_kill:
200	case LINUX_SYS_linux_tkill:
201	case LINUX_SYS_linux_rt_sigqueueinfo:
202		print_decimal_number(ip, narg, c);
203		putchar(',');
204		print_linux_signal(*ip);
205		ip++;
206		narg--;
207		break;
208	case LINUX_SYS_linux_tgkill:
209	case LINUX_SYS_linux_rt_tgsigqueueinfo:
210		print_decimal_number(ip, narg, c);
211		print_decimal_number(ip, narg, c);
212		putchar(',');
213		print_linux_signal(*ip);
214		ip++;
215		narg--;
216		break;
217#ifdef LINUX_SYS_linux_open
218	case LINUX_SYS_linux_open:
219#endif
220	case LINUX_SYS_linux_openat:
221		print_number(ip, narg, c);
222		putchar(',');
223		print_mask_arg(sysdecode_linux_open_flags, ip[0]);
224		if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
225			putchar(',');
226			decode_filemode(ip[1]);
227		}
228		ip += 2;
229		narg -= 2;
230		break;
231	case LINUX_SYS_linux_rt_sigaction:
232		putchar('(');
233		print_linux_signal(*ip);
234		ip++;
235		narg--;
236		c = ',';
237		break;
238	case LINUX_SYS_linux_ftruncate:
239	case LINUX_SYS_linux_truncate:
240		print_number(ip, narg, c);
241		print_number64(first, ip, narg, c);
242		break;
243	case LINUX_SYS_linux_getitimer:
244	case LINUX_SYS_linux_setitimer:
245		putchar('(');
246		print_integer_arg(sysdecode_itimer, *ip);
247		ip++;
248		narg--;
249		c = ',';
250		break;
251	case LINUX_SYS_linux_rt_sigprocmask:
252#ifdef LINUX_SYS_linux_sigprocmask
253	case LINUX_SYS_linux_sigprocmask:
254#endif
255		putchar('(');
256		print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
257		ip++;
258		narg--;
259		c = ',';
260		break;
261	}
262	switch (ktr->ktr_code) {
263	case LINUX_SYS_linux_fchownat:
264	case LINUX_SYS_linux_faccessat:
265	case LINUX_SYS_linux_fchmodat:
266#ifdef LINUX_SYS_linux_newfstatat
267	case LINUX_SYS_linux_newfstatat:
268#endif
269#ifdef LINUX_SYS_linux_fstatat64
270	case LINUX_SYS_linux_fstatat64:
271#endif
272	case LINUX_SYS_linux_linkat:
273	case LINUX_SYS_linux_unlinkat:
274	case LINUX_SYS_linux_utimensat:
275		putchar(',');
276		print_mask_arg0(sysdecode_linux_atflags, *ip);
277		ip++;
278		narg--;
279		break;
280	}
281	*resc = c;
282	*resip = ip;
283	*resnarg = narg;
284}
285
286#if defined(__amd64__)
287void
288ktrsyscall_linux32(struct ktr_syscall *ktr, register_t **resip,
289    int *resnarg, char *resc)
290{
291	int narg = ktr->ktr_narg;
292	register_t *ip, *first;
293	int quad_align, quad_slots;
294	char c;
295
296	ip = first = &ktr->ktr_args[0];
297	c = *resc;
298	quad_align = 0;
299	quad_slots = 2;
300	switch (ktr->ktr_code) {
301	case LINUX32_SYS_linux_faccessat:
302	case LINUX32_SYS_linux_fchmodat:
303	case LINUX32_SYS_linux_fchownat:
304	case LINUX32_SYS_linux_fstatat64:
305	case LINUX32_SYS_linux_futimesat:
306	case LINUX32_SYS_linux_linkat:
307	case LINUX32_SYS_linux_mkdirat:
308	case LINUX32_SYS_linux_mknodat:
309	case LINUX32_SYS_linux_openat:
310	case LINUX32_SYS_linux_readlinkat:
311	case LINUX32_SYS_linux_renameat:
312	case LINUX32_SYS_linux_unlinkat:
313	case LINUX32_SYS_linux_utimensat:
314		putchar('(');
315		print_integer_arg_valid(sysdecode_atfd, *ip);
316		c = ',';
317		ip++;
318		narg--;
319		break;
320	}
321	switch (ktr->ktr_code) {
322	case LINUX32_SYS_linux_access:
323	case LINUX32_SYS_linux_faccessat:
324		print_number(ip, narg, c);
325		putchar(',');
326		print_mask_arg(sysdecode_access_mode, *ip);
327		ip++;
328		narg--;
329		break;
330	case LINUX32_SYS_linux_chmod:
331	case LINUX32_SYS_fchmod:
332	case LINUX32_SYS_linux_fchmodat:
333		print_number(ip, narg, c);
334		putchar(',');
335		decode_filemode(*ip);
336		ip++;
337		narg--;
338		break;
339	case LINUX32_SYS_linux_mknodat:
340		print_number(ip, narg, c);
341		putchar(',');
342		decode_filemode(*ip);
343		ip++;
344		narg--;
345		break;
346	case LINUX32_SYS_linux_mkdir:
347	case LINUX32_SYS_linux_mkdirat:
348		print_number(ip, narg, c);
349		putchar(',');
350		decode_filemode(*ip);
351		ip++;
352		narg--;
353		break;
354	case LINUX32_SYS_linux_linkat:
355	case LINUX32_SYS_linux_renameat:
356	case LINUX32_SYS_linux_symlinkat:
357		print_number(ip, narg, c);
358		putchar(',');
359		print_integer_arg_valid(sysdecode_atfd, *ip);
360		ip++;
361		narg--;
362		print_number(ip, narg, c);
363		break;
364	case LINUX32_SYS_linux_fchownat:
365		print_number(ip, narg, c);
366		print_number(ip, narg, c);
367		print_number(ip, narg, c);
368		break;
369	case LINUX32_SYS_linux_fstatat64:
370	case LINUX32_SYS_linux_utimensat:
371		print_number(ip, narg, c);
372		print_number(ip, narg, c);
373		break;
374	case LINUX32_SYS_linux_unlinkat:
375		print_number(ip, narg, c);
376		break;
377	case LINUX32_SYS_linux_clock_gettime:
378	case LINUX32_SYS_linux_clock_settime:
379	case LINUX32_SYS_linux_clock_getres:
380	case LINUX32_SYS_linux_timer_create:
381	case LINUX32_SYS_linux_clock_gettime64:
382	case LINUX32_SYS_linux_clock_settime64:
383	case LINUX32_SYS_linux_clock_getres_time64:
384		putchar('(');
385		sysdecode_linux_clockid(stdout, *ip);
386		c = ',';
387		ip++;
388		narg--;
389		break;
390	case LINUX32_SYS_linux_clock_nanosleep:
391		putchar('(');
392		sysdecode_linux_clockid(stdout, *ip);
393		putchar(',');
394		ip++;
395		narg--;
396		print_mask_arg0(sysdecode_linux_clock_flags, *ip);
397		c = ',';
398		ip++;
399		narg--;
400		break;
401	case LINUX32_SYS_linux_clone:
402		putchar('(');
403		print_mask_arg(sysdecode_linux_clone_flags, *ip);
404		ip++;
405		narg--;
406		c = ',';
407		break;
408	case LINUX32_SYS_linux_kill:
409	case LINUX32_SYS_linux_tkill:
410	case LINUX32_SYS_linux_rt_sigqueueinfo:
411		print_decimal_number(ip, narg, c);
412		putchar(',');
413		print_linux_signal(*ip);
414		ip++;
415		narg--;
416		break;
417	case LINUX32_SYS_linux_tgkill:
418	case LINUX32_SYS_linux_rt_tgsigqueueinfo:
419		print_decimal_number(ip, narg, c);
420		print_decimal_number(ip, narg, c);
421		putchar(',');
422		print_linux_signal(*ip);
423		ip++;
424		narg--;
425		break;
426	case LINUX32_SYS_linux_open:
427	case LINUX32_SYS_linux_openat:
428		print_number(ip, narg, c);
429		putchar(',');
430		print_mask_arg(sysdecode_linux_open_flags, ip[0]);
431		if ((ip[0] & LINUX_O_CREAT) == LINUX_O_CREAT) {
432			putchar(',');
433			decode_filemode(ip[1]);
434		}
435		ip += 2;
436		narg -= 2;
437		break;
438	case LINUX32_SYS_linux_signal:
439	case LINUX32_SYS_linux_sigaction:
440	case LINUX32_SYS_linux_rt_sigaction:
441		putchar('(');
442		print_linux_signal(*ip);
443		ip++;
444		narg--;
445		c = ',';
446		break;
447	case LINUX32_SYS_linux_ftruncate:
448	case LINUX32_SYS_linux_truncate:
449		print_number(ip, narg, c);
450		print_number64(first, ip, narg, c);
451		break;
452	case LINUX32_SYS_linux_getitimer:
453	case LINUX32_SYS_linux_setitimer:
454		putchar('(');
455		print_integer_arg(sysdecode_itimer, *ip);
456		ip++;
457		narg--;
458		c = ',';
459		break;
460	case LINUX32_SYS_linux_rt_sigprocmask:
461	case LINUX32_SYS_linux_sigprocmask:
462		putchar('(');
463		print_integer_arg(sysdecode_linux_sigprocmask_how, *ip);
464		ip++;
465		narg--;
466		c = ',';
467		break;
468	}
469	switch (ktr->ktr_code) {
470	case LINUX32_SYS_linux_fchownat:
471	case LINUX32_SYS_linux_faccessat:
472	case LINUX32_SYS_linux_fchmodat:
473	case LINUX32_SYS_linux_fstatat64:
474	case LINUX32_SYS_linux_linkat:
475	case LINUX32_SYS_linux_unlinkat:
476	case LINUX32_SYS_linux_utimensat:
477		putchar(',');
478		print_mask_arg0(sysdecode_linux_atflags, *ip);
479		ip++;
480		narg--;
481		break;
482	}
483	*resc = c;
484	*resip = ip;
485	*resnarg = narg;
486}
487#endif /* __amd64__ */
488
489static void
490ktrsigset(const char *name, const l_sigset_t *mask, size_t sz)
491{
492	unsigned long i, c;
493
494	printf("%s [ ", name);
495	c = 0;
496	for (i = 1; i <= sz * CHAR_BIT; i++) {
497		if (!LINUX_SIGISMEMBER(*mask, i))
498			continue;
499		if (c != 0)
500			printf(", ");
501		printf("%s", sysdecode_linux_signal(i));
502		c++;
503	}
504	if (c == 0)
505		printf("empty ]\n");
506	else
507		printf(" ]\n");
508}
509
510bool
511ktrstruct_linux(const char *name, const char *data, size_t datalen)
512{
513	l_sigset_t mask;
514
515	if (strcmp(name, "l_sigset_t") == 0) {
516		/* Old Linux sigset_t is one word size. */
517		if (datalen < sizeof(int) || datalen > sizeof(l_sigset_t))
518			return (false);
519		memcpy(&mask, data, datalen);
520		ktrsigset(name, &mask, datalen);
521	} else
522		return (false);
523
524	return (true);
525}
526