xref: /freebsd/contrib/capsicum-test/procdesc.cc (revision 955a3f9ad586f38395e66127f9f2f4afbf3d5a94)
18ac5aef8SEnji Cooper // Tests for the process descriptor API for Linux.
28ac5aef8SEnji Cooper #include <sys/types.h>
38ac5aef8SEnji Cooper #include <sys/resource.h>
48ac5aef8SEnji Cooper #include <sys/select.h>
58ac5aef8SEnji Cooper #include <sys/socket.h>
68ac5aef8SEnji Cooper #include <sys/stat.h>
78ac5aef8SEnji Cooper #include <sys/time.h>
88ac5aef8SEnji Cooper #include <sys/wait.h>
98ac5aef8SEnji Cooper #include <fcntl.h>
108ac5aef8SEnji Cooper #include <poll.h>
118ac5aef8SEnji Cooper #include <pthread.h>
128ac5aef8SEnji Cooper #include <signal.h>
138ac5aef8SEnji Cooper #include <stdlib.h>
148ac5aef8SEnji Cooper #include <unistd.h>
158ac5aef8SEnji Cooper 
168ac5aef8SEnji Cooper #include <iomanip>
178ac5aef8SEnji Cooper #include <map>
188ac5aef8SEnji Cooper 
198ac5aef8SEnji Cooper #include "capsicum.h"
208ac5aef8SEnji Cooper #include "syscalls.h"
218ac5aef8SEnji Cooper #include "capsicum-test.h"
228ac5aef8SEnji Cooper 
238ac5aef8SEnji Cooper #ifndef __WALL
248ac5aef8SEnji Cooper // Linux requires __WALL in order for waitpid(specific_pid,...) to
258ac5aef8SEnji Cooper // see and reap any specific pid.  Define this to nothing for platforms
268ac5aef8SEnji Cooper // (FreeBSD) where it doesn't exist, to reduce macroing.
278ac5aef8SEnji Cooper #define __WALL 0
288ac5aef8SEnji Cooper #endif
298ac5aef8SEnji Cooper 
308ac5aef8SEnji Cooper //------------------------------------------------
318ac5aef8SEnji Cooper // Utilities for the tests.
328ac5aef8SEnji Cooper 
pdwait4_(int pd,int * status,int options,struct rusage * ru)338ac5aef8SEnji Cooper static pid_t pdwait4_(int pd, int *status, int options, struct rusage *ru) {
348ac5aef8SEnji Cooper #ifdef HAVE_PDWAIT4
358ac5aef8SEnji Cooper   return pdwait4(pd, status, options, ru);
368ac5aef8SEnji Cooper #else
378ac5aef8SEnji Cooper   // Simulate pdwait4() with wait4(pdgetpid()); this won't work in capability mode.
388ac5aef8SEnji Cooper   pid_t pid = -1;
398ac5aef8SEnji Cooper   int rc = pdgetpid(pd, &pid);
408ac5aef8SEnji Cooper   if (rc < 0) {
418ac5aef8SEnji Cooper     return rc;
428ac5aef8SEnji Cooper   }
438ac5aef8SEnji Cooper   options |= __WALL;
448ac5aef8SEnji Cooper   return wait4(pid, status, options, ru);
458ac5aef8SEnji Cooper #endif
468ac5aef8SEnji Cooper }
478ac5aef8SEnji Cooper 
print_rusage(FILE * f,struct rusage * ru)488ac5aef8SEnji Cooper static void print_rusage(FILE *f, struct rusage *ru) {
498ac5aef8SEnji Cooper   fprintf(f, "  User CPU time=%ld.%06ld\n", (long)ru->ru_utime.tv_sec, (long)ru->ru_utime.tv_usec);
508ac5aef8SEnji Cooper   fprintf(f, "  System CPU time=%ld.%06ld\n", (long)ru->ru_stime.tv_sec, (long)ru->ru_stime.tv_usec);
518ac5aef8SEnji Cooper   fprintf(f, "  Max RSS=%ld\n", ru->ru_maxrss);
528ac5aef8SEnji Cooper }
538ac5aef8SEnji Cooper 
print_stat(FILE * f,const struct stat * stat)548ac5aef8SEnji Cooper static void print_stat(FILE *f, const struct stat *stat) {
558ac5aef8SEnji Cooper   fprintf(f,
568ac5aef8SEnji Cooper           "{ .st_dev=%ld, st_ino=%ld, st_mode=%04o, st_nlink=%ld, st_uid=%d, st_gid=%d,\n"
578ac5aef8SEnji Cooper           "  .st_rdev=%ld, .st_size=%ld, st_blksize=%ld, .st_block=%ld,\n  "
588ac5aef8SEnji Cooper #ifdef HAVE_STAT_BIRTHTIME
598ac5aef8SEnji Cooper           ".st_birthtime=%ld, "
608ac5aef8SEnji Cooper #endif
618ac5aef8SEnji Cooper           ".st_atime=%ld, .st_mtime=%ld, .st_ctime=%ld}\n",
628ac5aef8SEnji Cooper           (long)stat->st_dev, (long)stat->st_ino, stat->st_mode,
638ac5aef8SEnji Cooper           (long)stat->st_nlink, stat->st_uid, stat->st_gid,
648ac5aef8SEnji Cooper           (long)stat->st_rdev, (long)stat->st_size, (long)stat->st_blksize,
658ac5aef8SEnji Cooper           (long)stat->st_blocks,
668ac5aef8SEnji Cooper #ifdef HAVE_STAT_BIRTHTIME
678ac5aef8SEnji Cooper           (long)stat->st_birthtime,
688ac5aef8SEnji Cooper #endif
698ac5aef8SEnji Cooper           (long)stat->st_atime, (long)stat->st_mtime, (long)stat->st_ctime);
708ac5aef8SEnji Cooper }
718ac5aef8SEnji Cooper 
72*955a3f9aSAlex Richardson static volatile sig_atomic_t had_signal[NSIG];
clear_had_signals()73*955a3f9aSAlex Richardson void clear_had_signals() {
74*955a3f9aSAlex Richardson   memset(const_cast<sig_atomic_t *>(had_signal), 0, sizeof(had_signal));
75*955a3f9aSAlex Richardson }
handle_signal(int x)768ac5aef8SEnji Cooper static void handle_signal(int x) {
778ac5aef8SEnji Cooper   had_signal[x] = true;
788ac5aef8SEnji Cooper }
798ac5aef8SEnji Cooper 
808ac5aef8SEnji Cooper // Check that the given child process terminates as expected.
CheckChildFinished(pid_t pid,bool signaled=false)818ac5aef8SEnji Cooper void CheckChildFinished(pid_t pid, bool signaled=false) {
828ac5aef8SEnji Cooper   // Wait for the child to finish.
838ac5aef8SEnji Cooper   int rc;
848ac5aef8SEnji Cooper   int status = 0;
858ac5aef8SEnji Cooper   do {
868ac5aef8SEnji Cooper     rc = waitpid(pid, &status, __WALL);
878ac5aef8SEnji Cooper     if (rc < 0) {
888ac5aef8SEnji Cooper       fprintf(stderr, "Warning: waitpid error %s (%d)\n", strerror(errno), errno);
898ac5aef8SEnji Cooper       ADD_FAILURE() << "Failed to wait for child";
908ac5aef8SEnji Cooper       break;
918ac5aef8SEnji Cooper     } else if (rc == pid) {
928ac5aef8SEnji Cooper       break;
938ac5aef8SEnji Cooper     }
948ac5aef8SEnji Cooper   } while (true);
958ac5aef8SEnji Cooper   EXPECT_EQ(pid, rc);
968ac5aef8SEnji Cooper   if (rc == pid) {
978ac5aef8SEnji Cooper     if (signaled) {
988ac5aef8SEnji Cooper       EXPECT_TRUE(WIFSIGNALED(status));
998ac5aef8SEnji Cooper     } else {
1008ac5aef8SEnji Cooper       EXPECT_TRUE(WIFEXITED(status)) << std::hex << status;
1018ac5aef8SEnji Cooper       EXPECT_EQ(0, WEXITSTATUS(status));
1028ac5aef8SEnji Cooper     }
1038ac5aef8SEnji Cooper   }
1048ac5aef8SEnji Cooper }
1058ac5aef8SEnji Cooper 
1068ac5aef8SEnji Cooper //------------------------------------------------
1078ac5aef8SEnji Cooper // Basic tests of process descriptor functionality
1088ac5aef8SEnji Cooper 
TEST(Pdfork,Simple)1098ac5aef8SEnji Cooper TEST(Pdfork, Simple) {
1108ac5aef8SEnji Cooper   int pd = -1;
111*955a3f9aSAlex Richardson   int pipefds[2];
1128ac5aef8SEnji Cooper   pid_t parent = getpid_();
113*955a3f9aSAlex Richardson   EXPECT_OK(pipe(pipefds));
1148ac5aef8SEnji Cooper   int pid = pdfork(&pd, 0);
1158ac5aef8SEnji Cooper   EXPECT_OK(pid);
1168ac5aef8SEnji Cooper   if (pid == 0) {
1178ac5aef8SEnji Cooper     // Child: check pid values.
1188ac5aef8SEnji Cooper     EXPECT_EQ(-1, pd);
1198ac5aef8SEnji Cooper     EXPECT_NE(parent, getpid_());
1208ac5aef8SEnji Cooper     EXPECT_EQ(parent, getppid());
121*955a3f9aSAlex Richardson     close(pipefds[0]);
122*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
123*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "Child waiting for exit message\n");
124*955a3f9aSAlex Richardson     // Terminate once the parent has completed the checks
125*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
126*955a3f9aSAlex Richardson     exit(testing::Test::HasFailure());
1278ac5aef8SEnji Cooper   }
128*955a3f9aSAlex Richardson   close(pipefds[1]);
129*955a3f9aSAlex Richardson   // Ensure the child has started.
130*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
131*955a3f9aSAlex Richardson 
1328ac5aef8SEnji Cooper   EXPECT_NE(-1, pd);
1338ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid);
1348ac5aef8SEnji Cooper   int pid_got;
1358ac5aef8SEnji Cooper   EXPECT_OK(pdgetpid(pd, &pid_got));
1368ac5aef8SEnji Cooper   EXPECT_EQ(pid, pid_got);
1378ac5aef8SEnji Cooper 
138*955a3f9aSAlex Richardson   // Tell the child to exit and wait until it is a zombie.
139*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
140*955a3f9aSAlex Richardson   // EXPECT_PID_ZOMBIE waits for up to ~500ms, that should be enough time for
141*955a3f9aSAlex Richardson   // the child to exit successfully.
1428ac5aef8SEnji Cooper   EXPECT_PID_ZOMBIE(pid);
143*955a3f9aSAlex Richardson   close(pipefds[0]);
1448ac5aef8SEnji Cooper 
1458ac5aef8SEnji Cooper   // Wait for the the child.
1468ac5aef8SEnji Cooper   int status;
1478ac5aef8SEnji Cooper   struct rusage ru;
1488ac5aef8SEnji Cooper   memset(&ru, 0, sizeof(ru));
1498ac5aef8SEnji Cooper   int waitrc = pdwait4_(pd, &status, 0, &ru);
1508ac5aef8SEnji Cooper   EXPECT_EQ(pid, waitrc);
1518ac5aef8SEnji Cooper   if (verbose) {
1528ac5aef8SEnji Cooper     fprintf(stderr, "For pd %d pid %d:\n", pd, pid);
1538ac5aef8SEnji Cooper     print_rusage(stderr, &ru);
1548ac5aef8SEnji Cooper   }
1558ac5aef8SEnji Cooper   EXPECT_PID_GONE(pid);
1568ac5aef8SEnji Cooper 
1578ac5aef8SEnji Cooper   // Can only pdwait4(pd) once (as initial call reaps zombie).
1588ac5aef8SEnji Cooper   memset(&ru, 0, sizeof(ru));
1598ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdwait4_(pd, &status, 0, &ru));
1608ac5aef8SEnji Cooper   EXPECT_EQ(ECHILD, errno);
1618ac5aef8SEnji Cooper 
1628ac5aef8SEnji Cooper   EXPECT_OK(close(pd));
1638ac5aef8SEnji Cooper }
1648ac5aef8SEnji Cooper 
TEST(Pdfork,InvalidFlag)1658ac5aef8SEnji Cooper TEST(Pdfork, InvalidFlag) {
1668ac5aef8SEnji Cooper   int pd = -1;
1678ac5aef8SEnji Cooper   int pid = pdfork(&pd, PD_DAEMON<<5);
1688ac5aef8SEnji Cooper   if (pid == 0) {
1698ac5aef8SEnji Cooper     exit(1);
1708ac5aef8SEnji Cooper   }
1718ac5aef8SEnji Cooper   EXPECT_EQ(-1, pid);
1728ac5aef8SEnji Cooper   EXPECT_EQ(EINVAL, errno);
1738ac5aef8SEnji Cooper   if (pid > 0) waitpid(pid, NULL, __WALL);
1748ac5aef8SEnji Cooper }
1758ac5aef8SEnji Cooper 
TEST(Pdfork,TimeCheck)1768ac5aef8SEnji Cooper TEST(Pdfork, TimeCheck) {
1778ac5aef8SEnji Cooper   time_t now = time(NULL);  // seconds since epoch
1788ac5aef8SEnji Cooper   EXPECT_NE(-1, now);
1798ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "Calling pdfork around %ld\n", (long)(long)now);
1808ac5aef8SEnji Cooper 
1818ac5aef8SEnji Cooper   int pd = -1;
1828ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
1838ac5aef8SEnji Cooper   EXPECT_OK(pid);
1848ac5aef8SEnji Cooper   if (pid == 0) {
1858ac5aef8SEnji Cooper     // Child: check we didn't get a valid process descriptor then exit.
1868ac5aef8SEnji Cooper     EXPECT_EQ(-1, pdgetpid(pd, &pid));
1878ac5aef8SEnji Cooper     EXPECT_EQ(EBADF, errno);
1888ac5aef8SEnji Cooper     exit(HasFailure());
1898ac5aef8SEnji Cooper   }
1908ac5aef8SEnji Cooper 
1918ac5aef8SEnji Cooper #ifdef HAVE_PROCDESC_FSTAT
1928ac5aef8SEnji Cooper   // Parent process. Ensure that [acm]times have been set correctly.
1938ac5aef8SEnji Cooper   struct stat stat;
1948ac5aef8SEnji Cooper   memset(&stat, 0, sizeof(stat));
1958ac5aef8SEnji Cooper   EXPECT_OK(fstat(pd, &stat));
1968ac5aef8SEnji Cooper   if (verbose) print_stat(stderr, &stat);
1978ac5aef8SEnji Cooper 
1988ac5aef8SEnji Cooper #ifdef HAVE_STAT_BIRTHTIME
1998ac5aef8SEnji Cooper   EXPECT_GE(now, stat.st_birthtime);
2008ac5aef8SEnji Cooper   EXPECT_EQ(stat.st_birthtime, stat.st_atime);
2018ac5aef8SEnji Cooper #endif
2028ac5aef8SEnji Cooper   EXPECT_LT((now - stat.st_atime), 2);
2038ac5aef8SEnji Cooper   EXPECT_EQ(stat.st_atime, stat.st_ctime);
2048ac5aef8SEnji Cooper   EXPECT_EQ(stat.st_ctime, stat.st_mtime);
2058ac5aef8SEnji Cooper #endif
2068ac5aef8SEnji Cooper 
2078ac5aef8SEnji Cooper   // Wait for the child to finish.
2088ac5aef8SEnji Cooper   pid_t pd_pid = -1;
2098ac5aef8SEnji Cooper   EXPECT_OK(pdgetpid(pd, &pd_pid));
2108ac5aef8SEnji Cooper   EXPECT_EQ(pid, pd_pid);
2118ac5aef8SEnji Cooper   CheckChildFinished(pid);
2128ac5aef8SEnji Cooper }
2138ac5aef8SEnji Cooper 
TEST(Pdfork,UseDescriptor)2148ac5aef8SEnji Cooper TEST(Pdfork, UseDescriptor) {
2158ac5aef8SEnji Cooper   int pd = -1;
2168ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
2178ac5aef8SEnji Cooper   EXPECT_OK(pid);
2188ac5aef8SEnji Cooper   if (pid == 0) {
2198ac5aef8SEnji Cooper     // Child: immediately exit
2208ac5aef8SEnji Cooper     exit(0);
2218ac5aef8SEnji Cooper   }
2228ac5aef8SEnji Cooper   CheckChildFinished(pid);
2238ac5aef8SEnji Cooper }
2248ac5aef8SEnji Cooper 
TEST(Pdfork,NonProcessDescriptor)2258ac5aef8SEnji Cooper TEST(Pdfork, NonProcessDescriptor) {
2268ac5aef8SEnji Cooper   int fd = open("/etc/passwd", O_RDONLY);
2278ac5aef8SEnji Cooper   EXPECT_OK(fd);
2288ac5aef8SEnji Cooper   // pd*() operations should fail on a non-process descriptor.
2298ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdkill(fd, SIGUSR1));
2308ac5aef8SEnji Cooper   int status;
2318ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdwait4_(fd, &status, 0, NULL));
2328ac5aef8SEnji Cooper   pid_t pid;
2338ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdgetpid(fd, &pid));
2348ac5aef8SEnji Cooper   close(fd);
2358ac5aef8SEnji Cooper }
2368ac5aef8SEnji Cooper 
SubThreadMain(void * arg)237*955a3f9aSAlex Richardson static void *SubThreadMain(void *arg) {
238*955a3f9aSAlex Richardson   // Notify the main thread that we have started
239*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "      subthread started: pipe=%p\n", arg);
240*955a3f9aSAlex Richardson   SEND_INT_MESSAGE((int)(intptr_t)arg, MSG_CHILD_STARTED);
2418ac5aef8SEnji Cooper   while (true) {
2428ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "      subthread: \"I aten't dead\"\n");
2438ac5aef8SEnji Cooper     usleep(100000);
2448ac5aef8SEnji Cooper   }
2458ac5aef8SEnji Cooper   return NULL;
2468ac5aef8SEnji Cooper }
2478ac5aef8SEnji Cooper 
ThreadMain(void *)2488ac5aef8SEnji Cooper static void *ThreadMain(void *) {
2498ac5aef8SEnji Cooper   int pd;
250*955a3f9aSAlex Richardson   int pipefds[2];
251*955a3f9aSAlex Richardson   EXPECT_EQ(0, pipe(pipefds));
2528ac5aef8SEnji Cooper   pid_t child = pdfork(&pd, 0);
2538ac5aef8SEnji Cooper   if (child == 0) {
254*955a3f9aSAlex Richardson     close(pipefds[0]);
255*955a3f9aSAlex Richardson     // Child: start a subthread then loop.
2568ac5aef8SEnji Cooper     pthread_t child_subthread;
257*955a3f9aSAlex Richardson     // Wait for the subthread startup using another pipe.
258*955a3f9aSAlex Richardson     int thread_pipefds[2];
259*955a3f9aSAlex Richardson     EXPECT_EQ(0, pipe(thread_pipefds));
260*955a3f9aSAlex Richardson     EXPECT_OK(pthread_create(&child_subthread, NULL, SubThreadMain,
261*955a3f9aSAlex Richardson                              (void *)(intptr_t)thread_pipefds[0]));
262*955a3f9aSAlex Richardson     if (verbose) {
263*955a3f9aSAlex Richardson       fprintf(stderr, "    pdforked process %d: waiting for subthread.\n",
264*955a3f9aSAlex Richardson               getpid());
265*955a3f9aSAlex Richardson     }
266*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(thread_pipefds[1], MSG_CHILD_STARTED);
267*955a3f9aSAlex Richardson     close(thread_pipefds[0]);
268*955a3f9aSAlex Richardson     close(thread_pipefds[1]);
269*955a3f9aSAlex Richardson     // Child: Notify parent that all threads have started
270*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "    pdforked process %d: subthread started\n", getpid());
271*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
2728ac5aef8SEnji Cooper     while (true) {
2738ac5aef8SEnji Cooper       if (verbose) fprintf(stderr, "    pdforked process %d: \"I aten't dead\"\n", getpid());
2748ac5aef8SEnji Cooper       usleep(100000);
2758ac5aef8SEnji Cooper     }
2768ac5aef8SEnji Cooper     exit(0);
2778ac5aef8SEnji Cooper   }
2788ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "  thread generated pd %d\n", pd);
279*955a3f9aSAlex Richardson   close(pipefds[1]);
280*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
281*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] got child startup message\n", getpid_());
2828ac5aef8SEnji Cooper 
2838ac5aef8SEnji Cooper   // Pass the process descriptor back to the main thread.
2848ac5aef8SEnji Cooper   return reinterpret_cast<void *>(pd);
2858ac5aef8SEnji Cooper }
2868ac5aef8SEnji Cooper 
TEST(Pdfork,FromThread)2878ac5aef8SEnji Cooper TEST(Pdfork, FromThread) {
2888ac5aef8SEnji Cooper   // Fire off a new thread to do all of the creation work.
2898ac5aef8SEnji Cooper   pthread_t child_thread;
2908ac5aef8SEnji Cooper   EXPECT_OK(pthread_create(&child_thread, NULL, ThreadMain, NULL));
2918ac5aef8SEnji Cooper   void *data;
2928ac5aef8SEnji Cooper   EXPECT_OK(pthread_join(child_thread, &data));
2938ac5aef8SEnji Cooper   int pd = reinterpret_cast<intptr_t>(data);
2948ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "retrieved pd %d from terminated thread\n", pd);
2958ac5aef8SEnji Cooper 
2968ac5aef8SEnji Cooper   // Kill and reap.
2978ac5aef8SEnji Cooper   pid_t pid;
2988ac5aef8SEnji Cooper   EXPECT_OK(pdgetpid(pd, &pid));
2998ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGKILL));
3008ac5aef8SEnji Cooper   int status;
3018ac5aef8SEnji Cooper   EXPECT_EQ(pid, pdwait4_(pd, &status, 0, NULL));
3028ac5aef8SEnji Cooper   EXPECT_TRUE(WIFSIGNALED(status));
3038ac5aef8SEnji Cooper }
3048ac5aef8SEnji Cooper 
3058ac5aef8SEnji Cooper //------------------------------------------------
3068ac5aef8SEnji Cooper // More complicated tests.
3078ac5aef8SEnji Cooper 
3088ac5aef8SEnji Cooper 
3098ac5aef8SEnji Cooper // Test fixture that pdfork()s off a child process, which terminates
3108ac5aef8SEnji Cooper // when it receives anything on a pipe.
3118ac5aef8SEnji Cooper class PipePdforkBase : public ::testing::Test {
3128ac5aef8SEnji Cooper  public:
PipePdforkBase(int pdfork_flags)3138ac5aef8SEnji Cooper   PipePdforkBase(int pdfork_flags) : pd_(-1), pid_(-1) {
314*955a3f9aSAlex Richardson     clear_had_signals();
3158ac5aef8SEnji Cooper     int pipes[2];
3168ac5aef8SEnji Cooper     EXPECT_OK(pipe(pipes));
3178ac5aef8SEnji Cooper     pipe_ = pipes[1];
3188ac5aef8SEnji Cooper     int parent = getpid_();
3198ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "[%d] about to pdfork()\n", getpid_());
3208ac5aef8SEnji Cooper     int rc = pdfork(&pd_, pdfork_flags);
3218ac5aef8SEnji Cooper     EXPECT_OK(rc);
3228ac5aef8SEnji Cooper     if (rc == 0) {
3238ac5aef8SEnji Cooper       // Child process: blocking-read an int from the pipe then exit with that value.
3248ac5aef8SEnji Cooper       EXPECT_NE(parent, getpid_());
3258ac5aef8SEnji Cooper       EXPECT_EQ(parent, getppid());
3268ac5aef8SEnji Cooper       if (verbose) fprintf(stderr, "  [%d] child of %d waiting for value on pipe\n", getpid_(), getppid());
3278ac5aef8SEnji Cooper       read(pipes[0], &rc, sizeof(rc));
3288ac5aef8SEnji Cooper       if (verbose) fprintf(stderr, "  [%d] got value %d on pipe, exiting\n", getpid_(), rc);
3298ac5aef8SEnji Cooper       exit(rc);
3308ac5aef8SEnji Cooper     }
3318ac5aef8SEnji Cooper     pid_ = rc;
3328ac5aef8SEnji Cooper     usleep(100);  // ensure the child has a chance to run
3338ac5aef8SEnji Cooper   }
~PipePdforkBase()3348ac5aef8SEnji Cooper   ~PipePdforkBase() {
3358ac5aef8SEnji Cooper     // Terminate by any means necessary.
3368ac5aef8SEnji Cooper     if (pd_ > 0) {
3378ac5aef8SEnji Cooper       pdkill(pd_, SIGKILL);
3388ac5aef8SEnji Cooper       close(pd_);
3398ac5aef8SEnji Cooper     }
3408ac5aef8SEnji Cooper     if (pid_ > 0) {
3418ac5aef8SEnji Cooper       kill(pid_, SIGKILL);
3428ac5aef8SEnji Cooper       waitpid(pid_, NULL, __WALL|WNOHANG);
3438ac5aef8SEnji Cooper     }
3448ac5aef8SEnji Cooper     // Check signal expectations.
3458ac5aef8SEnji Cooper     EXPECT_FALSE(had_signal[SIGCHLD]);
3468ac5aef8SEnji Cooper   }
TerminateChild()3478ac5aef8SEnji Cooper   int TerminateChild() {
3488ac5aef8SEnji Cooper     // Tell the child to exit.
3498ac5aef8SEnji Cooper     int zero = 0;
3508ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "[%d] write 0 to pipe\n", getpid_());
3518ac5aef8SEnji Cooper     return write(pipe_, &zero, sizeof(zero));
3528ac5aef8SEnji Cooper   }
3538ac5aef8SEnji Cooper  protected:
3548ac5aef8SEnji Cooper   int pd_;
3558ac5aef8SEnji Cooper   int pipe_;
3568ac5aef8SEnji Cooper   pid_t pid_;
3578ac5aef8SEnji Cooper };
3588ac5aef8SEnji Cooper 
3598ac5aef8SEnji Cooper class PipePdfork : public PipePdforkBase {
3608ac5aef8SEnji Cooper  public:
PipePdfork()3618ac5aef8SEnji Cooper   PipePdfork() : PipePdforkBase(0) {}
3628ac5aef8SEnji Cooper };
3638ac5aef8SEnji Cooper 
3648ac5aef8SEnji Cooper class PipePdforkDaemon : public PipePdforkBase {
3658ac5aef8SEnji Cooper  public:
PipePdforkDaemon()3668ac5aef8SEnji Cooper   PipePdforkDaemon() : PipePdforkBase(PD_DAEMON) {}
3678ac5aef8SEnji Cooper };
3688ac5aef8SEnji Cooper 
3698ac5aef8SEnji Cooper // Can we poll a process descriptor?
TEST_F(PipePdfork,Poll)3708ac5aef8SEnji Cooper TEST_F(PipePdfork, Poll) {
3718ac5aef8SEnji Cooper   // Poll the process descriptor, nothing happening.
3728ac5aef8SEnji Cooper   struct pollfd fdp;
3738ac5aef8SEnji Cooper   fdp.fd = pd_;
3748ac5aef8SEnji Cooper   fdp.events = POLLIN | POLLERR | POLLHUP;
3758ac5aef8SEnji Cooper   fdp.revents = 0;
3768ac5aef8SEnji Cooper   EXPECT_EQ(0, poll(&fdp, 1, 0));
3778ac5aef8SEnji Cooper 
3788ac5aef8SEnji Cooper   TerminateChild();
3798ac5aef8SEnji Cooper 
3808ac5aef8SEnji Cooper   // Poll again, should have activity on the process descriptor.
3818ac5aef8SEnji Cooper   EXPECT_EQ(1, poll(&fdp, 1, 2000));
3828ac5aef8SEnji Cooper   EXPECT_TRUE(fdp.revents & POLLHUP);
3838ac5aef8SEnji Cooper 
3848ac5aef8SEnji Cooper   // Poll a third time, still have POLLHUP.
3858ac5aef8SEnji Cooper   fdp.revents = 0;
3868ac5aef8SEnji Cooper   EXPECT_EQ(1, poll(&fdp, 1, 0));
3878ac5aef8SEnji Cooper   EXPECT_TRUE(fdp.revents & POLLHUP);
3888ac5aef8SEnji Cooper }
3898ac5aef8SEnji Cooper 
3908ac5aef8SEnji Cooper // Can multiple processes poll on the same descriptor?
TEST_F(PipePdfork,PollMultiple)3918ac5aef8SEnji Cooper TEST_F(PipePdfork, PollMultiple) {
392*955a3f9aSAlex Richardson   int pipefds[2];
393*955a3f9aSAlex Richardson   EXPECT_EQ(0, pipe(pipefds));
3948ac5aef8SEnji Cooper   int child = fork();
3958ac5aef8SEnji Cooper   EXPECT_OK(child);
3968ac5aef8SEnji Cooper   if (child == 0) {
397*955a3f9aSAlex Richardson     close(pipefds[0]);
398*955a3f9aSAlex Richardson     // Child: wait for parent to acknowledge startup
399*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
400*955a3f9aSAlex Richardson     // Child: wait for two messages from the parent and the forked process
401*955a3f9aSAlex Richardson     // before telling the other process to terminate.
402*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] waiting for read 1\n", getpid_());
403*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
404*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] waiting for read 2\n", getpid_());
405*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
4068ac5aef8SEnji Cooper     TerminateChild();
407*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] about to exit\n", getpid_());
408*955a3f9aSAlex Richardson     exit(testing::Test::HasFailure());
4098ac5aef8SEnji Cooper   }
410*955a3f9aSAlex Richardson   close(pipefds[1]);
411*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
412*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] got child startup message\n", getpid_());
4138ac5aef8SEnji Cooper   // Fork again
4148ac5aef8SEnji Cooper   int doppel = fork();
4158ac5aef8SEnji Cooper   EXPECT_OK(doppel);
4168ac5aef8SEnji Cooper   // We now have:
4178ac5aef8SEnji Cooper   //   pid A: main process, here
4188ac5aef8SEnji Cooper   //   |--pid B: pdfork()ed process, blocked on read()
419*955a3f9aSAlex Richardson   //   |--pid C: fork()ed process, in read() above
4208ac5aef8SEnji Cooper   //   +--pid D: doppel process, here
4218ac5aef8SEnji Cooper 
4228ac5aef8SEnji Cooper   // Both A and D execute the following code.
4238ac5aef8SEnji Cooper   // First, check no activity on the process descriptor yet.
4248ac5aef8SEnji Cooper   struct pollfd fdp;
4258ac5aef8SEnji Cooper   fdp.fd = pd_;
4268ac5aef8SEnji Cooper   fdp.events = POLLIN | POLLERR | POLLHUP;
4278ac5aef8SEnji Cooper   fdp.revents = 0;
4288ac5aef8SEnji Cooper   EXPECT_EQ(0, poll(&fdp, 1, 0));
4298ac5aef8SEnji Cooper 
430*955a3f9aSAlex Richardson   // Both A and D ask C to exit, allowing it to do so.
431*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] telling child to exit\n", getpid_());
432*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(pipefds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
433*955a3f9aSAlex Richardson   close(pipefds[0]);
434*955a3f9aSAlex Richardson 
4358ac5aef8SEnji Cooper   // Now, wait (indefinitely) for activity on the process descriptor.
4368ac5aef8SEnji Cooper   // We expect:
437*955a3f9aSAlex Richardson   //  - pid C will finish its two read() calls, write to the pipe and exit.
4388ac5aef8SEnji Cooper   //  - pid B will unblock from read(), and exit
4398ac5aef8SEnji Cooper   //  - this will generate an event on the process descriptor...
4408ac5aef8SEnji Cooper   //  - ...in both process A and process D.
441*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] waiting for child to exit\n", getpid_());
4428ac5aef8SEnji Cooper   EXPECT_EQ(1, poll(&fdp, 1, 2000));
4438ac5aef8SEnji Cooper   EXPECT_TRUE(fdp.revents & POLLHUP);
4448ac5aef8SEnji Cooper 
4458ac5aef8SEnji Cooper   if (doppel == 0) {
4468ac5aef8SEnji Cooper     // Child: process D exits.
4478ac5aef8SEnji Cooper     exit(0);
4488ac5aef8SEnji Cooper   } else {
4498ac5aef8SEnji Cooper     // Parent: wait on process D.
4508ac5aef8SEnji Cooper     int rc = 0;
4518ac5aef8SEnji Cooper     waitpid(doppel, &rc, __WALL);
4528ac5aef8SEnji Cooper     EXPECT_TRUE(WIFEXITED(rc));
4538ac5aef8SEnji Cooper     EXPECT_EQ(0, WEXITSTATUS(rc));
4548ac5aef8SEnji Cooper     // Also wait on process B.
4558ac5aef8SEnji Cooper     CheckChildFinished(child);
4568ac5aef8SEnji Cooper   }
4578ac5aef8SEnji Cooper }
4588ac5aef8SEnji Cooper 
4598ac5aef8SEnji Cooper // Check that exit status/rusage for a dead pdfork()ed child can be retrieved
4608ac5aef8SEnji Cooper // via any process descriptor, multiple times.
TEST_F(PipePdfork,MultipleRetrieveExitStatus)4618ac5aef8SEnji Cooper TEST_F(PipePdfork, MultipleRetrieveExitStatus) {
4628ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
4638ac5aef8SEnji Cooper   int pd_copy = dup(pd_);
4648ac5aef8SEnji Cooper   EXPECT_LT(0, TerminateChild());
4658ac5aef8SEnji Cooper 
4668ac5aef8SEnji Cooper   int status;
4678ac5aef8SEnji Cooper   struct rusage ru;
4688ac5aef8SEnji Cooper   memset(&ru, 0, sizeof(ru));
4698ac5aef8SEnji Cooper   int waitrc = pdwait4_(pd_copy, &status, 0, &ru);
4708ac5aef8SEnji Cooper   EXPECT_EQ(pid_, waitrc);
4718ac5aef8SEnji Cooper   if (verbose) {
4728ac5aef8SEnji Cooper     fprintf(stderr, "For pd %d -> pid %d:\n", pd_, pid_);
4738ac5aef8SEnji Cooper     print_rusage(stderr, &ru);
4748ac5aef8SEnji Cooper   }
4758ac5aef8SEnji Cooper   EXPECT_PID_GONE(pid_);
4768ac5aef8SEnji Cooper 
4778ac5aef8SEnji Cooper #ifdef NOTYET
4788ac5aef8SEnji Cooper   // Child has been reaped, so original process descriptor dangles but
4798ac5aef8SEnji Cooper   // still has access to rusage information.
4808ac5aef8SEnji Cooper   memset(&ru, 0, sizeof(ru));
4818ac5aef8SEnji Cooper   EXPECT_EQ(0, pdwait4_(pd_, &status, 0, &ru));
4828ac5aef8SEnji Cooper #endif
4838ac5aef8SEnji Cooper   close(pd_copy);
4848ac5aef8SEnji Cooper }
4858ac5aef8SEnji Cooper 
TEST_F(PipePdfork,ChildExit)4868ac5aef8SEnji Cooper TEST_F(PipePdfork, ChildExit) {
4878ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
4888ac5aef8SEnji Cooper   EXPECT_LT(0, TerminateChild());
4898ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid_);
4908ac5aef8SEnji Cooper 
4918ac5aef8SEnji Cooper   int status;
4928ac5aef8SEnji Cooper   int rc = pdwait4_(pd_, &status, 0, NULL);
4938ac5aef8SEnji Cooper   EXPECT_OK(rc);
4948ac5aef8SEnji Cooper   EXPECT_EQ(pid_, rc);
4958ac5aef8SEnji Cooper   pid_ = 0;
4968ac5aef8SEnji Cooper }
4978ac5aef8SEnji Cooper 
4988ac5aef8SEnji Cooper #ifdef HAVE_PROC_FDINFO
TEST_F(PipePdfork,FdInfo)4998ac5aef8SEnji Cooper TEST_F(PipePdfork, FdInfo) {
5008ac5aef8SEnji Cooper   char buffer[1024];
5018ac5aef8SEnji Cooper   sprintf(buffer, "/proc/%d/fdinfo/%d", getpid_(), pd_);
5028ac5aef8SEnji Cooper   int procfd = open(buffer, O_RDONLY);
5038ac5aef8SEnji Cooper   EXPECT_OK(procfd);
5048ac5aef8SEnji Cooper 
5058ac5aef8SEnji Cooper   EXPECT_OK(read(procfd, buffer, sizeof(buffer)));
5068ac5aef8SEnji Cooper   // The fdinfo should include the file pos of the underlying file
5078ac5aef8SEnji Cooper   EXPECT_NE((char*)NULL, strstr(buffer, "pos:\t0")) << buffer;
5088ac5aef8SEnji Cooper   // ...and the underlying pid
5098ac5aef8SEnji Cooper   char pidline[256];
5108ac5aef8SEnji Cooper   sprintf(pidline, "pid:\t%d", pid_);
5118ac5aef8SEnji Cooper   EXPECT_NE((char*)NULL, strstr(buffer, pidline)) << buffer;
5128ac5aef8SEnji Cooper   close(procfd);
5138ac5aef8SEnji Cooper }
5148ac5aef8SEnji Cooper #endif
5158ac5aef8SEnji Cooper 
5168ac5aef8SEnji Cooper // Closing a normal process descriptor terminates the underlying process.
TEST_F(PipePdfork,Close)5178ac5aef8SEnji Cooper TEST_F(PipePdfork, Close) {
5188ac5aef8SEnji Cooper   sighandler_t original = signal(SIGCHLD, handle_signal);
5198ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
5208ac5aef8SEnji Cooper   int status;
5218ac5aef8SEnji Cooper   EXPECT_EQ(0, waitpid(pid_, &status, __WALL|WNOHANG));
5228ac5aef8SEnji Cooper 
5238ac5aef8SEnji Cooper   EXPECT_OK(close(pd_));
5248ac5aef8SEnji Cooper   pd_ = -1;
5258ac5aef8SEnji Cooper   EXPECT_FALSE(had_signal[SIGCHLD]);
5268ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid_);
5278ac5aef8SEnji Cooper 
5288ac5aef8SEnji Cooper #ifdef __FreeBSD__
5298ac5aef8SEnji Cooper   EXPECT_EQ(-1, waitpid(pid_, NULL, __WALL));
5308ac5aef8SEnji Cooper   EXPECT_EQ(errno, ECHILD);
5318ac5aef8SEnji Cooper #else
5328ac5aef8SEnji Cooper   // Having closed the process descriptor means that pdwait4(pd) now doesn't work.
5338ac5aef8SEnji Cooper   int rc = pdwait4_(pd_, &status, 0, NULL);
5348ac5aef8SEnji Cooper   EXPECT_EQ(-1, rc);
5358ac5aef8SEnji Cooper   EXPECT_EQ(EBADF, errno);
5368ac5aef8SEnji Cooper 
5378ac5aef8SEnji Cooper   // Closing all process descriptors means the the child can only be reaped via pid.
5388ac5aef8SEnji Cooper   EXPECT_EQ(pid_, waitpid(pid_, &status, __WALL|WNOHANG));
5398ac5aef8SEnji Cooper #endif
5408ac5aef8SEnji Cooper   signal(SIGCHLD, original);
5418ac5aef8SEnji Cooper }
5428ac5aef8SEnji Cooper 
TEST_F(PipePdfork,CloseLast)5438ac5aef8SEnji Cooper TEST_F(PipePdfork, CloseLast) {
5448ac5aef8SEnji Cooper   sighandler_t original = signal(SIGCHLD, handle_signal);
5458ac5aef8SEnji Cooper   // Child should only die when last process descriptor is closed.
5468ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
5478ac5aef8SEnji Cooper   int pd_other = dup(pd_);
5488ac5aef8SEnji Cooper 
5498ac5aef8SEnji Cooper   EXPECT_OK(close(pd_));
5508ac5aef8SEnji Cooper   pd_ = -1;
5518ac5aef8SEnji Cooper 
5528ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
5538ac5aef8SEnji Cooper   int status;
5548ac5aef8SEnji Cooper   EXPECT_EQ(0, waitpid(pid_, &status, __WALL|WNOHANG));
5558ac5aef8SEnji Cooper 
5568ac5aef8SEnji Cooper   // Can no longer pdwait4() the closed process descriptor...
5578ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdwait4_(pd_, &status, WNOHANG, NULL));
5588ac5aef8SEnji Cooper   EXPECT_EQ(EBADF, errno);
5598ac5aef8SEnji Cooper   // ...but can pdwait4() the still-open process descriptor.
5608ac5aef8SEnji Cooper   errno = 0;
5618ac5aef8SEnji Cooper   EXPECT_EQ(0, pdwait4_(pd_other, &status, WNOHANG, NULL));
5628ac5aef8SEnji Cooper   EXPECT_EQ(0, errno);
5638ac5aef8SEnji Cooper 
5648ac5aef8SEnji Cooper   EXPECT_OK(close(pd_other));
5658ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid_);
5668ac5aef8SEnji Cooper 
5678ac5aef8SEnji Cooper   EXPECT_FALSE(had_signal[SIGCHLD]);
5688ac5aef8SEnji Cooper   signal(SIGCHLD, original);
5698ac5aef8SEnji Cooper }
5708ac5aef8SEnji Cooper 
FORK_TEST(Pdfork,OtherUserIfRoot)5712d936e6cSAlex Richardson FORK_TEST(Pdfork, OtherUserIfRoot) {
5722d936e6cSAlex Richardson   GTEST_SKIP_IF_NOT_ROOT();
5738ac5aef8SEnji Cooper   int pd;
574*955a3f9aSAlex Richardson   int status;
5758ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
5768ac5aef8SEnji Cooper   EXPECT_OK(pid);
5778ac5aef8SEnji Cooper   if (pid == 0) {
5788ac5aef8SEnji Cooper     // Child process: loop forever.
5798ac5aef8SEnji Cooper     while (true) usleep(100000);
5808ac5aef8SEnji Cooper   }
5818ac5aef8SEnji Cooper   usleep(100);
5828ac5aef8SEnji Cooper 
5838ac5aef8SEnji Cooper   // Now that the second process has been pdfork()ed, change euid.
5842d936e6cSAlex Richardson   ASSERT_NE(0u, other_uid) << "other_uid not initialized correctly, "
5852d936e6cSAlex Richardson                               "please pass the -u <uid> flag.";
5862d936e6cSAlex Richardson   EXPECT_EQ(0, setuid(other_uid));
5872d936e6cSAlex Richardson   EXPECT_EQ(other_uid, getuid());
5888ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "uid=%d euid=%d\n", getuid(), geteuid());
5898ac5aef8SEnji Cooper 
5908ac5aef8SEnji Cooper   // Fail to kill child with normal PID operation.
5918ac5aef8SEnji Cooper   EXPECT_EQ(-1, kill(pid, SIGKILL));
5928ac5aef8SEnji Cooper   EXPECT_EQ(EPERM, errno);
5938ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid);
5948ac5aef8SEnji Cooper 
595*955a3f9aSAlex Richardson   // Ideally, we should be able to send signals via a process descriptor even
596*955a3f9aSAlex Richardson   // if it's owned by another user, but this is not implementated on FreeBSD.
597*955a3f9aSAlex Richardson #ifdef __FreeBSD__
598*955a3f9aSAlex Richardson   // On FreeBSD, pdkill() still performs all the same checks that kill() does
599*955a3f9aSAlex Richardson   // and therefore cannot be used to send a signal to a process with another
600*955a3f9aSAlex Richardson   // UID unless we are root.
601*955a3f9aSAlex Richardson   EXPECT_SYSCALL_FAIL(EBADF, pdkill(pid, SIGKILL));
602*955a3f9aSAlex Richardson   EXPECT_PID_ALIVE(pid);
603*955a3f9aSAlex Richardson   // However, the process will be killed when we close the process descriptor.
604*955a3f9aSAlex Richardson   EXPECT_OK(close(pd));
605*955a3f9aSAlex Richardson   EXPECT_PID_GONE(pid);
606*955a3f9aSAlex Richardson   // Can't pdwait4() after close() since close() reparents the child to a reaper (init)
607*955a3f9aSAlex Richardson   EXPECT_SYSCALL_FAIL(EBADF, pdwait4_(pd, &status, WNOHANG, NULL));
608*955a3f9aSAlex Richardson #else
609*955a3f9aSAlex Richardson   // Sending a signal with pdkill() should be permitted though.
6108ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGKILL));
6118ac5aef8SEnji Cooper   EXPECT_PID_ZOMBIE(pid);
6128ac5aef8SEnji Cooper 
6138ac5aef8SEnji Cooper   int rc = pdwait4_(pd, &status, WNOHANG, NULL);
6148ac5aef8SEnji Cooper   EXPECT_OK(rc);
6158ac5aef8SEnji Cooper   EXPECT_EQ(pid, rc);
6168ac5aef8SEnji Cooper   EXPECT_TRUE(WIFSIGNALED(status));
617*955a3f9aSAlex Richardson #endif
6188ac5aef8SEnji Cooper }
6198ac5aef8SEnji Cooper 
TEST_F(PipePdfork,WaitPidThenPd)6208ac5aef8SEnji Cooper TEST_F(PipePdfork, WaitPidThenPd) {
6218ac5aef8SEnji Cooper   TerminateChild();
6228ac5aef8SEnji Cooper   int status;
6238ac5aef8SEnji Cooper   // If we waitpid(pid) first...
6248ac5aef8SEnji Cooper   int rc = waitpid(pid_, &status, __WALL);
6258ac5aef8SEnji Cooper   EXPECT_OK(rc);
6268ac5aef8SEnji Cooper   EXPECT_EQ(pid_, rc);
6278ac5aef8SEnji Cooper 
6288ac5aef8SEnji Cooper #ifdef NOTYET
6298ac5aef8SEnji Cooper   // ...the zombie is reaped but we can still subsequently pdwait4(pd).
6308ac5aef8SEnji Cooper   EXPECT_EQ(0, pdwait4_(pd_, &status, 0, NULL));
6318ac5aef8SEnji Cooper #endif
6328ac5aef8SEnji Cooper }
6338ac5aef8SEnji Cooper 
TEST_F(PipePdfork,WaitPdThenPid)6348ac5aef8SEnji Cooper TEST_F(PipePdfork, WaitPdThenPid) {
6358ac5aef8SEnji Cooper   TerminateChild();
6368ac5aef8SEnji Cooper   int status;
6378ac5aef8SEnji Cooper   // If we pdwait4(pd) first...
6388ac5aef8SEnji Cooper   int rc = pdwait4_(pd_, &status, 0, NULL);
6398ac5aef8SEnji Cooper   EXPECT_OK(rc);
6408ac5aef8SEnji Cooper   EXPECT_EQ(pid_, rc);
6418ac5aef8SEnji Cooper 
6428ac5aef8SEnji Cooper   // ...the zombie is reaped and cannot subsequently waitpid(pid).
6438ac5aef8SEnji Cooper   EXPECT_EQ(-1, waitpid(pid_, &status, __WALL));
6448ac5aef8SEnji Cooper   EXPECT_EQ(ECHILD, errno);
6458ac5aef8SEnji Cooper }
6468ac5aef8SEnji Cooper 
6478ac5aef8SEnji Cooper // Setting PD_DAEMON prevents close() from killing the child.
TEST_F(PipePdforkDaemon,Close)6488ac5aef8SEnji Cooper TEST_F(PipePdforkDaemon, Close) {
6498ac5aef8SEnji Cooper   EXPECT_OK(close(pd_));
6508ac5aef8SEnji Cooper   pd_ = -1;
6518ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid_);
6528ac5aef8SEnji Cooper 
6538ac5aef8SEnji Cooper   // Can still explicitly kill it via the pid.
6548ac5aef8SEnji Cooper   if (pid_ > 0) {
6558ac5aef8SEnji Cooper     EXPECT_OK(kill(pid_, SIGKILL));
6568ac5aef8SEnji Cooper     EXPECT_PID_DEAD(pid_);
6578ac5aef8SEnji Cooper   }
6588ac5aef8SEnji Cooper }
6598ac5aef8SEnji Cooper 
TestPdkill(pid_t pid,int pd)6608ac5aef8SEnji Cooper static void TestPdkill(pid_t pid, int pd) {
6618ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid);
6628ac5aef8SEnji Cooper   // SIGCONT is ignored by default.
6638ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGCONT));
6648ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid);
6658ac5aef8SEnji Cooper 
6668ac5aef8SEnji Cooper   // SIGINT isn't
6678ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGINT));
6688ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid);
6698ac5aef8SEnji Cooper 
6708ac5aef8SEnji Cooper   // pdkill() on zombie is no-op.
6718ac5aef8SEnji Cooper   errno = 0;
6728ac5aef8SEnji Cooper   EXPECT_EQ(0, pdkill(pd, SIGINT));
6738ac5aef8SEnji Cooper   EXPECT_EQ(0, errno);
6748ac5aef8SEnji Cooper 
6758ac5aef8SEnji Cooper   // pdkill() on reaped process gives -ESRCH.
6768ac5aef8SEnji Cooper   CheckChildFinished(pid, true);
6778ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdkill(pd, SIGINT));
6788ac5aef8SEnji Cooper   EXPECT_EQ(ESRCH, errno);
6798ac5aef8SEnji Cooper }
6808ac5aef8SEnji Cooper 
TEST_F(PipePdfork,Pdkill)6818ac5aef8SEnji Cooper TEST_F(PipePdfork, Pdkill) {
6828ac5aef8SEnji Cooper   TestPdkill(pid_, pd_);
6838ac5aef8SEnji Cooper }
6848ac5aef8SEnji Cooper 
TEST_F(PipePdforkDaemon,Pdkill)6858ac5aef8SEnji Cooper TEST_F(PipePdforkDaemon, Pdkill) {
6868ac5aef8SEnji Cooper   TestPdkill(pid_, pd_);
6878ac5aef8SEnji Cooper }
6888ac5aef8SEnji Cooper 
TEST(Pdfork,PdkillOtherSignal)6898ac5aef8SEnji Cooper TEST(Pdfork, PdkillOtherSignal) {
6908ac5aef8SEnji Cooper   int pd = -1;
691*955a3f9aSAlex Richardson   int pipefds[2];
692*955a3f9aSAlex Richardson   EXPECT_EQ(0, pipe(pipefds));
6938ac5aef8SEnji Cooper   int pid = pdfork(&pd, 0);
6948ac5aef8SEnji Cooper   EXPECT_OK(pid);
6958ac5aef8SEnji Cooper   if (pid == 0) {
696*955a3f9aSAlex Richardson     // Child: tell the parent that we have started before entering the loop,
697*955a3f9aSAlex Richardson     // and importantly only do so once we have registered the SIGUSR1 handler.
698*955a3f9aSAlex Richardson     close(pipefds[0]);
699*955a3f9aSAlex Richardson     clear_had_signals();
7008ac5aef8SEnji Cooper     signal(SIGUSR1, handle_signal);
701*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
702*955a3f9aSAlex Richardson     // Child: watch for SIGUSR1 forever.
7038ac5aef8SEnji Cooper     while (!had_signal[SIGUSR1]) {
7048ac5aef8SEnji Cooper       usleep(100000);
7058ac5aef8SEnji Cooper     }
7068ac5aef8SEnji Cooper     exit(123);
7078ac5aef8SEnji Cooper   }
708*955a3f9aSAlex Richardson   // Wait for child to start
709*955a3f9aSAlex Richardson   close(pipefds[1]);
710*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
711*955a3f9aSAlex Richardson   close(pipefds[0]);
7128ac5aef8SEnji Cooper 
7138ac5aef8SEnji Cooper   // Send an invalid signal.
7148ac5aef8SEnji Cooper   EXPECT_EQ(-1, pdkill(pd, 0xFFFF));
7158ac5aef8SEnji Cooper   EXPECT_EQ(EINVAL, errno);
7168ac5aef8SEnji Cooper 
7178ac5aef8SEnji Cooper   // Send an expected SIGUSR1 to the pdfork()ed child.
7188ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(pid);
7198ac5aef8SEnji Cooper   pdkill(pd, SIGUSR1);
7208ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid);
7218ac5aef8SEnji Cooper 
7228ac5aef8SEnji Cooper   // Child's exit status confirms whether it received the signal.
7238ac5aef8SEnji Cooper   int status;
7248ac5aef8SEnji Cooper   int rc = waitpid(pid, &status, __WALL);
7258ac5aef8SEnji Cooper   EXPECT_OK(rc);
7268ac5aef8SEnji Cooper   EXPECT_EQ(pid, rc);
727*955a3f9aSAlex Richardson   EXPECT_TRUE(WIFEXITED(status)) << "status: 0x" << std::hex << status;
7288ac5aef8SEnji Cooper   EXPECT_EQ(123, WEXITSTATUS(status));
7298ac5aef8SEnji Cooper }
7308ac5aef8SEnji Cooper 
PdforkParentDeath(int pdfork_flags)7318ac5aef8SEnji Cooper pid_t PdforkParentDeath(int pdfork_flags) {
7328ac5aef8SEnji Cooper   // Set up:
7338ac5aef8SEnji Cooper   //   pid A: main process, here
734*955a3f9aSAlex Richardson   //   +--pid B: fork()ed process, starts a child process with pdfork() then
735*955a3f9aSAlex Richardson   //             waits for parent to send a shutdown message.
7368ac5aef8SEnji Cooper   //      +--pid C: pdfork()ed process, looping forever
7378ac5aef8SEnji Cooper   int sock_fds[2];
7388ac5aef8SEnji Cooper   EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));
7398ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "[%d] parent about to fork()...\n", getpid_());
7408ac5aef8SEnji Cooper   pid_t child = fork();
7418ac5aef8SEnji Cooper   EXPECT_OK(child);
7428ac5aef8SEnji Cooper   if (child == 0) {
7438ac5aef8SEnji Cooper     int pd;
7448ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] child about to pdfork()...\n", getpid_());
745*955a3f9aSAlex Richardson     int pipefds[2]; // for startup notification
746*955a3f9aSAlex Richardson     EXPECT_OK(pipe(pipefds));
7478ac5aef8SEnji Cooper     pid_t grandchild = pdfork(&pd, pdfork_flags);
7488ac5aef8SEnji Cooper     if (grandchild == 0) {
749*955a3f9aSAlex Richardson       close(pipefds[0]);
750*955a3f9aSAlex Richardson       pid_t grandchildPid = getpid_();
751*955a3f9aSAlex Richardson       EXPECT_EQ(sizeof(grandchildPid), (size_t)write(pipefds[1], &grandchildPid, sizeof(grandchildPid)));
7528ac5aef8SEnji Cooper       while (true) {
753*955a3f9aSAlex Richardson         if (verbose) fprintf(stderr, "    [%d] grandchild: \"I aten't dead\"\n", grandchildPid);
7548ac5aef8SEnji Cooper         sleep(1);
7558ac5aef8SEnji Cooper       }
7568ac5aef8SEnji Cooper     }
757*955a3f9aSAlex Richardson     close(pipefds[1]);
7588ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] pdfork()ed grandchild %d, sending ID to parent\n", getpid_(), grandchild);
759*955a3f9aSAlex Richardson     // Wait for grandchild to start.
760*955a3f9aSAlex Richardson     pid_t grandchild2;
761*955a3f9aSAlex Richardson     EXPECT_EQ(sizeof(grandchild2), (size_t)read(pipefds[0], &grandchild2, sizeof(grandchild2)));
762*955a3f9aSAlex Richardson     EXPECT_EQ(grandchild, grandchild2) << "received invalid grandchild pid";
763*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "  [%d] grandchild %d has started successfully\n", getpid_(), grandchild);
764*955a3f9aSAlex Richardson     close(pipefds[0]);
765*955a3f9aSAlex Richardson 
766*955a3f9aSAlex Richardson     // Send grandchild pid to parent.
767*955a3f9aSAlex Richardson     EXPECT_EQ(sizeof(grandchild), (size_t)write(sock_fds[1], &grandchild, sizeof(grandchild)));
768*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "  [%d] sent grandchild pid %d to parent\n", getpid_(), grandchild);
769*955a3f9aSAlex Richardson     // Wait for parent to acknowledge the message.
770*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(sock_fds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
771*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "  [%d] parent acknowledged grandchild pid %d\n", getpid_(), grandchild);
7728ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] child terminating\n", getpid_());
773*955a3f9aSAlex Richardson     exit(testing::Test::HasFailure());
7748ac5aef8SEnji Cooper   }
7758ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "[%d] fork()ed child is %d\n", getpid_(), child);
7768ac5aef8SEnji Cooper   pid_t grandchild;
7778ac5aef8SEnji Cooper   read(sock_fds[0], &grandchild, sizeof(grandchild));
778*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] received grandchild id %d\n", getpid_(), grandchild);
7798ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(child);
7808ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(grandchild);
781*955a3f9aSAlex Richardson   // Tell child to exit.
782*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] telling child %d to exit\n", getpid_(), child);
783*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(sock_fds[0], MSG_PARENT_REQUEST_CHILD_EXIT);
7848ac5aef8SEnji Cooper   // Child dies, closing its process descriptor for the grandchild.
7858ac5aef8SEnji Cooper   EXPECT_PID_DEAD(child);
7868ac5aef8SEnji Cooper   CheckChildFinished(child);
7878ac5aef8SEnji Cooper   return grandchild;
7888ac5aef8SEnji Cooper }
7898ac5aef8SEnji Cooper 
TEST(Pdfork,Bagpuss)7908ac5aef8SEnji Cooper TEST(Pdfork, Bagpuss) {
7918ac5aef8SEnji Cooper   // "And of course when Bagpuss goes to sleep, all his friends go to sleep too"
7928ac5aef8SEnji Cooper   pid_t grandchild = PdforkParentDeath(0);
7938ac5aef8SEnji Cooper   // By default: child death => closed process descriptor => grandchild death.
7948ac5aef8SEnji Cooper   EXPECT_PID_DEAD(grandchild);
7958ac5aef8SEnji Cooper }
7968ac5aef8SEnji Cooper 
TEST(Pdfork,BagpussDaemon)7978ac5aef8SEnji Cooper TEST(Pdfork, BagpussDaemon) {
7988ac5aef8SEnji Cooper   pid_t grandchild = PdforkParentDeath(PD_DAEMON);
7998ac5aef8SEnji Cooper   // With PD_DAEMON: child death => closed process descriptor => no effect on grandchild.
8008ac5aef8SEnji Cooper   EXPECT_PID_ALIVE(grandchild);
8018ac5aef8SEnji Cooper   if (grandchild > 0) {
8028ac5aef8SEnji Cooper     EXPECT_OK(kill(grandchild, SIGKILL));
8038ac5aef8SEnji Cooper   }
8048ac5aef8SEnji Cooper }
8058ac5aef8SEnji Cooper 
8068ac5aef8SEnji Cooper // The exit of a pdfork()ed process should not generate SIGCHLD.
TEST_F(PipePdfork,NoSigchld)8078ac5aef8SEnji Cooper TEST_F(PipePdfork, NoSigchld) {
808*955a3f9aSAlex Richardson   clear_had_signals();
8098ac5aef8SEnji Cooper   sighandler_t original = signal(SIGCHLD, handle_signal);
8108ac5aef8SEnji Cooper   TerminateChild();
8118ac5aef8SEnji Cooper   int rc = 0;
8128ac5aef8SEnji Cooper   // Can waitpid() for the specific pid of the pdfork()ed child.
8138ac5aef8SEnji Cooper   EXPECT_EQ(pid_, waitpid(pid_, &rc, __WALL));
8148ac5aef8SEnji Cooper   EXPECT_TRUE(WIFEXITED(rc)) << "0x" << std::hex << rc;
8158ac5aef8SEnji Cooper   EXPECT_FALSE(had_signal[SIGCHLD]);
8168ac5aef8SEnji Cooper   signal(SIGCHLD, original);
8178ac5aef8SEnji Cooper }
8188ac5aef8SEnji Cooper 
8198ac5aef8SEnji Cooper // The exit of a pdfork()ed process whose process descriptors have
8208ac5aef8SEnji Cooper // all been closed should generate SIGCHLD.  The child process needs
8218ac5aef8SEnji Cooper // PD_DAEMON to survive the closure of the process descriptors.
TEST_F(PipePdforkDaemon,NoPDSigchld)8228ac5aef8SEnji Cooper TEST_F(PipePdforkDaemon, NoPDSigchld) {
823*955a3f9aSAlex Richardson   clear_had_signals();
8248ac5aef8SEnji Cooper   sighandler_t original = signal(SIGCHLD, handle_signal);
8258ac5aef8SEnji Cooper 
8268ac5aef8SEnji Cooper   EXPECT_OK(close(pd_));
8278ac5aef8SEnji Cooper   TerminateChild();
8288ac5aef8SEnji Cooper #ifdef __FreeBSD__
8298ac5aef8SEnji Cooper   EXPECT_EQ(-1, waitpid(pid_, NULL, __WALL));
8308ac5aef8SEnji Cooper   EXPECT_EQ(errno, ECHILD);
8318ac5aef8SEnji Cooper #else
8328ac5aef8SEnji Cooper   int rc = 0;
8338ac5aef8SEnji Cooper   // Can waitpid() for the specific pid of the pdfork()ed child.
8348ac5aef8SEnji Cooper   EXPECT_EQ(pid_, waitpid(pid_, &rc, __WALL));
8358ac5aef8SEnji Cooper   EXPECT_TRUE(WIFEXITED(rc)) << "0x" << std::hex << rc;
8368ac5aef8SEnji Cooper #endif
8378ac5aef8SEnji Cooper   EXPECT_FALSE(had_signal[SIGCHLD]);
8388ac5aef8SEnji Cooper   signal(SIGCHLD, original);
8398ac5aef8SEnji Cooper }
8408ac5aef8SEnji Cooper 
8418ac5aef8SEnji Cooper #ifdef HAVE_PROCDESC_FSTAT
TEST_F(PipePdfork,ModeBits)8428ac5aef8SEnji Cooper TEST_F(PipePdfork, ModeBits) {
8438ac5aef8SEnji Cooper   // Owner rwx bits indicate liveness of child
8448ac5aef8SEnji Cooper   struct stat stat;
8458ac5aef8SEnji Cooper   memset(&stat, 0, sizeof(stat));
8468ac5aef8SEnji Cooper   EXPECT_OK(fstat(pd_, &stat));
8478ac5aef8SEnji Cooper   if (verbose) print_stat(stderr, &stat);
8488ac5aef8SEnji Cooper   EXPECT_EQ(S_IRWXU, (long)(stat.st_mode & S_IRWXU));
8498ac5aef8SEnji Cooper 
8508ac5aef8SEnji Cooper   TerminateChild();
8518ac5aef8SEnji Cooper   usleep(100000);
8528ac5aef8SEnji Cooper 
8538ac5aef8SEnji Cooper   memset(&stat, 0, sizeof(stat));
8548ac5aef8SEnji Cooper   EXPECT_OK(fstat(pd_, &stat));
8558ac5aef8SEnji Cooper   if (verbose) print_stat(stderr, &stat);
8568ac5aef8SEnji Cooper   EXPECT_EQ(0, (int)(stat.st_mode & S_IRWXU));
8578ac5aef8SEnji Cooper }
8588ac5aef8SEnji Cooper #endif
8598ac5aef8SEnji Cooper 
TEST_F(PipePdfork,WildcardWait)8608ac5aef8SEnji Cooper TEST_F(PipePdfork, WildcardWait) {
8618ac5aef8SEnji Cooper   TerminateChild();
862*955a3f9aSAlex Richardson   EXPECT_PID_ZOMBIE(pid_);  // Ensure child is truly dead.
8638ac5aef8SEnji Cooper 
8648ac5aef8SEnji Cooper   // Wildcard waitpid(-1) should not see the pdfork()ed child because
8658ac5aef8SEnji Cooper   // there is still a process descriptor for it.
8668ac5aef8SEnji Cooper   int rc;
8678ac5aef8SEnji Cooper   EXPECT_EQ(-1, waitpid(-1, &rc, WNOHANG));
8688ac5aef8SEnji Cooper   EXPECT_EQ(ECHILD, errno);
8698ac5aef8SEnji Cooper 
8708ac5aef8SEnji Cooper   EXPECT_OK(close(pd_));
8718ac5aef8SEnji Cooper   pd_ = -1;
8728ac5aef8SEnji Cooper }
8738ac5aef8SEnji Cooper 
FORK_TEST(Pdfork,Pdkill)8748ac5aef8SEnji Cooper FORK_TEST(Pdfork, Pdkill) {
875*955a3f9aSAlex Richardson   clear_had_signals();
8768ac5aef8SEnji Cooper   int pd;
877*955a3f9aSAlex Richardson   int pipefds[2];
878*955a3f9aSAlex Richardson   EXPECT_OK(pipe(pipefds));
8798ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
8808ac5aef8SEnji Cooper   EXPECT_OK(pid);
8818ac5aef8SEnji Cooper 
8828ac5aef8SEnji Cooper   if (pid == 0) {
883*955a3f9aSAlex Richardson     // Child: set a SIGINT handler, notify the parent and sleep.
884*955a3f9aSAlex Richardson     close(pipefds[0]);
885*955a3f9aSAlex Richardson     clear_had_signals();
8868ac5aef8SEnji Cooper     signal(SIGINT, handle_signal);
887*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] child started\n", getpid_());
888*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
8898ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "[%d] child about to sleep(10)\n", getpid_());
890*955a3f9aSAlex Richardson     // Note: we could receive the SIGINT just before sleep(), so we use a loop
891*955a3f9aSAlex Richardson     // with a short delay instead of one long sleep().
892*955a3f9aSAlex Richardson     for (int i = 0; i < 50 && !had_signal[SIGINT]; i++) {
893*955a3f9aSAlex Richardson       usleep(100000);
894*955a3f9aSAlex Richardson     }
895*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] child slept, had[SIGINT]=%d\n",
896*955a3f9aSAlex Richardson                          getpid_(), (int)had_signal[SIGINT]);
897*955a3f9aSAlex Richardson     // Return non-zero if we didn't see SIGINT.
898*955a3f9aSAlex Richardson     exit(had_signal[SIGINT] ? 0 : 99);
8998ac5aef8SEnji Cooper   }
9008ac5aef8SEnji Cooper 
9018ac5aef8SEnji Cooper   // Parent: get child's PID.
9028ac5aef8SEnji Cooper   pid_t pd_pid;
9038ac5aef8SEnji Cooper   EXPECT_OK(pdgetpid(pd, &pd_pid));
9048ac5aef8SEnji Cooper   EXPECT_EQ(pid, pd_pid);
9058ac5aef8SEnji Cooper 
906*955a3f9aSAlex Richardson   // Interrupt the child once it's registered the SIGINT handler.
907*955a3f9aSAlex Richardson   close(pipefds[1]);
908*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] waiting for child\n", getpid_());
909*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
9108ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGINT));
911*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] sent SIGINT\n", getpid_());
9128ac5aef8SEnji Cooper 
9138ac5aef8SEnji Cooper   // Make sure the child finished properly (caught signal then exited).
9148ac5aef8SEnji Cooper   CheckChildFinished(pid);
9158ac5aef8SEnji Cooper }
9168ac5aef8SEnji Cooper 
FORK_TEST(Pdfork,PdkillSignal)9178ac5aef8SEnji Cooper FORK_TEST(Pdfork, PdkillSignal) {
9188ac5aef8SEnji Cooper   int pd;
919*955a3f9aSAlex Richardson   int pipefds[2];
920*955a3f9aSAlex Richardson   EXPECT_OK(pipe(pipefds));
9218ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
9228ac5aef8SEnji Cooper   EXPECT_OK(pid);
9238ac5aef8SEnji Cooper 
9248ac5aef8SEnji Cooper   if (pid == 0) {
925*955a3f9aSAlex Richardson     close(pipefds[0]);
926*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] child started\n", getpid_());
927*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(pipefds[1], MSG_CHILD_STARTED);
928*955a3f9aSAlex Richardson     // Child: wait for shutdown message. No SIGINT handler. The message should
929*955a3f9aSAlex Richardson     // never be received, since SIGINT should terminate the process.
930*955a3f9aSAlex Richardson     if (verbose) fprintf(stderr, "[%d] child about to read()\n", getpid_());
931*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(pipefds[1], MSG_PARENT_REQUEST_CHILD_EXIT);
932*955a3f9aSAlex Richardson     fprintf(stderr, "[%d] child read() returned unexpectedly\n", getpid_());
9338ac5aef8SEnji Cooper     exit(99);
9348ac5aef8SEnji Cooper   }
935*955a3f9aSAlex Richardson   // Wait for child to start before signalling.
936*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] waiting for child\n", getpid_());
937*955a3f9aSAlex Richardson   close(pipefds[1]);
938*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(pipefds[0], MSG_CHILD_STARTED);
9398ac5aef8SEnji Cooper   // Kill the child (as it doesn't handle SIGINT).
940*955a3f9aSAlex Richardson   if (verbose) fprintf(stderr, "[%d] sending SIGINT\n", getpid_());
9418ac5aef8SEnji Cooper   EXPECT_OK(pdkill(pd, SIGINT));
9428ac5aef8SEnji Cooper 
9438ac5aef8SEnji Cooper   // Make sure the child finished properly (terminated by signal).
9448ac5aef8SEnji Cooper   CheckChildFinished(pid, true);
9458ac5aef8SEnji Cooper }
9468ac5aef8SEnji Cooper 
9478ac5aef8SEnji Cooper //------------------------------------------------
9488ac5aef8SEnji Cooper // Test interactions with other parts of Capsicum:
9498ac5aef8SEnji Cooper //  - capability mode
9508ac5aef8SEnji Cooper //  - capabilities
9518ac5aef8SEnji Cooper 
FORK_TEST(Pdfork,DaemonUnrestricted)9528ac5aef8SEnji Cooper FORK_TEST(Pdfork, DaemonUnrestricted) {
9538ac5aef8SEnji Cooper   EXPECT_OK(cap_enter());
9548ac5aef8SEnji Cooper   int fd;
9558ac5aef8SEnji Cooper 
9568ac5aef8SEnji Cooper   // Capability mode leaves pdfork() available, with and without flag.
9578ac5aef8SEnji Cooper   int rc;
9588ac5aef8SEnji Cooper   rc = pdfork(&fd, PD_DAEMON);
9598ac5aef8SEnji Cooper   EXPECT_OK(rc);
9608ac5aef8SEnji Cooper   if (rc == 0) {
9618ac5aef8SEnji Cooper     // Child: immediately terminate.
9628ac5aef8SEnji Cooper     exit(0);
9638ac5aef8SEnji Cooper   }
9648ac5aef8SEnji Cooper 
9658ac5aef8SEnji Cooper   rc = pdfork(&fd, 0);
9668ac5aef8SEnji Cooper   EXPECT_OK(rc);
9678ac5aef8SEnji Cooper   if (rc == 0) {
9688ac5aef8SEnji Cooper     // Child: immediately terminate.
9698ac5aef8SEnji Cooper     exit(0);
9708ac5aef8SEnji Cooper   }
9718ac5aef8SEnji Cooper }
9728ac5aef8SEnji Cooper 
TEST(Pdfork,MissingRights)9738ac5aef8SEnji Cooper TEST(Pdfork, MissingRights) {
9748ac5aef8SEnji Cooper   pid_t parent = getpid_();
9758ac5aef8SEnji Cooper   int pd = -1;
9768ac5aef8SEnji Cooper   pid_t pid = pdfork(&pd, 0);
9778ac5aef8SEnji Cooper   EXPECT_OK(pid);
9788ac5aef8SEnji Cooper   if (pid == 0) {
9798ac5aef8SEnji Cooper     // Child: loop forever.
9808ac5aef8SEnji Cooper     EXPECT_NE(parent, getpid_());
9818ac5aef8SEnji Cooper     while (true) sleep(1);
9828ac5aef8SEnji Cooper   }
9838ac5aef8SEnji Cooper   // Create two capabilities from the process descriptor.
9848ac5aef8SEnji Cooper   cap_rights_t r_ro;
9858ac5aef8SEnji Cooper   cap_rights_init(&r_ro, CAP_READ, CAP_LOOKUP);
9868ac5aef8SEnji Cooper   int cap_incapable = dup(pd);
9878ac5aef8SEnji Cooper   EXPECT_OK(cap_incapable);
9888ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_incapable, &r_ro));
9898ac5aef8SEnji Cooper   cap_rights_t r_pdall;
9908ac5aef8SEnji Cooper   cap_rights_init(&r_pdall, CAP_PDGETPID, CAP_PDWAIT, CAP_PDKILL);
9918ac5aef8SEnji Cooper   int cap_capable = dup(pd);
9928ac5aef8SEnji Cooper   EXPECT_OK(cap_capable);
9938ac5aef8SEnji Cooper   EXPECT_OK(cap_rights_limit(cap_capable, &r_pdall));
9948ac5aef8SEnji Cooper 
9958ac5aef8SEnji Cooper   pid_t other_pid;
9968ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(pdgetpid(cap_incapable, &other_pid));
9978ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(pdkill(cap_incapable, SIGINT));
9988ac5aef8SEnji Cooper   int status;
9998ac5aef8SEnji Cooper   EXPECT_NOTCAPABLE(pdwait4_(cap_incapable, &status, 0, NULL));
10008ac5aef8SEnji Cooper 
10018ac5aef8SEnji Cooper   EXPECT_OK(pdgetpid(cap_capable, &other_pid));
10028ac5aef8SEnji Cooper   EXPECT_EQ(pid, other_pid);
10038ac5aef8SEnji Cooper   EXPECT_OK(pdkill(cap_capable, SIGINT));
10048ac5aef8SEnji Cooper   int rc = pdwait4_(pd, &status, 0, NULL);
10058ac5aef8SEnji Cooper   EXPECT_OK(rc);
10068ac5aef8SEnji Cooper   EXPECT_EQ(pid, rc);
10078ac5aef8SEnji Cooper }
10088ac5aef8SEnji Cooper 
10098ac5aef8SEnji Cooper 
10108ac5aef8SEnji Cooper //------------------------------------------------
10118ac5aef8SEnji Cooper // Passing process descriptors between processes.
10128ac5aef8SEnji Cooper 
TEST_F(PipePdfork,PassProcessDescriptor)10138ac5aef8SEnji Cooper TEST_F(PipePdfork, PassProcessDescriptor) {
10148ac5aef8SEnji Cooper   int sock_fds[2];
10158ac5aef8SEnji Cooper   EXPECT_OK(socketpair(AF_UNIX, SOCK_STREAM, 0, sock_fds));
10168ac5aef8SEnji Cooper 
10178ac5aef8SEnji Cooper   struct msghdr mh;
10188ac5aef8SEnji Cooper   mh.msg_name = NULL;  // No address needed
10198ac5aef8SEnji Cooper   mh.msg_namelen = 0;
10208ac5aef8SEnji Cooper   char buffer1[1024];
10218ac5aef8SEnji Cooper   struct iovec iov[1];
10228ac5aef8SEnji Cooper   iov[0].iov_base = buffer1;
10238ac5aef8SEnji Cooper   iov[0].iov_len = sizeof(buffer1);
10248ac5aef8SEnji Cooper   mh.msg_iov = iov;
10258ac5aef8SEnji Cooper   mh.msg_iovlen = 1;
10268ac5aef8SEnji Cooper   char buffer2[1024];
10278ac5aef8SEnji Cooper   mh.msg_control = buffer2;
10288ac5aef8SEnji Cooper   mh.msg_controllen = sizeof(buffer2);
10298ac5aef8SEnji Cooper   struct cmsghdr *cmptr;
10308ac5aef8SEnji Cooper 
10318ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "[%d] about to fork()\n", getpid_());
10328ac5aef8SEnji Cooper   pid_t child2 = fork();
10338ac5aef8SEnji Cooper   if (child2 == 0) {
10348ac5aef8SEnji Cooper     // Child: close our copy of the original process descriptor.
10358ac5aef8SEnji Cooper     close(pd_);
1036*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_STARTED);
10378ac5aef8SEnji Cooper     // Child: wait to receive process descriptor over socket
10388ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] child of %d waiting for process descriptor on socket\n", getpid_(), getppid());
10398ac5aef8SEnji Cooper     int rc = recvmsg(sock_fds[0], &mh, 0);
10408ac5aef8SEnji Cooper     EXPECT_OK(rc);
10418ac5aef8SEnji Cooper     EXPECT_LE(CMSG_LEN(sizeof(int)), mh.msg_controllen);
10428ac5aef8SEnji Cooper     cmptr = CMSG_FIRSTHDR(&mh);
10438ac5aef8SEnji Cooper     int pd = *(int*)CMSG_DATA(cmptr);
10448ac5aef8SEnji Cooper     EXPECT_EQ(CMSG_LEN(sizeof(int)), cmptr->cmsg_len);
10458ac5aef8SEnji Cooper     cmptr = CMSG_NXTHDR(&mh, cmptr);
10468ac5aef8SEnji Cooper     EXPECT_TRUE(cmptr == NULL);
10478ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] got process descriptor %d on socket\n", getpid_(), pd);
1048*955a3f9aSAlex Richardson     SEND_INT_MESSAGE(sock_fds[0], MSG_CHILD_FD_RECEIVED);
10498ac5aef8SEnji Cooper 
10508ac5aef8SEnji Cooper     // Child: confirm we can do pd*() operations on the process descriptor
10518ac5aef8SEnji Cooper     pid_t other;
10528ac5aef8SEnji Cooper     EXPECT_OK(pdgetpid(pd, &other));
10538ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] process descriptor %d is pid %d\n", getpid_(), pd, other);
10548ac5aef8SEnji Cooper 
1055*955a3f9aSAlex Richardson     // Wait until the parent has closed the process descriptor.
1056*955a3f9aSAlex Richardson     AWAIT_INT_MESSAGE(sock_fds[0], MSG_PARENT_CLOSED_FD);
1057*955a3f9aSAlex Richardson 
10588ac5aef8SEnji Cooper     if (verbose) fprintf(stderr, "  [%d] close process descriptor %d\n", getpid_(), pd);
10598ac5aef8SEnji Cooper     close(pd);
10608ac5aef8SEnji Cooper 
10618ac5aef8SEnji Cooper     // Last process descriptor closed, expect death
10628ac5aef8SEnji Cooper     EXPECT_PID_DEAD(other);
10638ac5aef8SEnji Cooper 
10648ac5aef8SEnji Cooper     exit(HasFailure());
10658ac5aef8SEnji Cooper   }
1066*955a3f9aSAlex Richardson   // Wait until the child has started.
1067*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_STARTED);
10688ac5aef8SEnji Cooper 
10698ac5aef8SEnji Cooper   // Send the process descriptor over the pipe to the sub-process
10708ac5aef8SEnji Cooper   mh.msg_controllen = CMSG_LEN(sizeof(int));
10718ac5aef8SEnji Cooper   cmptr = CMSG_FIRSTHDR(&mh);
10728ac5aef8SEnji Cooper   cmptr->cmsg_level = SOL_SOCKET;
10738ac5aef8SEnji Cooper   cmptr->cmsg_type = SCM_RIGHTS;
10748ac5aef8SEnji Cooper   cmptr->cmsg_len = CMSG_LEN(sizeof(int));
10758ac5aef8SEnji Cooper   *(int *)CMSG_DATA(cmptr) = pd_;
10768ac5aef8SEnji Cooper   buffer1[0] = 0;
10778ac5aef8SEnji Cooper   iov[0].iov_len = 1;
10788ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "[%d] send process descriptor %d on socket\n", getpid_(), pd_);
10798ac5aef8SEnji Cooper   int rc = sendmsg(sock_fds[1], &mh, 0);
10808ac5aef8SEnji Cooper   EXPECT_OK(rc);
1081*955a3f9aSAlex Richardson   // Wait until the child has received the process descriptor.
1082*955a3f9aSAlex Richardson   AWAIT_INT_MESSAGE(sock_fds[1], MSG_CHILD_FD_RECEIVED);
10838ac5aef8SEnji Cooper 
10848ac5aef8SEnji Cooper   if (verbose) fprintf(stderr, "[%d] close process descriptor %d\n", getpid_(), pd_);
10858ac5aef8SEnji Cooper   close(pd_);  // Not last open process descriptor
1086*955a3f9aSAlex Richardson   SEND_INT_MESSAGE(sock_fds[1], MSG_PARENT_CLOSED_FD);
10878ac5aef8SEnji Cooper 
10888ac5aef8SEnji Cooper   // wait for child2
10898ac5aef8SEnji Cooper   int status;
10908ac5aef8SEnji Cooper   EXPECT_EQ(child2, waitpid(child2, &status, __WALL));
10918ac5aef8SEnji Cooper   rc = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
10928ac5aef8SEnji Cooper   EXPECT_EQ(0, rc);
10938ac5aef8SEnji Cooper 
10948ac5aef8SEnji Cooper   // confirm death all round
10958ac5aef8SEnji Cooper   EXPECT_PID_DEAD(child2);
10968ac5aef8SEnji Cooper   EXPECT_PID_DEAD(pid_);
10978ac5aef8SEnji Cooper }
1098