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 "bus-kernel.h"
24 : #include "bus-policy.h"
25 : #include "bus-endpoint.h"
26 :
27 0 : int bus_kernel_set_endpoint_policy(int fd, uid_t uid, BusEndpoint *ep) {
28 :
29 : struct kdbus_cmd *update;
30 : struct kdbus_item *n;
31 : BusEndpointPolicy *po;
32 : Iterator i;
33 : size_t size;
34 : int r;
35 :
36 0 : size = ALIGN8(offsetof(struct kdbus_cmd, items));
37 :
38 0 : HASHMAP_FOREACH(po, ep->policy_hash, i) {
39 0 : size += ALIGN8(offsetof(struct kdbus_item, str) + strlen(po->name) + 1);
40 0 : size += ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
41 : }
42 :
43 0 : update = alloca0_align(size, 8);
44 0 : update->size = size;
45 :
46 0 : n = update->items;
47 :
48 0 : HASHMAP_FOREACH(po, ep->policy_hash, i) {
49 0 : n->type = KDBUS_ITEM_NAME;
50 0 : n->size = offsetof(struct kdbus_item, str) + strlen(po->name) + 1;
51 0 : strcpy(n->str, po->name);
52 0 : n = KDBUS_ITEM_NEXT(n);
53 :
54 0 : n->type = KDBUS_ITEM_POLICY_ACCESS;
55 0 : n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
56 :
57 0 : n->policy_access.type = KDBUS_POLICY_ACCESS_USER;
58 0 : n->policy_access.access = bus_kernel_translate_access(po->access);
59 0 : n->policy_access.id = uid;
60 :
61 0 : n = KDBUS_ITEM_NEXT(n);
62 : }
63 :
64 0 : r = ioctl(fd, KDBUS_CMD_ENDPOINT_UPDATE, update);
65 0 : if (r < 0)
66 0 : return -errno;
67 :
68 0 : return 0;
69 : }
70 :
71 0 : int bus_endpoint_new(BusEndpoint **ep) {
72 0 : assert(ep);
73 :
74 0 : *ep = new0(BusEndpoint, 1);
75 0 : if (!*ep)
76 0 : return -ENOMEM;
77 :
78 0 : return 0;
79 : }
80 :
81 0 : int bus_endpoint_add_policy(BusEndpoint *ep, const char *name, BusPolicyAccess access) {
82 0 : _cleanup_free_ BusEndpointPolicy *po = NULL;
83 0 : _cleanup_free_ char *key = NULL;
84 : int r;
85 :
86 0 : assert(ep);
87 0 : assert(name);
88 0 : assert(access > _BUS_POLICY_ACCESS_INVALID && access < _BUS_POLICY_ACCESS_MAX);
89 :
90 : /* check if we already have this name in the policy list. If we do, see if the new access level
91 : * is higher than the exising one, and upgrade the entry in that case. Otherwise, do nothing.
92 : */
93 :
94 0 : if (ep->policy_hash) {
95 0 : po = hashmap_get(ep->policy_hash, name);
96 0 : if (po) {
97 0 : if (po->access < access)
98 0 : po->access = access;
99 :
100 0 : return 0;
101 : }
102 : } else {
103 0 : ep->policy_hash = hashmap_new(&string_hash_ops);
104 0 : if (!ep->policy_hash)
105 0 : return -ENOMEM;
106 : }
107 :
108 0 : po = new0(BusEndpointPolicy, 1);
109 0 : if (!po)
110 0 : return -ENOMEM;
111 :
112 0 : key = strdup(name);
113 0 : if (!key)
114 0 : return -ENOMEM;
115 :
116 0 : po->name = key;
117 0 : po->access = access;
118 :
119 0 : r = hashmap_put(ep->policy_hash, key, po);
120 0 : if (r < 0)
121 0 : return r;
122 :
123 0 : po = NULL;
124 0 : key = NULL;
125 0 : return 0;
126 : }
127 :
128 115 : void bus_endpoint_free(BusEndpoint *endpoint) {
129 115 : if (!endpoint)
130 115 : return;
131 :
132 0 : hashmap_free_free_free(endpoint->policy_hash);
133 0 : free(endpoint);
134 : }
|