(root)/
strace-6.5/
src/
clone.c
       1  /*
       2   * Copyright (c) 1999-2000 Wichert Akkerman <wichert@cistron.nl>
       3   * Copyright (c) 2002-2005 Roland McGrath <roland@redhat.com>
       4   * Copyright (c) 2008 Jan Kratochvil <jan.kratochvil@redhat.com>
       5   * Copyright (c) 2009-2013 Denys Vlasenko <dvlasenk@redhat.com>
       6   * Copyright (c) 2006-2015 Dmitry V. Levin <ldv@strace.io>
       7   * Copyright (c) 2014-2022 The strace developers.
       8   * All rights reserved.
       9   *
      10   * SPDX-License-Identifier: LGPL-2.1-or-later
      11   */
      12  
      13  #include "defs.h"
      14  #include "scno.h"
      15  #include <linux/sched.h>
      16  
      17  #include "xlat/clone_flags.h"
      18  #include "xlat/clone3_flags.h"
      19  #include "xlat/setns_types.h"
      20  #include "xlat/unshare_flags.h"
      21  
      22  #if defined IA64
      23  # define ARG_FLAGS	0
      24  # define ARG_STACK	1
      25  # define ARG_STACKSIZE	(shuffle_scno(tcp->scno) == __NR_clone2 ? 2 : -1)
      26  # define ARG_PTID	(shuffle_scno(tcp->scno) == __NR_clone2 ? 3 : 2)
      27  # define ARG_CTID	(shuffle_scno(tcp->scno) == __NR_clone2 ? 4 : 3)
      28  # define ARG_TLS	(shuffle_scno(tcp->scno) == __NR_clone2 ? 5 : 4)
      29  #elif defined S390 || defined S390X
      30  # define ARG_STACK	0
      31  # define ARG_FLAGS	1
      32  # define ARG_PTID	2
      33  # define ARG_CTID	3
      34  # define ARG_TLS	4
      35  #elif defined X86_64 || defined X32
      36  /* x86 personality processes have the last two arguments flipped. */
      37  # define ARG_FLAGS	0
      38  # define ARG_STACK	1
      39  # define ARG_PTID	2
      40  # define ARG_CTID	((current_personality != 1) ? 3 : 4)
      41  # define ARG_TLS	((current_personality != 1) ? 4 : 3)
      42  #elif defined ALPHA || defined TILE || defined OR1K || defined CSKY
      43  # define ARG_FLAGS	0
      44  # define ARG_STACK	1
      45  # define ARG_PTID	2
      46  # define ARG_CTID	3
      47  # define ARG_TLS	4
      48  #else
      49  # define ARG_FLAGS	0
      50  # define ARG_STACK	1
      51  # define ARG_PTID	2
      52  # define ARG_TLS	3
      53  # define ARG_CTID	4
      54  #endif
      55  
      56  static void
      57  print_tls_arg(struct tcb *const tcp, const kernel_ulong_t addr)
      58  {
      59  #ifdef HAVE_STRUCT_USER_DESC
      60  	if ((SUPPORTED_PERSONALITIES == 1) || (current_personality == 1))
      61  	{
      62  		print_user_desc(tcp, addr, USER_DESC_BOTH);
      63  	}
      64  	else
      65  #endif /* HAVE_STRUCT_USER_DESC */
      66  	{
      67  		printaddr(addr);
      68  	}
      69  }
      70  
      71  SYS_FUNC(clone)
      72  {
      73  	const kernel_ulong_t flags = tcp->u_arg[ARG_FLAGS] & ~CSIGNAL;
      74  
      75  	if (entering(tcp)) {
      76  		const unsigned int sig = tcp->u_arg[ARG_FLAGS] & CSIGNAL;
      77  
      78  		tprints_arg_name_begin("child_stack");
      79  		printaddr(tcp->u_arg[ARG_STACK]);
      80  		tprint_arg_name_end();
      81  		tprint_arg_next();
      82  #ifdef ARG_STACKSIZE
      83  		if (ARG_STACKSIZE != -1) {
      84  			tprints_arg_name_begin("stack_size");
      85  			PRINT_VAL_X(tcp->u_arg[ARG_STACKSIZE]);
      86  			tprint_arg_name_end();
      87  			tprint_arg_next();
      88  		}
      89  #endif
      90  		tprints_arg_name_begin("flags");
      91  		if (flags) {
      92  			tprint_flags_begin();
      93  			printflags64_in(clone_flags, flags, "CLONE_???");
      94  			if (sig) {
      95  				tprint_flags_or();
      96  				printsignal(sig);
      97  			}
      98  			tprint_flags_end();
      99  		} else {
     100  			printsignal(sig);
     101  		}
     102  		tprint_arg_name_end();
     103  		/*
     104  		 * TODO on syscall entry:
     105  		 * We can clear CLONE_PTRACE here since it is an ancient hack
     106  		 * to allow us to catch children, and we use another hack for that.
     107  		 * But CLONE_PTRACE can conceivably be used by malicious programs
     108  		 * to subvert us. By clearing this bit, we can defend against it:
     109  		 * in untraced execution, CLONE_PTRACE should have no effect.
     110  		 *
     111  		 * We can also clear CLONE_UNTRACED, since it allows to start
     112  		 * children outside of our control. At the moment
     113  		 * I'm trying to figure out whether there is a *legitimate*
     114  		 * use of this flag which we should respect.
     115  		 */
     116  		if ((flags & (CLONE_PARENT_SETTID|CLONE_PIDFD|CLONE_CHILD_SETTID
     117  			      |CLONE_CHILD_CLEARTID|CLONE_SETTLS)) == 0)
     118  			return RVAL_DECODED | RVAL_TID;
     119  	} else {
     120  		if (flags & (CLONE_PARENT_SETTID|CLONE_PIDFD)) {
     121  			kernel_ulong_t addr = tcp->u_arg[ARG_PTID];
     122  
     123  			tprint_arg_next();
     124  			tprints_arg_name_begin("parent_tid");
     125  			if (flags & CLONE_PARENT_SETTID)
     126  				printnum_pid(tcp, addr, PT_TID);
     127  			else
     128  				printnum_fd(tcp, addr);
     129  			tprint_arg_name_end();
     130  		}
     131  		if (flags & CLONE_SETTLS) {
     132  			tprint_arg_next();
     133  			tprints_arg_name_begin("tls");
     134  			print_tls_arg(tcp, tcp->u_arg[ARG_TLS]);
     135  			tprint_arg_name_end();
     136  		}
     137  		if (flags & (CLONE_CHILD_SETTID|CLONE_CHILD_CLEARTID)) {
     138  			tprint_arg_next();
     139  			tprints_arg_name_begin("child_tidptr");
     140  			printaddr(tcp->u_arg[ARG_CTID]);
     141  			tprint_arg_name_end();
     142  		}
     143  	}
     144  	return RVAL_TID;
     145  }
     146  
     147  static void
     148  tprint_value_changed_struct_begin(void)
     149  {
     150  	tprint_value_changed();
     151  	tprint_struct_begin();
     152  }
     153  
     154  SYS_FUNC(clone3)
     155  {
     156  	static const size_t minsz = offsetofend(struct clone_args, tls);
     157  
     158  	const kernel_ulong_t addr = tcp->u_arg[0];
     159  	const kernel_ulong_t size = tcp->u_arg[1];
     160  
     161  	struct clone_args arg = { 0 };
     162  	kernel_ulong_t fetch_size;
     163  
     164  	fetch_size = MIN(size, sizeof(arg));
     165  
     166  	if (entering(tcp)) {
     167  		if (fetch_size < minsz) {
     168  			printaddr(addr);
     169  			goto out;
     170  		} else if (umoven_or_printaddr(tcp, addr, fetch_size, &arg)) {
     171  			goto out;
     172  		}
     173  
     174  		tprint_struct_begin();
     175  		tprints_field_name("flags");
     176  		tprint_flags_begin();
     177  		printflags_ex(arg.flags, "CLONE_???", XLAT_STYLE_DEFAULT,
     178  			      clone_flags, clone3_flags, NULL);
     179  		tprint_flags_end();
     180  
     181  		if (arg.flags & CLONE_PIDFD) {
     182  			tprint_struct_next();
     183  			PRINT_FIELD_ADDR64(arg, pidfd);
     184  		}
     185  
     186  		if (arg.flags & (CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID)) {
     187  			tprint_struct_next();
     188  			PRINT_FIELD_ADDR64(arg, child_tid);
     189  		}
     190  
     191  		if (arg.flags & CLONE_PARENT_SETTID) {
     192  			tprint_struct_next();
     193  			PRINT_FIELD_ADDR64(arg, parent_tid);
     194  		}
     195  
     196  		if (arg.exit_signal < INT_MAX) {
     197  			tprint_struct_next();
     198  			PRINT_FIELD_OBJ_VAL(arg, exit_signal, printsignal);
     199  		} else {
     200  			tprint_struct_next();
     201  			PRINT_FIELD_U(arg, exit_signal);
     202  		}
     203  
     204  		tprint_struct_next();
     205  		PRINT_FIELD_ADDR64(arg, stack);
     206  		tprint_struct_next();
     207  		PRINT_FIELD_X(arg, stack_size);
     208  
     209  		if (arg.flags & CLONE_SETTLS) {
     210  			tprint_struct_next();
     211  			PRINT_FIELD_OBJ_TCB_VAL(arg, tls, tcp,
     212  						print_tls_arg);
     213  		}
     214  
     215  		if (arg.set_tid || arg.set_tid_size) {
     216  			static const unsigned int max_set_tid_size = 32;
     217  
     218  			if (!arg.set_tid || !arg.set_tid_size ||
     219  			    arg.set_tid_size > max_set_tid_size) {
     220  				tprint_struct_next();
     221  				PRINT_FIELD_ADDR64(arg, set_tid);
     222  			} else {
     223  				int buf;
     224  
     225  				tprint_struct_next();
     226  				PRINT_FIELD_OBJ_TCB_VAL(arg, set_tid, tcp,
     227  					print_array, arg.set_tid_size,
     228  					&buf, sizeof(buf), tfetch_mem,
     229  					print_int_array_member, 0);
     230  			}
     231  			tprint_struct_next();
     232  			PRINT_FIELD_U(arg, set_tid_size);
     233  		}
     234  
     235  		if (fetch_size > offsetof(struct clone_args, cgroup)
     236  		    && (arg.cgroup || arg.flags & CLONE_INTO_CGROUP)) {
     237  			tprint_struct_next();
     238  			PRINT_FIELD_U(arg, cgroup);
     239  		}
     240  
     241  		if (size > fetch_size)
     242  			print_nonzero_bytes(tcp, tprint_struct_next,
     243  					    addr, fetch_size,
     244  					    MIN(size, get_pagesize()),
     245  					    QUOTE_FORCE_HEX);
     246  
     247  		tprint_struct_end();
     248  
     249  		if ((arg.flags & (CLONE_PIDFD | CLONE_PARENT_SETTID)) ||
     250  		    (size > fetch_size))
     251  			return RVAL_TID;
     252  
     253  		goto out;
     254  	}
     255  
     256  	/* exiting */
     257  
     258  	if (syserror(tcp))
     259  		goto out;
     260  
     261  	if (umoven(tcp, addr, fetch_size, &arg)) {
     262  		tprint_value_changed();
     263  		printaddr(addr);
     264  		goto out;
     265  	}
     266  
     267  	void (*prefix_fun)(void) = tprint_value_changed_struct_begin;
     268  
     269  	if (arg.flags & CLONE_PIDFD) {
     270  		prefix_fun();
     271  		prefix_fun = tprint_struct_next;
     272  		tprints_field_name("pidfd");
     273  		printnum_fd(tcp, arg.pidfd);
     274  	}
     275  
     276  	if (arg.flags & CLONE_PARENT_SETTID) {
     277  		prefix_fun();
     278  		prefix_fun = tprint_struct_next;
     279  		tprints_field_name("parent_tid");
     280  		printnum_pid(tcp, arg.parent_tid, PT_TID);
     281  	}
     282  
     283  	if (size > fetch_size) {
     284  		/*
     285  		 * TODO: it is possible to also store the tail on entering
     286  		 *       and then compare against it on exiting in order
     287  		 *       to avoid double-printing, but it would also require yet
     288  		 *       another complication of print_nonzero_bytes interface.
     289  		 */
     290  		if (print_nonzero_bytes(tcp, prefix_fun, addr, fetch_size,
     291  					MIN(size, get_pagesize()),
     292  					QUOTE_FORCE_HEX)) {
     293  			prefix_fun = tprint_struct_next;
     294  		}
     295  	}
     296  
     297  	if (prefix_fun != tprint_value_changed_struct_begin)
     298  		tprint_struct_end();
     299  
     300  out:
     301  	tprint_arg_next();
     302  	PRINT_VAL_U(size);
     303  
     304  	return RVAL_DECODED | RVAL_TID;
     305  }
     306  
     307  
     308  SYS_FUNC(setns)
     309  {
     310  	printfd(tcp, tcp->u_arg[0]);
     311  	tprint_arg_next();
     312  	printflags(setns_types, tcp->u_arg[1], "CLONE_NEW???");
     313  
     314  	return RVAL_DECODED;
     315  }
     316  
     317  SYS_FUNC(unshare)
     318  {
     319  	printflags64(unshare_flags, tcp->u_arg[0], "CLONE_???");
     320  	return RVAL_DECODED;
     321  }
     322  
     323  SYS_FUNC(fork)
     324  {
     325  	return RVAL_DECODED | RVAL_TGID;
     326  }