Mirror of strace – the linux syscall tracer
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

ioctl.c 9.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379
  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-2019 The strace developers.
  7. * All rights reserved.
  8. *
  9. * SPDX-License-Identifier: LGPL-2.1-or-later
  10. */
  11. #include "defs.h"
  12. #include <linux/ioctl.h>
  13. #include "xlat/ioctl_dirs.h"
  14. static int
  15. compare(const void *a, const void *b)
  16. {
  17. const unsigned int code1 = (const uintptr_t) a;
  18. const unsigned int code2 = ((struct_ioctlent *) b)->code;
  19. return (code1 > code2) ? 1 : (code1 < code2) ? -1 : 0;
  20. }
  21. static const struct_ioctlent *
  22. ioctl_lookup(const unsigned int code)
  23. {
  24. struct_ioctlent *iop;
  25. iop = bsearch((const void *) (const uintptr_t) code, ioctlent,
  26. nioctlents, sizeof(ioctlent[0]), compare);
  27. while (iop > ioctlent) {
  28. iop--;
  29. if (iop->code != code) {
  30. iop++;
  31. break;
  32. }
  33. }
  34. return iop;
  35. }
  36. static const struct_ioctlent *
  37. ioctl_next_match(const struct_ioctlent *iop)
  38. {
  39. const unsigned int code = iop->code;
  40. iop++;
  41. if (iop < ioctlent + nioctlents && iop->code == code)
  42. return iop;
  43. return NULL;
  44. }
  45. static void
  46. ioctl_print_code(const unsigned int code)
  47. {
  48. const bool abbrev = xlat_verbose(xlat_verbosity) != XLAT_STYLE_VERBOSE;
  49. tprints("_IOC(");
  50. printflags_ex(_IOC_DIR(code), abbrev ? "_IOC_???" : NULL,
  51. abbrev ? XLAT_STYLE_DEFAULT : XLAT_STYLE_ABBREV,
  52. ioctl_dirs, NULL);
  53. tprintf(", %#x, %#x, %#x)",
  54. _IOC_TYPE(code), _IOC_NR(code), _IOC_SIZE(code));
  55. }
  56. static int
  57. evdev_decode_number(const unsigned int code)
  58. {
  59. const unsigned int nr = _IOC_NR(code);
  60. const bool abbrev = xlat_verbose(xlat_verbosity) != XLAT_STYLE_VERBOSE;
  61. if (_IOC_DIR(code) == _IOC_WRITE) {
  62. if (nr >= 0xc0 && nr <= 0xc0 + 0x3f) {
  63. tprints("EVIOCSABS(");
  64. printxval_ex(evdev_abs, nr - 0xc0,
  65. abbrev ? "ABS_???" : NULL,
  66. abbrev ? XLAT_STYLE_DEFAULT
  67. : XLAT_STYLE_ABBREV);
  68. tprints(")");
  69. return 1;
  70. }
  71. }
  72. if (_IOC_DIR(code) != _IOC_READ)
  73. return 0;
  74. if (nr >= 0x20 && nr <= 0x20 + 0x1f) {
  75. tprints("EVIOCGBIT(");
  76. if (nr == 0x20)
  77. tprintf("0");
  78. else
  79. printxval_ex(evdev_ev, nr - 0x20,
  80. abbrev ? "EV_???" : NULL,
  81. abbrev ? XLAT_STYLE_DEFAULT
  82. : XLAT_STYLE_ABBREV);
  83. tprintf(", %u)", _IOC_SIZE(code));
  84. return 1;
  85. } else if (nr >= 0x40 && nr <= 0x40 + 0x3f) {
  86. tprints("EVIOCGABS(");
  87. printxval_ex(evdev_abs, nr - 0x40, abbrev ? "ABS_???" : NULL,
  88. abbrev ? XLAT_STYLE_DEFAULT : XLAT_STYLE_ABBREV);
  89. tprints(")");
  90. return 1;
  91. }
  92. switch (nr) {
  93. case 0x06:
  94. tprintf("EVIOCGNAME(%u)", _IOC_SIZE(code));
  95. return 1;
  96. case 0x07:
  97. tprintf("EVIOCGPHYS(%u)", _IOC_SIZE(code));
  98. return 1;
  99. case 0x08:
  100. tprintf("EVIOCGUNIQ(%u)", _IOC_SIZE(code));
  101. return 1;
  102. case 0x09:
  103. tprintf("EVIOCGPROP(%u)", _IOC_SIZE(code));
  104. return 1;
  105. case 0x0a:
  106. tprintf("EVIOCGMTSLOTS(%u)", _IOC_SIZE(code));
  107. return 1;
  108. case 0x18:
  109. tprintf("EVIOCGKEY(%u)", _IOC_SIZE(code));
  110. return 1;
  111. case 0x19:
  112. tprintf("EVIOCGLED(%u)", _IOC_SIZE(code));
  113. return 1;
  114. case 0x1a:
  115. tprintf("EVIOCGSND(%u)", _IOC_SIZE(code));
  116. return 1;
  117. case 0x1b:
  118. tprintf("EVIOCGSW(%u)", _IOC_SIZE(code));
  119. return 1;
  120. default:
  121. return 0;
  122. }
  123. }
  124. static int
  125. hiddev_decode_number(const unsigned int code)
  126. {
  127. if (_IOC_DIR(code) == _IOC_READ) {
  128. switch (_IOC_NR(code)) {
  129. case 0x04:
  130. tprintf("HIDIOCGRAWNAME(%u)", _IOC_SIZE(code));
  131. return 1;
  132. case 0x05:
  133. tprintf("HIDIOCGRAWPHYS(%u)", _IOC_SIZE(code));
  134. return 1;
  135. case 0x06:
  136. tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
  137. return 1;
  138. case 0x12:
  139. tprintf("HIDIOCGPHYS(%u)", _IOC_SIZE(code));
  140. return 1;
  141. default:
  142. return 0;
  143. }
  144. } else if (_IOC_DIR(code) == (_IOC_READ | _IOC_WRITE)) {
  145. switch (_IOC_NR(code)) {
  146. case 0x06:
  147. tprintf("HIDIOCSFEATURE(%u)", _IOC_SIZE(code));
  148. return 1;
  149. case 0x07:
  150. tprintf("HIDIOCGFEATURE(%u)", _IOC_SIZE(code));
  151. return 1;
  152. default:
  153. return 0;
  154. }
  155. }
  156. return 0;
  157. }
  158. static int
  159. ioctl_decode_command_number(struct tcb *tcp)
  160. {
  161. const unsigned int code = tcp->u_arg[1];
  162. switch (_IOC_TYPE(code)) {
  163. case 'E':
  164. return evdev_decode_number(code);
  165. case 'H':
  166. return hiddev_decode_number(code);
  167. case 'M':
  168. if (_IOC_DIR(code) == _IOC_WRITE) {
  169. tprintf("MIXER_WRITE(%u)", _IOC_NR(code));
  170. return 1;
  171. } else if (_IOC_DIR(code) == _IOC_READ) {
  172. tprintf("MIXER_READ(%u)", _IOC_NR(code));
  173. return 1;
  174. }
  175. return 0;
  176. case 'U':
  177. if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x2c) {
  178. tprintf("UI_GET_SYSNAME(%u)", _IOC_SIZE(code));
  179. return 1;
  180. }
  181. return 0;
  182. case 'j':
  183. if (_IOC_DIR(code) == _IOC_READ && _IOC_NR(code) == 0x13) {
  184. tprintf("JSIOCGNAME(%u)", _IOC_SIZE(code));
  185. return 1;
  186. }
  187. return 0;
  188. case 'k':
  189. if (_IOC_DIR(code) == _IOC_WRITE && _IOC_NR(code) == 0) {
  190. tprintf("SPI_IOC_MESSAGE(%u)", _IOC_SIZE(code));
  191. return 1;
  192. }
  193. return 0;
  194. default:
  195. return 0;
  196. }
  197. }
  198. /**
  199. * Decode arg parameter of the ioctl call.
  200. *
  201. * @return There are two flags of the return value important for the purposes of
  202. * processing by SYS_FUNC(ioctl):
  203. * - RVAL_IOCTL_DECODED: indicates that ioctl decoder code
  204. * has printed arg parameter;
  205. * - RVAL_DECODED: indicates that decoding is done.
  206. * As a result, the following behaviour is expected:
  207. * - on entering:
  208. * - 0: decoding should be continued on exiting;
  209. * - RVAL_IOCTL_DECODED: decoding on exiting is not needed
  210. * and decoder has printed arg value;
  211. * - RVAL_DECODED: decoding on exiting is not needed
  212. * and generic handler should print arg value.
  213. * - on exiting:
  214. * - 0: generic handler should print arg value;
  215. * - RVAL_IOCTL_DECODED: decoder has printed arg value.
  216. *
  217. * Note that it makes no sense to return just RVAL_DECODED on exiting,
  218. * but, of course, it is not prohibited (for example, it may be useful
  219. * in cases where the return path is common on entering and on exiting
  220. * the syscall).
  221. *
  222. * SYS_FUNC(ioctl) converts RVAL_IOCTL_DECODED flag to RVAL_DECODED,
  223. * and passes all other bits of ioctl_decode return value unchanged.
  224. */
  225. static int
  226. ioctl_decode(struct tcb *tcp)
  227. {
  228. const unsigned int code = tcp->u_arg[1];
  229. const kernel_ulong_t arg = tcp->u_arg[2];
  230. switch (_IOC_TYPE(code)) {
  231. case 0x03:
  232. return hdio_ioctl(tcp, code, arg);
  233. case 0x12:
  234. return block_ioctl(tcp, code, arg);
  235. case '"': /* 0x22 */
  236. return scsi_ioctl(tcp, code, arg);
  237. case '$': /* 0x24 */
  238. return perf_ioctl(tcp, code, arg);
  239. #ifdef HAVE_STRUCT_PTP_SYS_OFFSET
  240. case '=': /* 0x3d */
  241. return ptp_ioctl(tcp, code, arg);
  242. #endif
  243. #ifdef HAVE_LINUX_INPUT_H
  244. case 'E':
  245. return evdev_ioctl(tcp, code, arg);
  246. #endif
  247. case 'I':
  248. return inotify_ioctl(tcp, code, arg);
  249. case 'L':
  250. return loop_ioctl(tcp, code, arg);
  251. #ifdef HAVE_STRUCT_MTD_WRITE_REQ
  252. case 'M':
  253. return mtd_ioctl(tcp, code, arg);
  254. #endif
  255. #ifdef HAVE_STRUCT_UBI_ATTACH_REQ_MAX_BEB_PER1024
  256. case 'O':
  257. return ubi_ioctl(tcp, code, arg);
  258. #endif
  259. case 'R':
  260. return random_ioctl(tcp, code, arg);
  261. case 'T':
  262. return term_ioctl(tcp, code, arg);
  263. case 'V':
  264. return v4l2_ioctl(tcp, code, arg);
  265. case 'W':
  266. return watchdog_ioctl(tcp, code, arg);
  267. case 'X':
  268. return fs_x_ioctl(tcp, code, arg);
  269. case 'f': {
  270. #if defined(ALPHA) || defined(POWERPC)
  271. int ret = file_ioctl(tcp, code, arg);
  272. if (ret != RVAL_DECODED)
  273. return ret;
  274. return term_ioctl(tcp, code, arg);
  275. #else /* !(ALPHA || POWERPC) */
  276. return file_ioctl(tcp, code, arg);
  277. #endif /* (ALPHA || POWERPC) */
  278. }
  279. #ifdef HAVE_STRUCT_UBI_ATTACH_REQ_MAX_BEB_PER1024
  280. case 'o':
  281. return ubi_ioctl(tcp, code, arg);
  282. #endif
  283. case 'p':
  284. return rtc_ioctl(tcp, code, arg);
  285. #if defined(ALPHA) || defined(POWERPC)
  286. case 't':
  287. return term_ioctl(tcp, code, arg);
  288. #endif /* !ALPHA */
  289. case 0x89:
  290. return sock_ioctl(tcp, code, arg);
  291. #ifdef HAVE_LINUX_BTRFS_H
  292. case 0x94:
  293. return btrfs_ioctl(tcp, code, arg);
  294. #endif
  295. #ifdef HAVE_LINUX_USERFAULTFD_H
  296. case 0xaa:
  297. return uffdio_ioctl(tcp, code, arg);
  298. #endif
  299. case 0xab:
  300. return nbd_ioctl(tcp, code, arg);
  301. #ifdef HAVE_LINUX_KVM_H
  302. case 0xae:
  303. return kvm_ioctl(tcp, code, arg);
  304. #endif
  305. case 0xb7:
  306. return nsfs_ioctl(tcp, code, arg);
  307. #ifdef HAVE_LINUX_DM_IOCTL_H
  308. case 0xfd:
  309. return dm_ioctl(tcp, code, arg);
  310. #endif
  311. default:
  312. break;
  313. }
  314. return 0;
  315. }
  316. SYS_FUNC(ioctl)
  317. {
  318. const struct_ioctlent *iop;
  319. int ret;
  320. if (entering(tcp)) {
  321. printfd(tcp, tcp->u_arg[0]);
  322. tprints(", ");
  323. if (xlat_verbosity != XLAT_STYLE_ABBREV)
  324. tprintf("%#x", (unsigned int) tcp->u_arg[1]);
  325. if (xlat_verbosity == XLAT_STYLE_VERBOSE)
  326. tprints(" /* ");
  327. if (xlat_verbosity != XLAT_STYLE_RAW) {
  328. ret = ioctl_decode_command_number(tcp);
  329. if (!(ret & IOCTL_NUMBER_STOP_LOOKUP)) {
  330. iop = ioctl_lookup(tcp->u_arg[1]);
  331. if (iop) {
  332. if (ret)
  333. tprints(" or ");
  334. tprints(iop->symbol);
  335. while ((iop = ioctl_next_match(iop)))
  336. tprintf(" or %s", iop->symbol);
  337. } else if (!ret) {
  338. ioctl_print_code(tcp->u_arg[1]);
  339. }
  340. }
  341. }
  342. if (xlat_verbosity == XLAT_STYLE_VERBOSE)
  343. tprints(" */");
  344. ret = ioctl_decode(tcp);
  345. } else {
  346. ret = ioctl_decode(tcp) | RVAL_DECODED;
  347. }
  348. if (ret & RVAL_IOCTL_DECODED) {
  349. ret &= ~RVAL_IOCTL_DECODED;
  350. ret |= RVAL_DECODED;
  351. } else if (ret & RVAL_DECODED) {
  352. tprintf(", %#" PRI_klx, tcp->u_arg[2]);
  353. }
  354. return ret;
  355. }