Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 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> |
Wichert Akkerman | c6c1ea5 | 2001-08-03 21:52:13 +0000 | [diff] [blame] | 5 | * Copyright (c) 1996-2001 Wichert Akkerman <wichert@cistron.nl> |
Elliott Hughes | 28e98bc | 2018-06-14 16:59:04 -0700 | [diff] [blame] | 6 | * Copyright (c) 1999-2018 The strace developers. |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 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. |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 30 | */ |
| 31 | |
| 32 | #include "defs.h" |
Felix Janda | 3460dc4 | 2015-03-28 18:40:13 +0100 | [diff] [blame] | 33 | #include <linux/ioctl.h> |
Dmitry V. Levin | 924996a | 2015-01-20 00:24:36 +0000 | [diff] [blame] | 34 | #include "xlat/ioctl_dirs.h" |
Wichert Akkerman | a966785 | 2001-03-17 17:26:34 +0000 | [diff] [blame] | 35 | |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 36 | static int |
Denys Vlasenko | 1201426 | 2011-05-30 14:00:14 +0200 | [diff] [blame] | 37 | compare(const void *a, const void *b) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 38 | { |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 39 | const unsigned int code1 = (const uintptr_t) a; |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 40 | const unsigned int code2 = ((struct_ioctlent *) b)->code; |
Denys Vlasenko | feb40c4 | 2012-03-20 13:11:51 +0100 | [diff] [blame] | 41 | return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 42 | } |
| 43 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 44 | static const struct_ioctlent * |
Dmitry V. Levin | df7aa2b | 2015-01-19 17:02:16 +0000 | [diff] [blame] | 45 | ioctl_lookup(const unsigned int code) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 46 | { |
Denys Vlasenko | a9fe13c | 2013-02-22 13:26:10 +0100 | [diff] [blame] | 47 | struct_ioctlent *iop; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 48 | |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 49 | iop = bsearch((const void *) (const uintptr_t) code, ioctlent, |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 50 | nioctlents, sizeof(ioctlent[0]), compare); |
| 51 | while (iop > ioctlent) { |
| 52 | iop--; |
| 53 | if (iop->code != code) { |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 54 | iop++; |
| 55 | break; |
| 56 | } |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 57 | } |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 58 | return iop; |
| 59 | } |
| 60 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 61 | static const struct_ioctlent * |
Denys Vlasenko | a9fe13c | 2013-02-22 13:26:10 +0100 | [diff] [blame] | 62 | ioctl_next_match(const struct_ioctlent *iop) |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 63 | { |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 64 | const unsigned int code = iop->code; |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 65 | iop++; |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 66 | if (iop < ioctlent + nioctlents && iop->code == code) |
| 67 | return iop; |
| 68 | return NULL; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 69 | } |
| 70 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 71 | static void |
Dmitry V. Levin | 924996a | 2015-01-20 00:24:36 +0000 | [diff] [blame] | 72 | ioctl_print_code(const unsigned int code) |
| 73 | { |
| 74 | tprints("_IOC("); |
| 75 | printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???"); |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 76 | tprintf(", %#x, %#x, %#x)", |
Dmitry V. Levin | 924996a | 2015-01-20 00:24:36 +0000 | [diff] [blame] | 77 | _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code)); |
| 78 | } |
| 79 | |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 80 | static int |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 81 | evdev_decode_number(const unsigned int code) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 82 | { |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 83 | const unsigned int nr = _IOC_NR(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 84 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 85 | if (_IOC_DIR(code) == _IOC_WRITE) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 86 | if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) { |
| 87 | tprints("EVIOCSABS("); |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 88 | printxval_indexn(evdev_abs, evdev_abs_size, nr - 0xc0, |
| 89 | "ABS_???"); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 90 | tprints(")"); |
| 91 | return 1; |
| 92 | } |
| 93 | } |
| 94 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 95 | if (_IOC_DIR(code) != _IOC_READ) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 96 | return 0; |
| 97 | |
| 98 | if (nr >= 0x20 && nr <= 0x20 + 0x1f) { |
| 99 | tprints("EVIOCGBIT("); |
Elliott Hughes | c187376 | 2018-12-19 15:13:36 -0800 | [diff] [blame^] | 100 | if (nr == 0x20) |
| 101 | tprintf("0"); |
| 102 | else |
| 103 | printxval(evdev_ev, nr - 0x20, "EV_???"); |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 104 | tprintf(", %u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 105 | return 1; |
| 106 | } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) { |
| 107 | tprints("EVIOCGABS("); |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 108 | printxval_indexn(evdev_abs, evdev_abs_size, nr - 0x40, |
| 109 | "ABS_???"); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 110 | tprints(")"); |
| 111 | return 1; |
| 112 | } |
| 113 | |
| 114 | switch (_IOC_NR(nr)) { |
| 115 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 116 | tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 117 | return 1; |
| 118 | case 0x07: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 119 | tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 120 | return 1; |
| 121 | case 0x08: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 122 | tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 123 | return 1; |
| 124 | case 0x09: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 125 | tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 126 | return 1; |
| 127 | case 0x0a: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 128 | tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 129 | return 1; |
| 130 | case 0x18: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 131 | tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 132 | return 1; |
| 133 | case 0x19: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 134 | tprintf("EVIOCGLED(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 135 | return 1; |
| 136 | case 0x1a: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 137 | tprintf("EVIOCGSND(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 138 | return 1; |
| 139 | case 0x1b: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 140 | tprintf("EVIOCGSW(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 141 | return 1; |
| 142 | default: |
| 143 | return 0; |
| 144 | } |
| 145 | } |
| 146 | |
| 147 | static int |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 148 | hiddev_decode_number(const unsigned int code) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 149 | { |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 150 | if (_IOC_DIR(code) == _IOC_READ) { |
| 151 | switch (_IOC_NR(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 152 | case 0x04: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 153 | tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 154 | return 1; |
| 155 | case 0x05: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 156 | tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 157 | return 1; |
| 158 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 159 | tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 160 | return 1; |
| 161 | case 0x12: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 162 | tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 163 | return 1; |
| 164 | default: |
| 165 | return 0; |
| 166 | } |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 167 | } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) { |
| 168 | switch (_IOC_NR(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 169 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 170 | tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 171 | return 1; |
| 172 | case 0x07: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 173 | tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 174 | return 1; |
| 175 | default: |
| 176 | return 0; |
| 177 | } |
| 178 | } |
| 179 | |
| 180 | return 0; |
| 181 | } |
| 182 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 183 | static int |
Dmitry V. Levin | 4f63c11 | 2015-07-02 22:31:11 +0000 | [diff] [blame] | 184 | ioctl_decode_command_number(struct tcb *tcp) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 185 | { |
Dmitry V. Levin | 4f63c11 | 2015-07-02 22:31:11 +0000 | [diff] [blame] | 186 | const unsigned int code = tcp->u_arg[1]; |
| 187 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 188 | switch (_IOC_TYPE(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 189 | case 'E': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 190 | return evdev_decode_number(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 191 | case 'H': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 192 | return hiddev_decode_number(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 193 | case 'M': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 194 | if (_IOC_DIR(code) == _IOC_WRITE) { |
| 195 | tprintf("MIXER_WRITE(%u)", _IOC_NR(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 196 | return 1; |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 197 | } else if (_IOC_DIR(code) == _IOC_READ) { |
| 198 | tprintf("MIXER_READ(%u)", _IOC_NR(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 199 | return 1; |
| 200 | } |
| 201 | return 0; |
| 202 | case 'U': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 203 | if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) { |
| 204 | tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 205 | return 1; |
| 206 | } |
| 207 | return 0; |
| 208 | case 'j': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 209 | if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) { |
| 210 | tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 211 | return 1; |
| 212 | } |
| 213 | return 0; |
| 214 | case 'k': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 215 | if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) { |
| 216 | tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 217 | return 1; |
| 218 | } |
| 219 | return 0; |
| 220 | default: |
| 221 | return 0; |
| 222 | } |
| 223 | } |
| 224 | |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 225 | /** |
| 226 | * Decode arg parameter of the ioctl call. |
| 227 | * |
| 228 | * @return There are two flags of the return value important for the purposes of |
| 229 | * processing by SYS_FUNC(ioctl): |
| 230 | * - RVAL_IOCTL_DECODED: indicates that ioctl decoder code |
| 231 | * has printed arg parameter; |
| 232 | * - RVAL_DECODED: indicates that decoding is done. |
| 233 | * As a result, the following behaviour is expected: |
| 234 | * - on entering: |
| 235 | * - 0: decoding should be continued on exiting; |
| 236 | * - RVAL_IOCTL_DECODED: decoding on exiting is not needed |
| 237 | * and decoder has printed arg value; |
| 238 | * - RVAL_DECODED: decoding on exiting is not needed |
| 239 | * and generic handler should print arg value. |
| 240 | * - on exiting: |
| 241 | * - 0: generic handler should print arg value; |
| 242 | * - RVAL_IOCTL_DECODED: decoder has printed arg value. |
| 243 | * |
| 244 | * Note that it makes no sense to return just RVAL_DECODED on exiting, |
| 245 | * but, of course, it is not prohibited (for example, it may be useful |
| 246 | * in cases where the return path is common on entering and on exiting |
| 247 | * the syscall). |
| 248 | * |
| 249 | * SYS_FUNC(ioctl) converts RVAL_IOCTL_DECODED flag to RVAL_DECODED, |
| 250 | * and passes all other bits of ioctl_decode return value unchanged. |
| 251 | */ |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 252 | static int |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 253 | ioctl_decode(struct tcb *tcp) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 254 | { |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 255 | const unsigned int code = tcp->u_arg[1]; |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 256 | const kernel_ulong_t arg = tcp->u_arg[2]; |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 257 | |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 258 | switch (_IOC_TYPE(code)) { |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 259 | case '$': |
| 260 | return perf_ioctl(tcp, code, arg); |
Roland McGrath | bb3af52 | 2003-01-14 07:53:34 +0000 | [diff] [blame] | 261 | #if defined(ALPHA) || defined(POWERPC) |
Dmitry V. Levin | 25f3758 | 2016-05-24 00:19:03 +0000 | [diff] [blame] | 262 | case 'f': { |
| 263 | int ret = file_ioctl(tcp, code, arg); |
Jeff Mahoney | 398fe04 | 2016-05-18 18:09:40 -0400 | [diff] [blame] | 264 | if (ret != RVAL_DECODED) |
| 265 | return ret; |
Elliott Hughes | 28e98bc | 2018-06-14 16:59:04 -0700 | [diff] [blame] | 266 | ATTRIBUTE_FALLTHROUGH; |
Dmitry V. Levin | 25f3758 | 2016-05-24 00:19:03 +0000 | [diff] [blame] | 267 | } |
| 268 | case 't': |
Jeff Mahoney | 398fe04 | 2016-05-18 18:09:40 -0400 | [diff] [blame] | 269 | case 'T': |
| 270 | return term_ioctl(tcp, code, arg); |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 271 | #else /* !ALPHA */ |
Jeff Mahoney | 398fe04 | 2016-05-18 18:09:40 -0400 | [diff] [blame] | 272 | case 'f': |
| 273 | return file_ioctl(tcp, code, arg); |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 274 | case 0x54: |
| 275 | #endif /* !ALPHA */ |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 276 | return term_ioctl(tcp, code, arg); |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 277 | case 0x89: |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 278 | return sock_ioctl(tcp, code, arg); |
Roland McGrath | d83c50b | 2004-10-06 22:27:43 +0000 | [diff] [blame] | 279 | case 'p': |
| 280 | return rtc_ioctl(tcp, code, arg); |
Dmitry V. Levin | 4ef6db4 | 2011-01-15 20:15:31 +0000 | [diff] [blame] | 281 | case 0x03: |
Dmitry V. Levin | b3f0040 | 2016-05-26 00:07:17 +0000 | [diff] [blame] | 282 | return hdio_ioctl(tcp, code, arg); |
Dmitry V. Levin | 4ef6db4 | 2011-01-15 20:15:31 +0000 | [diff] [blame] | 283 | case 0x12: |
| 284 | return block_ioctl(tcp, code, arg); |
Dmitry V. Levin | 4dd9f3f | 2016-05-26 00:37:26 +0000 | [diff] [blame] | 285 | case 'X': |
| 286 | return fs_x_ioctl(tcp, code, arg); |
Dmitry V. Levin | b011af5 | 2007-06-30 11:37:09 +0000 | [diff] [blame] | 287 | case 0x22: |
| 288 | return scsi_ioctl(tcp, code, arg); |
Mike Frysinger | ebee04c | 2012-04-17 22:19:31 -0400 | [diff] [blame] | 289 | case 'L': |
| 290 | return loop_ioctl(tcp, code, arg); |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 291 | #ifdef HAVE_STRUCT_MTD_WRITE_REQ |
Mike Frysinger | 0cbed35 | 2012-04-04 22:22:01 -0400 | [diff] [blame] | 292 | case 'M': |
| 293 | return mtd_ioctl(tcp, code, arg); |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 294 | #endif |
| 295 | #ifdef HAVE_STRUCT_UBI_ATTACH_REQ_MAX_BEB_PER1024 |
Mike Frysinger | d648f29 | 2013-05-01 23:35:30 -0400 | [diff] [blame] | 296 | case 'o': |
| 297 | case 'O': |
| 298 | return ubi_ioctl(tcp, code, arg); |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 299 | #endif |
Philippe De Muyter | 0cc9614 | 2014-11-03 21:27:40 +0100 | [diff] [blame] | 300 | case 'V': |
| 301 | return v4l2_ioctl(tcp, code, arg); |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 302 | #ifdef HAVE_STRUCT_PTP_SYS_OFFSET |
Stefan Sørensen | b88a6f8 | 2014-01-31 12:01:01 +0100 | [diff] [blame] | 303 | case '=': |
| 304 | return ptp_ioctl(tcp, code, arg); |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 305 | #endif |
Etienne Gemsa | 4f750b9 | 2015-02-20 17:14:10 +0100 | [diff] [blame] | 306 | #ifdef HAVE_LINUX_INPUT_H |
| 307 | case 'E': |
| 308 | return evdev_ioctl(tcp, code, arg); |
| 309 | #endif |
Dr. David Alan Gilbert | 5d1216a | 2016-05-10 11:49:02 +0100 | [diff] [blame] | 310 | #ifdef HAVE_LINUX_USERFAULTFD_H |
| 311 | case 0xaa: |
| 312 | return uffdio_ioctl(tcp, code, arg); |
| 313 | #endif |
Jeff Mahoney | 8cc6962 | 2016-05-18 18:09:39 -0400 | [diff] [blame] | 314 | #ifdef HAVE_LINUX_BTRFS_H |
| 315 | case 0x94: |
| 316 | return btrfs_ioctl(tcp, code, arg); |
| 317 | #endif |
Elliott Hughes | 39bac05 | 2017-05-25 16:56:11 -0700 | [diff] [blame] | 318 | case 0xb7: |
| 319 | return nsfs_ioctl(tcp, code, arg); |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 320 | #ifdef HAVE_LINUX_DM_IOCTL_H |
| 321 | case 0xfd: |
| 322 | return dm_ioctl(tcp, code, arg); |
| 323 | #endif |
Elliott Hughes | b755614 | 2018-02-20 17:03:16 -0800 | [diff] [blame] | 324 | #ifdef HAVE_LINUX_KVM_H |
| 325 | case 0xae: |
| 326 | return kvm_ioctl(tcp, code, arg); |
| 327 | #endif |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 328 | case 'I': |
| 329 | return inotify_ioctl(tcp, code, arg); |
Elliott Hughes | c187376 | 2018-12-19 15:13:36 -0800 | [diff] [blame^] | 330 | case 0xab: |
| 331 | return nbd_ioctl(tcp, code, arg); |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 332 | default: |
| 333 | break; |
| 334 | } |
| 335 | return 0; |
| 336 | } |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 337 | |
| 338 | SYS_FUNC(ioctl) |
| 339 | { |
| 340 | const struct_ioctlent *iop; |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 341 | int ret; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 342 | |
| 343 | if (entering(tcp)) { |
| 344 | printfd(tcp, tcp->u_arg[0]); |
| 345 | tprints(", "); |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 346 | |
| 347 | if (xlat_verbosity != XLAT_STYLE_ABBREV) |
| 348 | tprintf("%#x", (unsigned int) tcp->u_arg[1]); |
| 349 | if (xlat_verbosity == XLAT_STYLE_VERBOSE) |
| 350 | tprints(" /* "); |
| 351 | if (xlat_verbosity != XLAT_STYLE_RAW) { |
| 352 | ret = ioctl_decode_command_number(tcp); |
| 353 | if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) { |
| 354 | iop = ioctl_lookup(tcp->u_arg[1]); |
| 355 | if (iop) { |
| 356 | if (ret) |
| 357 | tprints(" or "); |
| 358 | tprints(iop->symbol); |
| 359 | while ((iop = ioctl_next_match(iop))) |
| 360 | tprintf(" or %s", iop->symbol); |
| 361 | } else if (!ret) { |
| 362 | ioctl_print_code(tcp->u_arg[1]); |
| 363 | } |
Gabriel Laskar | 8b6046a | 2015-12-04 01:07:33 +0100 | [diff] [blame] | 364 | } |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 365 | } |
Elliott Hughes | 03a418e | 2018-06-15 13:11:40 -0700 | [diff] [blame] | 366 | if (xlat_verbosity == XLAT_STYLE_VERBOSE) |
| 367 | tprints(" */"); |
| 368 | |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 369 | ret = ioctl_decode(tcp); |
| 370 | } else { |
| 371 | ret = ioctl_decode(tcp) | RVAL_DECODED; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 372 | } |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 373 | |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 374 | if (ret & RVAL_IOCTL_DECODED) { |
| 375 | ret &= ~RVAL_IOCTL_DECODED; |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 376 | ret |= RVAL_DECODED; |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 377 | } else if (ret & RVAL_DECODED) { |
| 378 | tprintf(", %#" PRI_klx, tcp->u_arg[2]); |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 379 | } |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 380 | |
| 381 | return ret; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 382 | } |