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