bus-policy.c revision 524d896ac17518b824b2c94b3b0b2a23c23da08f
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers/***
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers This file is part of systemd.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Copyright 2014 Daniel Mack
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is free software; you can redistribute it and/or modify it
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers under the terms of the GNU Lesser General Public License as published by
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers the Free Software Foundation; either version 2.1 of the License, or
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers (at your option) any later version.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers systemd is distributed in the hope that it will be useful, but
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers WITHOUT ANY WARRANTY; without even the implied warranty of
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers Lesser General Public License for more details.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers You should have received a copy of the GNU Lesser General Public License
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers along with systemd; If not, see <http://www.gnu.org/licenses/>.
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers***/
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers#include <stdlib.h>
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include "kdbus.h"
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include "util.h"
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include "bus-kernel.h"
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers#include "bus-policy.h"
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sieversint bus_kernel_translate_access(BusPolicyAccess access) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers assert(access >= 0);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers assert(access < _BUS_POLICY_ACCESS_MAX);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers switch (access) {
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers case BUS_POLICY_ACCESS_SEE:
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return KDBUS_POLICY_SEE;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers case BUS_POLICY_ACCESS_TALK:
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return KDBUS_POLICY_TALK;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers case BUS_POLICY_ACCESS_OWN:
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers return KDBUS_POLICY_OWN;
472780d8b1ec3f3f4ff78eb21a013136e5aa1cfeKay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers default:
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers assert_not_reached("Unknown policy access");
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers }
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers}
0d6ce9236f61cb991d7e8f2359d818e41ead0cf5Kay Sievers
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sieversint bus_kernel_translate_policy(const BusNamePolicy *policy, struct kdbus_item *item) {
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers int r;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers assert(policy);
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers assert(item);
ad37f393fa97f4274cc3bf97a0d8c388a429037eKay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers switch (policy->type) {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers case BUSNAME_POLICY_TYPE_USER: {
de892aea1c486b59e04884268b612081d1660514Kay Sievers const char *user = policy->name;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers uid_t uid;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers r = get_user_creds(&user, &uid, NULL, NULL, NULL);
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers if (r < 0)
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers return r;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers item->policy_access.type = KDBUS_POLICY_ACCESS_USER;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers item->policy_access.id = uid;
decd634e801bee2c554edb35383cc9d43417a850Kay Sievers break;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers }
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers case BUSNAME_POLICY_TYPE_GROUP: {
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers const char *group = policy->name;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers gid_t gid;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers r = get_group_creds(&group, &gid);
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers if (r < 0)
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers return r;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers item->policy_access.type = KDBUS_POLICY_ACCESS_GROUP;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers item->policy_access.id = gid;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers break;
f610d6de38119b372b377ec41b2a6089872d3294Kay Sievers }
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers default:
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers assert_not_reached("Unknown policy type");
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers }
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers item->policy_access.access = bus_kernel_translate_access(policy->access);
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers return 0;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers}
de892aea1c486b59e04884268b612081d1660514Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sieversint bus_kernel_make_starter(
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers int fd,
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers const char *name,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers bool activating,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers bool accept_fd,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers BusNamePolicy *policy,
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers BusPolicyAccess world_policy) {
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers struct kdbus_cmd_free cmd_free = { .size = sizeof(cmd_free) };
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers struct kdbus_cmd_hello *hello;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers struct kdbus_item *n;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers size_t policy_cnt = 0;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers BusNamePolicy *po;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers size_t size;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers int r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert(fd >= 0);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers assert(name);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers LIST_FOREACH(policy, po, policy)
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers policy_cnt++;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (world_policy >= 0)
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers policy_cnt++;
984c4348ff14d29c526d3d372daa82e278eeb5b4Kay Sievers
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers size = offsetof(struct kdbus_cmd_hello, items) +
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers ALIGN8(offsetof(struct kdbus_item, str) + strlen(name) + 1) +
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers policy_cnt * ALIGN8(offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access));
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers hello = alloca0_align(size, 8);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
a660c63c551b88136ac6176855b5907cc533e848Kay Sievers n = hello->items;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers strcpy(n->str, name);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
01d183ddae6fb3445c4519cf1d90c6575f17292eKay Sievers n->type = KDBUS_ITEM_NAME;
01d183ddae6fb3445c4519cf1d90c6575f17292eKay Sievers n = KDBUS_ITEM_NEXT(n);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers LIST_FOREACH(policy, po, policy) {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers n->type = KDBUS_ITEM_POLICY_ACCESS;
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers r = bus_kernel_translate_policy(po, n);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers if (r < 0)
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers return r;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers n = KDBUS_ITEM_NEXT(n);
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers }
d23965a64eb5c2c97b839dc2e3e79fc1613994f1Kay Sievers
137661d87525a3c339afd2804e577532d58d3fbcKay Sievers if (world_policy >= 0) {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers n->type = KDBUS_ITEM_POLICY_ACCESS;
de892aea1c486b59e04884268b612081d1660514Kay Sievers n->size = offsetof(struct kdbus_item, policy_access) + sizeof(struct kdbus_policy_access);
3c123e0899b56c0587db36420da5e049c56d9e19Lukas Nykryn n->policy_access.type = KDBUS_POLICY_ACCESS_WORLD;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers n->policy_access.access = bus_kernel_translate_access(world_policy);
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers }
de892aea1c486b59e04884268b612081d1660514Kay Sievers
de892aea1c486b59e04884268b612081d1660514Kay Sievers hello->size = size;
de892aea1c486b59e04884268b612081d1660514Kay Sievers hello->flags =
de892aea1c486b59e04884268b612081d1660514Kay Sievers (activating ? KDBUS_HELLO_ACTIVATOR : KDBUS_HELLO_POLICY_HOLDER) |
de892aea1c486b59e04884268b612081d1660514Kay Sievers (accept_fd ? KDBUS_HELLO_ACCEPT_FD : 0);
de892aea1c486b59e04884268b612081d1660514Kay Sievers hello->pool_size = KDBUS_POOL_SIZE;
de892aea1c486b59e04884268b612081d1660514Kay Sievers hello->attach_flags_send = _KDBUS_ATTACH_ANY;
de892aea1c486b59e04884268b612081d1660514Kay Sievers hello->attach_flags_recv = _KDBUS_ATTACH_ANY;
de892aea1c486b59e04884268b612081d1660514Kay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (ioctl(fd, KDBUS_CMD_HELLO, hello) < 0) {
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers if (errno == ENOTTY) /* Major API change */
de892aea1c486b59e04884268b612081d1660514Kay Sievers return -ESOCKTNOSUPPORT;
3c123e0899b56c0587db36420da5e049c56d9e19Lukas Nykryn return -errno;
3c123e0899b56c0587db36420da5e049c56d9e19Lukas Nykryn }
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
de892aea1c486b59e04884268b612081d1660514Kay Sievers /* not interested in any output values */
de892aea1c486b59e04884268b612081d1660514Kay Sievers cmd_free.offset = hello->offset;
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers (void) ioctl(fd, KDBUS_CMD_FREE, &cmd_free);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers /* The higher 32bit of the bus_flags fields are considered
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers * 'incompatible flags'. Refuse them all for now. */
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers if (hello->bus_flags > 0xFFFFFFFFULL)
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return -ESOCKTNOSUPPORT;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers return fd;
1328f66ad16b5afeb5684858c27e121a46c1959eKay Sievers}
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sieversstatic const char* const bus_policy_access_table[_BUS_POLICY_ACCESS_MAX] = {
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers [BUS_POLICY_ACCESS_SEE] = "see",
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers [BUS_POLICY_ACCESS_TALK] = "talk",
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers [BUS_POLICY_ACCESS_OWN] = "own",
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers};
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay Sievers
0035597a30d120f70df2dd7da3d6128fb8ba6051Kay SieversDEFINE_STRING_TABLE_LOOKUP(bus_policy_access, BusPolicyAccess);
0260944060426d54d9ecb40930baad985cbd02a1Kay Sievers