• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <sys/capability.h>
5 #include <sys/types.h>
6 #include <sys/wait.h>
7 #include <unistd.h>
8 
9 /*
10  * tests for cap_launch.
11  */
12 
13 #define MORE_THAN_ENOUGH 20
14 #define NO_MORE 1
15 
16 struct test_case_s {
17     int pass_on;
18     const char *chroot;
19     uid_t uid;
20     gid_t gid;
21     int ngroups;
22     const gid_t groups[MORE_THAN_ENOUGH];
23     const char *args[MORE_THAN_ENOUGH];
24     const char **envp;
25     const char *iab;
26     cap_mode_t mode;
27     int result;
28 };
29 
30 #ifdef WITH_PTHREADS
31 #include <pthread.h>
32 #else /* WITH_PTHREADS */
33 #endif /* WITH_PTHREADS */
34 
main(int argc,char ** argv)35 int main(int argc, char **argv) {
36     static struct test_case_s vs[] = {
37 	{
38 	    .args = { "../progs/tcapsh-static", "--", "-c", "echo hello" },
39 	    .result = 0
40 	},
41 	{
42 	    .args = { "../progs/tcapsh-static", "--is-uid=123" },
43 	    .result = 256
44 	},
45 	{
46 	    .args = { "../progs/tcapsh-static", "--is-uid=123" },
47 	    .result = 0,
48 	    .uid = 123,
49 	},
50 	{
51 	    .args = { "../progs/tcapsh-static", "--is-gid=123" },
52 	    .result = 0,
53 	    .gid = 123,
54 	    .ngroups = 1,
55 	    .groups = { 456 },
56 	    .iab = "",
57 	},
58 	{
59 	    .args = { "../progs/tcapsh-static", "--dropped=cap_chown",
60 		      "--has-i=cap_chown" },
61 	    .result = 0,
62 	    .iab = "!%cap_chown"
63 	},
64 	{
65 	    .args = { "../progs/tcapsh-static", "--dropped=cap_chown",
66 		      "--has-i=cap_chown", "--is-uid=234",
67 		      "--has-a=cap_chown", "--has-p=cap_chown" },
68 	    .uid = 234,
69 	    .result = 0,
70 	    .iab = "!^cap_chown"
71 	},
72 	{
73 	    .args = { "../progs/tcapsh-static", "--inmode=NOPRIV",
74 		      "--has-no-new-privs" },
75 	    .result = 0,
76 	    .mode = CAP_MODE_NOPRIV
77 	},
78 	{
79 	    .args = { "/noop" },
80 	    .result = 0,
81 	    .chroot = ".",
82 	},
83 	{
84 	    .pass_on = NO_MORE
85 	},
86     };
87 
88     cap_t orig = cap_get_proc();
89 
90     int success = 1, i;
91     for (i=0; vs[i].pass_on != NO_MORE; i++) {
92 	const struct test_case_s *v = &vs[i];
93 	printf("[%d] test should %s\n", i,
94 	       v->result ? "generate error" : "work");
95 	cap_launch_t attr = cap_new_launcher(v->args[0], v->args, v->envp);
96 	if (v->chroot) {
97 	    cap_launcher_set_chroot(attr, v->chroot);
98 	}
99 	if (v->uid) {
100 	    cap_launcher_setuid(attr, v->uid);
101 	}
102 	if (v->gid) {
103 	    cap_launcher_setgroups(attr, v->gid, v->ngroups, v->groups);
104 	}
105 	if (v->iab) {
106 	    cap_iab_t iab = cap_iab_from_text(v->iab);
107 	    if (iab == NULL) {
108 		fprintf(stderr, "[%d] failed to decode iab [%s]", i, v->iab);
109 		perror(":");
110 		success = 0;
111 		continue;
112 	    }
113 	    cap_iab_t old = cap_launcher_set_iab(attr, iab);
114 	    if (cap_free(old)) {
115 		fprintf(stderr, "[%d] failed to decode iab [%s]", i, v->iab);
116 		perror(":");
117 		success = 0;
118 		continue;
119 	    }
120 	}
121 	if (v->mode) {
122 	    cap_launcher_set_mode(attr, v->mode);
123 	}
124 
125 	pid_t child = cap_launch(attr, NULL);
126 
127 	if (child <= 0) {
128 	    fprintf(stderr, "[%d] failed to launch", i);
129 	    perror(":");
130 	    success = 0;
131 	    continue;
132 	}
133 	if (cap_free(attr)) {
134 	    fprintf(stderr, "[%d] failed to free launcher", i);
135 	    perror(":");
136 	    success = 0;
137 	}
138 	int result;
139 	int ret = waitpid(child, &result, 0);
140 	if (ret != child) {
141 	    fprintf(stderr, "[%d] failed to wait", i);
142 	    perror(":");
143 	    success = 0;
144 	    continue;
145 	}
146 	if (result != v->result) {
147 	    fprintf(stderr, "[%d] bad result: got=%d want=%d", i, result,
148 		    v->result);
149 	    perror(":");
150 	    success = 0;
151 	    continue;
152 	}
153     }
154 
155     cap_t final = cap_get_proc();
156     if (cap_compare(orig, final)) {
157 	char *was = cap_to_text(orig, NULL);
158 	char *is = cap_to_text(final, NULL);
159 	printf("cap_launch_test: orig:'%s' != final:'%s'\n", was, is);
160 	cap_free(is);
161 	cap_free(was);
162 	success = 0;
163     }
164     cap_free(final);
165     cap_free(orig);
166 
167     if (success) {
168 	printf("cap_launch_test: PASSED\n");
169     } else {
170 	printf("cap_launch_test: FAILED\n");
171 	exit(1);
172     }
173 }
174