diff options
Diffstat (limited to 'ipc/kdbus/endpoint.c')
-rw-r--r-- | ipc/kdbus/endpoint.c | 303 |
1 files changed, 0 insertions, 303 deletions
diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c deleted file mode 100644 index 5694ff6dc..000000000 --- a/ipc/kdbus/endpoint.c +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright (C) 2013-2015 Kay Sievers - * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org> - * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org> - * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com> - * Copyright (C) 2013-2015 Linux Foundation - * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org> - * - * 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 <linux/fs.h> -#include <linux/idr.h> -#include <linux/init.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/sizes.h> -#include <linux/slab.h> -#include <linux/uaccess.h> -#include <linux/uio.h> - -#include "bus.h" -#include "connection.h" -#include "domain.h" -#include "endpoint.h" -#include "handle.h" -#include "item.h" -#include "message.h" -#include "policy.h" - -static void kdbus_ep_free(struct kdbus_node *node) -{ - struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); - - WARN_ON(!list_empty(&ep->conn_list)); - - kdbus_policy_db_clear(&ep->policy_db); - kdbus_bus_unref(ep->bus); - kdbus_user_unref(ep->user); - kfree(ep); -} - -static void kdbus_ep_release(struct kdbus_node *node, bool was_active) -{ - struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); - - /* disconnect all connections to this endpoint */ - for (;;) { - struct kdbus_conn *conn; - - mutex_lock(&ep->lock); - conn = list_first_entry_or_null(&ep->conn_list, - struct kdbus_conn, - ep_entry); - if (!conn) { - mutex_unlock(&ep->lock); - break; - } - - /* take reference, release lock, disconnect without lock */ - kdbus_conn_ref(conn); - mutex_unlock(&ep->lock); - - kdbus_conn_disconnect(conn, false); - kdbus_conn_unref(conn); - } -} - -/** - * kdbus_ep_new() - create a new endpoint - * @bus: The bus this endpoint will be created for - * @name: The name of the endpoint - * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*) - * @uid: The uid of the node - * @gid: The gid of the node - * @is_custom: Whether this is a custom endpoint - * - * This function will create a new endpoint with the given - * name and properties for a given bus. - * - * Return: a new kdbus_ep on success, ERR_PTR on failure. - */ -struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, - unsigned int access, kuid_t uid, kgid_t gid, - bool is_custom) -{ - struct kdbus_ep *e; - int ret; - - /* - * Validate only custom endpoints names, default endpoints - * with a "bus" name are created when the bus is created - */ - if (is_custom) { - ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, - uid); - if (ret < 0) - return ERR_PTR(ret); - } - - e = kzalloc(sizeof(*e), GFP_KERNEL); - if (!e) - return ERR_PTR(-ENOMEM); - - kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT); - - e->node.free_cb = kdbus_ep_free; - e->node.release_cb = kdbus_ep_release; - e->node.uid = uid; - e->node.gid = gid; - e->node.mode = S_IRUSR | S_IWUSR; - if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) - e->node.mode |= S_IRGRP | S_IWGRP; - if (access & KDBUS_MAKE_ACCESS_WORLD) - e->node.mode |= S_IROTH | S_IWOTH; - - mutex_init(&e->lock); - INIT_LIST_HEAD(&e->conn_list); - kdbus_policy_db_init(&e->policy_db); - e->bus = kdbus_bus_ref(bus); - - ret = kdbus_node_link(&e->node, &bus->node, name); - if (ret < 0) - goto exit_unref; - - /* - * Transactions on custom endpoints are never accounted on the global - * user limits. Instead, for each custom endpoint, we create a custom, - * unique user, which all transactions are accounted on. Regardless of - * the user using that endpoint, it is always accounted on the same - * user-object. This budget is not shared with ordinary users on - * non-custom endpoints. - */ - if (is_custom) { - e->user = kdbus_user_lookup(bus->domain, INVALID_UID); - if (IS_ERR(e->user)) { - ret = PTR_ERR(e->user); - e->user = NULL; - goto exit_unref; - } - } - - return e; - -exit_unref: - kdbus_node_drain(&e->node); - kdbus_node_unref(&e->node); - return ERR_PTR(ret); -} - -/** - * kdbus_ep_ref() - increase the reference counter of a kdbus_ep - * @ep: The endpoint to reference - * - * Every user of an endpoint, except for its creator, must add a reference to - * the kdbus_ep instance using this function. - * - * Return: the ep itself - */ -struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) -{ - if (ep) - kdbus_node_ref(&ep->node); - return ep; -} - -/** - * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep - * @ep: The ep to unref - * - * Release a reference. If the reference count drops to 0, the ep will be - * freed. - * - * Return: NULL - */ -struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep) -{ - if (ep) - kdbus_node_unref(&ep->node); - return NULL; -} - -/** - * kdbus_ep_is_privileged() - check whether a file is privileged - * @ep: endpoint to operate on - * @file: file to test - * - * Return: True if @file is privileged in the domain of @ep. - */ -bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file) -{ - return !ep->user && - file_ns_capable(file, ep->bus->domain->user_namespace, - CAP_IPC_OWNER); -} - -/** - * kdbus_ep_is_owner() - check whether a file should be treated as bus owner - * @ep: endpoint to operate on - * @file: file to test - * - * Return: True if @file should be treated as bus owner on @ep - */ -bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file) -{ - return !ep->user && - (uid_eq(file->f_cred->euid, ep->bus->node.uid) || - kdbus_ep_is_privileged(ep, file)); -} - -/** - * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE - * @bus: bus to operate on - * @argp: command payload - * - * Return: NULL or newly created endpoint on success, ERR_PTR on failure. - */ -struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp) -{ - const char *item_make_name; - struct kdbus_ep *ep = NULL; - struct kdbus_cmd *cmd; - int ret; - - struct kdbus_arg argv[] = { - { .type = KDBUS_ITEM_NEGOTIATE }, - { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, - }; - struct kdbus_args args = { - .allowed_flags = KDBUS_FLAG_NEGOTIATE | - KDBUS_MAKE_ACCESS_GROUP | - KDBUS_MAKE_ACCESS_WORLD, - .argv = argv, - .argc = ARRAY_SIZE(argv), - }; - - ret = kdbus_args_parse(&args, argp, &cmd); - if (ret < 0) - return ERR_PTR(ret); - if (ret > 0) - return NULL; - - item_make_name = argv[1].item->str; - - ep = kdbus_ep_new(bus, item_make_name, cmd->flags, - current_euid(), current_egid(), true); - if (IS_ERR(ep)) { - ret = PTR_ERR(ep); - ep = NULL; - goto exit; - } - - if (!kdbus_node_activate(&ep->node)) { - ret = -ESHUTDOWN; - goto exit; - } - -exit: - ret = kdbus_args_clear(&args, ret); - if (ret < 0) { - if (ep) { - kdbus_node_drain(&ep->node); - kdbus_ep_unref(ep); - } - return ERR_PTR(ret); - } - return ep; -} - -/** - * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE - * @ep: endpoint to operate on - * @argp: command payload - * - * Return: >=0 on success, negative error code on failure. - */ -int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp) -{ - struct kdbus_cmd *cmd; - int ret; - - struct kdbus_arg argv[] = { - { .type = KDBUS_ITEM_NEGOTIATE }, - { .type = KDBUS_ITEM_NAME, .multiple = true }, - { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, - }; - struct kdbus_args args = { - .allowed_flags = KDBUS_FLAG_NEGOTIATE, - .argv = argv, - .argc = ARRAY_SIZE(argv), - }; - - ret = kdbus_args_parse(&args, argp, &cmd); - if (ret != 0) - return ret; - - ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size, - 0, true, ep); - return kdbus_args_clear(&args, ret); -} |