1*8ac5aef8SEnji Cooper /* Small standalone test program to check the existence of Capsicum syscalls */ 2*8ac5aef8SEnji Cooper #include <sys/types.h> 3*8ac5aef8SEnji Cooper #include <sys/stat.h> 4*8ac5aef8SEnji Cooper #include <sys/wait.h> 5*8ac5aef8SEnji Cooper #include <fcntl.h> 6*8ac5aef8SEnji Cooper #include <unistd.h> 7*8ac5aef8SEnji Cooper #include <sys/syscall.h> 8*8ac5aef8SEnji Cooper #include <stdio.h> 9*8ac5aef8SEnji Cooper #include <string.h> 10*8ac5aef8SEnji Cooper #include <errno.h> 11*8ac5aef8SEnji Cooper #include <stdlib.h> 12*8ac5aef8SEnji Cooper #include <signal.h> 13*8ac5aef8SEnji Cooper 14*8ac5aef8SEnji Cooper #include "capsicum.h" 15*8ac5aef8SEnji Cooper 16*8ac5aef8SEnji Cooper #ifdef __linux__ 17*8ac5aef8SEnji Cooper // glibc on Linux caches getpid() return value. 18*8ac5aef8SEnji Cooper int getpid_(void) { return syscall(__NR_getpid); } 19*8ac5aef8SEnji Cooper #else 20*8ac5aef8SEnji Cooper #define getpid_ getpid 21*8ac5aef8SEnji Cooper #endif 22*8ac5aef8SEnji Cooper 23*8ac5aef8SEnji Cooper static int seen_sigchld = 0; 24*8ac5aef8SEnji Cooper static void handle_signal(int x) { 25*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] received SIGCHLD\n", getpid_()); 26*8ac5aef8SEnji Cooper seen_sigchld = 1; 27*8ac5aef8SEnji Cooper } 28*8ac5aef8SEnji Cooper 29*8ac5aef8SEnji Cooper int main(int argc, char *argv[]) { 30*8ac5aef8SEnji Cooper signal(SIGCHLD, handle_signal); 31*8ac5aef8SEnji Cooper int lifetime = 4; /* seconds */ 32*8ac5aef8SEnji Cooper if (1 < argc) { 33*8ac5aef8SEnji Cooper lifetime = atoi(argv[1]); 34*8ac5aef8SEnji Cooper } 35*8ac5aef8SEnji Cooper 36*8ac5aef8SEnji Cooper /* cap_rights_limit() available? */ 37*8ac5aef8SEnji Cooper cap_rights_t r_rws; 38*8ac5aef8SEnji Cooper cap_rights_init(&r_rws, CAP_READ, CAP_WRITE, CAP_SEEK); 39*8ac5aef8SEnji Cooper int cap_fd = dup(STDOUT_FILENO); 40*8ac5aef8SEnji Cooper int rc = cap_rights_limit(cap_fd, &r_rws); 41*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] cap_fd=%d\n", getpid_(), cap_fd); 42*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** cap_rights_limit() failed: errno=%d %s\n", errno, strerror(errno)); 43*8ac5aef8SEnji Cooper 44*8ac5aef8SEnji Cooper /* cap_rights_get() available? */ 45*8ac5aef8SEnji Cooper cap_rights_t rights; 46*8ac5aef8SEnji Cooper cap_rights_init(&rights, 0); 47*8ac5aef8SEnji Cooper rc = cap_rights_get(cap_fd, &rights); 48*8ac5aef8SEnji Cooper char buffer[256]; 49*8ac5aef8SEnji Cooper cap_rights_describe(&rights, buffer); 50*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] cap_rights_get(cap_fd=%d) rc=%d rights=%s\n", getpid_(), cap_fd, rc, buffer); 51*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** cap_rights_get() failed: errno=%d %s\n", errno, strerror(errno)); 52*8ac5aef8SEnji Cooper 53*8ac5aef8SEnji Cooper /* fstat() policed? */ 54*8ac5aef8SEnji Cooper struct stat buf; 55*8ac5aef8SEnji Cooper rc = fstat(cap_fd, &buf); 56*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] fstat(cap_fd=%d) rc=%d errno=%d\n", getpid_(), cap_fd, rc, errno); 57*8ac5aef8SEnji Cooper if (rc != -1) fprintf(stderr, "*** fstat() unexpectedly succeeded\n"); 58*8ac5aef8SEnji Cooper 59*8ac5aef8SEnji Cooper /* pdfork() available? */ 60*8ac5aef8SEnji Cooper int pd = -1; 61*8ac5aef8SEnji Cooper rc = pdfork(&pd, 0); 62*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** pdfork() failed: errno=%d %s\n", errno, strerror(errno)); 63*8ac5aef8SEnji Cooper 64*8ac5aef8SEnji Cooper if (rc == 0) { /* child */ 65*8ac5aef8SEnji Cooper int count = 0; 66*8ac5aef8SEnji Cooper while (count < 20) { 67*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] child alive, parent is ppid=%d\n", getpid_(), getppid()); 68*8ac5aef8SEnji Cooper sleep(1); 69*8ac5aef8SEnji Cooper } 70*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] child exit(0)\n", getpid_()); 71*8ac5aef8SEnji Cooper exit(0); 72*8ac5aef8SEnji Cooper } 73*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] pdfork() rc=%d pd=%d\n", getpid_(), rc, pd); 74*8ac5aef8SEnji Cooper 75*8ac5aef8SEnji Cooper /* pdgetpid() available? */ 76*8ac5aef8SEnji Cooper pid_t actual_pid = rc; 77*8ac5aef8SEnji Cooper pid_t got_pid = -1; 78*8ac5aef8SEnji Cooper rc = pdgetpid(pd, &got_pid); 79*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** pdgetpid(pd=%d) failed: errno=%d %s\n", pd, errno, strerror(errno)); 80*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] pdgetpid(pd=%d)=%d, pdfork returned %d\n", getpid_(), pd, got_pid, actual_pid); 81*8ac5aef8SEnji Cooper 82*8ac5aef8SEnji Cooper sleep(lifetime); 83*8ac5aef8SEnji Cooper 84*8ac5aef8SEnji Cooper /* pdkill() available? */ 85*8ac5aef8SEnji Cooper rc = pdkill(pd, SIGKILL); 86*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] pdkill(pd=%d, SIGKILL) -> rc=%d\n", getpid_(), pd, rc); 87*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** pdkill() failed: errno=%d %s\n", errno, strerror(errno)); 88*8ac5aef8SEnji Cooper usleep(50000); /* Allow time for death and signals */ 89*8ac5aef8SEnji Cooper 90*8ac5aef8SEnji Cooper /* Death of a pdforked child should be invisible */ 91*8ac5aef8SEnji Cooper if (seen_sigchld) fprintf(stderr, "*** SIGCHLD emitted\n"); 92*8ac5aef8SEnji Cooper int status; 93*8ac5aef8SEnji Cooper rc = wait4(-1, &status, WNOHANG, NULL); 94*8ac5aef8SEnji Cooper if (rc > 0) fprintf(stderr, "*** wait4(-1, ...) unexpectedly found child %d\n", rc); 95*8ac5aef8SEnji Cooper 96*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] forking off a child process to check cap_enter()\n", getpid_()); 97*8ac5aef8SEnji Cooper pid_t child = fork(); 98*8ac5aef8SEnji Cooper if (child == 0) { /* child */ 99*8ac5aef8SEnji Cooper /* cap_getmode() / cap_enter() available? */ 100*8ac5aef8SEnji Cooper unsigned int cap_mode = -1; 101*8ac5aef8SEnji Cooper rc = cap_getmode(&cap_mode); 102*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] cap_getmode() -> rc=%d, cap_mode=%d\n", getpid_(), rc, cap_mode); 103*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** cap_getmode() failed: errno=%d %s\n", errno, strerror(errno)); 104*8ac5aef8SEnji Cooper 105*8ac5aef8SEnji Cooper rc = cap_enter(); 106*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] cap_enter() -> rc=%d\n", getpid_(), rc); 107*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** cap_enter() failed: errno=%d %s\n", errno, strerror(errno)); 108*8ac5aef8SEnji Cooper 109*8ac5aef8SEnji Cooper rc = cap_getmode(&cap_mode); 110*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] cap_getmode() -> rc=%d, cap_mode=%d\n", getpid_(), rc, cap_mode); 111*8ac5aef8SEnji Cooper if (rc < 0) fprintf(stderr, "*** cap_getmode() failed: errno=%d %s\n", errno, strerror(errno)); 112*8ac5aef8SEnji Cooper 113*8ac5aef8SEnji Cooper /* open disallowed? */ 114*8ac5aef8SEnji Cooper rc = open("/etc/passwd", O_RDONLY); 115*8ac5aef8SEnji Cooper fprintf(stderr, " [%d] open('/etc/passwd') -> rc=%d, errno=%d\n", getpid_(), rc, errno); 116*8ac5aef8SEnji Cooper if (rc != -1) fprintf(stderr, "*** open() unexpectedly succeeded\n"); 117*8ac5aef8SEnji Cooper #ifdef ECAPMODE 118*8ac5aef8SEnji Cooper if (errno != ECAPMODE) fprintf(stderr, "*** open() failed with errno %d not ECAPMODE\n", errno); 119*8ac5aef8SEnji Cooper #endif 120*8ac5aef8SEnji Cooper exit(0); 121*8ac5aef8SEnji Cooper } 122*8ac5aef8SEnji Cooper rc = wait4(child, &status, 0, NULL); 123*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] child %d exited with status %x\n", getpid_(), child, status); 124*8ac5aef8SEnji Cooper 125*8ac5aef8SEnji Cooper /* fexecve() available? */ 126*8ac5aef8SEnji Cooper char* argv_pass[] = {(char*)"/bin/ls", "-l", "smoketest", NULL}; 127*8ac5aef8SEnji Cooper char* null_envp[] = {NULL}; 128*8ac5aef8SEnji Cooper int ls_bin = open("/bin/ls", O_RDONLY); 129*8ac5aef8SEnji Cooper fprintf(stderr, "[%d] about to fexecve('/bin/ls', '-l', 'smoketest')\n", getpid_()); 130*8ac5aef8SEnji Cooper rc = fexecve(ls_bin, argv_pass, null_envp); 131*8ac5aef8SEnji Cooper /* should never reach here */ 132*8ac5aef8SEnji Cooper fprintf(stderr, "*** fexecve(fd=%d) failed: rc=%d errno=%d %s\n", ls_bin, rc, errno, strerror(errno)); 133*8ac5aef8SEnji Cooper 134*8ac5aef8SEnji Cooper return 0; 135*8ac5aef8SEnji Cooper } 136