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