1 /* 2 * Copyright (c) 1991, 1992 Paul Kranenburg <pk (at) cs.few.eur.nl> 3 * Copyright (c) 1993 Branko Lankester <branko (at) hacktic.nl> 4 * Copyright (c) 1993, 1994, 1995, 1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-2001 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 1999-2017 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 #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 43 static int 44 compare(const void *a, const void *b) 45 { 46 const unsigned int code1 = (const uintptr_t) a; 47 const unsigned int code2 = ((struct_ioctlent *) b)->code; 48 return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0; 49 } 50 51 static const struct_ioctlent * 52 ioctl_lookup(const unsigned int code) 53 { 54 struct_ioctlent *iop; 55 56 iop = bsearch((const void *) (const uintptr_t) code, ioctlent, 57 nioctlents, sizeof(ioctlent[0]), compare); 58 while (iop > ioctlent) { 59 iop--; 60 if (iop->code != code) { 61 iop++; 62 break; 63 } 64 } 65 return iop; 66 } 67 68 static const struct_ioctlent * 69 ioctl_next_match(const struct_ioctlent *iop) 70 { 71 const unsigned int code = iop->code; 72 iop++; 73 if (iop < ioctlent + nioctlents && iop->code == code) 74 return iop; 75 return NULL; 76 } 77 78 static void 79 ioctl_print_code(const unsigned int code) 80 { 81 tprints("_IOC("); 82 printflags(ioctl_dirs, _IOC_DIR(code), "_IOC_???"); 83 tprintf(", %#x, %#x, %#x)", 84 _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code)); 85 } 86 87 static int 88 evdev_decode_number(const unsigned int code) 89 { 90 const unsigned int nr = _IOC_NR(code); 91 92 if (_IOC_DIR(code) == _IOC_WRITE) { 93 if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) { 94 tprints("EVIOCSABS("); 95 printxval(evdev_abs, nr - 0xc0, "ABS_???"); 96 tprints(")"); 97 return 1; 98 } 99 } 100 101 if (_IOC_DIR(code) != _IOC_READ) 102 return 0; 103 104 if (nr >= 0x20 && nr <= 0x20 + 0x1f) { 105 tprints("EVIOCGBIT("); 106 printxval(evdev_ev, nr - 0x20, "EV_???"); 107 tprintf(", %u)", _IOC_SIZE(code)); 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: 118 tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code)); 119 return 1; 120 case 0x07: 121 tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code)); 122 return 1; 123 case 0x08: 124 tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code)); 125 return 1; 126 case 0x09: 127 tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code)); 128 return 1; 129 case 0x0a: 130 tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code)); 131 return 1; 132 case 0x18: 133 tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code)); 134 return 1; 135 case 0x19: 136 tprintf("EVIOCGLED(%u)", _IOC_SIZE(code)); 137 return 1; 138 case 0x1a: 139 tprintf("EVIOCGSND(%u)", _IOC_SIZE(code)); 140 return 1; 141 case 0x1b: 142 tprintf("EVIOCGSW(%u)", _IOC_SIZE(code)); 143 return 1; 144 default: 145 return 0; 146 } 147 } 148 149 static int 150 hiddev_decode_number(const unsigned int code) 151 { 152 if (_IOC_DIR(code) == _IOC_READ) { 153 switch (_IOC_NR(code)) { 154 case 0x04: 155 tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code)); 156 return 1; 157 case 0x05: 158 tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code)); 159 return 1; 160 case 0x06: 161 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); 162 return 1; 163 case 0x12: 164 tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code)); 165 return 1; 166 default: 167 return 0; 168 } 169 } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) { 170 switch (_IOC_NR(code)) { 171 case 0x06: 172 tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code)); 173 return 1; 174 case 0x07: 175 tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code)); 176 return 1; 177 default: 178 return 0; 179 } 180 } 181 182 return 0; 183 } 184 185 static int 186 ioctl_decode_command_number(struct tcb *tcp) 187 { 188 const unsigned int code = tcp->u_arg[1]; 189 190 switch (_IOC_TYPE(code)) { 191 case 'E': 192 return evdev_decode_number(code); 193 case 'H': 194 return hiddev_decode_number(code); 195 case 'M': 196 if (_IOC_DIR(code) == _IOC_WRITE) { 197 tprintf("MIXER_WRITE(%u)", _IOC_NR(code)); 198 return 1; 199 } else if (_IOC_DIR(code) == _IOC_READ) { 200 tprintf("MIXER_READ(%u)", _IOC_NR(code)); 201 return 1; 202 } 203 return 0; 204 case 'U': 205 if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) { 206 tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code)); 207 return 1; 208 } 209 return 0; 210 case 'j': 211 if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) { 212 tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code)); 213 return 1; 214 } 215 return 0; 216 case 'k': 217 if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) { 218 tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code)); 219 return 1; 220 } 221 return 0; 222 default: 223 return 0; 224 } 225 } 226 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 */ 254 static int 255 ioctl_decode(struct tcb *tcp) 256 { 257 const unsigned int code = tcp->u_arg[1]; 258 const kernel_ulong_t arg = tcp->u_arg[2]; 259 260 switch (_IOC_TYPE(code)) { 261 #if defined(ALPHA) || defined(POWERPC) 262 case 'f': { 263 int ret = file_ioctl(tcp, code, arg); 264 if (ret != RVAL_DECODED) 265 return ret; 266 } 267 case 't': 268 case 'T': 269 return term_ioctl(tcp, code, arg); 270 #else /* !ALPHA */ 271 case 'f': 272 return file_ioctl(tcp, code, arg); 273 case 0x54: 274 #endif /* !ALPHA */ 275 return term_ioctl(tcp, code, arg); 276 case 0x89: 277 return sock_ioctl(tcp, code, arg); 278 case 'p': 279 return rtc_ioctl(tcp, code, arg); 280 case 0x03: 281 return hdio_ioctl(tcp, code, arg); 282 case 0x12: 283 return block_ioctl(tcp, code, arg); 284 case 'X': 285 return fs_x_ioctl(tcp, code, arg); 286 case 0x22: 287 return scsi_ioctl(tcp, code, arg); 288 case 'L': 289 return loop_ioctl(tcp, code, arg); 290 #ifdef HAVE_STRUCT_MTD_WRITE_REQ 291 case 'M': 292 return mtd_ioctl(tcp, code, arg); 293 #endif 294 #ifdef HAVE_STRUCT_UBI_ATTACH_REQ_MAX_BEB_PER1024 295 case 'o': 296 case 'O': 297 return ubi_ioctl(tcp, code, arg); 298 #endif 299 case 'V': 300 return v4l2_ioctl(tcp, code, arg); 301 #ifdef HAVE_STRUCT_PTP_SYS_OFFSET 302 case '=': 303 return ptp_ioctl(tcp, code, arg); 304 #endif 305 #ifdef HAVE_LINUX_INPUT_H 306 case 'E': 307 return evdev_ioctl(tcp, code, arg); 308 #endif 309 #ifdef HAVE_LINUX_USERFAULTFD_H 310 case 0xaa: 311 return uffdio_ioctl(tcp, code, arg); 312 #endif 313 #ifdef HAVE_LINUX_BTRFS_H 314 case 0x94: 315 return btrfs_ioctl(tcp, code, arg); 316 #endif 317 case 0xb7: 318 return nsfs_ioctl(tcp, code, arg); 319 #ifdef HAVE_LINUX_DM_IOCTL_H 320 case 0xfd: 321 return dm_ioctl(tcp, code, arg); 322 #endif 323 #ifdef HAVE_LINUX_KVM_H 324 case 0xae: 325 return kvm_ioctl(tcp, code, arg); 326 #endif 327 default: 328 break; 329 } 330 return 0; 331 } 332 333 SYS_FUNC(ioctl) 334 { 335 const struct_ioctlent *iop; 336 int ret; 337 338 if (entering(tcp)) { 339 printfd(tcp, tcp->u_arg[0]); 340 tprints(", "); 341 ret = ioctl_decode_command_number(tcp); 342 if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) { 343 iop = ioctl_lookup(tcp->u_arg[1]); 344 if (iop) { 345 if (ret) 346 tprints(" or "); 347 tprints(iop->symbol); 348 while ((iop = ioctl_next_match(iop))) 349 tprintf(" or %s", iop->symbol); 350 } else if (!ret) { 351 ioctl_print_code(tcp->u_arg[1]); 352 } 353 } 354 ret = ioctl_decode(tcp); 355 } else { 356 ret = ioctl_decode(tcp) | RVAL_DECODED; 357 } 358 359 if (ret & RVAL_IOCTL_DECODED) { 360 ret &= ~RVAL_IOCTL_DECODED; 361 ret |= RVAL_DECODED; 362 } else if (ret & RVAL_DECODED) { 363 tprintf(", %#" PRI_klx, tcp->u_arg[2]); 364 } 365 366 return ret; 367 } 368