Line data Source code
1 : /***
2 : This file is part of systemd.
3 :
4 : Copyright 2014 Daniel Mack
5 :
6 : systemd is free software; you can redistribute it and/or modify it
7 : under the terms of the GNU Lesser General Public License as published by
8 : the Free Software Foundation; either version 2.1 of the License, or
9 : (at your option) any later version.
10 :
11 : systemd is distributed in the hope that it will be useful, but
12 : WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public License
17 : along with systemd; If not, see <http://www.gnu.org/licenses/>.
18 : ***/
19 :
20 : #include <stdlib.h>
21 :
22 : #include "kdbus.h"
23 : #include "util.h"
24 : #include "bus-kernel.h"
25 : #include "bus-policy.h"
26 :
27 0 : int bus_kernel_translate_access(BusPolicyAccess access) {
28 0 : assert(access >= 0);
29 0 : assert(access < _BUS_POLICY_ACCESS_MAX);
30 :
31 0 : switch (access) {
32 :
33 : case BUS_POLICY_ACCESS_SEE:
34 0 : return KDBUS_POLICY_SEE;
35 :
36 : case BUS_POLICY_ACCESS_TALK:
37 0 : return KDBUS_POLICY_TALK;
38 :
39 : case BUS_POLICY_ACCESS_OWN:
40 0 : return KDBUS_POLICY_OWN;
41 :
42 : default:
43 0 : assert_not_reached("Unknown policy access");
44 : }
45 : }
46 :
47 0 : int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
48 : int r;
49 :
50 0 : assert(policy);
51 0 : assert(item);
52 :
53 0 : switch (policy->type) {
54 :
55 : case BUSNAME_POLICY_TYPE_USER: {
56 0 : const char *user = policy->name;
57 : uid_t uid;
58 :
59 0 : r = get_user_creds(&user, &uid, NULL, NULL, NULL);
60 0 : if (r < 0)
61 0 : return r;
62 :
63 0 : item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
64 0 : item->policy_access.id = uid;
65 0 : break;
66 : }
67 :
68 : case BUSNAME_POLICY_TYPE_GROUP: {
69 0 : const char *group = policy->name;
70 : gid_t gid;
71 :
72 0 : r = get_group_creds(&group, &gid);
73 0 : if (r < 0)
74 0 : return r;
75 :
76 0 : item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
77 0 : item->policy_access.id = gid;
78 0 : break;
79 : }
80 :
81 : default:
82 0 : assert_not_reached("Unknown policy type");
83 : }
84 :
85 0 : item->policy_access.access = bus_kernel_translate_access(policy->access);
86 :
87 0 : return 0;
88 : }
89 :
90 0 : int bus_kernel_make_starter(
91 : int fd,
92 : const char *name,
93 : bool activating,
94 : bool accept_fd,
95 : BusNamePolicy *policy,
96 : BusPolicyAccess world_policy) {
97 :
98 0 : struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) };
99 : struct kdbus_cmd_hello *hello;
100 : struct kdbus_item *n;
101 0 : size_t policy_cnt = 0;
102 : BusNamePolicy *po;
103 : size_t size;
104 : int r;
105 :
106 0 : assert(fd >= 0);
107 0 : assert(name);
108 :
109 0 : LIST_FOREACH(policy, po, policy)
110 0 : policy_cnt++;
111 :
112 0 : if (world_policy >= 0)
113 0 : policy_cnt++;
114 :
115 0 : size = offsetof(struct kdbus_cmd_hello, items) +
116 0 : ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
117 0 : policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
118 :
119 0 : hello = alloca0_align(size, 8);
120 :
121 0 : n = hello->items;
122 0 : strcpy(n->str, name);
123 0 : n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
124 0 : n->type = KDBUS_ITEM_NAME;
125 0 : n = KDBUS_ITEM_NEXT(n);
126 :
127 0 : LIST_FOREACH(policy, po, policy) {
128 0 : n->type = KDBUS_ITEM_POLICY_ACCESS;
129 0 : n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
130 :
131 0 : r = bus_kernel_translate_policy(po, n);
132 0 : if (r < 0)
133 0 : return r;
134 :
135 0 : n = KDBUS_ITEM_NEXT(n);
136 : }
137 :
138 0 : if (world_policy >= 0) {
139 0 : n->type = KDBUS_ITEM_POLICY_ACCESS;
140 0 : n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
141 0 : n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
142 0 : n->policy_access.access = bus_kernel_translate_access(world_policy);
143 : }
144 :
145 0 : hello->size = size;
146 0 : hello->flags =
147 0 : (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
148 0 : (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
149 0 : hello->pool_size = KDBUS_POOL_SIZE;
150 0 : hello->attach_flags_send = _KDBUS_ATTACH_ANY;
151 0 : hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
152 :
153 0 : if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
154 0 : if (errno == ENOTTY) /* Major API change */
155 0 : return -ESOCKTNOSUPPORT;
156 0 : return -errno;
157 : }
158 :
159 : /* not interested in any output values */
160 0 : cmd_free.offset = hello->offset;
161 0 : (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
162 :
163 : /* The higher 32bit of the bus_flags fields are considered
164 : * 'incompatible flags'. Refuse them all for now. */
165 0 : if (hello->bus_flags > 0xFFFFFFFFULL)
166 0 : return -ESOCKTNOSUPPORT;
167 :
168 0 : return fd;
169 : }
170 :
171 : static const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = {
172 : [BUS_POLICY_ACCESS_SEE] = "see",
173 : [BUS_POLICY_ACCESS_TALK] = "talk",
174 : [BUS_POLICY_ACCESS_OWN] = "own",
175 : };
176 :
177 10 : DEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess);
|