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