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.

loop.c 4.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  1. /*
  2. * Copyright (c) 2012 The Chromium OS Authors.
  3. * Copyright (c) 2012-2018 The strace developers.
  4. * Written by Mike Frysinger <vapier@gentoo.org>.
  5. *
  6. * SPDX-License-Identifier: LGPL-2.1-or-later
  7. */
  8. #include "defs.h"
  9. #include <linux/ioctl.h>
  10. #include <linux/loop.h>
  11. typedef struct loop_info struct_loop_info;
  12. #include DEF_MPERS_TYPE(struct_loop_info)
  13. #include MPERS_DEFS
  14. #include "print_fields.h"
  15. #define XLAT_MACROS_ONLY
  16. #include "xlat/loop_cmds.h"
  17. #undef XLAT_MACROS_ONLY
  18. #include "xlat/loop_flags_options.h"
  19. #include "xlat/loop_crypt_type_options.h"
  20. static void
  21. decode_loop_info(struct tcb *const tcp, const kernel_ulong_t addr)
  22. {
  23. struct_loop_info info;
  24. tprints(", ");
  25. if (umove_or_printaddr(tcp, addr, &info))
  26. return;
  27. tprintf("{lo_number=%d", info.lo_number);
  28. if (!abbrev(tcp)) {
  29. PRINT_FIELD_DEV(", ", info, lo_device);
  30. tprintf(", lo_inode=%" PRI_klu, (kernel_ulong_t) info.lo_inode);
  31. PRINT_FIELD_DEV(", ", info, lo_rdevice);
  32. }
  33. tprintf(", lo_offset=%#x", info.lo_offset);
  34. if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
  35. tprints(", lo_encrypt_type=");
  36. printxval(loop_crypt_type_options, info.lo_encrypt_type,
  37. "LO_CRYPT_???");
  38. /*
  39. * It is converted to unsigned before use in kernel, see
  40. * loop_info64_from_old in drivers/block/loop.c
  41. */
  42. tprintf(", lo_encrypt_key_size=%" PRIu32,
  43. (uint32_t) info.lo_encrypt_key_size);
  44. }
  45. tprints(", lo_flags=");
  46. printflags(loop_flags_options, info.lo_flags, "LO_FLAGS_???");
  47. PRINT_FIELD_CSTRING(", ", info, lo_name);
  48. if (!abbrev(tcp) || info.lo_encrypt_type != LO_CRYPT_NONE) {
  49. const unsigned int lo_encrypt_key_size =
  50. MIN((unsigned) info.lo_encrypt_key_size, LO_KEY_SIZE);
  51. PRINT_FIELD_STRING(", ", info, lo_encrypt_key,
  52. lo_encrypt_key_size, 0);
  53. }
  54. if (!abbrev(tcp))
  55. tprintf(", lo_init=[%#" PRI_klx ", %#" PRI_klx "]"
  56. ", reserved=[%#hhx, %#hhx, %#hhx, %#hhx]}",
  57. (kernel_ulong_t) info.lo_init[0],
  58. (kernel_ulong_t) info.lo_init[1],
  59. info.reserved[0], info.reserved[1],
  60. info.reserved[2], info.reserved[3]);
  61. else
  62. tprints(", ...}");
  63. }
  64. static void
  65. decode_loop_info64(struct tcb *const tcp, const kernel_ulong_t addr)
  66. {
  67. struct loop_info64 info64;
  68. tprints(", ");
  69. if (umove_or_printaddr(tcp, addr, &info64))
  70. return;
  71. if (!abbrev(tcp)) {
  72. PRINT_FIELD_DEV("{", info64, lo_device);
  73. tprintf(", lo_inode=%" PRIu64, (uint64_t) info64.lo_inode);
  74. PRINT_FIELD_DEV(", ", info64, lo_rdevice);
  75. tprintf(", lo_offset=%#" PRIx64 ", lo_sizelimit=%" PRIu64
  76. ", lo_number=%" PRIu32,
  77. (uint64_t) info64.lo_offset,
  78. (uint64_t) info64.lo_sizelimit,
  79. (uint32_t) info64.lo_number);
  80. } else {
  81. tprintf("{lo_offset=%#" PRIx64 ", lo_number=%" PRIu32,
  82. (uint64_t) info64.lo_offset,
  83. (uint32_t) info64.lo_number);
  84. }
  85. if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
  86. tprints(", lo_encrypt_type=");
  87. printxval(loop_crypt_type_options, info64.lo_encrypt_type,
  88. "LO_CRYPT_???");
  89. tprintf(", lo_encrypt_key_size=%" PRIu32,
  90. info64.lo_encrypt_key_size);
  91. }
  92. tprints(", lo_flags=");
  93. printflags(loop_flags_options, info64.lo_flags, "LO_FLAGS_???");
  94. PRINT_FIELD_CSTRING(", ", info64, lo_file_name);
  95. if (!abbrev(tcp) || info64.lo_encrypt_type != LO_CRYPT_NONE) {
  96. PRINT_FIELD_CSTRING(", ", info64, lo_crypt_name);
  97. const unsigned int lo_encrypt_key_size =
  98. MIN((unsigned) info64.lo_encrypt_key_size, LO_KEY_SIZE);
  99. PRINT_FIELD_STRING(", ", info64, lo_encrypt_key,
  100. lo_encrypt_key_size, 0);
  101. }
  102. if (!abbrev(tcp))
  103. tprintf(", lo_init=[%#" PRIx64 ", %#" PRIx64 "]}",
  104. (uint64_t) info64.lo_init[0],
  105. (uint64_t) info64.lo_init[1]);
  106. else
  107. tprints(", ...}");
  108. }
  109. MPERS_PRINTER_DECL(int, loop_ioctl,
  110. struct tcb *tcp, const unsigned int code,
  111. const kernel_ulong_t arg)
  112. {
  113. switch (code) {
  114. case LOOP_GET_STATUS:
  115. if (entering(tcp))
  116. return 0;
  117. ATTRIBUTE_FALLTHROUGH;
  118. case LOOP_SET_STATUS:
  119. decode_loop_info(tcp, arg);
  120. break;
  121. case LOOP_GET_STATUS64:
  122. if (entering(tcp))
  123. return 0;
  124. ATTRIBUTE_FALLTHROUGH;
  125. case LOOP_SET_STATUS64:
  126. decode_loop_info64(tcp, arg);
  127. break;
  128. case LOOP_CLR_FD:
  129. case LOOP_SET_CAPACITY:
  130. /* newer loop-control stuff */
  131. case LOOP_CTL_GET_FREE:
  132. /* Takes no arguments */
  133. break;
  134. case LOOP_SET_FD:
  135. case LOOP_CHANGE_FD:
  136. tprints(", ");
  137. printfd(tcp, arg);
  138. break;
  139. /* newer loop-control stuff */
  140. case LOOP_CTL_ADD:
  141. case LOOP_CTL_REMOVE:
  142. tprintf(", %d", (int) arg);
  143. break;
  144. case LOOP_SET_DIRECT_IO:
  145. case LOOP_SET_BLOCK_SIZE:
  146. tprintf(", %" PRI_klu, arg);
  147. break;
  148. default:
  149. return RVAL_DECODED;
  150. }
  151. return RVAL_IOCTL_DECODED;
  152. }