(root)/
strace-6.5/
tests/
clone_ptrace.c
       1  /*
       2   * Check handling of CLONE_PTRACE'ed processes.
       3   *
       4   * Copyright (c) 2015-2022 The strace developers.
       5   * All rights reserved.
       6   *
       7   * SPDX-License-Identifier: GPL-2.0-or-later
       8   */
       9  
      10  #include "tests.h"
      11  
      12  #include <errno.h>
      13  #include <sched.h>
      14  #include <signal.h>
      15  #include <stdio.h>
      16  #include <stdlib.h>
      17  #include <string.h>
      18  #include <sys/wait.h>
      19  #include <unistd.h>
      20  
      21  static siginfo_t sinfo;
      22  
      23  #ifndef QUIET_ATTACH
      24  # define QUIET_ATTACH 0
      25  #endif
      26  #ifndef QUIET_EXIT
      27  # define QUIET_EXIT 0
      28  #endif
      29  
      30  static void
      31  handler(const int no, siginfo_t *const si, void *const uc)
      32  {
      33  	memcpy(&sinfo, si, sizeof(sinfo));
      34  }
      35  
      36  static int
      37  child(void *const arg)
      38  {
      39  	for(;;)
      40  		pause();
      41  	return 0;
      42  }
      43  
      44  #ifdef IA64
      45  extern int __clone2(int (*)(void *), void *, size_t, int, void *, ...);
      46  # define do_clone(fn_, stack_, size_, flags_, arg_, ...)	\
      47  	__clone2((fn_), (stack_), (size_), (flags_), (arg_), ## __VA_ARGS__)
      48  #else
      49  # define do_clone(fn_, stack_, size_, flags_, arg_, ...)	\
      50  	clone((fn_), (stack_), (flags_), (arg_), ## __VA_ARGS__)
      51  #endif
      52  
      53  int
      54  main(void)
      55  {
      56  	const int sig = SIGUSR1;
      57  	sigset_t mask;
      58  	sigemptyset(&mask);
      59  	sigaddset(&mask, sig);
      60  	if (sigprocmask(SIG_UNBLOCK, &mask, NULL))
      61  		perror_msg_and_fail("sigprocmask");
      62  
      63  	const unsigned long child_stack_size = get_page_size();
      64  	void *const child_stack =
      65  		tail_alloc(child_stack_size * 2) + child_stack_size;
      66  
      67  	const pid_t pid = do_clone(child, child_stack, child_stack_size,
      68  				   CLONE_PTRACE | SIGCHLD, 0);
      69  	if (pid < 0)
      70  		perror_msg_and_fail("clone");
      71  
      72  	static const struct sigaction sa = {
      73  		.sa_sigaction = handler,
      74  		.sa_flags = SA_SIGINFO
      75  	};
      76  	if (sigaction(SIGCHLD, &sa, NULL))
      77  		perror_msg_and_fail("sigaction");
      78  
      79  	kill(pid, sig);
      80  
      81  	FILE *const fp = fdopen(3, "a");
      82  	if (!fp)
      83  		perror_msg_and_fail("fdopen");
      84  #if !QUIET_ATTACH
      85  	if (fprintf(fp, "%s: Detached unknown pid %d\n",
      86  		    getenv("STRACE_EXE") ?: "strace", pid) < 0)
      87  		perror_msg_and_fail("fprintf");
      88  #endif
      89  
      90  	int status;
      91  	while (wait(&status) != pid) {
      92  		if (errno != EINTR)
      93  			perror_msg_and_fail("wait");
      94  	}
      95  	if (!WIFSIGNALED(status) || WTERMSIG(status) != sig)
      96  		error_msg_and_fail("unexpected child exit status %d", status);
      97  
      98  	char utm_str[64];
      99  	char stm_str[64];
     100  	printf("--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=%d"
     101  	       ", si_uid=%d, si_status=%s, si_utime=%s, si_stime=%s} ---\n"
     102  #if !QUIET_EXIT
     103  	       "+++ exited with 0 +++\n"
     104  #endif
     105  	       , pid, geteuid(), "SIGUSR1",
     106  	       clock_t_str((unsigned int) sinfo.si_utime, ARRSZ_PAIR(utm_str)),
     107  	       clock_t_str((unsigned int) sinfo.si_stime, ARRSZ_PAIR(stm_str)));
     108  
     109  	return 0;
     110  }