1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2022 Dmitry Chagin <[email protected]>
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
print_linux_signal(int signo)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
ktrsyscall_linux(struct ktr_syscall * ktr,register_t ** resip,int * resnarg,char * resc)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
ktrsyscall_linux32(struct ktr_syscall * ktr,register_t ** resip,int * resnarg,char * resc)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
ktrsigset(const char * name,const l_sigset_t * mask,size_t sz)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
ktrstruct_linux(const char * name,const char * data,size_t datalen)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