]> granicus.if.org Git - strace/blob - ioctl.c
tests: add variants of IPC tests with different xlat verbosity levels
[strace] / ioctl.c
1 /*
2  * Copyright (c) 1991, 1992 Paul Kranenburg <pk@cs.few.eur.nl>
3  * Copyright (c) 1993 Branko Lankester <branko@hacktic.nl>
4  * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
5  * Copyright (c) 1996-2001 Wichert Akkerman <wichert@cistron.nl>
6  * Copyright (c) 1999-2018 The strace developers.
7  * All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  * 1. Redistributions of source code must retain the above copyright
13  *    notice, this list of conditions and the following disclaimer.
14  * 2. Redistributions in binary form must reproduce the above copyright
15  *    notice, this list of conditions and the following disclaimer in the
16  *    documentation and/or other materials provided with the distribution.
17  * 3. The name of the author may not be used to endorse or promote products
18  *    derived from this software without specific prior written permission.
19  *
20  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
21  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
22  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
24  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
29  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30  */
31
32 #include "defs.h"
33 #include <linux/ioctl.h>
34 #include "xlat/ioctl_dirs.h"
35
36 #include "xlat/evdev_ev.h"
37
38 static int
39 compare(const void *a, const void *b)
40 {
41         const unsigned int code1 = (const uintptr_t) a;
42         const unsigned int code2 = ((struct_ioctlent *) b)->code;
43         return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0;
44 }
45
46 static const struct_ioctlent *
47 ioctl_lookup(const unsigned int code)
48 {
49         struct_ioctlent *iop;
50
51         iop = bsearch((const void *) (const uintptr_t) code, ioctlent,
52                         nioctlents, sizeof(ioctlent[0]), compare);
53         while (iop > ioctlent) {
54                 iop--;
55                 if (iop->code != code) {
56                         iop++;
57                         break;
58                 }
59         }
60         return iop;
61 }
62
63 static const struct_ioctlent *
64 ioctl_next_match(const struct_ioctlent *iop)
65 {
66         const unsigned int code = iop->code;
67         iop++;
68         if (iop < ioctlent + nioctlents && iop->code == code)
69                 return iop;
70         return NULL;
71 }
72
73 static void
74 ioctl_print_code(const unsigned int code)
75 {
76         tprints("_IOC(");
77         printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???");
78         tprintf(", %#x, %#x, %#x)",
79                 _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
80 }
81
82 static int
83 evdev_decode_number(const unsigned int code)
84 {
85         const unsigned int nr = _IOC_NR(code);
86
87         if (_IOC_DIR(code) == _IOC_WRITE) {
88                 if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) {
89                         tprints("EVIOCSABS(");
90                         printxval_indexn(evdev_abs, evdev_abs_size, nr - 0xc0,
91                                          "ABS_???");
92                         tprints(")");
93                         return 1;
94                 }
95         }
96
97         if (_IOC_DIR(code) != _IOC_READ)
98                 return 0;
99
100         if (nr >= 0x20 && nr <= 0x20 + 0x1f) {
101                 tprints("EVIOCGBIT(");
102                 printxval(evdev_ev, nr - 0x20, "EV_???");
103                 tprintf(", %u)", _IOC_SIZE(code));
104                 return 1;
105         } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) {
106                 tprints("EVIOCGABS(");
107                 printxval_indexn(evdev_abs, evdev_abs_size, nr - 0x40,
108                                  "ABS_???");
109                 tprints(")");
110                 return 1;
111         }
112
113         switch (_IOC_NR(nr)) {
114                 case 0x06:
115                         tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code));
116                         return 1;
117                 case 0x07:
118                         tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code));
119                         return 1;
120                 case 0x08:
121                         tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code));
122                         return 1;
123                 case 0x09:
124                         tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code));
125                         return 1;
126                 case 0x0a:
127                         tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code));
128                         return 1;
129                 case 0x18:
130                         tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code));
131                         return 1;
132                 case 0x19:
133                         tprintf("EVIOCGLED(%u)", _IOC_SIZE(code));
134                         return 1;
135                 case 0x1a:
136                         tprintf("EVIOCGSND(%u)", _IOC_SIZE(code));
137                         return 1;
138                 case 0x1b:
139                         tprintf("EVIOCGSW(%u)", _IOC_SIZE(code));
140                         return 1;
141                 default:
142                         return 0;
143         }
144 }
145
146 static int
147 hiddev_decode_number(const unsigned int code)
148 {
149         if (_IOC_DIR(code) == _IOC_READ) {
150                 switch (_IOC_NR(code)) {
151                         case 0x04:
152                                 tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code));
153                                 return 1;
154                         case 0x05:
155                                 tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code));
156                                 return 1;
157                         case 0x06:
158                                 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
159                                 return 1;
160                         case 0x12:
161                                 tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code));
162                                 return 1;
163                         default:
164                                 return 0;
165                 }
166         } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) {
167                 switch (_IOC_NR(code)) {
168                         case 0x06:
169                                 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
170                                 return 1;
171                         case 0x07:
172                                 tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code));
173                                 return 1;
174                         default:
175                                 return 0;
176                 }
177         }
178
179         return 0;
180 }
181
182 static int
183 ioctl_decode_command_number(struct tcb *tcp)
184 {
185         const unsigned int code = tcp->u_arg[1];
186
187         switch (_IOC_TYPE(code)) {
188                 case 'E':
189                         return evdev_decode_number(code);
190                 case 'H':
191                         return hiddev_decode_number(code);
192                 case 'M':
193                         if (_IOC_DIR(code) == _IOC_WRITE) {
194                                 tprintf("MIXER_WRITE(%u)", _IOC_NR(code));
195                                 return 1;
196                         } else if (_IOC_DIR(code) == _IOC_READ) {
197                                 tprintf("MIXER_READ(%u)", _IOC_NR(code));
198                                 return 1;
199                         }
200                         return 0;
201                 case 'U':
202                         if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) {
203                                 tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code));
204                                 return 1;
205                         }
206                         return 0;
207                 case 'j':
208                         if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) {
209                                 tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code));
210                                 return 1;
211                         }
212                         return 0;
213                 case 'k':
214                         if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) {
215                                 tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code));
216                                 return 1;
217                         }
218                         return 0;
219                 default:
220                         return 0;
221         }
222 }
223
224 /**
225  * Decode arg parameter of the ioctl call.
226  *
227  * @return There are two flags of the return value important for the purposes of
228  *         processing by SYS_FUNC(ioctl):
229  *          - RVAL_IOCTL_DECODED: indicates that ioctl decoder code
230  *                                has printed arg parameter;
231  *          - RVAL_DECODED: indicates that decoding is done.
232  *         As a result, the following behaviour is expected:
233  *          - on entering:
234  *            - 0: decoding should be continued on exiting;
235  *            - RVAL_IOCTL_DECODED: decoding on exiting is not needed
236  *                                  and decoder has printed arg value;
237  *            - RVAL_DECODED: decoding on exiting is not needed
238  *                            and generic handler should print arg value.
239  *          - on exiting:
240  *            - 0: generic handler should print arg value;
241  *            - RVAL_IOCTL_DECODED: decoder has printed arg value.
242  *
243  *         Note that it makes no sense to return just RVAL_DECODED on exiting,
244  *         but, of course, it is not prohibited (for example, it may be useful
245  *         in cases where the return path is common on entering and on exiting
246  *         the syscall).
247  *
248  *         SYS_FUNC(ioctl) converts RVAL_IOCTL_DECODED flag to RVAL_DECODED,
249  *         and passes all other bits of ioctl_decode return value unchanged.
250  */
251 static int
252 ioctl_decode(struct tcb *tcp)
253 {
254         const unsigned int code = tcp->u_arg[1];
255         const kernel_ulong_t arg = tcp->u_arg[2];
256
257         switch (_IOC_TYPE(code)) {
258 #if defined(ALPHA) || defined(POWERPC)
259         case 'f': {
260                 int ret = file_ioctl(tcp, code, arg);
261                 if (ret != RVAL_DECODED)
262                         return ret;
263                 ATTRIBUTE_FALLTHROUGH;
264         }
265         case 't':
266         case 'T':
267                 return term_ioctl(tcp, code, arg);
268 #else /* !ALPHA */
269         case 'f':
270                 return file_ioctl(tcp, code, arg);
271         case 0x54:
272 #endif /* !ALPHA */
273                 return term_ioctl(tcp, code, arg);
274         case 0x89:
275                 return sock_ioctl(tcp, code, arg);
276         case 'p':
277                 return rtc_ioctl(tcp, code, arg);
278         case 0x03:
279                 return hdio_ioctl(tcp, code, arg);
280         case 0x12:
281                 return block_ioctl(tcp, code, arg);
282         case 'X':
283                 return fs_x_ioctl(tcp, code, arg);
284         case 0x22:
285                 return scsi_ioctl(tcp, code, arg);
286         case 'L':
287                 return loop_ioctl(tcp, code, arg);
288 #ifdef HAVE_STRUCT_MTD_WRITE_REQ
289         case 'M':
290                 return mtd_ioctl(tcp, code, arg);
291 #endif
292 #ifdef HAVE_STRUCT_UBI_ATTACH_REQ_MAX_BEB_PER1024
293         case 'o':
294         case 'O':
295                 return ubi_ioctl(tcp, code, arg);
296 #endif
297         case 'V':
298                 return v4l2_ioctl(tcp, code, arg);
299 #ifdef HAVE_STRUCT_PTP_SYS_OFFSET
300         case '=':
301                 return ptp_ioctl(tcp, code, arg);
302 #endif
303 #ifdef HAVE_LINUX_INPUT_H
304         case 'E':
305                 return evdev_ioctl(tcp, code, arg);
306 #endif
307 #ifdef HAVE_LINUX_USERFAULTFD_H
308         case 0xaa:
309                 return uffdio_ioctl(tcp, code, arg);
310 #endif
311 #ifdef HAVE_LINUX_BTRFS_H
312         case 0x94:
313                 return btrfs_ioctl(tcp, code, arg);
314 #endif
315         case 0xb7:
316                 return nsfs_ioctl(tcp, code, arg);
317 #ifdef HAVE_LINUX_DM_IOCTL_H
318         case 0xfd:
319                 return dm_ioctl(tcp, code, arg);
320 #endif
321 #ifdef HAVE_LINUX_KVM_H
322         case 0xae:
323                 return kvm_ioctl(tcp, code, arg);
324 #endif
325         default:
326                 break;
327         }
328         return 0;
329 }
330
331 SYS_FUNC(ioctl)
332 {
333         const struct_ioctlent *iop;
334         int ret;
335
336         if (entering(tcp)) {
337                 printfd(tcp, tcp->u_arg[0]);
338                 tprints(", ");
339
340                 if (xlat_verbosity != XLAT_STYLE_ABBREV)
341                         tprintf("%#x", (unsigned int) tcp->u_arg[1]);
342                 if (xlat_verbosity == XLAT_STYLE_VERBOSE)
343                         tprints(" /* ");
344                 if (xlat_verbosity != XLAT_STYLE_RAW) {
345                         ret = ioctl_decode_command_number(tcp);
346                         if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
347                                 iop = ioctl_lookup(tcp->u_arg[1]);
348                                 if (iop) {
349                                         if (ret)
350                                                 tprints(" or ");
351                                         tprints(iop->symbol);
352                                         while ((iop = ioctl_next_match(iop)))
353                                                 tprintf(" or %s", iop->symbol);
354                                 } else if (!ret) {
355                                         ioctl_print_code(tcp->u_arg[1]);
356                                 }
357                         }
358                 }
359                 if (xlat_verbosity == XLAT_STYLE_VERBOSE)
360                         tprints(" */");
361
362                 ret = ioctl_decode(tcp);
363         } else {
364                 ret = ioctl_decode(tcp) | RVAL_DECODED;
365         }
366
367         if (ret & RVAL_IOCTL_DECODED) {
368                 ret &= ~RVAL_IOCTL_DECODED;
369                 ret |= RVAL_DECODED;
370         } else if (ret & RVAL_DECODED) {
371                 tprintf(", %#" PRI_klx, tcp->u_arg[2]);
372         }
373
374         return ret;
375 }