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