]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/kdump/linux.c
libarchive: merge from vendor branch
[FreeBSD/FreeBSD.git] / usr.bin / kdump / linux.c
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 }