]> git.ipfire.org Git - thirdparty/systemd.git/blob - src/core/bus-policy.c
util-lib: split out allocation calls into alloc-util.[ch]
[thirdparty/systemd.git] / src / core / bus-policy.c
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 "alloc-util.h"
23 #include "bus-kernel.h"
24 #include "bus-policy.h"
25 #include "kdbus.h"
26 #include "string-table.h"
27 #include "user-util.h"
28 #include "util.h"
29
30 int bus_kernel_translate_access(BusPolicyAccess access) {
31 assert(access >= 0);
32 assert(access < _BUS_POLICY_ACCESS_MAX);
33
34 switch (access) {
35
36 case BUS_POLICY_ACCESS_SEE:
37 return KDBUS_POLICY_SEE;
38
39 case BUS_POLICY_ACCESS_TALK:
40 return KDBUS_POLICY_TALK;
41
42 case BUS_POLICY_ACCESS_OWN:
43 return KDBUS_POLICY_OWN;
44
45 default:
46 assert_not_reached("Unknown policy access");
47 }
48 }
49
50 int bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
51 int r;
52
53 assert(policy);
54 assert(item);
55
56 switch (policy->type) {
57
58 case BUSNAME_POLICY_TYPE_USER: {
59 const char *user = policy->name;
60 uid_t uid;
61
62 r = get_user_creds(&user, &uid, NULL, NULL, NULL);
63 if (r < 0)
64 return r;
65
66 item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
67 item->policy_access.id = uid;
68 break;
69 }
70
71 case BUSNAME_POLICY_TYPE_GROUP: {
72 const char *group = policy->name;
73 gid_t gid;
74
75 r = get_group_creds(&group, &gid);
76 if (r < 0)
77 return r;
78
79 item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
80 item->policy_access.id = gid;
81 break;
82 }
83
84 default:
85 assert_not_reached("Unknown policy type");
86 }
87
88 item->policy_access.access = bus_kernel_translate_access(policy->access);
89
90 return 0;
91 }
92
93 int bus_kernel_make_starter(
94 int fd,
95 const char *name,
96 bool activating,
97 bool accept_fd,
98 BusNamePolicy *policy,
99 BusPolicyAccess world_policy) {
100
101 struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) };
102 struct kdbus_cmd_hello *hello;
103 struct kdbus_item *n;
104 size_t policy_cnt = 0;
105 BusNamePolicy *po;
106 size_t size;
107 int r;
108
109 assert(fd >= 0);
110 assert(name);
111
112 LIST_FOREACH(policy, po, policy)
113 policy_cnt++;
114
115 if (world_policy >= 0)
116 policy_cnt++;
117
118 size = offsetof(struct kdbus_cmd_hello, items) +
119 ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
120 policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
121
122 hello = alloca0_align(size, 8);
123
124 n = hello->items;
125 strcpy(n->str, name);
126 n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
127 n->type = KDBUS_ITEM_NAME;
128 n = KDBUS_ITEM_NEXT(n);
129
130 LIST_FOREACH(policy, po, policy) {
131 n->type = KDBUS_ITEM_POLICY_ACCESS;
132 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
133
134 r = bus_kernel_translate_policy(po, n);
135 if (r < 0)
136 return r;
137
138 n = KDBUS_ITEM_NEXT(n);
139 }
140
141 if (world_policy >= 0) {
142 n->type = KDBUS_ITEM_POLICY_ACCESS;
143 n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
144 n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
145 n->policy_access.access = bus_kernel_translate_access(world_policy);
146 }
147
148 hello->size = size;
149 hello->flags =
150 (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
151 (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
152 hello->pool_size = KDBUS_POOL_SIZE;
153 hello->attach_flags_send = _KDBUS_ATTACH_ANY;
154 hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
155
156 if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
157 if (errno == ENOTTY) /* Major API change */
158 return -ESOCKTNOSUPPORT;
159 return -errno;
160 }
161
162 /* not interested in any output values */
163 cmd_free.offset = hello->offset;
164 (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
165
166 /* The higher 32bit of the bus_flags fields are considered
167 * 'incompatible flags'. Refuse them all for now. */
168 if (hello->bus_flags > 0xFFFFFFFFULL)
169 return -ESOCKTNOSUPPORT;
170
171 return fd;
172 }
173
174 static const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = {
175 [BUS_POLICY_ACCESS_SEE] = "see",
176 [BUS_POLICY_ACCESS_TALK] = "talk",
177 [BUS_POLICY_ACCESS_OWN] = "own",
178 };
179
180 DEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess);