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
52 static void
print_linux_signal(int signo)53 print_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
64 void
ktrsyscall_linux(struct ktr_syscall * ktr,register_t ** resip,int * resnarg,char * resc)65 ktrsyscall_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__)
287 void
ktrsyscall_linux32(struct ktr_syscall * ktr,register_t ** resip,int * resnarg,char * resc)288 ktrsyscall_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
489 static void
ktrsigset(const char * name,const l_sigset_t * mask,size_t sz)490 ktrsigset(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
510 bool
ktrstruct_linux(const char * name,const char * data,size_t datalen)511 ktrstruct_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