From 6d461a4fe7896faa1aec5a5417888cf179e46b9f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Fabian=20Silva=20Delgado?= Date: Mon, 22 Feb 2016 01:12:47 -0300 Subject: Linux-libre 4.4.2-gnu --- ipc/kdbus/policy.c | 489 ----------------------------------------------------- 1 file changed, 489 deletions(-) delete mode 100644 ipc/kdbus/policy.c (limited to 'ipc/kdbus/policy.c') diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c deleted file mode 100644 index f2618e15e..000000000 --- a/ipc/kdbus/policy.c +++ /dev/null @@ -1,489 +0,0 @@ -/* - * Copyright (C) 2013-2015 Kay Sievers - * Copyright (C) 2013-2015 Greg Kroah-Hartman - * Copyright (C) 2013-2015 Daniel Mack - * Copyright (C) 2013-2015 David Herrmann - * Copyright (C) 2013-2015 Linux Foundation - * Copyright (C) 2014-2015 Djalal Harouni - * - * kdbus is free software; you can redistribute it and/or modify it under - * the terms of the GNU Lesser General Public License as published by the - * Free Software Foundation; either version 2.1 of the License, or (at - * your option) any later version. - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "bus.h" -#include "connection.h" -#include "domain.h" -#include "item.h" -#include "names.h" -#include "policy.h" - -#define KDBUS_POLICY_HASH_SIZE 64 - -/** - * struct kdbus_policy_db_entry_access - a database entry access item - * @type: One of KDBUS_POLICY_ACCESS_* types - * @access: Access to grant. One of KDBUS_POLICY_* - * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid - * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid - * @list: List entry item for the entry's list - * - * This is the internal version of struct kdbus_policy_db_access. - */ -struct kdbus_policy_db_entry_access { - u8 type; /* USER, GROUP, WORLD */ - u8 access; /* OWN, TALK, SEE */ - union { - kuid_t uid; /* global uid */ - kgid_t gid; /* global gid */ - }; - struct list_head list; -}; - -/** - * struct kdbus_policy_db_entry - a policy database entry - * @name: The name to match the policy entry against - * @hentry: The hash entry for the database's entries_hash - * @access_list: List head for keeping tracks of the entry's - * access items. - * @owner: The owner of this entry. Can be a kdbus_conn or - * a kdbus_ep object. - * @wildcard: The name is a wildcard, such as ending on '.*' - */ -struct kdbus_policy_db_entry { - char *name; - struct hlist_node hentry; - struct list_head access_list; - const void *owner; - bool wildcard:1; -}; - -static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e) -{ - struct kdbus_policy_db_entry_access *a, *tmp; - - list_for_each_entry_safe(a, tmp, &e->access_list, list) { - list_del(&a->list); - kfree(a); - } - - kfree(e->name); - kfree(e); -} - -static unsigned int kdbus_strnhash(const char *str, size_t len) -{ - unsigned long hash = init_name_hash(); - - while (len--) - hash = partial_name_hash(*str++, hash); - - return end_name_hash(hash); -} - -static const struct kdbus_policy_db_entry * -kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash) -{ - struct kdbus_policy_db_entry *e; - const char *dot; - size_t len; - - /* find exact match */ - hash_for_each_possible(db->entries_hash, e, hentry, hash) - if (strcmp(e->name, name) == 0 && !e->wildcard) - return e; - - /* find wildcard match */ - - dot = strrchr(name, '.'); - if (!dot) - return NULL; - - len = dot - name; - hash = kdbus_strnhash(name, len); - - hash_for_each_possible(db->entries_hash, e, hentry, hash) - if (e->wildcard && !strncmp(e->name, name, len) && - !e->name[len]) - return e; - - return NULL; -} - -/** - * kdbus_policy_db_clear - release all memory from a policy db - * @db: The policy database - */ -void kdbus_policy_db_clear(struct kdbus_policy_db *db) -{ - struct kdbus_policy_db_entry *e; - struct hlist_node *tmp; - unsigned int i; - - /* purge entries */ - down_write(&db->entries_rwlock); - hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) { - hash_del(&e->hentry); - kdbus_policy_entry_free(e); - } - up_write(&db->entries_rwlock); -} - -/** - * kdbus_policy_db_init() - initialize a new policy database - * @db: The location of the database - * - * This initializes a new policy-db. The underlying memory must have been - * cleared to zero by the caller. - */ -void kdbus_policy_db_init(struct kdbus_policy_db *db) -{ - hash_init(db->entries_hash); - init_rwsem(&db->entries_rwlock); -} - -/** - * kdbus_policy_query_unlocked() - Query the policy database - * @db: Policy database - * @cred: Credentials to test against - * @name: Name to query - * @hash: Hash value of @name - * - * Same as kdbus_policy_query() but requires the caller to lock the policy - * database against concurrent writes. - * - * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. - */ -int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, - const struct cred *cred, const char *name, - unsigned int hash) -{ - struct kdbus_policy_db_entry_access *a; - const struct kdbus_policy_db_entry *e; - int i, highest = -EPERM; - - e = kdbus_policy_lookup(db, name, hash); - if (!e) - return -EPERM; - - list_for_each_entry(a, &e->access_list, list) { - if ((int)a->access <= highest) - continue; - - switch (a->type) { - case KDBUS_POLICY_ACCESS_USER: - if (uid_eq(cred->euid, a->uid)) - highest = a->access; - break; - case KDBUS_POLICY_ACCESS_GROUP: - if (gid_eq(cred->egid, a->gid)) { - highest = a->access; - break; - } - - for (i = 0; i < cred->group_info->ngroups; i++) { - kgid_t gid = GROUP_AT(cred->group_info, i); - - if (gid_eq(gid, a->gid)) { - highest = a->access; - break; - } - } - - break; - case KDBUS_POLICY_ACCESS_WORLD: - highest = a->access; - break; - } - - /* OWN is the highest possible policy */ - if (highest >= KDBUS_POLICY_OWN) - break; - } - - return highest; -} - -/** - * kdbus_policy_query() - Query the policy database - * @db: Policy database - * @cred: Credentials to test against - * @name: Name to query - * @hash: Hash value of @name - * - * Query the policy database @db for the access rights of @cred to the name - * @name. The access rights of @cred are returned, or -EPERM if no access is - * granted. - * - * This call effectively searches for the highest access-right granted to - * @cred. The caller should really cache those as policy lookups are rather - * expensive. - * - * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none. - */ -int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, - const char *name, unsigned int hash) -{ - int ret; - - down_read(&db->entries_rwlock); - ret = kdbus_policy_query_unlocked(db, cred, name, hash); - up_read(&db->entries_rwlock); - - return ret; -} - -static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db, - const void *owner) -{ - struct kdbus_policy_db_entry *e; - struct hlist_node *tmp; - int i; - - hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) - if (e->owner == owner) { - hash_del(&e->hentry); - kdbus_policy_entry_free(e); - } -} - -/** - * kdbus_policy_remove_owner() - remove all entries related to a connection - * @db: The policy database - * @owner: The connection which items to remove - */ -void kdbus_policy_remove_owner(struct kdbus_policy_db *db, - const void *owner) -{ - down_write(&db->entries_rwlock); - __kdbus_policy_remove_owner(db, owner); - up_write(&db->entries_rwlock); -} - -/* - * Convert user provided policy access to internal kdbus policy - * access - */ -static struct kdbus_policy_db_entry_access * -kdbus_policy_make_access(const struct kdbus_policy_access *uaccess) -{ - int ret; - struct kdbus_policy_db_entry_access *a; - - a = kzalloc(sizeof(*a), GFP_KERNEL); - if (!a) - return ERR_PTR(-ENOMEM); - - ret = -EINVAL; - switch (uaccess->access) { - case KDBUS_POLICY_SEE: - case KDBUS_POLICY_TALK: - case KDBUS_POLICY_OWN: - a->access = uaccess->access; - break; - default: - goto err; - } - - switch (uaccess->type) { - case KDBUS_POLICY_ACCESS_USER: - a->uid = make_kuid(current_user_ns(), uaccess->id); - if (!uid_valid(a->uid)) - goto err; - - break; - case KDBUS_POLICY_ACCESS_GROUP: - a->gid = make_kgid(current_user_ns(), uaccess->id); - if (!gid_valid(a->gid)) - goto err; - - break; - case KDBUS_POLICY_ACCESS_WORLD: - break; - default: - goto err; - } - - a->type = uaccess->type; - - return a; - -err: - kfree(a); - return ERR_PTR(ret); -} - -/** - * kdbus_policy_set() - set a connection's policy rules - * @db: The policy database - * @items: A list of kdbus_item elements that contain both - * names and access rules to set. - * @items_size: The total size of the items. - * @max_policies: The maximum number of policy entries to allow. - * Pass 0 for no limit. - * @allow_wildcards: Boolean value whether wildcard entries (such - * ending on '.*') should be allowed. - * @owner: The owner of the new policy items. - * - * This function sets a new set of policies for a given owner. The names and - * access rules are gathered by walking the list of items passed in as - * argument. An item of type KDBUS_ITEM_NAME is expected before any number of - * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this - * pattern than denoted in @max_policies, -EINVAL is returned. - * - * In order to allow atomic replacement of rules, the function first removes - * all entries that have been created for the given owner previously. - * - * Callers to this function must make sure that the owner is a custom - * endpoint, or if the endpoint is a default endpoint, then it must be - * either a policy holder or an activator. - * - * Return: 0 on success, negative errno on failure. - */ -int kdbus_policy_set(struct kdbus_policy_db *db, - const struct kdbus_item *items, - size_t items_size, - size_t max_policies, - bool allow_wildcards, - const void *owner) -{ - struct kdbus_policy_db_entry_access *a; - struct kdbus_policy_db_entry *e, *p; - const struct kdbus_item *item; - struct hlist_node *tmp; - HLIST_HEAD(entries); - HLIST_HEAD(restore); - size_t count = 0; - int i, ret = 0; - u32 hash; - - /* Walk the list of items and look for new policies */ - e = NULL; - KDBUS_ITEMS_FOREACH(item, items, items_size) { - switch (item->type) { - case KDBUS_ITEM_NAME: { - size_t len; - - if (max_policies && ++count > max_policies) { - ret = -E2BIG; - goto exit; - } - - if (!kdbus_name_is_valid(item->str, true)) { - ret = -EINVAL; - goto exit; - } - - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) { - ret = -ENOMEM; - goto exit; - } - - INIT_LIST_HEAD(&e->access_list); - e->owner = owner; - hlist_add_head(&e->hentry, &entries); - - e->name = kstrdup(item->str, GFP_KERNEL); - if (!e->name) { - ret = -ENOMEM; - goto exit; - } - - /* - * If a supplied name ends with an '.*', cut off that - * part, only store anything before it, and mark the - * entry as wildcard. - */ - len = strlen(e->name); - if (len > 2 && - e->name[len - 3] == '.' && - e->name[len - 2] == '*') { - if (!allow_wildcards) { - ret = -EINVAL; - goto exit; - } - - e->name[len - 3] = '\0'; - e->wildcard = true; - } - - break; - } - - case KDBUS_ITEM_POLICY_ACCESS: - if (!e) { - ret = -EINVAL; - goto exit; - } - - a = kdbus_policy_make_access(&item->policy_access); - if (IS_ERR(a)) { - ret = PTR_ERR(a); - goto exit; - } - - list_add_tail(&a->list, &e->access_list); - break; - } - } - - down_write(&db->entries_rwlock); - - /* remember previous entries to restore in case of failure */ - hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) - if (e->owner == owner) { - hash_del(&e->hentry); - hlist_add_head(&e->hentry, &restore); - } - - hlist_for_each_entry_safe(e, tmp, &entries, hentry) { - /* prevent duplicates */ - hash = kdbus_strhash(e->name); - hash_for_each_possible(db->entries_hash, p, hentry, hash) - if (strcmp(e->name, p->name) == 0 && - e->wildcard == p->wildcard) { - ret = -EEXIST; - goto restore; - } - - hlist_del(&e->hentry); - hash_add(db->entries_hash, &e->hentry, hash); - } - -restore: - /* if we failed, flush all entries we added so far */ - if (ret < 0) - __kdbus_policy_remove_owner(db, owner); - - /* if we failed, restore entries, otherwise release them */ - hlist_for_each_entry_safe(e, tmp, &restore, hentry) { - hlist_del(&e->hentry); - if (ret < 0) { - hash = kdbus_strhash(e->name); - hash_add(db->entries_hash, &e->hentry, hash); - } else { - kdbus_policy_entry_free(e); - } - } - - up_write(&db->entries_rwlock); - -exit: - hlist_for_each_entry_safe(e, tmp, &entries, hentry) { - hlist_del(&e->hentry); - kdbus_policy_entry_free(e); - } - - return ret; -} -- cgit v1.2.3