(root)/
glibc-2.38/
sysdeps/
unix/
sysv/
linux/
tst-clone2-internal.c
       1  /* Test if CLONE_VM does not change pthread pid/tid field (BZ #19957)
       2     Copyright (C) 2021-2023 Free Software Foundation, Inc.
       3     This file is part of the GNU C Library.
       4  
       5     The GNU C Library is free software; you can redistribute it and/or
       6     modify it under the terms of the GNU Lesser General Public
       7     License as published by the Free Software Foundation; either
       8     version 2.1 of the License, or (at your option) any later version.
       9  
      10     The GNU C Library is distributed in the hope that it will be useful,
      11     but WITHOUT ANY WARRANTY; without even the implied warranty of
      12     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
      13     Lesser General Public License for more details.
      14  
      15     You should have received a copy of the GNU Lesser General Public
      16     License along with the GNU C Library; if not, see
      17     <https://www.gnu.org/licenses/>.  */
      18  
      19  #include <sched.h>
      20  #include <signal.h>
      21  #include <string.h>
      22  #include <stdio.h>
      23  #include <fcntl.h>
      24  #include <unistd.h>
      25  #include <stddef.h>
      26  #include <stdbool.h>
      27  #include <stdint.h>
      28  #include <stdlib.h>
      29  #include <errno.h>
      30  #include <sys/types.h>
      31  #include <sys/wait.h>
      32  #include <sys/syscall.h>
      33  #include <clone_internal.h>
      34  #include <support/xunistd.h>
      35  #include <support/check.h>
      36  
      37  static int sig;
      38  static int pipefd[2];
      39  
      40  static int
      41  f (void *a)
      42  {
      43    close (pipefd[0]);
      44  
      45    pid_t ppid = getppid ();
      46    pid_t pid = getpid ();
      47    pid_t tid = gettid ();
      48  
      49    if (write (pipefd[1], &ppid, sizeof ppid) != sizeof (ppid))
      50      FAIL_EXIT1 ("write ppid failed\n");
      51    if (write (pipefd[1], &pid, sizeof pid) != sizeof (pid))
      52      FAIL_EXIT1 ("write pid failed\n");
      53    if (write (pipefd[1], &tid, sizeof tid) != sizeof (tid))
      54      FAIL_EXIT1 ("write tid failed\n");
      55  
      56    return 0;
      57  }
      58  
      59  
      60  static int
      61  do_test (void)
      62  {
      63    sig = SIGRTMIN;
      64    sigset_t ss;
      65    sigemptyset (&ss);
      66    sigaddset (&ss, sig);
      67    if (sigprocmask (SIG_BLOCK, &ss, NULL) != 0)
      68      FAIL_EXIT1 ("sigprocmask failed: %m");
      69  
      70    if (pipe2 (pipefd, O_CLOEXEC))
      71      FAIL_EXIT1 ("pipe failed: %m");
      72  
      73  #ifdef __ia64__
      74  # define STACK_SIZE 256 * 1024
      75  #else
      76  # define STACK_SIZE 128 * 1024
      77  #endif
      78    char st[STACK_SIZE] __attribute__ ((aligned));
      79    struct clone_args clone_args =
      80      {
      81        .stack = (uintptr_t) st,
      82        .stack_size = sizeof (st),
      83      };
      84    pid_t p = __clone_internal (&clone_args, f, 0);
      85  
      86    close (pipefd[1]);
      87  
      88    if (p == -1)
      89      FAIL_EXIT1("clone failed: %m");
      90  
      91    pid_t ppid, pid, tid;
      92    if (read (pipefd[0], &ppid, sizeof pid) != sizeof pid)
      93      {
      94        kill (p, SIGKILL);
      95        FAIL_EXIT1 ("read ppid failed: %m");
      96      }
      97    if (read (pipefd[0], &pid, sizeof pid) != sizeof pid)
      98      {
      99        kill (p, SIGKILL);
     100        FAIL_EXIT1 ("read pid failed: %m");
     101      }
     102    if (read (pipefd[0], &tid, sizeof tid) != sizeof tid)
     103      {
     104        kill (p, SIGKILL);
     105        FAIL_EXIT1 ("read tid failed: %m");
     106      }
     107  
     108    close (pipefd[0]);
     109  
     110    pid_t own_pid = getpid ();
     111    pid_t own_tid = syscall (__NR_gettid);
     112  
     113    /* Some sanity checks for clone syscall: returned ppid should be current
     114       pid and both returned tid/pid should be different from current one.  */
     115    if ((ppid != own_pid) || (pid == own_pid) || (tid == own_tid))
     116      FAIL_RET ("ppid=%i pid=%i tid=%i | own_pid=%i own_tid=%i",
     117  	      (int)ppid, (int)pid, (int)tid, (int)own_pid, (int)own_tid);
     118  
     119    int e;
     120    xwaitpid (p, &e, __WCLONE);
     121    TEST_VERIFY (WIFEXITED (e));
     122    TEST_COMPARE (WEXITSTATUS (e), 0);
     123    return 0;
     124  }
     125  
     126  #include <support/test-driver.c>