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-1996 Rick Sladkey <jrs (at) world.std.com> 5 * Copyright (c) 1996-1999 Wichert Akkerman <wichert (at) cistron.nl> 6 * Copyright (c) 2002-2004 Roland McGrath <roland (at) redhat.com> 7 * Copyright (c) 2010 Andreas Schwab <schwab (at) linux-m68k.org> 8 * Copyright (c) 2014-2015 Dmitry V. Levin <ldv (at) altlinux.org> 9 * Copyright (c) 2014-2018 The strace developers. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. The name of the author may not be used to endorse or promote products 21 * derived from this software without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 24 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 25 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 26 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 28 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 29 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 30 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 31 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 32 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 33 */ 34 35 #include "defs.h" 36 37 #ifdef HAVE_STRUCT_USER_DESC 38 39 # include <asm/ldt.h> 40 41 # include "print_fields.h" 42 # include "xstring.h" 43 44 void 45 print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr, 46 enum user_desc_print_filter filter) 47 { 48 struct user_desc desc; 49 unsigned *entry_number = get_tcb_priv_data(tcp); 50 51 switch (filter) { 52 case USER_DESC_ENTERING: 53 if (umove_or_printaddr(tcp, addr, &desc.entry_number)) 54 return; 55 56 break; 57 58 case USER_DESC_EXITING: 59 if (!addr || !verbose(tcp)) 60 return; 61 if (syserror(tcp) || umove(tcp, addr, &desc)) { 62 if (entry_number) 63 tprints(", ...}"); 64 65 return; 66 } 67 68 break; 69 70 case USER_DESC_BOTH: 71 if (umove_or_printaddr(tcp, addr, &desc)) 72 return; 73 74 break; 75 } 76 77 if (filter & USER_DESC_ENTERING) { 78 PRINT_FIELD_ID("{", desc, entry_number); 79 80 /* 81 * If we don't print the whole structure now, let's save it for 82 * later. 83 */ 84 if (filter == USER_DESC_ENTERING) { 85 entry_number = xmalloc(sizeof(*entry_number)); 86 87 *entry_number = desc.entry_number; 88 set_tcb_priv_data(tcp, entry_number, free); 89 } 90 } 91 92 if (filter & USER_DESC_EXITING) { 93 /* 94 * It should be the same in case of get_thread_area, but we can 95 * never be sure... 96 */ 97 if (filter == USER_DESC_EXITING) { 98 if (entry_number) { 99 if (*entry_number != desc.entry_number) { 100 if ((int) desc.entry_number == -1) 101 tprints(" => -1"); 102 else 103 tprintf(" => %u", 104 desc.entry_number); 105 } 106 } else { 107 /* 108 * This is really strange. If we are here, it 109 * means that we failed on entering but somehow 110 * succeeded on exiting. 111 */ 112 PRINT_FIELD_ID(" => {", desc, entry_number); 113 } 114 } 115 116 PRINT_FIELD_0X(", ", desc, base_addr); 117 PRINT_FIELD_0X(", ", desc, limit); 118 PRINT_FIELD_U_CAST(", ", desc, seg_32bit, unsigned int); 119 PRINT_FIELD_U_CAST(", ", desc, contents, unsigned int); 120 PRINT_FIELD_U_CAST(", ", desc, read_exec_only, unsigned int); 121 PRINT_FIELD_U_CAST(", ", desc, limit_in_pages, unsigned int); 122 PRINT_FIELD_U_CAST(", ", desc, seg_not_present, unsigned int); 123 PRINT_FIELD_U_CAST(", ", desc, useable, unsigned int); 124 125 # ifdef HAVE_STRUCT_USER_DESC_LM 126 /* lm is totally ignored for 32-bit processes */ 127 if (current_klongsize == 8) 128 PRINT_FIELD_U_CAST(", ", desc, lm, unsigned int); 129 # endif /* HAVE_STRUCT_USER_DESC_LM */ 130 131 tprints("}"); 132 } 133 } 134 135 SYS_FUNC(modify_ldt) 136 { 137 if (entering(tcp)) { 138 tprintf("%d, ", (int) tcp->u_arg[0]); 139 if (tcp->u_arg[2] != sizeof(struct user_desc)) 140 printaddr(tcp->u_arg[1]); 141 else 142 print_user_desc(tcp, tcp->u_arg[1], USER_DESC_BOTH); 143 tprintf(", %" PRI_klu, tcp->u_arg[2]); 144 145 return 0; 146 } 147 148 /* 149 * For some reason ("tht ABI for sys_modify_ldt() expects 150 * 'int'"), modify_ldt clips higher bits on x86_64. 151 */ 152 153 if (syserror(tcp) || (kernel_ulong_t) tcp->u_rval < 0xfffff000) 154 return 0; 155 156 tcp->u_error = -(unsigned int) tcp->u_rval; 157 158 return 0; 159 } 160 161 SYS_FUNC(set_thread_area) 162 { 163 if (entering(tcp)) { 164 print_user_desc(tcp, tcp->u_arg[0], USER_DESC_BOTH); 165 } else { 166 struct user_desc desc; 167 168 if (!verbose(tcp) || syserror(tcp) || 169 umove(tcp, tcp->u_arg[0], &desc) < 0) { 170 /* returned entry_number is not available */ 171 } else { 172 static char outstr[32]; 173 174 xsprintf(outstr, "entry_number=%u", desc.entry_number); 175 tcp->auxstr = outstr; 176 return RVAL_STR; 177 } 178 } 179 return 0; 180 } 181 182 SYS_FUNC(get_thread_area) 183 { 184 print_user_desc(tcp, tcp->u_arg[0], 185 entering(tcp) ? USER_DESC_ENTERING : USER_DESC_EXITING); 186 return 0; 187 } 188 189 #endif /* HAVE_STRUCT_USER_DESC */ 190 191 #if defined(M68K) || defined(MIPS) 192 SYS_FUNC(set_thread_area) 193 { 194 printaddr(tcp->u_arg[0]); 195 196 return RVAL_DECODED; 197 198 } 199 #endif 200 201 #if defined(M68K) 202 SYS_FUNC(get_thread_area) 203 { 204 return RVAL_DECODED | RVAL_HEX; 205 } 206 #endif 207