kdbus: the driver, original and non-working
[platform/kernel/linux-exynos.git] / tools / testing / selftests / kdbus / test-activator.c
1 #include <stdio.h>
2 #include <string.h>
3 #include <time.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <stdbool.h>
7 #include <stddef.h>
8 #include <unistd.h>
9 #include <stdint.h>
10 #include <errno.h>
11 #include <assert.h>
12 #include <poll.h>
13 #include <sys/capability.h>
14 #include <sys/types.h>
15 #include <sys/wait.h>
16
17 #include "kdbus-test.h"
18 #include "kdbus-util.h"
19 #include "kdbus-enum.h"
20
21 static int kdbus_starter_poll(struct kdbus_conn *conn)
22 {
23         int ret;
24         struct pollfd fd;
25
26         fd.fd = conn->fd;
27         fd.events = POLLIN | POLLPRI | POLLHUP;
28         fd.revents = 0;
29
30         ret = poll(&fd, 1, 100);
31         if (ret == 0)
32                 return -ETIMEDOUT;
33         else if (ret > 0) {
34                 if (fd.revents & POLLIN)
35                         return 0;
36
37                 if (fd.revents & (POLLHUP | POLLERR))
38                         ret = -ECONNRESET;
39         }
40
41         return ret;
42 }
43
44 /* Ensure that kdbus activator logic is safe */
45 static int kdbus_priv_activator(struct kdbus_test_env *env)
46 {
47         int ret;
48         struct kdbus_msg *msg = NULL;
49         uint64_t cookie = 0xdeadbeef;
50         uint64_t flags = KDBUS_NAME_REPLACE_EXISTING;
51         struct kdbus_conn *activator;
52         struct kdbus_conn *service;
53         struct kdbus_conn *client;
54         struct kdbus_conn *holder;
55         struct kdbus_policy_access *access;
56
57         access = (struct kdbus_policy_access[]){
58                 {
59                         .type = KDBUS_POLICY_ACCESS_USER,
60                         .id = getuid(),
61                         .access = KDBUS_POLICY_OWN,
62                 },
63                 {
64                         .type = KDBUS_POLICY_ACCESS_USER,
65                         .id = getuid(),
66                         .access = KDBUS_POLICY_TALK,
67                 },
68         };
69
70         activator = kdbus_hello_activator(env->buspath, "foo.priv.activator",
71                                           access, 2);
72         ASSERT_RETURN(activator);
73
74         service = kdbus_hello(env->buspath, 0, NULL, 0);
75         ASSERT_RETURN(service);
76
77         client = kdbus_hello(env->buspath, 0, NULL, 0);
78         ASSERT_RETURN(client);
79
80         /*
81          * Make sure that other users can't TALK to the activator
82          */
83
84         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
85                 /* Try to talk using the ID */
86                 ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0,
87                                      0, activator->id, 0, NULL);
88                 ASSERT_EXIT(ret == -ENXIO);
89
90                 /* Try to talk to the name */
91                 ret = kdbus_msg_send(unpriv, "foo.priv.activator",
92                                      0xdeadbeef, 0, 0, 0,
93                                      KDBUS_DST_ID_NAME, 0, NULL);
94                 ASSERT_EXIT(ret == -EPERM);
95         }));
96         ASSERT_RETURN(ret >= 0);
97
98         /*
99          * Make sure that we did not receive anything, so the
100          * service will not be started automatically
101          */
102
103         ret = kdbus_starter_poll(activator);
104         ASSERT_RETURN(ret == -ETIMEDOUT);
105
106         /*
107          * Now try to emulate the starter/service logic and
108          * acquire the name.
109          */
110
111         cookie++;
112         ret = kdbus_msg_send(service, "foo.priv.activator", cookie,
113                              0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
114         ASSERT_RETURN(ret == 0);
115
116         ret = kdbus_starter_poll(activator);
117         ASSERT_RETURN(ret == 0);
118
119         /* Policies are still checked, access denied */
120
121         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
122                 ret = kdbus_name_acquire(unpriv, "foo.priv.activator",
123                                          &flags);
124                 ASSERT_RETURN(ret == -EPERM);
125         }));
126         ASSERT_RETURN(ret >= 0);
127
128         ret = kdbus_name_acquire(service, "foo.priv.activator",
129                                  &flags);
130         ASSERT_RETURN(ret == 0);
131
132         /* We read our previous starter message */
133
134         ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
135         ASSERT_RETURN(ret == 0);
136
137         /* Try to talk, we still fail */
138
139         cookie++;
140         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
141                 /* Try to talk to the name */
142                 ret = kdbus_msg_send(unpriv, "foo.priv.activator",
143                                      cookie, 0, 0, 0,
144                                      KDBUS_DST_ID_NAME, 0, NULL);
145                 ASSERT_EXIT(ret == -EPERM);
146         }));
147         ASSERT_RETURN(ret >= 0);
148
149         /* Still nothing to read */
150
151         ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
152         ASSERT_RETURN(ret == -ETIMEDOUT);
153
154         /* We receive every thing now */
155
156         cookie++;
157         ret = kdbus_msg_send(client, "foo.priv.activator", cookie,
158                              0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
159         ASSERT_RETURN(ret == 0);
160         ret = kdbus_msg_recv_poll(service, 100, &msg, NULL);
161         ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
162
163         kdbus_msg_free(msg);
164
165         /* Policies default to deny TALK now */
166         kdbus_conn_free(activator);
167
168         cookie++;
169         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
170                 /* Try to talk to the name */
171                 ret = kdbus_msg_send(unpriv, "foo.priv.activator",
172                                      cookie, 0, 0, 0,
173                                      KDBUS_DST_ID_NAME,
174                                      0, NULL);
175                 ASSERT_EXIT(ret == -EPERM);
176         }));
177         ASSERT_RETURN(ret >= 0);
178
179         ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
180         ASSERT_RETURN(ret == -ETIMEDOUT);
181
182         /* Same user is able to TALK */
183         cookie++;
184         ret = kdbus_msg_send(client, "foo.priv.activator", cookie,
185                              0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
186         ASSERT_RETURN(ret == 0);
187         ret = kdbus_msg_recv_poll(service, 100, &msg, NULL);
188         ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
189
190         kdbus_msg_free(msg);
191
192         access = (struct kdbus_policy_access []){
193                 {
194                         .type = KDBUS_POLICY_ACCESS_WORLD,
195                         .id = getuid(),
196                         .access = KDBUS_POLICY_TALK,
197                 },
198         };
199
200         holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator",
201                                        access, 1, KDBUS_HELLO_POLICY_HOLDER);
202         ASSERT_RETURN(holder);
203
204         /* Now we are able to TALK to the name */
205
206         cookie++;
207         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
208                 /* Try to talk to the name */
209                 ret = kdbus_msg_send(unpriv, "foo.priv.activator",
210                                      cookie, 0, 0, 0,
211                                      KDBUS_DST_ID_NAME,
212                                      0, NULL);
213                 ASSERT_EXIT(ret == 0);
214         }));
215         ASSERT_RETURN(ret >= 0);
216
217         ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
218         ASSERT_RETURN(ret == 0);
219
220         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
221                 ret = kdbus_name_acquire(unpriv, "foo.priv.activator",
222                                          &flags);
223                 ASSERT_RETURN(ret == -EPERM);
224         }));
225         ASSERT_RETURN(ret >= 0);
226
227         kdbus_conn_free(service);
228         kdbus_conn_free(client);
229         kdbus_conn_free(holder);
230
231         return 0;
232 }
233
234 int kdbus_test_activator(struct kdbus_test_env *env)
235 {
236         int ret;
237         struct kdbus_conn *activator;
238         struct pollfd fds[2];
239         bool activator_done = false;
240         struct kdbus_policy_access access[2];
241
242         access[0].type = KDBUS_POLICY_ACCESS_USER;
243         access[0].id = getuid();
244         access[0].access = KDBUS_POLICY_OWN;
245
246         access[1].type = KDBUS_POLICY_ACCESS_WORLD;
247         access[1].access = KDBUS_POLICY_TALK;
248
249         activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
250                                           access, 2);
251         ASSERT_RETURN(activator);
252
253         ret = kdbus_add_match_empty(env->conn);
254         ASSERT_RETURN(ret == 0);
255
256         ret = kdbus_list(env->conn, KDBUS_LIST_NAMES |
257                                     KDBUS_LIST_UNIQUE |
258                                     KDBUS_LIST_ACTIVATORS |
259                                     KDBUS_LIST_QUEUED);
260         ASSERT_RETURN(ret == 0);
261
262         ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef,
263                              0, 0, 0, KDBUS_DST_ID_NAME, 0, NULL);
264         ASSERT_RETURN(ret == 0);
265
266         fds[0].fd = activator->fd;
267         fds[1].fd = env->conn->fd;
268
269         kdbus_printf("-- entering poll loop ...\n");
270
271         for (;;) {
272                 int i, nfds = sizeof(fds) / sizeof(fds[0]);
273
274                 for (i = 0; i < nfds; i++) {
275                         fds[i].events = POLLIN | POLLPRI;
276                         fds[i].revents = 0;
277                 }
278
279                 ret = poll(fds, nfds, 3000);
280                 ASSERT_RETURN(ret >= 0);
281
282                 ret = kdbus_list(env->conn, KDBUS_LIST_NAMES);
283                 ASSERT_RETURN(ret == 0);
284
285                 if ((fds[0].revents & POLLIN) && !activator_done) {
286                         uint64_t flags = KDBUS_NAME_REPLACE_EXISTING;
287
288                         kdbus_printf("Starter was called back!\n");
289
290                         ret = kdbus_name_acquire(env->conn,
291                                                  "foo.test.activator", &flags);
292                         ASSERT_RETURN(ret == 0);
293
294                         activator_done = true;
295                 }
296
297                 if (fds[1].revents & POLLIN) {
298                         kdbus_msg_recv(env->conn, NULL, NULL);
299                         break;
300                 }
301         }
302
303         /* Check if all uids/gids are mapped */
304         if (!all_uids_gids_are_mapped())
305                 return TEST_SKIP;
306
307         /* Check now capabilities, so we run the previous tests */
308         ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
309         ASSERT_RETURN(ret >= 0);
310
311         if (!ret)
312                 return TEST_SKIP;
313
314         ret = kdbus_priv_activator(env);
315         ASSERT_RETURN(ret == 0);
316
317         kdbus_conn_free(activator);
318
319         return TEST_OK;
320 }