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.

ldt.c 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  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-1996 Rick Sladkey <jrs@world.std.com>
  5. * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
  6. * Copyright (c) 2002-2004 Roland McGrath <roland@redhat.com>
  7. * Copyright (c) 2010 Andreas Schwab <schwab@linux-m68k.org>
  8. * Copyright (c) 2014-2015 Dmitry V. Levin <ldv@altlinux.org>
  9. * Copyright (c) 2014-2018 The strace developers.
  10. * All rights reserved.
  11. *
  12. * SPDX-License-Identifier: LGPL-2.1-or-later
  13. */
  14. #include "defs.h"
  15. #ifdef HAVE_STRUCT_USER_DESC
  16. # include <asm/ldt.h>
  17. # include "print_fields.h"
  18. # include "xstring.h"
  19. void
  20. print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr,
  21. enum user_desc_print_filter filter)
  22. {
  23. struct user_desc desc;
  24. unsigned *entry_number = get_tcb_priv_data(tcp);
  25. switch (filter) {
  26. case USER_DESC_ENTERING:
  27. if (umove_or_printaddr(tcp, addr, &desc.entry_number))
  28. return;
  29. break;
  30. case USER_DESC_EXITING:
  31. if (!addr || !verbose(tcp))
  32. return;
  33. if (syserror(tcp) || umove(tcp, addr, &desc)) {
  34. if (entry_number)
  35. tprints(", ...}");
  36. return;
  37. }
  38. break;
  39. case USER_DESC_BOTH:
  40. if (umove_or_printaddr(tcp, addr, &desc))
  41. return;
  42. break;
  43. }
  44. if (filter & USER_DESC_ENTERING) {
  45. PRINT_FIELD_ID("{", desc, entry_number);
  46. /*
  47. * If we don't print the whole structure now, let's save it for
  48. * later.
  49. */
  50. if (filter == USER_DESC_ENTERING) {
  51. entry_number = xmalloc(sizeof(*entry_number));
  52. *entry_number = desc.entry_number;
  53. set_tcb_priv_data(tcp, entry_number, free);
  54. }
  55. }
  56. if (filter & USER_DESC_EXITING) {
  57. /*
  58. * It should be the same in case of get_thread_area, but we can
  59. * never be sure...
  60. */
  61. if (filter == USER_DESC_EXITING) {
  62. if (entry_number) {
  63. if (*entry_number != desc.entry_number) {
  64. if ((int) desc.entry_number == -1)
  65. tprints(" => -1");
  66. else
  67. tprintf(" => %u",
  68. desc.entry_number);
  69. }
  70. } else {
  71. /*
  72. * This is really strange. If we are here, it
  73. * means that we failed on entering but somehow
  74. * succeeded on exiting.
  75. */
  76. PRINT_FIELD_ID(" => {", desc, entry_number);
  77. }
  78. }
  79. PRINT_FIELD_0X(", ", desc, base_addr);
  80. PRINT_FIELD_0X(", ", desc, limit);
  81. PRINT_FIELD_U_CAST(", ", desc, seg_32bit, unsigned int);
  82. PRINT_FIELD_U_CAST(", ", desc, contents, unsigned int);
  83. PRINT_FIELD_U_CAST(", ", desc, read_exec_only, unsigned int);
  84. PRINT_FIELD_U_CAST(", ", desc, limit_in_pages, unsigned int);
  85. PRINT_FIELD_U_CAST(", ", desc, seg_not_present, unsigned int);
  86. PRINT_FIELD_U_CAST(", ", desc, useable, unsigned int);
  87. # ifdef HAVE_STRUCT_USER_DESC_LM
  88. /* lm is totally ignored for 32-bit processes */
  89. if (current_klongsize == 8)
  90. PRINT_FIELD_U_CAST(", ", desc, lm, unsigned int);
  91. # endif /* HAVE_STRUCT_USER_DESC_LM */
  92. tprints("}");
  93. }
  94. }
  95. SYS_FUNC(modify_ldt)
  96. {
  97. if (entering(tcp)) {
  98. tprintf("%d, ", (int) tcp->u_arg[0]);
  99. if (tcp->u_arg[2] != sizeof(struct user_desc))
  100. printaddr(tcp->u_arg[1]);
  101. else
  102. print_user_desc(tcp, tcp->u_arg[1], USER_DESC_BOTH);
  103. tprintf(", %" PRI_klu, tcp->u_arg[2]);
  104. return 0;
  105. }
  106. /*
  107. * For some reason ("tht ABI for sys_modify_ldt() expects
  108. * 'int'"), modify_ldt clips higher bits on x86_64.
  109. */
  110. if (syserror(tcp) || (kernel_ulong_t) tcp->u_rval < 0xfffff000)
  111. return 0;
  112. tcp->u_error = -(unsigned int) tcp->u_rval;
  113. return 0;
  114. }
  115. SYS_FUNC(set_thread_area)
  116. {
  117. if (entering(tcp)) {
  118. print_user_desc(tcp, tcp->u_arg[0], USER_DESC_BOTH);
  119. } else {
  120. struct user_desc desc;
  121. if (!verbose(tcp) || syserror(tcp) ||
  122. umove(tcp, tcp->u_arg[0], &desc) < 0) {
  123. /* returned entry_number is not available */
  124. } else {
  125. static char outstr[32];
  126. xsprintf(outstr, "entry_number=%u", desc.entry_number);
  127. tcp->auxstr = outstr;
  128. return RVAL_STR;
  129. }
  130. }
  131. return 0;
  132. }
  133. SYS_FUNC(get_thread_area)
  134. {
  135. print_user_desc(tcp, tcp->u_arg[0],
  136. entering(tcp) ? USER_DESC_ENTERING : USER_DESC_EXITING);
  137. return 0;
  138. }
  139. #endif /* HAVE_STRUCT_USER_DESC */
  140. #if defined(M68K) || defined(MIPS)
  141. SYS_FUNC(set_thread_area)
  142. {
  143. printaddr(tcp->u_arg[0]);
  144. return RVAL_DECODED;
  145. }
  146. #endif
  147. #if defined(M68K)
  148. SYS_FUNC(get_thread_area)
  149. {
  150. return RVAL_DECODED | RVAL_HEX;
  151. }
  152. #endif