]> granicus.if.org Git - strace/blob - sock.c
nlattr: add UID/GID netlink attribute decoders
[strace] / sock.c
1 /*
2  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
3  * Copyright (c) 1996-2017 The strace developers.
4  * All rights reserved.
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  * 3. The name of the author may not be used to endorse or promote products
15  *    derived from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "defs.h"
30 #include "print_fields.h"
31
32 #include <sys/socket.h>
33 #if defined ALPHA || defined SH || defined SH64
34 # include <linux/ioctl.h>
35 #endif
36 #include <linux/sockios.h>
37 #include <arpa/inet.h>
38 #include <net/if.h>
39
40 #include DEF_MPERS_TYPE(struct_ifconf)
41 #include DEF_MPERS_TYPE(struct_ifreq)
42
43 typedef struct ifconf struct_ifconf;
44 typedef struct ifreq struct_ifreq;
45
46 #include MPERS_DEFS
47
48 #include "xlat/iffflags.h"
49
50 #define XLAT_MACROS_ONLY
51 # include "xlat/arp_hardware_types.h"
52 #undef XLAT_MACROS_ONLY
53
54 static void
55 print_ifname(const char *ifname)
56 {
57         print_quoted_string(ifname, IFNAMSIZ + 1, QUOTE_0_TERMINATED);
58 }
59
60 static void
61 print_ifreq(struct tcb *const tcp, const unsigned int code,
62             const kernel_ulong_t arg, const struct_ifreq *const ifr)
63 {
64         switch (code) {
65         case SIOCSIFADDR:
66         case SIOCGIFADDR:
67                 PRINT_FIELD_SOCKADDR("", *ifr, ifr_addr);
68                 break;
69         case SIOCSIFDSTADDR:
70         case SIOCGIFDSTADDR:
71                 PRINT_FIELD_SOCKADDR("", *ifr, ifr_dstaddr);
72                 break;
73         case SIOCSIFBRDADDR:
74         case SIOCGIFBRDADDR:
75                 PRINT_FIELD_SOCKADDR("", *ifr, ifr_broadaddr);
76                 break;
77         case SIOCSIFNETMASK:
78         case SIOCGIFNETMASK:
79                 PRINT_FIELD_SOCKADDR("", *ifr, ifr_netmask);
80                 break;
81         case SIOCSIFHWADDR:
82         case SIOCGIFHWADDR: {
83                 static uint8_t hwaddr_sizes[] = {
84                         [0 ... ARPHRD_IEEE802_TR] = 255,
85
86                         [ARPHRD_NETROM]     =  7 /* AX25_ADDR_LEN */,
87                         [ARPHRD_ETHER]      =  6 /* ETH_ALEN */,
88                         /* ARPHRD_EETHER - no actual devices in Linux */
89                         [ARPHRD_AX25]       =  7 /* AX25_ADDR_LEN */,
90                         /* ARPHRD_PRONET - no actual devices in Linux */
91                         /* ARPHRD_CHAOS - no actual devices in Linux */
92                         [ARPHRD_IEEE802]    =  6 /* FC_ALEN */,
93                         [ARPHRD_ARCNET]     =  1 /* ARCNET_ALEN */,
94                         /* ARPHRD_APPLETLK - no actual devices in Linux */
95                         [ARPHRD_DLCI]       = sizeof(short),
96                         /* ARPHRD_ATM - no explicit setting */
97                         /* ARPHRD_METRICOM - no actual devices in Linux */
98                         [ARPHRD_IEEE1394]   = 16 /* FWNET_ALEN */,
99                         [ARPHRD_EUI64]      =  8 /* EUI64_ADDR_LEN */,
100                         [ARPHRD_INFINIBAND] = 20 /* INFINIBAND_ALEN */,
101                         [ARPHRD_SLIP]       =  0,
102                         /* ARPHRD_CSLIP - no actual devices in Linux */
103                         /* ARPHRD_SLIP6 - no actual devices in Linux */
104                         /* ARPHRD_CSLIP6 - no actual devices in Linux */
105                         /* ARPHRD_RSRVD - no actual devices in Linux */
106                         /* ARPHRD_ADAPT - no actual devices in Linux */
107                         [ARPHRD_ROSE]       =  5 /* ROSE_ADDR_LEN */,
108                         [ARPHRD_X25]        =  0,
109                         /* ARPHRD_HWX25 - no actual devices in Linux */
110                         [ARPHRD_CAN]        =  0,
111                         [ARPHRD_PPP]        =  0,
112                         /* ARPHRD_CISCO - no actual devices in Linux */
113                         /* ARPHRD_LAPB - no actual devices in Linux */
114                         /* ARPHRD_DDCMP - no actual devices in Linux */
115                         [ARPHRD_RAWHDLC]    =  0,
116                         [ARPHRD_RAWIP]      =  0,
117                         [ARPHRD_TUNNEL]     =  4 /* IPIP */,
118                         [ARPHRD_TUNNEL6]    = 16 /* sizeof(struct in6_addr) */,
119                         /* ARPHRD_FRAD - no actual devices in Linux */
120                         /* ARPHRD_SKIP - no actual devices in Linux */
121                         [ARPHRD_LOOPBACK]   =  6 /* ETH_ALEN */,
122                         [ARPHRD_LOCALTLK]   =  1 /* LTALK_ALEN */,
123                         [ARPHRD_FDDI]       =  6 /* FDDI_K_ALEN */,
124                         /* ARPHRD_BIF - no actual devices in Linux */
125                         [ARPHRD_SIT]        =  4,
126                         [ARPHRD_IPDDP]      =  0,
127                         [ARPHRD_IPGRE]      =  4,
128                         [ARPHRD_PIMREG]     =  0,
129                         [ARPHRD_HIPPI]      =  6 /* HIPPI_ALEN */,
130                         /* ARPHRD_ASH - no actual devices in Linux */
131                         /* ARPHRD_ECONET - no actual devices in Linux */
132                         [ARPHRD_IRDA]       =  4 /* LAP_ALEN */,
133                         /* ARPHRD_FCPP - no actual devices in Linux */
134                         /* ARPHRD_FCAL - no actual devices in Linux */
135                         /* ARPHRD_FCPL - no actual devices in Linux */
136                         /* ARPHRD_FCFABRIC - no actual devices in Linux */
137                         /* ARPHRD_IEEE802_TR - no actual devices in Linux */
138                         [ARPHRD_IEEE80211]  =  6 /* ETH_ALEN */,
139                         [ARPHRD_IEEE80211_PRISM] = 6 /* ETH_ALEN */,
140                         [ARPHRD_IEEE80211_RADIOTAP] = 6 /* ETH_ALEN */,
141                         [ARPHRD_IEEE802154]
142                                 = 8 /* IEEE802154_EXTENDED_ADDR_LEN */,
143                         [ARPHRD_IEEE802154_MONITOR]
144                                 = 8 /* IEEE802154_EXTENDED_ADDR_LEN */,
145                         [ARPHRD_PHONET]     =  1,
146                         [ARPHRD_PHONET_PIPE] = 1,
147                         [ARPHRD_CAIF]       =  0,
148                         [ARPHRD_IP6GRE]     = 16 /* sizeof(struct in6_addr) */,
149                         [ARPHRD_NETLINK]    =  0,
150                         [ARPHRD_6LOWPAN]    =  8 /* EUI64_ADDR_LEN */
151                                 /* ^ or ETH_ALEN, depending on lltype */,
152                         [ARPHRD_VSOCKMON]   =  0,
153                 };
154
155                 uint16_t proto = ifr->ifr_hwaddr.sa_family;
156                 uint8_t sz = (proto < ARRAY_SIZE(hwaddr_sizes))
157                                 ? hwaddr_sizes[proto] : 255;
158
159                 PRINT_FIELD_XVAL_SORTED_SIZED("ifr_hwaddr={", ifr->ifr_hwaddr,
160                                               sa_family, arp_hardware_types,
161                                               arp_hardware_types_size,
162                                               "ARPHRD_???");
163                 PRINT_FIELD_MAC_SZ(", ", ifr->ifr_hwaddr, sa_data,
164                                    MIN(sizeof(ifr->ifr_hwaddr.sa_data), sz));
165                 tprints("}");
166                 break;
167         }
168         case SIOCSIFFLAGS:
169         case SIOCGIFFLAGS:
170                 tprints("ifr_flags=");
171                 printflags(iffflags, (unsigned short) ifr->ifr_flags, "IFF_???");
172                 break;
173         case SIOCSIFMETRIC:
174         case SIOCGIFMETRIC:
175                 tprintf("ifr_metric=%d", ifr->ifr_metric);
176                 break;
177         case SIOCSIFMTU:
178         case SIOCGIFMTU:
179                 tprintf("ifr_mtu=%d", ifr->ifr_mtu);
180                 break;
181         case SIOCSIFSLAVE:
182         case SIOCGIFSLAVE:
183                 tprints("ifr_slave=");
184                 print_ifname(ifr->ifr_slave);
185                 break;
186         case SIOCSIFTXQLEN:
187         case SIOCGIFTXQLEN:
188                 tprintf("ifr_qlen=%d", ifr->ifr_qlen);
189                 break;
190         case SIOCSIFMAP:
191         case SIOCGIFMAP:
192                 tprintf("ifr_map={mem_start=%#" PRI_klx ", "
193                         "mem_end=%#" PRI_klx ", base_addr=%#x, "
194                         "irq=%u, dma=%u, port=%u}",
195                         (kernel_ulong_t) ifr->ifr_map.mem_start,
196                         (kernel_ulong_t) ifr->ifr_map.mem_end,
197                         (unsigned) ifr->ifr_map.base_addr,
198                         (unsigned) ifr->ifr_map.irq,
199                         (unsigned) ifr->ifr_map.dma,
200                         (unsigned) ifr->ifr_map.port);
201                 break;
202         }
203 }
204
205 static unsigned int
206 print_ifc_len(int len)
207 {
208         const unsigned int n = (unsigned int) len / sizeof(struct_ifreq);
209
210         if (len < 0 || n * sizeof(struct_ifreq) != (unsigned int) len)
211                 tprintf("%d", len);
212         else
213                 tprintf("%u * sizeof(struct ifreq)", n);
214
215         return n;
216 }
217
218 static bool
219 print_ifconf_ifreq(struct tcb *tcp, void *elem_buf, size_t elem_size,
220                    void *dummy)
221 {
222         struct_ifreq *ifr = elem_buf;
223
224         tprints("{ifr_name=");
225         print_ifname(ifr->ifr_name);
226         PRINT_FIELD_SOCKADDR(", ", *ifr, ifr_addr);
227         tprints("}");
228
229         return true;
230 }
231
232 /*
233  * There are two different modes of operation:
234  *
235  * - Get buffer size.  In this case, the callee sets ifc_buf to NULL,
236  *   and the kernel returns the buffer size in ifc_len.
237  * - Get actual data.  In this case, the callee specifies the buffer address
238  *   in ifc_buf and its size in ifc_len.  The kernel fills the buffer with
239  *   the data, and its amount is returned in ifc_len.
240  *
241  * Note that, technically, the whole struct ifconf is overwritten,
242  * so ifc_buf could be different on exit, but current ioctl handler
243  * implementation does not touch it.
244  */
245 static int
246 decode_ifconf(struct tcb *const tcp, const kernel_ulong_t addr)
247 {
248         struct_ifconf *entering_ifc = NULL;
249         struct_ifconf *ifc =
250                 entering(tcp) ? malloc(sizeof(*ifc)) : alloca(sizeof(*ifc));
251
252         if (exiting(tcp)) {
253                 entering_ifc = get_tcb_priv_data(tcp);
254
255                 if (!entering_ifc) {
256                         error_func_msg("where is my ifconf?");
257                         return 0;
258                 }
259         }
260
261         if (!ifc || umove(tcp, addr, ifc) < 0) {
262                 if (entering(tcp)) {
263                         free(ifc);
264
265                         tprints(", ");
266                         printaddr(addr);
267                 } else {
268                         /*
269                          * We failed to fetch the structure on exiting syscall,
270                          * print whatever was fetched on entering syscall.
271                          */
272                         if (!entering_ifc->ifc_buf)
273                                 print_ifc_len(entering_ifc->ifc_len);
274
275                         tprints(", ifc_buf=");
276                         printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
277
278                         tprints("}");
279                 }
280
281                 return RVAL_IOCTL_DECODED;
282         }
283
284         if (entering(tcp)) {
285                 tprints(", {ifc_len=");
286                 if (ifc->ifc_buf)
287                         print_ifc_len(ifc->ifc_len);
288
289                 set_tcb_priv_data(tcp, ifc, free);
290
291                 return 0;
292         }
293
294         /* exiting */
295
296         if (entering_ifc->ifc_buf && (entering_ifc->ifc_len != ifc->ifc_len))
297                 tprints(" => ");
298         if (!entering_ifc->ifc_buf || (entering_ifc->ifc_len != ifc->ifc_len))
299                 print_ifc_len(ifc->ifc_len);
300
301         tprints(", ifc_buf=");
302
303         if (!entering_ifc->ifc_buf || syserror(tcp)) {
304                 printaddr(ptr_to_kulong(entering_ifc->ifc_buf));
305                 if (entering_ifc->ifc_buf != ifc->ifc_buf) {
306                         tprints(" => ");
307                         printaddr(ptr_to_kulong(ifc->ifc_buf));
308                 }
309         } else {
310                 struct_ifreq ifr;
311
312                 print_array(tcp, ptr_to_kulong(ifc->ifc_buf),
313                             ifc->ifc_len / sizeof(struct_ifreq),
314                             &ifr, sizeof(ifr),
315                             tfetch_mem, print_ifconf_ifreq, NULL);
316         }
317
318         tprints("}");
319
320         return RVAL_IOCTL_DECODED;
321 }
322
323 MPERS_PRINTER_DECL(int, sock_ioctl,
324                    struct tcb *tcp, const unsigned int code,
325                    const kernel_ulong_t arg)
326 {
327         struct_ifreq ifr;
328
329         switch (code) {
330         case SIOCGIFCONF:
331                 return decode_ifconf(tcp, arg);
332
333 #ifdef SIOCBRADDBR
334         case SIOCBRADDBR:
335         case SIOCBRDELBR:
336                 tprints(", ");
337                 printstr(tcp, arg);
338                 break;
339 #endif
340
341 #ifdef FIOSETOWN
342         case FIOSETOWN:
343 #endif
344 #ifdef SIOCSPGRP
345         case SIOCSPGRP:
346 #endif
347                 tprints(", ");
348                 printnum_int(tcp, arg, "%d");
349                 break;
350
351 #ifdef FIOGETOWN
352         case FIOGETOWN:
353 #endif
354 #ifdef SIOCGPGRP
355         case SIOCGPGRP:
356 #endif
357 #ifdef SIOCATMARK
358         case SIOCATMARK:
359 #endif
360                 if (entering(tcp))
361                         return 0;
362                 tprints(", ");
363                 printnum_int(tcp, arg, "%d");
364                 break;
365
366 #ifdef SIOCBRADDIF
367         case SIOCBRADDIF:
368 #endif
369 #ifdef SIOCBRDELIF
370         case SIOCBRDELIF:
371 #endif
372                 /* no arguments */
373                 break;
374
375         case SIOCSIFNAME:
376         case SIOCSIFADDR:
377         case SIOCSIFDSTADDR:
378         case SIOCSIFBRDADDR:
379         case SIOCSIFNETMASK:
380         case SIOCSIFFLAGS:
381         case SIOCSIFMETRIC:
382         case SIOCSIFMTU:
383         case SIOCSIFSLAVE:
384         case SIOCSIFHWADDR:
385         case SIOCSIFTXQLEN:
386         case SIOCSIFMAP:
387                 tprints(", ");
388                 if (umove_or_printaddr(tcp, arg, &ifr))
389                         break;
390
391                 tprints("{ifr_name=");
392                 print_ifname(ifr.ifr_name);
393                 tprints(", ");
394                 if (code == SIOCSIFNAME) {
395                         tprints("ifr_newname=");
396                         print_ifname(ifr.ifr_newname);
397                 } else {
398                         print_ifreq(tcp, code, arg, &ifr);
399                 }
400                 tprints("}");
401                 break;
402
403         case SIOCGIFNAME:
404         case SIOCGIFINDEX:
405         case SIOCGIFADDR:
406         case SIOCGIFDSTADDR:
407         case SIOCGIFBRDADDR:
408         case SIOCGIFNETMASK:
409         case SIOCGIFFLAGS:
410         case SIOCGIFMETRIC:
411         case SIOCGIFMTU:
412         case SIOCGIFSLAVE:
413         case SIOCGIFHWADDR:
414         case SIOCGIFTXQLEN:
415         case SIOCGIFMAP:
416                 if (entering(tcp)) {
417                         tprints(", ");
418                         if (umove_or_printaddr(tcp, arg, &ifr))
419                                 break;
420
421                         if (SIOCGIFNAME == code) {
422                                 tprintf("{ifr_index=%d", ifr.ifr_ifindex);
423                         } else {
424                                 tprints("{ifr_name=");
425                                 print_ifname(ifr.ifr_name);
426                         }
427                         return 0;
428                 } else {
429                         if (syserror(tcp)) {
430                                 tprints("}");
431                                 break;
432                         }
433
434                         tprints(", ");
435                         if (umove(tcp, arg, &ifr) < 0) {
436                                 tprints("???}");
437                                 break;
438                         }
439
440                         if (SIOCGIFNAME == code) {
441                                 tprints("ifr_name=");
442                                 print_ifname(ifr.ifr_name);
443                         } else {
444                                 print_ifreq(tcp, code, arg, &ifr);
445                         }
446                         tprints("}");
447                         break;
448                 }
449
450         default:
451                 return RVAL_DECODED;
452         }
453
454         return RVAL_IOCTL_DECODED;
455 }