(root)/
strace-6.5/
src/
ldt.c
       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@strace.io>
       9   * Copyright (c) 2014-2021 The strace developers.
      10   * All rights reserved.
      11   *
      12   * SPDX-License-Identifier: LGPL-2.1-or-later
      13   */
      14  
      15  #include "defs.h"
      16  
      17  #ifdef HAVE_STRUCT_USER_DESC
      18  
      19  # include <asm/ldt.h>
      20  
      21  # include "xstring.h"
      22  
      23  void
      24  print_user_desc(struct tcb *const tcp, const kernel_ulong_t addr,
      25  		enum user_desc_print_filter filter)
      26  {
      27  	struct user_desc desc;
      28  	unsigned *entry_number = get_tcb_priv_data(tcp);
      29  
      30  	switch (filter) {
      31  	case USER_DESC_ENTERING:
      32  		if (umove_or_printaddr(tcp, addr, &desc.entry_number))
      33  			return;
      34  
      35  		break;
      36  
      37  	case USER_DESC_EXITING:
      38  		if (!addr || !verbose(tcp))
      39  			return;
      40  		if (syserror(tcp) || umove(tcp, addr, &desc)) {
      41  			if (entry_number) {
      42  				tprint_struct_next();
      43  				tprint_more_data_follows();
      44  				tprint_struct_end();
      45  			}
      46  
      47  			return;
      48  		}
      49  
      50  		break;
      51  
      52  	case USER_DESC_BOTH:
      53  		if (umove_or_printaddr(tcp, addr, &desc))
      54  			return;
      55  
      56  		break;
      57  	}
      58  
      59  	if (filter & USER_DESC_ENTERING) {
      60  		tprint_struct_begin();
      61  		PRINT_FIELD_ID(desc, entry_number);
      62  
      63  		/*
      64  		 * If we don't print the whole structure now, let's save it for
      65  		 * later.
      66  		 */
      67  		if (filter == USER_DESC_ENTERING) {
      68  			entry_number = xmalloc(sizeof(*entry_number));
      69  
      70  			*entry_number = desc.entry_number;
      71  			set_tcb_priv_data(tcp, entry_number, free);
      72  		}
      73  	}
      74  
      75  	if (filter & USER_DESC_EXITING) {
      76  		/*
      77  		 * It should be the same in case of get_thread_area, but we can
      78  		 * never be sure...
      79  		 */
      80  		if (filter == USER_DESC_EXITING) {
      81  			if (entry_number) {
      82  				if (*entry_number != desc.entry_number) {
      83  					tprint_value_changed();
      84  					PRINT_VAL_ID(desc.entry_number);
      85  				}
      86  			} else {
      87  				/*
      88  				 * This is really strange. If we are here, it
      89  				 * means that we failed on entering but somehow
      90  				 * succeeded on exiting.
      91  				 */
      92  				tprint_value_changed();
      93  				tprint_struct_begin();
      94  				PRINT_FIELD_ID(desc, entry_number);
      95  			}
      96  		}
      97  
      98  		tprint_struct_next();
      99  		PRINT_FIELD_0X(desc, base_addr);
     100  		tprint_struct_next();
     101  		PRINT_FIELD_0X(desc, limit);
     102  		tprint_struct_next();
     103  		PRINT_FIELD_U_CAST(desc, seg_32bit, unsigned int);
     104  		tprint_struct_next();
     105  		PRINT_FIELD_U_CAST(desc, contents, unsigned int);
     106  		tprint_struct_next();
     107  		PRINT_FIELD_U_CAST(desc, read_exec_only, unsigned int);
     108  		tprint_struct_next();
     109  		PRINT_FIELD_U_CAST(desc, limit_in_pages, unsigned int);
     110  		tprint_struct_next();
     111  		PRINT_FIELD_U_CAST(desc, seg_not_present, unsigned int);
     112  		tprint_struct_next();
     113  		PRINT_FIELD_U_CAST(desc, useable, unsigned int);
     114  
     115  # ifdef HAVE_STRUCT_USER_DESC_LM
     116  		/* lm is totally ignored for 32-bit processes */
     117  		if (current_klongsize == 8) {
     118  			tprint_struct_next();
     119  			PRINT_FIELD_U_CAST(desc, lm, unsigned int);
     120  		}
     121  # endif /* HAVE_STRUCT_USER_DESC_LM */
     122  
     123  		tprint_struct_end();
     124  	}
     125  }
     126  
     127  SYS_FUNC(modify_ldt)
     128  {
     129  	if (entering(tcp)) {
     130  		/* func */
     131  		PRINT_VAL_D((int) tcp->u_arg[0]);
     132  		tprint_arg_next();
     133  
     134  		/* ptr */
     135  		if (tcp->u_arg[2] != sizeof(struct user_desc))
     136  			printaddr(tcp->u_arg[1]);
     137  		else
     138  			print_user_desc(tcp, tcp->u_arg[1], USER_DESC_BOTH);
     139  		tprint_arg_next();
     140  
     141  		PRINT_VAL_U(tcp->u_arg[2]);
     142  
     143  		return 0;
     144  	}
     145  
     146  	/*
     147  	 * For some reason ("tht ABI for sys_modify_ldt() expects
     148  	 * 'int'"), modify_ldt clips higher bits on x86_64.
     149  	 */
     150  
     151  	if (syserror(tcp) || (kernel_ulong_t) tcp->u_rval < 0xfffff000)
     152  		return 0;
     153  
     154  	tcp->u_error = -(unsigned int) tcp->u_rval;
     155  
     156  	return 0;
     157  }
     158  
     159  SYS_FUNC(set_thread_area)
     160  {
     161  	if (entering(tcp)) {
     162  		print_user_desc(tcp, tcp->u_arg[0], USER_DESC_BOTH);
     163  	} else {
     164  		struct user_desc desc;
     165  
     166  		if (!verbose(tcp) || syserror(tcp) ||
     167  		    umove(tcp, tcp->u_arg[0], &desc) < 0) {
     168  			/* returned entry_number is not available */
     169  		} else {
     170  			static char outstr[32];
     171  
     172  			xsprintf(outstr, "entry_number=%u", desc.entry_number);
     173  			tcp->auxstr = outstr;
     174  			return RVAL_STR;
     175  		}
     176  	}
     177  	return 0;
     178  }
     179  
     180  SYS_FUNC(get_thread_area)
     181  {
     182  	print_user_desc(tcp, tcp->u_arg[0],
     183  			entering(tcp) ? USER_DESC_ENTERING : USER_DESC_EXITING);
     184  	return 0;
     185  }
     186  
     187  #endif /* HAVE_STRUCT_USER_DESC */
     188  
     189  #if defined(M68K) || defined(MIPS)
     190  SYS_FUNC(set_thread_area)
     191  {
     192  	printaddr(tcp->u_arg[0]);
     193  
     194  	return RVAL_DECODED;
     195  
     196  }
     197  #endif
     198  
     199  #if defined(M68K)
     200  SYS_FUNC(get_thread_area)
     201  {
     202  	return RVAL_DECODED | RVAL_HEX;
     203  }
     204  #endif