]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - usr.bin/kdump/linux.c
zfs: merge openzfs/zfs@95f71c019
[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 #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 }