]> granicus.if.org Git - strace/blob - printsiginfo.c
Robustify mpers.awk against invalid input
[strace] / printsiginfo.c
1 #include "defs.h"
2
3 #include DEF_MPERS_TYPE(siginfo_t)
4
5 #include <signal.h>
6 #include <linux/audit.h>
7
8 #include MPERS_DEFS
9
10 #ifndef IN_MPERS
11 #include "printsiginfo.h"
12 #endif
13
14 #include "xlat/audit_arch.h"
15 #include "xlat/sigbus_codes.h"
16 #include "xlat/sigchld_codes.h"
17 #include "xlat/sigfpe_codes.h"
18 #include "xlat/sigill_codes.h"
19 #include "xlat/siginfo_codes.h"
20 #include "xlat/sigpoll_codes.h"
21 #include "xlat/sigprof_codes.h"
22 #include "xlat/sigsegv_codes.h"
23 #include "xlat/sigsys_codes.h"
24 #include "xlat/sigtrap_codes.h"
25
26 #ifdef SIGEMT
27 # include "xlat/sigemt_codes.h"
28 #endif
29
30 #ifndef SI_FROMUSER
31 # define SI_FROMUSER(sip)       ((sip)->si_code <= 0)
32 #endif
33
34 static void
35 printsigsource(const siginfo_t *sip)
36 {
37         tprintf(", si_pid=%u, si_uid=%u",
38                 (unsigned int) sip->si_pid,
39                 (unsigned int) sip->si_uid);
40 }
41
42 static void
43 printsigval(const siginfo_t *sip, bool verbose)
44 {
45         if (!verbose)
46                 tprints(", ...");
47         else
48                 tprintf(", si_value={int=%d, ptr=%#lx}",
49                         sip->si_int,
50                         (unsigned long) sip->si_ptr);
51 }
52
53 static void
54 print_si_code(int si_signo, int si_code)
55 {
56         const char *code = xlookup(siginfo_codes, si_code);
57
58         if (!code) {
59                 switch (si_signo) {
60                 case SIGTRAP:
61                         code = xlookup(sigtrap_codes, si_code);
62                         break;
63                 case SIGCHLD:
64                         code = xlookup(sigchld_codes, si_code);
65                         break;
66                 case SIGPOLL:
67                         code = xlookup(sigpoll_codes, si_code);
68                         break;
69                 case SIGPROF:
70                         code = xlookup(sigprof_codes, si_code);
71                         break;
72                 case SIGILL:
73                         code = xlookup(sigill_codes, si_code);
74                         break;
75 #ifdef SIGEMT
76                 case SIGEMT:
77                         code = xlookup(sigemt_codes, si_code);
78                         break;
79 #endif
80                 case SIGFPE:
81                         code = xlookup(sigfpe_codes, si_code);
82                         break;
83                 case SIGSEGV:
84                         code = xlookup(sigsegv_codes, si_code);
85                         break;
86                 case SIGBUS:
87                         code = xlookup(sigbus_codes, si_code);
88                         break;
89                 case SIGSYS:
90                         code = xlookup(sigsys_codes, si_code);
91                         break;
92                 }
93         }
94
95         if (code)
96                 tprints(code);
97         else
98                 tprintf("%#x", si_code);
99 }
100
101 static void
102 print_si_info(const siginfo_t *sip, bool verbose)
103 {
104         if (sip->si_errno) {
105                 tprints(", si_errno=");
106                 if ((unsigned) sip->si_errno < nerrnos
107                     && errnoent[sip->si_errno])
108                         tprints(errnoent[sip->si_errno]);
109                 else
110                         tprintf("%d", sip->si_errno);
111         }
112
113         if (SI_FROMUSER(sip)) {
114                 switch (sip->si_code) {
115                 case SI_USER:
116                         printsigsource(sip);
117                         break;
118                 case SI_TKILL:
119                         printsigsource(sip);
120                         break;
121 #if defined HAVE_SIGINFO_T_SI_TIMERID && defined HAVE_SIGINFO_T_SI_OVERRUN
122                 case SI_TIMER:
123                         tprintf(", si_timerid=%#x, si_overrun=%d",
124                                 sip->si_timerid, sip->si_overrun);
125                         printsigval(sip, verbose);
126                         break;
127 #endif
128                 default:
129                         printsigsource(sip);
130                         if (sip->si_ptr)
131                                 printsigval(sip, verbose);
132                         break;
133                 }
134         } else {
135                 switch (sip->si_signo) {
136                 case SIGCHLD:
137                         printsigsource(sip);
138                         tprints(", si_status=");
139                         if (sip->si_code == CLD_EXITED)
140                                 tprintf("%d", sip->si_status);
141                         else
142                                 printsignal(sip->si_status);
143                         if (!verbose)
144                                 tprints(", ...");
145                         else
146                                 tprintf(", si_utime=%llu, si_stime=%llu",
147                                         (unsigned long long) sip->si_utime,
148                                         (unsigned long long) sip->si_stime);
149                         break;
150                 case SIGILL: case SIGFPE:
151                 case SIGSEGV: case SIGBUS:
152                         tprintf(", si_addr=%#lx",
153                                 (unsigned long) sip->si_addr);
154                         break;
155                 case SIGPOLL:
156                         switch (sip->si_code) {
157                         case POLL_IN: case POLL_OUT: case POLL_MSG:
158                                 tprintf(", si_band=%ld",
159                                         (long) sip->si_band);
160                                 break;
161                         }
162                         break;
163 #ifdef HAVE_SIGINFO_T_SI_SYSCALL
164                 case SIGSYS:
165                         tprintf(", si_call_addr=%#lx, si_syscall=__NR_%s, si_arch=",
166                                 (unsigned long) sip->si_call_addr,
167                                 syscall_name(sip->si_syscall));
168                         printxval(audit_arch, sip->si_arch, "AUDIT_ARCH_???");
169                         break;
170 #endif
171                 default:
172                         if (sip->si_pid || sip->si_uid)
173                                 printsigsource(sip);
174                         if (sip->si_ptr)
175                                 printsigval(sip, verbose);
176                 }
177         }
178 }
179
180 #ifdef IN_MPERS
181 static
182 #endif
183 void
184 printsiginfo(const siginfo_t *sip, bool verbose)
185 {
186         if (sip->si_signo == 0) {
187                 tprints("{}");
188                 return;
189         }
190         tprints("{si_signo=");
191         printsignal(sip->si_signo);
192
193         tprints(", si_code=");
194         print_si_code(sip->si_signo, sip->si_code);
195
196 #ifdef SI_NOINFO
197         if (sip->si_code != SI_NOINFO)
198 #endif
199                 print_si_info(sip, verbose);
200
201         tprints("}");
202 }
203
204 MPERS_PRINTER_DECL(void, printsiginfo_at)(struct tcb *tcp, long addr)
205 {
206         siginfo_t si;
207
208         if (!umove_or_printaddr(tcp, addr, &si))
209                 printsiginfo(&si, verbose(tcp));
210 }