1 // RUN: %clangxx_tsan -O1 %s -o %t && %run %t 2>&1 | FileCheck %s 2 3 // The test models how sandbox2 unshares user namespace after clone: 4 // https://github.com/google/sandboxed-api/blob/c95837a6c131fbdf820db352a97d54fcbcbde6c0/sandboxed_api/sandbox2/forkserver.cc#L249 5 // which works only in sigle-threaded processes. 6 7 #include "../test.h" 8 #include <errno.h> 9 #include <sched.h> 10 #include <sys/types.h> 11 #include <sys/wait.h> 12 #ifdef __linux__ 13 # include <linux/version.h> 14 #endif 15 16 #if __PPC64__ && RHEL_MAJOR == 7 && RHEL_MINOR == 9 17 # define PPC64_RHEL7_9 1 18 #endif 19 20 #ifndef PPC64_RHEL7_9 21 static int cloned(void *arg) { 22 // Unshare can fail for other reasons, e.g. no permissions, 23 // so check only the error we are interested in: 24 // if the process is multi-threaded unshare must return EINVAL. 25 if (unshare(CLONE_NEWUSER) && errno == EINVAL) { 26 fprintf(stderr, "unshare failed: %d\n", errno); 27 exit(1); 28 } 29 exit(0); 30 return 0; 31 } 32 #endif 33 34 int main() { 35 #ifndef PPC64_RHEL7_9 36 char stack[64 << 10] __attribute__((aligned(64))); 37 int pid = clone(cloned, stack + sizeof(stack), SIGCHLD, 0); 38 if (pid == -1) { 39 fprintf(stderr, "failed to clone: %d\n", errno); 40 exit(1); 41 } 42 int status = 0; 43 while (wait(&status) != pid) { 44 } 45 if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) { 46 fprintf(stderr, "child failed: %d\n", status); 47 exit(1); 48 } 49 #endif 50 fprintf(stderr, "DONE\n"); 51 } 52 53 // CHECK: DONE 54