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