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