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 | #ifdef HAVE_LINUX_INPUT_H |
| 37 | # include <linux/input.h> |
| 38 | #endif |
| 39 | |
| 40 | #include "xlat/evdev_abs.h" |
| 41 | #include "xlat/evdev_ev.h" |
| 42 | |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 43 | static int |
Denys Vlasenko | 1201426 | 2011-05-30 14:00:14 +0200 | [diff] [blame] | 44 | compare(const void *a, const void *b) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 45 | { |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 46 | const unsigned int code1 = (const uintptr_t) a; |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 47 | const unsigned int code2 = ((struct_ioctlent *) b)->code; |
Denys Vlasenko | feb40c4 | 2012-03-20 13:11:51 +0100 | [diff] [blame] | 48 | return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 49 | } |
| 50 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 51 | static const struct_ioctlent * |
Dmitry V. Levin | df7aa2b | 2015-01-19 17:02:16 +0000 | [diff] [blame] | 52 | ioctl_lookup(const unsigned int code) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 53 | { |
Denys Vlasenko | a9fe13c | 2013-02-22 13:26:10 +0100 | [diff] [blame] | 54 | struct_ioctlent *iop; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 55 | |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 56 | iop = bsearch((const void *) (const uintptr_t) code, ioctlent, |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 57 | nioctlents, sizeof(ioctlent[0]), compare); |
| 58 | while (iop > ioctlent) { |
| 59 | iop--; |
| 60 | if (iop->code != code) { |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 61 | iop++; |
| 62 | break; |
| 63 | } |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 64 | } |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 65 | return iop; |
| 66 | } |
| 67 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 68 | static const struct_ioctlent * |
Denys Vlasenko | a9fe13c | 2013-02-22 13:26:10 +0100 | [diff] [blame] | 69 | ioctl_next_match(const struct_ioctlent *iop) |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 70 | { |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 71 | const unsigned int code = iop->code; |
Denys Vlasenko | 1c2e912 | 2012-03-20 10:57:41 +0100 | [diff] [blame] | 72 | iop++; |
Roland McGrath | 2843a4e | 2003-11-14 02:54:03 +0000 | [diff] [blame] | 73 | if (iop < ioctlent + nioctlents && iop->code == code) |
| 74 | return iop; |
| 75 | return NULL; |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 76 | } |
| 77 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 78 | static void |
Dmitry V. Levin | 924996a | 2015-01-20 00:24:36 +0000 | [diff] [blame] | 79 | ioctl_print_code(const unsigned int code) |
| 80 | { |
| 81 | tprints("_IOC("); |
| 82 | printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???"); |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 83 | tprintf(", %#x, %#x, %#x)", |
Dmitry V. Levin | 924996a | 2015-01-20 00:24:36 +0000 | [diff] [blame] | 84 | _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code)); |
| 85 | } |
| 86 | |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 87 | static int |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 88 | evdev_decode_number(const unsigned int code) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 89 | { |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 90 | const unsigned int nr = _IOC_NR(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 91 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 92 | if (_IOC_DIR(code) == _IOC_WRITE) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 93 | if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) { |
| 94 | tprints("EVIOCSABS("); |
Dmitry V. Levin | 1f1559e | 2016-05-27 01:11:40 +0000 | [diff] [blame] | 95 | printxval(evdev_abs, nr - 0xc0, "ABS_???"); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 96 | tprints(")"); |
| 97 | return 1; |
| 98 | } |
| 99 | } |
| 100 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 101 | if (_IOC_DIR(code) != _IOC_READ) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 102 | return 0; |
| 103 | |
| 104 | if (nr >= 0x20 && nr <= 0x20 + 0x1f) { |
| 105 | tprints("EVIOCGBIT("); |
| 106 | printxval(evdev_ev, nr - 0x20, "EV_???"); |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 107 | tprintf(", %u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 108 | return 1; |
| 109 | } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) { |
| 110 | tprints("EVIOCGABS("); |
| 111 | printxval(evdev_abs, nr - 0x40, "ABS_???"); |
| 112 | tprints(")"); |
| 113 | return 1; |
| 114 | } |
| 115 | |
| 116 | switch (_IOC_NR(nr)) { |
| 117 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 118 | tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 119 | return 1; |
| 120 | case 0x07: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 121 | tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 122 | return 1; |
| 123 | case 0x08: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 124 | tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 125 | return 1; |
| 126 | case 0x09: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 127 | tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 128 | return 1; |
| 129 | case 0x0a: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 130 | tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 131 | return 1; |
| 132 | case 0x18: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 133 | tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 134 | return 1; |
| 135 | case 0x19: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 136 | tprintf("EVIOCGLED(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 137 | return 1; |
| 138 | case 0x1a: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 139 | tprintf("EVIOCGSND(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 140 | return 1; |
| 141 | case 0x1b: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 142 | tprintf("EVIOCGSW(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 143 | return 1; |
| 144 | default: |
| 145 | return 0; |
| 146 | } |
| 147 | } |
| 148 | |
| 149 | static int |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 150 | hiddev_decode_number(const unsigned int code) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 151 | { |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 152 | if (_IOC_DIR(code) == _IOC_READ) { |
| 153 | switch (_IOC_NR(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 154 | case 0x04: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 155 | tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 156 | return 1; |
| 157 | case 0x05: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 158 | tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 159 | return 1; |
| 160 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 161 | tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 162 | return 1; |
| 163 | case 0x12: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 164 | tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 165 | return 1; |
| 166 | default: |
| 167 | return 0; |
| 168 | } |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 169 | } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) { |
| 170 | switch (_IOC_NR(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 171 | case 0x06: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 172 | tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 173 | return 1; |
| 174 | case 0x07: |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 175 | tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 176 | return 1; |
| 177 | default: |
| 178 | return 0; |
| 179 | } |
| 180 | } |
| 181 | |
| 182 | return 0; |
| 183 | } |
| 184 | |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 185 | static int |
Dmitry V. Levin | 4f63c11 | 2015-07-02 22:31:11 +0000 | [diff] [blame] | 186 | ioctl_decode_command_number(struct tcb *tcp) |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 187 | { |
Dmitry V. Levin | 4f63c11 | 2015-07-02 22:31:11 +0000 | [diff] [blame] | 188 | const unsigned int code = tcp->u_arg[1]; |
| 189 | |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 190 | switch (_IOC_TYPE(code)) { |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 191 | case 'E': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 192 | return evdev_decode_number(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 193 | case 'H': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 194 | return hiddev_decode_number(code); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 195 | case 'M': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 196 | if (_IOC_DIR(code) == _IOC_WRITE) { |
| 197 | tprintf("MIXER_WRITE(%u)", _IOC_NR(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 198 | return 1; |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 199 | } else if (_IOC_DIR(code) == _IOC_READ) { |
| 200 | tprintf("MIXER_READ(%u)", _IOC_NR(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 201 | return 1; |
| 202 | } |
| 203 | return 0; |
| 204 | case 'U': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 205 | if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) { |
| 206 | tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 207 | return 1; |
| 208 | } |
| 209 | return 0; |
| 210 | case 'j': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 211 | if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) { |
| 212 | tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 213 | return 1; |
| 214 | } |
| 215 | return 0; |
| 216 | case 'k': |
Dmitry V. Levin | 2803e75 | 2015-07-02 22:23:53 +0000 | [diff] [blame] | 217 | if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) { |
| 218 | tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code)); |
Gabriel Laskar | 6f9a01c | 2015-01-21 23:35:27 +0100 | [diff] [blame] | 219 | return 1; |
| 220 | } |
| 221 | return 0; |
| 222 | default: |
| 223 | return 0; |
| 224 | } |
| 225 | } |
| 226 | |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 227 | /** |
| 228 | * Decode arg parameter of the ioctl call. |
| 229 | * |
| 230 | * @return There are two flags of the return value important for the purposes of |
| 231 | * processing by SYS_FUNC(ioctl): |
| 232 | * - RVAL_IOCTL_DECODED: indicates that ioctl decoder code |
| 233 | * has printed arg parameter; |
| 234 | * - RVAL_DECODED: indicates that decoding is done. |
| 235 | * As a result, the following behaviour is expected: |
| 236 | * - on entering: |
| 237 | * - 0: decoding should be continued on exiting; |
| 238 | * - RVAL_IOCTL_DECODED: decoding on exiting is not needed |
| 239 | * and decoder has printed arg value; |
| 240 | * - RVAL_DECODED: decoding on exiting is not needed |
| 241 | * and generic handler should print arg value. |
| 242 | * - on exiting: |
| 243 | * - 0: generic handler should print arg value; |
| 244 | * - RVAL_IOCTL_DECODED: decoder has printed arg value. |
| 245 | * |
| 246 | * Note that it makes no sense to return just RVAL_DECODED on exiting, |
| 247 | * but, of course, it is not prohibited (for example, it may be useful |
| 248 | * in cases where the return path is common on entering and on exiting |
| 249 | * the syscall). |
| 250 | * |
| 251 | * SYS_FUNC(ioctl) converts RVAL_IOCTL_DECODED flag to RVAL_DECODED, |
| 252 | * and passes all other bits of ioctl_decode return value unchanged. |
| 253 | */ |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 254 | static int |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 255 | ioctl_decode(struct tcb *tcp) |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 256 | { |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 257 | const unsigned int code = tcp->u_arg[1]; |
Elliott Hughes | d35df49 | 2017-02-15 15:19:05 -0800 | [diff] [blame] | 258 | const kernel_ulong_t arg = tcp->u_arg[2]; |
Dmitry V. Levin | 802c942 | 2015-07-02 22:27:51 +0000 | [diff] [blame] | 259 | |
Dmitry V. Levin | c7afb48 | 2015-01-19 18:44:21 +0000 | [diff] [blame] | 260 | switch (_IOC_TYPE(code)) { |
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 |
Wichert Akkerman | 76baf7c | 1999-02-19 00:21:36 +0000 | [diff] [blame] | 328 | default: |
| 329 | break; |
| 330 | } |
| 331 | return 0; |
| 332 | } |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 333 | |
| 334 | SYS_FUNC(ioctl) |
| 335 | { |
| 336 | const struct_ioctlent *iop; |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 337 | int ret; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 338 | |
| 339 | if (entering(tcp)) { |
| 340 | printfd(tcp, tcp->u_arg[0]); |
| 341 | tprints(", "); |
Gabriel Laskar | 9c4fc34 | 2015-09-23 10:11:55 +0200 | [diff] [blame] | 342 | ret = ioctl_decode_command_number(tcp); |
Gabriel Laskar | 8b6046a | 2015-12-04 01:07:33 +0100 | [diff] [blame] | 343 | if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) { |
| 344 | iop = ioctl_lookup(tcp->u_arg[1]); |
| 345 | if (iop) { |
| 346 | if (ret) |
| 347 | tprints(" or "); |
| 348 | tprints(iop->symbol); |
| 349 | while ((iop = ioctl_next_match(iop))) |
| 350 | tprintf(" or %s", iop->symbol); |
| 351 | } else if (!ret) { |
| 352 | ioctl_print_code(tcp->u_arg[1]); |
| 353 | } |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 354 | } |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 355 | ret = ioctl_decode(tcp); |
| 356 | } else { |
| 357 | ret = ioctl_decode(tcp) | RVAL_DECODED; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 358 | } |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 359 | |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 360 | if (ret & RVAL_IOCTL_DECODED) { |
| 361 | ret &= ~RVAL_IOCTL_DECODED; |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 362 | ret |= RVAL_DECODED; |
Elliott Hughes | 77c3ff8 | 2017-09-08 17:11:00 -0700 | [diff] [blame] | 363 | } else if (ret & RVAL_DECODED) { |
| 364 | tprintf(", %#" PRI_klx, tcp->u_arg[2]); |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 365 | } |
Dmitry V. Levin | 204c2bc | 2015-07-08 14:10:56 +0000 | [diff] [blame] | 366 | |
| 367 | return ret; |
Dmitry V. Levin | 044eef2 | 2015-07-02 21:37:23 +0000 | [diff] [blame] | 368 | } |