(root)/
strace-6.5/
src/
ptrace.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, 1994, 1995, 1996 Rick Sladkey <jrs@world.std.com>
       5   * Copyright (c) 1996-1999 Wichert Akkerman <wichert@cistron.nl>
       6   * Copyright (c) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
       7   *                     Linux for s390 port by D.J. Barrow
       8   *                    <barrow_dj@mail.yahoo.com,djbarrow@de.ibm.com>
       9   * Copyright (c) 2000 PocketPenguins Inc.  Linux for Hitachi SuperH
      10   *                    port by Greg Banks <gbanks@pocketpenguins.com>
      11   * Copyright (c) 1999-2022 The strace developers.
      12   *
      13   * All rights reserved.
      14   *
      15   * SPDX-License-Identifier: LGPL-2.1-or-later
      16   */
      17  
      18  #include "defs.h"
      19  
      20  #ifdef HAVE_ELF_H
      21  # include <elf.h>
      22  #endif
      23  
      24  #include "iovec.h"
      25  #include "ptrace.h"
      26  #include "ptrace_syscall_info.h"
      27  #include "regs.h"
      28  
      29  #include "xlat/nt_descriptor_types.h"
      30  #include "xlat/ptrace_cmds.h"
      31  #include "xlat/compat_ptrace_cmds.h"
      32  #include "xlat/ptrace_setoptions_flags.h"
      33  #include "xlat/ptrace_peeksiginfo_flags.h"
      34  
      35  #define uoff(member)	offsetof(struct user, member)
      36  #define XLAT_UOFF(member)	{ uoff(member), "offsetof(struct user, " #member ")" }
      37  
      38  #ifdef COMPAT_PTRACE_GETREGS
      39  # define HAVE_COMPAT_PTRACE_MACROS 1
      40  #else
      41  # define HAVE_COMPAT_PTRACE_MACROS 0
      42  #endif
      43  
      44  static const struct xlat_data struct_user_offsets_data[] = {
      45  #include "userent.h"
      46  	{ 0, 0 }
      47  };
      48  
      49  static const struct xlat struct_user_offsets = {
      50  	.type = XT_SORTED,
      51  	.size = ARRAY_SIZE(struct_user_offsets_data) - 1,
      52  	.data = struct_user_offsets_data,
      53  };
      54  
      55  static void
      56  print_user_offset_addr(const kernel_ulong_t addr)
      57  {
      58  	const uint64_t last_user_offset = struct_user_offsets.size ?
      59  		struct_user_offsets.data[struct_user_offsets.size - 1].val : 0;
      60  
      61  	uint64_t base_addr = addr;
      62  	const char *str = xlookup_le(&struct_user_offsets, &base_addr);
      63  
      64  	/* We don't want to pretty print addresses beyond struct user */
      65  	if (addr > base_addr && base_addr == last_user_offset)
      66  		str = NULL;
      67  
      68  	if (!str || xlat_verbose(xlat_verbosity) != XLAT_STYLE_ABBREV)
      69  		printaddr(addr);
      70  	if (!str || xlat_verbose(xlat_verbosity) == XLAT_STYLE_RAW)
      71  		return;
      72  
      73  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
      74  		tprint_comment_begin();
      75  
      76  	tprints_string(str);
      77  	if (base_addr != addr) {
      78  		tprint_plus();
      79  		PRINT_VAL_U(addr - (kernel_ulong_t) base_addr);
      80  	}
      81  
      82  	if (xlat_verbose(xlat_verbosity) == XLAT_STYLE_VERBOSE)
      83  		tprint_comment_end();
      84  }
      85  
      86  static void
      87  decode_peeksiginfo_args(struct tcb *const tcp, const kernel_ulong_t addr)
      88  {
      89  	struct {
      90  		uint64_t off;
      91  		uint32_t flags;
      92  		uint32_t nr;
      93  	} psi;
      94  
      95  	if (!umove_or_printaddr(tcp, addr, &psi)) {
      96  		tprint_struct_begin();
      97  		PRINT_FIELD_U(psi, off);
      98  		tprint_struct_next();
      99  
     100  		PRINT_FIELD_FLAGS(psi, flags, ptrace_peeksiginfo_flags,
     101  				  "PTRACE_PEEKSIGINFO_???");
     102  		tprint_struct_next();
     103  
     104  		PRINT_FIELD_U(psi, nr);
     105  		tprint_struct_end();
     106  	}
     107  }
     108  
     109  static int
     110  decode_seccomp_metadata(struct tcb *const tcp,
     111  			const kernel_ulong_t addr,
     112  			const kernel_ulong_t size)
     113  {
     114  	struct {
     115  		uint64_t filter_off;
     116  		uint64_t flags;
     117  	} md;
     118  
     119  	if (entering(tcp)) {
     120  		if (size < sizeof(md.filter_off)) {
     121  			printaddr(addr);
     122  			return RVAL_DECODED;
     123  		}
     124  
     125  		if (umove_or_printaddr(tcp, addr, &md.filter_off)) {
     126  			return RVAL_DECODED;
     127  		}
     128  
     129  		tprint_struct_begin();
     130  		PRINT_FIELD_U(md, filter_off);
     131  	} else {
     132  		const size_t offset = sizeof(md.filter_off);
     133  
     134  		if (!syserror(tcp) && size > offset) {
     135  			tprint_struct_next();
     136  
     137  			if (size < sizeof(md) ||
     138  			    !tfetch_mem(tcp, addr + offset,
     139  					sizeof(md.flags), &md.flags)) {
     140  				tprint_unavailable();
     141  			} else {
     142  				PRINT_FIELD_FLAGS(md, flags,
     143  						  seccomp_filter_flags,
     144  						  "SECCOMP_FILTER_FLAG_???");
     145  				if (size > sizeof(md)) {
     146  					tprint_struct_next();
     147  					tprint_more_data_follows();
     148  				}
     149  			}
     150  		}
     151  
     152  		tprint_struct_end();
     153  	}
     154  
     155  	return 0;
     156  }
     157  
     158  static void
     159  decode_regset(struct tcb *const tcp, const strace_iovec *iov,
     160  	      const unsigned int nt)
     161  {
     162  	switch (nt) {
     163  		case NT_PRSTATUS:
     164  			decode_prstatus_regset(tcp, iov->iov_base, iov->iov_len);
     165  			break;
     166  		case NT_FPREGSET:
     167  			decode_fpregset(tcp, iov->iov_base, iov->iov_len);
     168  			break;
     169  		default:
     170  			printaddr(iov->iov_base);
     171  			break;
     172  	}
     173  }
     174  
     175  static int
     176  decode_getregset(struct tcb *const tcp, const kernel_ulong_t addr,
     177  		 const unsigned int nt)
     178  {
     179  	strace_iovec iov;
     180  
     181  	if (!fetch_struct_iovec(tcp, addr, &iov)) {
     182  		printaddr(addr);
     183  		return RVAL_DECODED;
     184  	}
     185  
     186  	if (entering(tcp)) {
     187  		set_tcb_priv_ulong(tcp, iov.iov_len);
     188  	} else {
     189  		const unsigned long old_len = get_tcb_priv_ulong(tcp);
     190  
     191  		tprint_struct_begin();
     192  		tprints_field_name("iov_base");
     193  		decode_regset(tcp, &iov, nt);
     194  		tprint_struct_next();
     195  
     196  		if (old_len == iov.iov_len) {
     197  			PRINT_FIELD_U(iov, iov_len);
     198  		} else {
     199  			tprints_field_name("iov_len");
     200  			PRINT_VAL_U(old_len);
     201  			tprint_value_changed();
     202  			PRINT_VAL_U(iov.iov_len);
     203  		}
     204  		tprint_struct_end();
     205  	}
     206  
     207  	return 0;
     208  }
     209  
     210  static int
     211  decode_setregset(struct tcb *const tcp, const kernel_ulong_t addr,
     212  		 const unsigned int nt)
     213  {
     214  	strace_iovec iov;
     215  
     216  	if (entering(tcp)) {
     217  		if (!fetch_struct_iovec(tcp, addr, &iov)) {
     218  			printaddr(addr);
     219  			return RVAL_DECODED;
     220  		}
     221  
     222  		tprint_struct_begin();
     223  		tprints_field_name("iov_base");
     224  		decode_regset(tcp, &iov, nt);
     225  		tprint_struct_next();
     226  
     227  		PRINT_FIELD_U(iov, iov_len);
     228  
     229  		set_tcb_priv_ulong(tcp, iov.iov_len);
     230  	} else {
     231  		if (fetch_struct_iovec(tcp, addr, &iov) &&
     232  		    get_tcb_priv_ulong(tcp) != iov.iov_len) {
     233  			tprint_value_changed();
     234  			PRINT_VAL_U(iov.iov_len);
     235  		}
     236  
     237  		tprint_struct_end();
     238  	}
     239  
     240  	return 0;
     241  }
     242  
     243  #ifdef PTRACE_GETREGS64
     244  # include "arch_pt_regs64.c"
     245  #endif
     246  
     247  static int
     248  decode_ptrace_entering(struct tcb *const tcp)
     249  {
     250  	const kernel_ulong_t request = tcp->u_arg[0];
     251  	const int pid = tcp->u_arg[1];
     252  	const kernel_ulong_t addr = tcp->u_arg[2];
     253  	const kernel_ulong_t data = tcp->u_arg[3];
     254  
     255  /*
     256   * SPARC systems have the meaning of data and addr reversed
     257   * for PTRACE_[GS]ETREGS and PTRACE_[GS]ETFPREGS:
     258   * data is ignored and the registers are copied from/to the address addr.
     259   */
     260  #if defined SPARC || defined SPARC64
     261  # define regs_addr	addr
     262  #else
     263  # define regs_addr	data
     264  #endif
     265  
     266  	/* COMPAT_PTRACE_* */
     267  #if HAVE_COMPAT_PTRACE_MACROS
     268  	if (current_personality != 1) {
     269  		switch (request) {
     270  		case COMPAT_PTRACE_GETREGS:
     271  		case COMPAT_PTRACE_SETREGS:
     272  		case COMPAT_PTRACE_GETFPREGS:
     273  		case COMPAT_PTRACE_SETFPREGS:
     274  		case COMPAT_PTRACE_GET_THREAD_AREA:
     275  		case COMPAT_PTRACE_SET_SYSCALL:
     276  		case COMPAT_PTRACE_GETVFPREGS:
     277  		case COMPAT_PTRACE_SETVFPREGS:
     278  		case COMPAT_PTRACE_GETHBPREGS:
     279  		case COMPAT_PTRACE_SETHBPREGS:
     280  			printxvals_ex(request, "COMPAT_PTRACE_???",
     281  				      xlat_verbose(xlat_verbosity)
     282  					== XLAT_STYLE_RAW ? XLAT_STYLE_RAW
     283  							  : XLAT_STYLE_VERBOSE,
     284  				      compat_ptrace_cmds, NULL);
     285  			tprint_arg_next();
     286  			printpid(tcp, pid, PT_TGID);
     287  			tprint_arg_next();
     288  			printaddr(addr);
     289  			tprint_arg_next();
     290  			printaddr(data);
     291  			return RVAL_DECODED;
     292  		}
     293  	}
     294  #endif /* HAVE_COMPAT_PTRACE_MACROS */
     295  
     296  	/* request */
     297  	printxval64(ptrace_cmds, request, "PTRACE_???");
     298  
     299  	if (request == PTRACE_TRACEME) {
     300  		/* pid, addr, and data are ignored. */
     301  		return RVAL_DECODED;
     302  	}
     303  
     304  	/* pid */
     305  	tprint_arg_next();
     306  	printpid(tcp, pid, PT_TGID);
     307  
     308  	switch (request) {
     309  	case PTRACE_ATTACH:
     310  	case PTRACE_INTERRUPT:
     311  	case PTRACE_KILL:
     312  	case PTRACE_LISTEN:
     313  		/* addr and data are ignored */
     314  		return RVAL_DECODED;
     315  	}
     316  
     317  	/* addr */
     318  	tprint_arg_next();
     319  	switch (request) {
     320  	case PTRACE_PEEKUSER:
     321  #ifdef IA64
     322  		print_user_offset_addr(addr);
     323  		/* data is ignored */
     324  		return RVAL_DECODED | RVAL_HEX;
     325  #endif
     326  	case PTRACE_POKEUSER:
     327  		print_user_offset_addr(addr);
     328  		break;
     329  	case PTRACE_GETREGSET:
     330  	case PTRACE_SETREGSET:
     331  		printxval(nt_descriptor_types, addr, "NT_???");
     332  		break;
     333  	case PTRACE_GETSIGMASK:
     334  	case PTRACE_SETSIGMASK:
     335  	case PTRACE_SECCOMP_GET_FILTER:
     336  	case PTRACE_SECCOMP_GET_METADATA:
     337  	case PTRACE_GET_SYSCALL_INFO:
     338  		PRINT_VAL_U(addr);
     339  		break;
     340  	case PTRACE_PEEKSIGINFO:
     341  		decode_peeksiginfo_args(tcp, addr);
     342  		break;
     343  #ifdef PTRACE_SETREGS
     344  	case PTRACE_SETREGS:
     345  		decode_pt_regs(tcp, regs_addr);
     346  		return RVAL_DECODED;
     347  #endif
     348  #ifdef PTRACE_SETREGS64
     349  	case PTRACE_SETREGS64:
     350  		decode_pt_regs64(tcp, regs_addr);
     351  		return RVAL_DECODED;
     352  #endif
     353  #ifdef PTRACE_SETFPREGS
     354  	case PTRACE_SETFPREGS:
     355  		decode_pt_fpregs(tcp, regs_addr);
     356  		return RVAL_DECODED;
     357  #endif
     358  #ifdef PTRACE_GETREGS
     359  	case PTRACE_GETREGS:
     360  		/* print regs_addr on exiting syscall */
     361  		return 0;
     362  #endif
     363  #ifdef PTRACE_GETREGS64
     364  	case PTRACE_GETREGS64:
     365  		/* print regs_addr on exiting syscall */
     366  		return 0;
     367  #endif
     368  #ifdef PTRACE_GETFPREGS
     369  	case PTRACE_GETFPREGS:
     370  		/* print regs_addr on exiting syscall */
     371  		return 0;
     372  #endif
     373  #ifdef IA64
     374  	case PTRACE_PEEKDATA:
     375  	case PTRACE_PEEKTEXT:
     376  		printaddr(addr);
     377  		/* data is ignored */
     378  		return RVAL_DECODED | RVAL_HEX;
     379  #endif /* IA64 */
     380  	default:
     381  		printaddr(addr);
     382  	}
     383  
     384  	/* data */
     385  	tprint_arg_next();
     386  	switch (request) {
     387  	case PTRACE_CONT:
     388  	case PTRACE_DETACH:
     389  	case PTRACE_SYSCALL:
     390  #ifdef PTRACE_SINGLESTEP
     391  	case PTRACE_SINGLESTEP:
     392  #endif
     393  #ifdef PTRACE_SINGLEBLOCK
     394  	case PTRACE_SINGLEBLOCK:
     395  #endif
     396  #ifdef PTRACE_SYSEMU
     397  	case PTRACE_SYSEMU:
     398  #endif
     399  #ifdef PTRACE_SYSEMU_SINGLESTEP
     400  	case PTRACE_SYSEMU_SINGLESTEP:
     401  #endif
     402  		printsignal(data);
     403  		break;
     404  	case PTRACE_SEIZE:
     405  	case PTRACE_SETOPTIONS:
     406  #ifdef PTRACE_OLDSETOPTIONS
     407  	case PTRACE_OLDSETOPTIONS:
     408  #endif
     409  		printflags64(ptrace_setoptions_flags, data, "PTRACE_O_???");
     410  		break;
     411  	case PTRACE_SETSIGINFO:
     412  		printsiginfo_at(tcp, data);
     413  		break;
     414  	case PTRACE_SETSIGMASK:
     415  		print_sigset_addr_len(tcp, data, addr);
     416  		break;
     417  	case PTRACE_GETREGSET:
     418  		return decode_getregset(tcp, data, addr);
     419  	case PTRACE_SETREGSET:
     420  		return decode_setregset(tcp, data, addr);
     421  		break;
     422  	case PTRACE_SECCOMP_GET_METADATA:
     423  		return decode_seccomp_metadata(tcp, data, addr);
     424  #ifndef IA64
     425  	case PTRACE_PEEKDATA:
     426  	case PTRACE_PEEKTEXT:
     427  	case PTRACE_PEEKUSER:
     428  #endif
     429  	case PTRACE_GETEVENTMSG:
     430  	case PTRACE_GETSIGINFO:
     431  	case PTRACE_GETSIGMASK:
     432  	case PTRACE_PEEKSIGINFO:
     433  	case PTRACE_SECCOMP_GET_FILTER:
     434  	case PTRACE_GET_SYSCALL_INFO:
     435  		if (verbose(tcp)) {
     436  			/* print data on exiting syscall */
     437  			return 0;
     438  		}
     439  		ATTRIBUTE_FALLTHROUGH;
     440  	default:
     441  		printaddr(data);
     442  		break;
     443  	}
     444  
     445  	return RVAL_DECODED;
     446  }
     447  
     448  static int
     449  decode_ptrace_exiting(struct tcb *const tcp)
     450  {
     451  	const kernel_ulong_t request = tcp->u_arg[0];
     452  	const kernel_ulong_t addr = tcp->u_arg[2];
     453  	const kernel_ulong_t data = tcp->u_arg[3];
     454  
     455  	switch (request) {
     456  #ifndef IA64
     457  	case PTRACE_PEEKDATA:
     458  	case PTRACE_PEEKTEXT:
     459  	case PTRACE_PEEKUSER:
     460  		printnum_ptr(tcp, data);
     461  		break;
     462  #endif
     463  	case PTRACE_GETEVENTMSG:
     464  		printnum_ulong(tcp, data);
     465  		break;
     466  	case PTRACE_GETREGSET:
     467  		return decode_getregset(tcp, data, addr);
     468  	case PTRACE_SETREGSET:
     469  		return decode_setregset(tcp, data, addr);
     470  	case PTRACE_GETSIGINFO:
     471  		printsiginfo_at(tcp, data);
     472  		break;
     473  	case PTRACE_GETSIGMASK:
     474  		print_sigset_addr_len(tcp, data, addr);
     475  		break;
     476  	case PTRACE_PEEKSIGINFO:
     477  		print_siginfo_array(tcp, data, tcp->u_rval);
     478  		break;
     479  	case PTRACE_SECCOMP_GET_FILTER:
     480  		print_seccomp_fprog(tcp, data, tcp->u_rval);
     481  		break;
     482  	case PTRACE_SECCOMP_GET_METADATA:
     483  		return decode_seccomp_metadata(tcp, data, tcp->u_rval);
     484  	case PTRACE_GET_SYSCALL_INFO:
     485  		print_ptrace_syscall_info(tcp, data, addr);
     486  		break;
     487  #ifdef PTRACE_GETREGS
     488  	case PTRACE_GETREGS:
     489  		decode_pt_regs(tcp, regs_addr);
     490  		break;
     491  #endif
     492  #ifdef PTRACE_GETREGS64
     493  	case PTRACE_GETREGS64:
     494  		decode_pt_regs64(tcp, regs_addr);
     495  		break;
     496  #endif
     497  #ifdef PTRACE_GETFPREGS
     498  	case PTRACE_GETFPREGS:
     499  		decode_pt_fpregs(tcp, regs_addr);
     500  		break;
     501  #endif
     502  	}
     503  
     504  	return 0;
     505  }
     506  
     507  SYS_FUNC(ptrace)
     508  {
     509  	return entering(tcp) ? decode_ptrace_entering(tcp)
     510  			     : decode_ptrace_exiting(tcp);
     511  }