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