kdbus: the driver, original and non-working
[platform/kernel/linux-exynos.git] / tools / testing / selftests / kdbus / test-policy-priv.c
1 #include <errno.h>
2 #include <stdio.h>
3 #include <string.h>
4 #include <fcntl.h>
5 #include <stdlib.h>
6 #include <stdint.h>
7 #include <stdbool.h>
8 #include <unistd.h>
9 #include <time.h>
10 #include <sys/capability.h>
11 #include <sys/eventfd.h>
12 #include <sys/wait.h>
13
14 #include "kdbus-test.h"
15 #include "kdbus-util.h"
16 #include "kdbus-enum.h"
17
18 static int test_policy_priv_by_id(const char *bus,
19                                   struct kdbus_conn *conn_dst,
20                                   bool drop_second_user,
21                                   int parent_status,
22                                   int child_status)
23 {
24         int ret = 0;
25         uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
26
27         ASSERT_RETURN(conn_dst);
28
29         ret = RUN_UNPRIVILEGED_CONN(unpriv, bus, ({
30                 ret = kdbus_msg_send(unpriv, NULL,
31                                      expected_cookie, 0, 0, 0,
32                                      conn_dst->id, 0, NULL);
33                 ASSERT_EXIT(ret == child_status);
34         }));
35         ASSERT_RETURN(ret >= 0);
36
37         ret = kdbus_msg_recv_poll(conn_dst, 300, NULL, NULL);
38         ASSERT_RETURN(ret == parent_status);
39
40         return 0;
41 }
42
43 static int test_policy_priv_by_broadcast(const char *bus,
44                                          struct kdbus_conn *conn_dst,
45                                          int drop_second_user,
46                                          int parent_status,
47                                          int child_status)
48 {
49         int efd;
50         int ret = 0;
51         eventfd_t event_status = 0;
52         struct kdbus_msg *msg = NULL;
53         uid_t second_uid = UNPRIV_UID;
54         gid_t second_gid = UNPRIV_GID;
55         struct kdbus_conn *child_2 = conn_dst;
56         uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
57
58         /* Drop to another unprivileged user other than UNPRIV_UID */
59         if (drop_second_user == DROP_OTHER_UNPRIV) {
60                 second_uid = UNPRIV_UID - 1;
61                 second_gid = UNPRIV_GID - 1;
62         }
63
64         /* child will signal parent to send broadcast */
65         efd = eventfd(0, EFD_CLOEXEC);
66         ASSERT_RETURN_VAL(efd >= 0, efd);
67
68         ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
69                 struct kdbus_conn *child;
70
71                 child = kdbus_hello(bus, 0, NULL, 0);
72                 ASSERT_EXIT(child);
73
74                 ret = kdbus_add_match_empty(child);
75                 ASSERT_EXIT(ret == 0);
76
77                 /* signal parent */
78                 ret = eventfd_write(efd, 1);
79                 ASSERT_EXIT(ret == 0);
80
81                 /* Use a little bit high time */
82                 ret = kdbus_msg_recv_poll(child, 500, &msg, NULL);
83                 ASSERT_EXIT(ret == child_status);
84
85                 /*
86                  * If we expect the child to get the broadcast
87                  * message, then check the received cookie.
88                  */
89                 if (ret == 0) {
90                         ASSERT_EXIT(expected_cookie == msg->cookie);
91                 }
92
93                 /* Use expected_cookie since 'msg' might be NULL */
94                 ret = kdbus_msg_send(child, NULL, expected_cookie + 1,
95                                      0, 0, 0, KDBUS_DST_ID_BROADCAST,
96                                      0, NULL);
97                 ASSERT_EXIT(ret == 0);
98
99                 kdbus_msg_free(msg);
100                 kdbus_conn_free(child);
101         }),
102         ({
103                 if (drop_second_user == DO_NOT_DROP) {
104                         ASSERT_RETURN(child_2);
105
106                         ret = eventfd_read(efd, &event_status);
107                         ASSERT_RETURN(ret >= 0 && event_status == 1);
108
109                         ret = kdbus_msg_send(child_2, NULL,
110                                              expected_cookie, 0, 0, 0,
111                                              KDBUS_DST_ID_BROADCAST,
112                                              0, NULL);
113                         ASSERT_RETURN(ret == 0);
114
115                         /* Use a little bit high time */
116                         ret = kdbus_msg_recv_poll(child_2, 1000,
117                                                   &msg, NULL);
118                         ASSERT_RETURN(ret == parent_status);
119
120                         /*
121                          * Check returned cookie in case we expect
122                          * success.
123                          */
124                         if (ret == 0) {
125                                 ASSERT_RETURN(msg->cookie ==
126                                               expected_cookie + 1);
127                         }
128
129                         kdbus_msg_free(msg);
130                 } else {
131                         /*
132                          * Two unprivileged users will try to
133                          * communicate using broadcast.
134                          */
135                         ret = RUN_UNPRIVILEGED(second_uid, second_gid, ({
136                                 child_2 = kdbus_hello(bus, 0, NULL, 0);
137                                 ASSERT_EXIT(child_2);
138
139                                 ret = kdbus_add_match_empty(child_2);
140                                 ASSERT_EXIT(ret == 0);
141
142                                 ret = eventfd_read(efd, &event_status);
143                                 ASSERT_EXIT(ret >= 0 && event_status == 1);
144
145                                 ret = kdbus_msg_send(child_2, NULL,
146                                                 expected_cookie, 0, 0, 0,
147                                                 KDBUS_DST_ID_BROADCAST,
148                                                 0, NULL);
149                                 ASSERT_EXIT(ret == 0);
150
151                                 /* Use a little bit high time */
152                                 ret = kdbus_msg_recv_poll(child_2, 1000,
153                                                           &msg, NULL);
154                                 ASSERT_EXIT(ret == parent_status);
155
156                                 /*
157                                  * Check returned cookie in case we expect
158                                  * success.
159                                  */
160                                 if (ret == 0) {
161                                         ASSERT_EXIT(msg->cookie ==
162                                                     expected_cookie + 1);
163                                 }
164
165                                 kdbus_msg_free(msg);
166                                 kdbus_conn_free(child_2);
167                         }),
168                         ({ 0; }));
169                         ASSERT_RETURN(ret == 0);
170                 }
171         }));
172         ASSERT_RETURN(ret == 0);
173
174         close(efd);
175
176         return ret;
177 }
178
179 static void nosig(int sig)
180 {
181 }
182
183 static int test_priv_before_policy_upload(struct kdbus_test_env *env)
184 {
185         int ret = 0;
186         struct kdbus_conn *conn;
187
188         conn = kdbus_hello(env->buspath, 0, NULL, 0);
189         ASSERT_RETURN(conn);
190
191         /*
192          * Make sure unprivileged bus user cannot acquire names
193          * before registring any policy holder.
194          */
195
196         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
197                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
198                 ASSERT_EXIT(ret < 0);
199         }));
200         ASSERT_RETURN(ret == 0);
201
202         /*
203          * Make sure unprivileged bus users cannot talk by default
204          * to privileged ones, unless a policy holder that allows
205          * this was uploaded.
206          */
207
208         ret = test_policy_priv_by_id(env->buspath, conn, false,
209                                      -ETIMEDOUT, -EPERM);
210         ASSERT_RETURN(ret == 0);
211
212         /* Activate matching for a privileged connection */
213         ret = kdbus_add_match_empty(conn);
214         ASSERT_RETURN(ret == 0);
215
216         /*
217          * First make sure that BROADCAST with msg flag
218          * KDBUS_MSG_EXPECT_REPLY will fail with -ENOTUNIQ
219          */
220         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
221                 ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef,
222                                      KDBUS_MSG_EXPECT_REPLY,
223                                      5000000000ULL, 0,
224                                      KDBUS_DST_ID_BROADCAST,
225                                      0, NULL);
226                 ASSERT_EXIT(ret == -ENOTUNIQ);
227         }));
228         ASSERT_RETURN(ret == 0);
229
230         /*
231          * Test broadcast with a privileged connection.
232          *
233          * The first unprivileged receiver should not get the
234          * broadcast message sent by the privileged connection,
235          * since there is no a TALK policy that allows the
236          * unprivileged to TALK to the privileged connection. It
237          * will fail with -ETIMEDOUT
238          *
239          * Then second case:
240          * The privileged connection should get the broadcast
241          * message from the unprivileged one. Since the receiver is
242          * a privileged bus user and it has default TALK access to
243          * all connections it will receive those.
244          */
245
246         ret = test_policy_priv_by_broadcast(env->buspath, conn,
247                                             DO_NOT_DROP,
248                                             0, -ETIMEDOUT);
249         ASSERT_RETURN(ret == 0);
250
251
252         /*
253          * Test broadcast with two unprivileged connections running
254          * under the same user.
255          *
256          * Both connections should succeed.
257          */
258
259         ret = test_policy_priv_by_broadcast(env->buspath, NULL,
260                                             DROP_SAME_UNPRIV, 0, 0);
261         ASSERT_RETURN(ret == 0);
262
263         /*
264          * Test broadcast with two unprivileged connections running
265          * under different users.
266          *
267          * Both connections will fail with -ETIMEDOUT.
268          */
269
270         ret = test_policy_priv_by_broadcast(env->buspath, NULL,
271                                             DROP_OTHER_UNPRIV,
272                                             -ETIMEDOUT, -ETIMEDOUT);
273         ASSERT_RETURN(ret == 0);
274
275         kdbus_conn_free(conn);
276
277         return ret;
278 }
279
280 static int test_broadcast_after_policy_upload(struct kdbus_test_env *env)
281 {
282         int ret;
283         int efd;
284         eventfd_t event_status = 0;
285         struct kdbus_msg *msg = NULL;
286         struct kdbus_conn *owner_a, *owner_b;
287         struct kdbus_conn *holder_a, *holder_b;
288         struct kdbus_policy_access access = {};
289         uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
290
291         owner_a = kdbus_hello(env->buspath, 0, NULL, 0);
292         ASSERT_RETURN(owner_a);
293
294         ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL);
295         ASSERT_EXIT(ret >= 0);
296
297         /*
298          * Make sure unprivileged bus users cannot talk by default
299          * to privileged ones, unless a policy holder that allows
300          * this was uploaded.
301          */
302
303         ++expected_cookie;
304         ret = test_policy_priv_by_id(env->buspath, owner_a, false,
305                                      -ETIMEDOUT, -EPERM);
306         ASSERT_RETURN(ret == 0);
307
308         /*
309          * Make sure that privileged won't receive broadcasts unless
310          * it installs a match. It will fail with -ETIMEDOUT
311          *
312          * At same time check that the unprivileged connection will
313          * not receive the broadcast message from the privileged one
314          * since the privileged one owns a name with a restricted
315          * policy TALK (actually the TALK policy is still not
316          * registered so we fail by default), thus the unprivileged
317          * receiver is not able to TALK to that name.
318          */
319
320         ret = test_policy_priv_by_broadcast(env->buspath, owner_a,
321                                             DO_NOT_DROP,
322                                             -ETIMEDOUT, -ETIMEDOUT);
323         ASSERT_RETURN(ret == 0);
324
325         /* Activate matching for a privileged connection */
326         ret = kdbus_add_match_empty(owner_a);
327         ASSERT_RETURN(ret == 0);
328
329         /*
330          * Redo the previous test. The privileged conn owner_a is
331          * able to TALK to any connection so it will receive the
332          * broadcast message now.
333          */
334
335         ret = test_policy_priv_by_broadcast(env->buspath, owner_a,
336                                             DO_NOT_DROP,
337                                             0, -ETIMEDOUT);
338         ASSERT_RETURN(ret == 0);
339
340         /*
341          * Test that broadcast between two unprivileged users running
342          * under the same user still succeed.
343          */
344
345         ret = test_policy_priv_by_broadcast(env->buspath, NULL,
346                                             DROP_SAME_UNPRIV, 0, 0);
347         ASSERT_RETURN(ret == 0);
348
349         /*
350          * Test broadcast with two unprivileged connections running
351          * under different users.
352          *
353          * Both connections will fail with -ETIMEDOUT.
354          */
355
356         ret = test_policy_priv_by_broadcast(env->buspath, NULL,
357                                             DROP_OTHER_UNPRIV,
358                                             -ETIMEDOUT, -ETIMEDOUT);
359         ASSERT_RETURN(ret == 0);
360
361         access = (struct kdbus_policy_access){
362                 .type = KDBUS_POLICY_ACCESS_USER,
363                 .id = geteuid(),
364                 .access = KDBUS_POLICY_OWN,
365         };
366
367         holder_a = kdbus_hello_registrar(env->buspath,
368                                          "com.example.broadcastA",
369                                          &access, 1,
370                                          KDBUS_HELLO_POLICY_HOLDER);
371         ASSERT_RETURN(holder_a);
372
373         holder_b = kdbus_hello_registrar(env->buspath,
374                                          "com.example.broadcastB",
375                                          &access, 1,
376                                          KDBUS_HELLO_POLICY_HOLDER);
377         ASSERT_RETURN(holder_b);
378
379         /* Free connections and their received messages and restart */
380         kdbus_conn_free(owner_a);
381
382         owner_a = kdbus_hello(env->buspath, 0, NULL, 0);
383         ASSERT_RETURN(owner_a);
384
385         /* Activate matching for a privileged connection */
386         ret = kdbus_add_match_empty(owner_a);
387         ASSERT_RETURN(ret == 0);
388
389         ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL);
390         ASSERT_EXIT(ret >= 0);
391
392         owner_b = kdbus_hello(env->buspath, 0, NULL, 0);
393         ASSERT_RETURN(owner_b);
394
395         ret = kdbus_name_acquire(owner_b, "com.example.broadcastB", NULL);
396         ASSERT_EXIT(ret >= 0);
397
398         /* Activate matching for a privileged connection */
399         ret = kdbus_add_match_empty(owner_b);
400         ASSERT_RETURN(ret == 0);
401
402         /*
403          * Test that even if "com.example.broadcastA" and
404          * "com.example.broadcastB" do have a TALK access by default
405          * they are able to signal each other using broadcast due to
406          * the fact they are privileged connections, they receive
407          * all broadcasts if the match allows it.
408          */
409
410         ++expected_cookie;
411         ret = kdbus_msg_send(owner_a, NULL, expected_cookie, 0,
412                              0, 0, KDBUS_DST_ID_BROADCAST, 0, NULL);
413         ASSERT_RETURN(ret == 0);
414
415         ret = kdbus_msg_recv_poll(owner_b, 100, &msg, NULL);
416         ASSERT_RETURN(ret == 0);
417         ASSERT_RETURN(msg->cookie == expected_cookie);
418
419         /* Check src ID */
420         ASSERT_RETURN(msg->src_id == owner_a->id);
421
422         kdbus_msg_free(msg);
423
424         /* Release name "com.example.broadcastB" */
425
426         ret = kdbus_name_release(owner_b, "com.example.broadcastB");
427         ASSERT_EXIT(ret >= 0);
428
429         /* KDBUS_POLICY_OWN for unprivileged connections */
430         access = (struct kdbus_policy_access){
431                 .type = KDBUS_POLICY_ACCESS_WORLD,
432                 .id = geteuid(),
433                 .access = KDBUS_POLICY_OWN,
434         };
435
436         /* Update the policy so unprivileged will own the name */
437
438         ret = kdbus_conn_update_policy(holder_b,
439                                        "com.example.broadcastB",
440                                        &access, 1);
441         ASSERT_RETURN(ret == 0);
442
443         /*
444          * Send broadcasts from an unprivileged connection that
445          * owns a name "com.example.broadcastB".
446          *
447          * We'll have four destinations here:
448          *
449          * 1) destination owner_a: privileged connection that owns
450          * "com.example.broadcastA". It will receive the broadcast
451          * since it is a privileged has default TALK access to all
452          * connections, and it is subscribed to the match.
453          * Will succeed.
454          *
455          * owner_b: privileged connection (running under a different
456          * uid) that do not own names, but with an empty broadcast
457          * match, so it will receive broadcasts since it has default
458          * TALK access to all connection.
459          *
460          * unpriv_a: unpriv connection that do not own any name.
461          * It will receive the broadcast since it is running under
462          * the same user of the one broadcasting and did install
463          * matches. It should get the message.
464          *
465          * unpriv_b: unpriv connection is not interested in broadcast
466          * messages, so it did not install broadcast matches. Should
467          * fail with -ETIMEDOUT
468          */
469
470         ++expected_cookie;
471         efd = eventfd(0, EFD_CLOEXEC);
472         ASSERT_RETURN_VAL(efd >= 0, efd);
473
474         ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({
475                 struct kdbus_conn *unpriv_owner;
476                 struct kdbus_conn *unpriv_a, *unpriv_b;
477
478                 unpriv_owner = kdbus_hello(env->buspath, 0, NULL, 0);
479                 ASSERT_EXIT(unpriv_owner);
480
481                 unpriv_a = kdbus_hello(env->buspath, 0, NULL, 0);
482                 ASSERT_EXIT(unpriv_a);
483
484                 unpriv_b = kdbus_hello(env->buspath, 0, NULL, 0);
485                 ASSERT_EXIT(unpriv_b);
486
487                 ret = kdbus_name_acquire(unpriv_owner,
488                                          "com.example.broadcastB",
489                                          NULL);
490                 ASSERT_EXIT(ret >= 0);
491
492                 ret = kdbus_add_match_empty(unpriv_a);
493                 ASSERT_EXIT(ret == 0);
494
495                 /* Signal that we are doing broadcasts */
496                 ret = eventfd_write(efd, 1);
497                 ASSERT_EXIT(ret == 0);
498
499                 /*
500                  * Do broadcast from a connection that owns the
501                  * names "com.example.broadcastB".
502                  */
503                 ret = kdbus_msg_send(unpriv_owner, NULL,
504                                      expected_cookie,
505                                      0, 0, 0,
506                                      KDBUS_DST_ID_BROADCAST,
507                                      0, NULL);
508                 ASSERT_EXIT(ret == 0);
509
510                 /*
511                  * Unprivileged connection running under the same
512                  * user. It should succeed.
513                  */
514                 ret = kdbus_msg_recv_poll(unpriv_a, 300, &msg, NULL);
515                 ASSERT_EXIT(ret == 0 && msg->cookie == expected_cookie);
516
517                 /*
518                  * Did not install matches, not interested in
519                  * broadcasts
520                  */
521                 ret = kdbus_msg_recv_poll(unpriv_b, 300, NULL, NULL);
522                 ASSERT_EXIT(ret == -ETIMEDOUT);
523         }),
524         ({
525                 ret = eventfd_read(efd, &event_status);
526                 ASSERT_RETURN(ret >= 0 && event_status == 1);
527
528                 /*
529                  * owner_a must fail with -ETIMEDOUT, since it owns
530                  * name "com.example.broadcastA" and its TALK
531                  * access is restriced.
532                  */
533                 ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
534                 ASSERT_RETURN(ret == 0);
535
536                 /* confirm the received cookie */
537                 ASSERT_RETURN(msg->cookie == expected_cookie);
538
539                 kdbus_msg_free(msg);
540
541                 /*
542                  * owner_b got the broadcast from an unprivileged
543                  * connection.
544                  */
545                 ret = kdbus_msg_recv_poll(owner_b, 300, &msg, NULL);
546                 ASSERT_RETURN(ret == 0);
547
548                 /* confirm the received cookie */
549                 ASSERT_RETURN(msg->cookie == expected_cookie);
550
551                 kdbus_msg_free(msg);
552
553         }));
554         ASSERT_RETURN(ret == 0);
555
556         close(efd);
557
558         /*
559          * Test broadcast with two unprivileged connections running
560          * under different users.
561          *
562          * Both connections will fail with -ETIMEDOUT.
563          */
564
565         ret = test_policy_priv_by_broadcast(env->buspath, NULL,
566                                             DROP_OTHER_UNPRIV,
567                                             -ETIMEDOUT, -ETIMEDOUT);
568         ASSERT_RETURN(ret == 0);
569
570         /* Drop received broadcasts by privileged */
571         ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL);
572         ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL);
573         ASSERT_RETURN(ret == 0);
574
575         ret = kdbus_msg_recv(owner_a, NULL, NULL);
576         ASSERT_RETURN(ret == -EAGAIN);
577
578         ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL);
579         ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL);
580         ASSERT_RETURN(ret == 0);
581
582         ret = kdbus_msg_recv(owner_b, NULL, NULL);
583         ASSERT_RETURN(ret == -EAGAIN);
584
585         /*
586          * Perform last tests, allow others to talk to name
587          * "com.example.broadcastA". So now receiving broadcasts
588          * from it should succeed since the TALK policy allow it.
589          */
590
591         /* KDBUS_POLICY_OWN for unprivileged connections */
592         access = (struct kdbus_policy_access){
593                 .type = KDBUS_POLICY_ACCESS_WORLD,
594                 .id = geteuid(),
595                 .access = KDBUS_POLICY_TALK,
596         };
597
598         ret = kdbus_conn_update_policy(holder_a,
599                                        "com.example.broadcastA",
600                                        &access, 1);
601         ASSERT_RETURN(ret == 0);
602
603         /*
604          * Unprivileged is able to TALK to "com.example.broadcastA"
605          * now so it will receive its broadcasts
606          */
607         ret = test_policy_priv_by_broadcast(env->buspath, owner_a,
608                                             DO_NOT_DROP, 0, 0);
609         ASSERT_RETURN(ret == 0);
610
611         ++expected_cookie;
612         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
613                 ret = kdbus_name_acquire(unpriv, "com.example.broadcastB",
614                                          NULL);
615                 ASSERT_EXIT(ret >= 0);
616                 ret = kdbus_msg_send(unpriv, NULL, expected_cookie,
617                                      0, 0, 0, KDBUS_DST_ID_BROADCAST, 0, NULL);
618                 ASSERT_EXIT(ret == 0);
619         }));
620         ASSERT_RETURN(ret == 0);
621
622         /* owner_a is privileged it will get the broadcast now. */
623         ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
624         ASSERT_RETURN(ret == 0);
625
626         /* confirm the received cookie */
627         ASSERT_RETURN(msg->cookie == expected_cookie);
628
629         kdbus_msg_free(msg);
630
631         /*
632          * owner_a released name "com.example.broadcastA". It should
633          * receive broadcasts since it is still privileged and has
634          * the right match.
635          *
636          * Unprivileged connection will own a name and will try to
637          * signal to the privileged connection.
638          */
639
640         ret = kdbus_name_release(owner_a, "com.example.broadcastA");
641         ASSERT_EXIT(ret >= 0);
642
643         ++expected_cookie;
644         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
645                 ret = kdbus_name_acquire(unpriv, "com.example.broadcastB",
646                                          NULL);
647                 ASSERT_EXIT(ret >= 0);
648                 ret = kdbus_msg_send(unpriv, NULL, expected_cookie,
649                                      0, 0, 0, KDBUS_DST_ID_BROADCAST, 0, NULL);
650                 ASSERT_EXIT(ret == 0);
651         }));
652         ASSERT_RETURN(ret == 0);
653
654         /* owner_a will get the broadcast now. */
655         ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
656         ASSERT_RETURN(ret == 0);
657
658         /* confirm the received cookie */
659         ASSERT_RETURN(msg->cookie == expected_cookie);
660
661         kdbus_msg_free(msg);
662
663         kdbus_conn_free(owner_a);
664         kdbus_conn_free(owner_b);
665         kdbus_conn_free(holder_a);
666         kdbus_conn_free(holder_b);
667
668         return 0;
669 }
670
671 static int test_policy_priv(struct kdbus_test_env *env)
672 {
673         struct kdbus_conn *conn_a, *conn_b, *conn, *owner;
674         struct kdbus_policy_access access, *acc;
675         sigset_t sset;
676         size_t num;
677         int ret;
678
679         /*
680          * Make sure we have CAP_SETUID/SETGID so we can drop privileges
681          */
682
683         ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
684         ASSERT_RETURN(ret >= 0);
685
686         if (!ret)
687                 return TEST_SKIP;
688
689         /* make sure that uids and gids are mapped */
690         if (!all_uids_gids_are_mapped())
691                 return TEST_SKIP;
692
693         /*
694          * Setup:
695          *  conn_a: policy holder for com.example.a
696          *  conn_b: name holder of com.example.b
697          */
698
699         signal(SIGUSR1, nosig);
700         sigemptyset(&sset);
701         sigaddset(&sset, SIGUSR1);
702         sigprocmask(SIG_BLOCK, &sset, NULL);
703
704         conn = kdbus_hello(env->buspath, 0, NULL, 0);
705         ASSERT_RETURN(conn);
706
707         /*
708          * Before registering any policy holder, make sure that the
709          * bus is secure by default. This test is necessary, it catches
710          * several cases where old D-Bus was vulnerable.
711          */
712
713         ret = test_priv_before_policy_upload(env);
714         ASSERT_RETURN(ret == 0);
715
716         /*
717          * Make sure unprivileged are not able to register policy
718          * holders
719          */
720
721         ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
722                 struct kdbus_conn *holder;
723
724                 holder = kdbus_hello_registrar(env->buspath,
725                                                "com.example.a", NULL, 0,
726                                                KDBUS_HELLO_POLICY_HOLDER);
727                 ASSERT_EXIT(holder == NULL && errno == EPERM);
728         }),
729         ({ 0; }));
730         ASSERT_RETURN(ret == 0);
731
732
733         /* Register policy holder */
734
735         conn_a = kdbus_hello_registrar(env->buspath, "com.example.a",
736                                        NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
737         ASSERT_RETURN(conn_a);
738
739         conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
740         ASSERT_RETURN(conn_b);
741
742         ret = kdbus_name_acquire(conn_b, "com.example.b", NULL);
743         ASSERT_EXIT(ret >= 0);
744
745         /*
746          * Make sure bus-owners can always acquire names.
747          */
748         ret = kdbus_name_acquire(conn, "com.example.a", NULL);
749         ASSERT_EXIT(ret >= 0);
750
751         kdbus_conn_free(conn);
752
753         /*
754          * Make sure unprivileged users cannot acquire names with default
755          * policy assigned.
756          */
757
758         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
759                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
760                 ASSERT_EXIT(ret < 0);
761         }));
762         ASSERT_RETURN(ret >= 0);
763
764         /*
765          * Make sure unprivileged users can acquire names if we make them
766          * world-accessible.
767          */
768
769         access = (struct kdbus_policy_access){
770                 .type = KDBUS_POLICY_ACCESS_WORLD,
771                 .id = 0,
772                 .access = KDBUS_POLICY_OWN,
773         };
774
775         /*
776          * Make sure unprivileged/normal connections are not able
777          * to update policies
778          */
779
780         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
781                 ret = kdbus_conn_update_policy(unpriv, "com.example.a",
782                                                &access, 1);
783                 ASSERT_EXIT(ret == -EOPNOTSUPP);
784         }));
785         ASSERT_RETURN(ret == 0);
786
787         ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
788         ASSERT_RETURN(ret == 0);
789
790         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
791                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
792                 ASSERT_EXIT(ret >= 0);
793         }));
794         ASSERT_RETURN(ret >= 0);
795
796         /*
797          * Make sure unprivileged users can acquire names if we make them
798          * gid-accessible. But only if the gid matches.
799          */
800
801         access = (struct kdbus_policy_access){
802                 .type = KDBUS_POLICY_ACCESS_GROUP,
803                 .id = UNPRIV_GID,
804                 .access = KDBUS_POLICY_OWN,
805         };
806
807         ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
808         ASSERT_RETURN(ret == 0);
809
810         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
811                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
812                 ASSERT_EXIT(ret >= 0);
813         }));
814         ASSERT_RETURN(ret >= 0);
815
816         access = (struct kdbus_policy_access){
817                 .type = KDBUS_POLICY_ACCESS_GROUP,
818                 .id = 1,
819                 .access = KDBUS_POLICY_OWN,
820         };
821
822         ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
823         ASSERT_RETURN(ret == 0);
824
825         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
826                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
827                 ASSERT_EXIT(ret < 0);
828         }));
829         ASSERT_RETURN(ret >= 0);
830
831         /*
832          * Make sure unprivileged users can acquire names if we make them
833          * uid-accessible. But only if the uid matches.
834          */
835
836         access = (struct kdbus_policy_access){
837                 .type = KDBUS_POLICY_ACCESS_USER,
838                 .id = UNPRIV_UID,
839                 .access = KDBUS_POLICY_OWN,
840         };
841
842         ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
843         ASSERT_RETURN(ret == 0);
844
845         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
846                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
847                 ASSERT_EXIT(ret >= 0);
848         }));
849         ASSERT_RETURN(ret >= 0);
850
851         access = (struct kdbus_policy_access){
852                 .type = KDBUS_POLICY_ACCESS_USER,
853                 .id = 1,
854                 .access = KDBUS_POLICY_OWN,
855         };
856
857         ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
858         ASSERT_RETURN(ret == 0);
859
860         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
861                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
862                 ASSERT_EXIT(ret < 0);
863         }));
864         ASSERT_RETURN(ret >= 0);
865
866         /*
867          * Make sure unprivileged users cannot acquire names if no owner-policy
868          * matches, even if SEE/TALK policies match.
869          */
870
871         num = 4;
872         acc = (struct kdbus_policy_access[]){
873                 {
874                         .type = KDBUS_POLICY_ACCESS_GROUP,
875                         .id = UNPRIV_GID,
876                         .access = KDBUS_POLICY_SEE,
877                 },
878                 {
879                         .type = KDBUS_POLICY_ACCESS_USER,
880                         .id = UNPRIV_UID,
881                         .access = KDBUS_POLICY_TALK,
882                 },
883                 {
884                         .type = KDBUS_POLICY_ACCESS_WORLD,
885                         .id = 0,
886                         .access = KDBUS_POLICY_TALK,
887                 },
888                 {
889                         .type = KDBUS_POLICY_ACCESS_WORLD,
890                         .id = 0,
891                         .access = KDBUS_POLICY_SEE,
892                 },
893         };
894
895         ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num);
896         ASSERT_RETURN(ret == 0);
897
898         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
899                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
900                 ASSERT_EXIT(ret < 0);
901         }));
902         ASSERT_RETURN(ret >= 0);
903
904         /*
905          * Make sure unprivileged users can acquire names if the only matching
906          * policy is somewhere in the middle.
907          */
908
909         num = 5;
910         acc = (struct kdbus_policy_access[]){
911                 {
912                         .type = KDBUS_POLICY_ACCESS_USER,
913                         .id = 1,
914                         .access = KDBUS_POLICY_OWN,
915                 },
916                 {
917                         .type = KDBUS_POLICY_ACCESS_USER,
918                         .id = 2,
919                         .access = KDBUS_POLICY_OWN,
920                 },
921                 {
922                         .type = KDBUS_POLICY_ACCESS_USER,
923                         .id = UNPRIV_UID,
924                         .access = KDBUS_POLICY_OWN,
925                 },
926                 {
927                         .type = KDBUS_POLICY_ACCESS_USER,
928                         .id = 3,
929                         .access = KDBUS_POLICY_OWN,
930                 },
931                 {
932                         .type = KDBUS_POLICY_ACCESS_USER,
933                         .id = 4,
934                         .access = KDBUS_POLICY_OWN,
935                 },
936         };
937
938         ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num);
939         ASSERT_RETURN(ret == 0);
940
941         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
942                 ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
943                 ASSERT_EXIT(ret >= 0);
944         }));
945         ASSERT_RETURN(ret >= 0);
946
947         /*
948          * Clear policies
949          */
950
951         ret = kdbus_conn_update_policy(conn_a, "com.example.a", NULL, 0);
952         ASSERT_RETURN(ret == 0);
953
954         /*
955          * Make sure privileged bus users can _always_ talk to others.
956          */
957
958         conn = kdbus_hello(env->buspath, 0, NULL, 0);
959         ASSERT_RETURN(conn);
960
961         ret = kdbus_msg_send(conn, "com.example.b", 0xdeadbeef, 0, 0, 0, 0,
962                              0, NULL);
963         ASSERT_EXIT(ret >= 0);
964
965         ret = kdbus_msg_recv_poll(conn_b, 300, NULL, NULL);
966         ASSERT_EXIT(ret >= 0);
967
968         kdbus_conn_free(conn);
969
970         /*
971          * Make sure unprivileged bus users cannot talk by default.
972          */
973
974         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
975                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
976                                      0, 0, 0, NULL);
977                 ASSERT_EXIT(ret == -EPERM);
978         }));
979         ASSERT_RETURN(ret >= 0);
980
981         /*
982          * Make sure unprivileged bus users can talk to equals, even without
983          * policy.
984          */
985
986         access = (struct kdbus_policy_access){
987                 .type = KDBUS_POLICY_ACCESS_USER,
988                 .id = UNPRIV_UID,
989                 .access = KDBUS_POLICY_OWN,
990         };
991
992         ret = kdbus_conn_update_policy(conn_a, "com.example.c", &access, 1);
993         ASSERT_RETURN(ret == 0);
994
995         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
996                 struct kdbus_conn *owner;
997
998                 owner = kdbus_hello(env->buspath, 0, NULL, 0);
999                 ASSERT_RETURN(owner);
1000
1001                 ret = kdbus_name_acquire(owner, "com.example.c", NULL);
1002                 ASSERT_EXIT(ret >= 0);
1003
1004                 ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
1005                                      0, 0, 0, NULL);
1006                 ASSERT_EXIT(ret >= 0);
1007                 ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL);
1008                 ASSERT_EXIT(ret >= 0);
1009
1010                 kdbus_conn_free(owner);
1011         }));
1012         ASSERT_RETURN(ret >= 0);
1013
1014         /*
1015          * Make sure unprivileged bus users can talk to privileged users if a
1016          * suitable UID policy is set.
1017          */
1018
1019         access = (struct kdbus_policy_access){
1020                 .type = KDBUS_POLICY_ACCESS_USER,
1021                 .id = UNPRIV_UID,
1022                 .access = KDBUS_POLICY_TALK,
1023         };
1024
1025         ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
1026         ASSERT_RETURN(ret == 0);
1027
1028         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1029                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1030                                      0, 0, 0, NULL);
1031                 ASSERT_EXIT(ret >= 0);
1032         }));
1033         ASSERT_RETURN(ret >= 0);
1034
1035         ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
1036         ASSERT_EXIT(ret >= 0);
1037
1038         /*
1039          * Make sure unprivileged bus users can talk to privileged users if a
1040          * suitable GID policy is set.
1041          */
1042
1043         access = (struct kdbus_policy_access){
1044                 .type = KDBUS_POLICY_ACCESS_GROUP,
1045                 .id = UNPRIV_GID,
1046                 .access = KDBUS_POLICY_TALK,
1047         };
1048
1049         ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
1050         ASSERT_RETURN(ret == 0);
1051
1052         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1053                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1054                                      0, 0, 0, NULL);
1055                 ASSERT_EXIT(ret >= 0);
1056         }));
1057         ASSERT_RETURN(ret >= 0);
1058
1059         ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
1060         ASSERT_EXIT(ret >= 0);
1061
1062         /*
1063          * Make sure unprivileged bus users can talk to privileged users if a
1064          * suitable WORLD policy is set.
1065          */
1066
1067         access = (struct kdbus_policy_access){
1068                 .type = KDBUS_POLICY_ACCESS_WORLD,
1069                 .id = 0,
1070                 .access = KDBUS_POLICY_TALK,
1071         };
1072
1073         ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
1074         ASSERT_RETURN(ret == 0);
1075
1076         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1077                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1078                                      0, 0, 0, NULL);
1079                 ASSERT_EXIT(ret >= 0);
1080         }));
1081         ASSERT_RETURN(ret >= 0);
1082
1083         ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
1084         ASSERT_EXIT(ret >= 0);
1085
1086         /*
1087          * Make sure unprivileged bus users cannot talk to privileged users if
1088          * no suitable policy is set.
1089          */
1090
1091         num = 5;
1092         acc = (struct kdbus_policy_access[]){
1093                 {
1094                         .type = KDBUS_POLICY_ACCESS_USER,
1095                         .id = 0,
1096                         .access = KDBUS_POLICY_OWN,
1097                 },
1098                 {
1099                         .type = KDBUS_POLICY_ACCESS_USER,
1100                         .id = 1,
1101                         .access = KDBUS_POLICY_TALK,
1102                 },
1103                 {
1104                         .type = KDBUS_POLICY_ACCESS_USER,
1105                         .id = UNPRIV_UID,
1106                         .access = KDBUS_POLICY_SEE,
1107                 },
1108                 {
1109                         .type = KDBUS_POLICY_ACCESS_USER,
1110                         .id = 3,
1111                         .access = KDBUS_POLICY_TALK,
1112                 },
1113                 {
1114                         .type = KDBUS_POLICY_ACCESS_USER,
1115                         .id = 4,
1116                         .access = KDBUS_POLICY_TALK,
1117                 },
1118         };
1119
1120         ret = kdbus_conn_update_policy(conn_a, "com.example.b", acc, num);
1121         ASSERT_RETURN(ret == 0);
1122
1123         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1124                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1125                                      0, 0, 0, NULL);
1126                 ASSERT_EXIT(ret == -EPERM);
1127         }));
1128         ASSERT_RETURN(ret >= 0);
1129
1130         /*
1131          * Make sure unprivileged bus users can talk to privileged users if a
1132          * suitable OWN privilege overwrites TALK.
1133          */
1134
1135         access = (struct kdbus_policy_access){
1136                 .type = KDBUS_POLICY_ACCESS_WORLD,
1137                 .id = 0,
1138                 .access = KDBUS_POLICY_OWN,
1139         };
1140
1141         ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
1142         ASSERT_RETURN(ret == 0);
1143
1144         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1145                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1146                                      0, 0, 0, NULL);
1147                 ASSERT_EXIT(ret >= 0);
1148         }));
1149         ASSERT_RETURN(ret >= 0);
1150
1151         ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
1152         ASSERT_EXIT(ret >= 0);
1153
1154         /*
1155          * Make sure the TALK cache is reset correctly when policies are
1156          * updated.
1157          */
1158
1159         access = (struct kdbus_policy_access){
1160                 .type = KDBUS_POLICY_ACCESS_WORLD,
1161                 .id = 0,
1162                 .access = KDBUS_POLICY_TALK,
1163         };
1164
1165         ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
1166         ASSERT_RETURN(ret == 0);
1167
1168         ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
1169                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1170                                      0, 0, 0, NULL);
1171                 ASSERT_EXIT(ret >= 0);
1172
1173                 ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
1174                 ASSERT_EXIT(ret >= 0);
1175
1176                 ret = kdbus_conn_update_policy(conn_a, "com.example.b",
1177                                                NULL, 0);
1178                 ASSERT_RETURN(ret == 0);
1179
1180                 ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
1181                                      0, 0, 0, NULL);
1182                 ASSERT_EXIT(ret == -EPERM);
1183         }));
1184         ASSERT_RETURN(ret >= 0);
1185
1186         /*
1187          * Make sure the TALK cache is reset correctly when policy holders
1188          * disconnect.
1189          */
1190
1191         access = (struct kdbus_policy_access){
1192                 .type = KDBUS_POLICY_ACCESS_WORLD,
1193                 .id = 0,
1194                 .access = KDBUS_POLICY_OWN,
1195         };
1196
1197         conn = kdbus_hello_registrar(env->buspath, "com.example.c",
1198                                      NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
1199         ASSERT_RETURN(conn);
1200
1201         ret = kdbus_conn_update_policy(conn, "com.example.c", &access, 1);
1202         ASSERT_RETURN(ret == 0);
1203
1204         owner = kdbus_hello(env->buspath, 0, NULL, 0);
1205         ASSERT_RETURN(owner);
1206
1207         ret = kdbus_name_acquire(owner, "com.example.c", NULL);
1208         ASSERT_RETURN(ret >= 0);
1209
1210         ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
1211                 struct kdbus_conn *unpriv;
1212
1213                 /* wait for parent to be finished */
1214                 sigemptyset(&sset);
1215                 ret = sigsuspend(&sset);
1216                 ASSERT_RETURN(ret == -1 && errno == EINTR);
1217
1218                 unpriv = kdbus_hello(env->buspath, 0, NULL, 0);
1219                 ASSERT_RETURN(unpriv);
1220
1221                 ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
1222                                      0, 0, 0, NULL);
1223                 ASSERT_EXIT(ret >= 0);
1224
1225                 ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL);
1226                 ASSERT_EXIT(ret >= 0);
1227
1228                 /* free policy holder */
1229                 kdbus_conn_free(conn);
1230
1231                 ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
1232                                      0, 0, 0, NULL);
1233                 ASSERT_EXIT(ret == -EPERM);
1234
1235                 kdbus_conn_free(unpriv);
1236         }), ({
1237                 /* make sure policy holder is only valid in child */
1238                 kdbus_conn_free(conn);
1239                 kill(pid, SIGUSR1);
1240         }));
1241         ASSERT_RETURN(ret >= 0);
1242
1243
1244         /*
1245          * The following tests are necessary.
1246          */
1247
1248         ret = test_broadcast_after_policy_upload(env);
1249         ASSERT_RETURN(ret == 0);
1250
1251         kdbus_conn_free(owner);
1252
1253         /*
1254          * cleanup resources
1255          */
1256
1257         kdbus_conn_free(conn_b);
1258         kdbus_conn_free(conn_a);
1259
1260         return TEST_OK;
1261 }
1262
1263 int kdbus_test_policy_priv(struct kdbus_test_env *env)
1264 {
1265         pid_t pid;
1266         int ret;
1267
1268         /* make sure to exit() if a child returns from fork() */
1269         pid = getpid();
1270         ret = test_policy_priv(env);
1271         if (pid != getpid())
1272                 exit(1);
1273
1274         return ret;
1275 }