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