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 * 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 44void 45print_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 135SYS_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 RVAL_PRINT_ERR_VAL; 159} 160 161SYS_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 182SYS_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) 192SYS_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) 202SYS_FUNC(get_thread_area) 203{ 204 return RVAL_DECODED | RVAL_HEX; 205} 206#endif 207