+++ /dev/null
-/*
- * 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
- *
- * 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/hashtable.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/random.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 "notify.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "policy.h"
-#include "util.h"
-
-static void kdbus_bus_free(struct kdbus_node *node)
-{
- struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node);
-
- WARN_ON(!list_empty(&bus->monitors_list));
- WARN_ON(!hash_empty(bus->conn_hash));
-
- kdbus_notify_free(bus);
-
- kdbus_user_unref(bus->creator);
- kdbus_name_registry_free(bus->name_registry);
- kdbus_domain_unref(bus->domain);
- kdbus_policy_db_clear(&bus->policy_db);
- kdbus_meta_proc_unref(bus->creator_meta);
- kfree(bus);
-}
-
-static void kdbus_bus_release(struct kdbus_node *node, bool was_active)
-{
- struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node);
-
- if (was_active)
- atomic_dec(&bus->creator->buses);
-}
-
-static struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain,
- const char *name,
- struct kdbus_bloom_parameter *bloom,
- const u64 *pattach_owner,
- const u64 *pattach_recv,
- u64 flags, kuid_t uid, kgid_t gid)
-{
- struct kdbus_bus *b;
- u64 attach_owner;
- u64 attach_recv;
- int ret;
-
- if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE ||
- !KDBUS_IS_ALIGNED8(bloom->size) || bloom->n_hash < 1)
- return ERR_PTR(-EINVAL);
-
- ret = kdbus_sanitize_attach_flags(pattach_recv ? *pattach_recv : 0,
- &attach_recv);
- if (ret < 0)
- return ERR_PTR(ret);
-
- ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0,
- &attach_owner);
- if (ret < 0)
- return ERR_PTR(ret);
-
- ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid);
- if (ret < 0)
- return ERR_PTR(ret);
-
- b = kzalloc(sizeof(*b), GFP_KERNEL);
- if (!b)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(&b->node, KDBUS_NODE_BUS);
-
- b->node.free_cb = kdbus_bus_free;
- b->node.release_cb = kdbus_bus_release;
- b->node.uid = uid;
- b->node.gid = gid;
- b->node.mode = S_IRUSR | S_IXUSR;
-
- if (flags & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- b->node.mode |= S_IRGRP | S_IXGRP;
- if (flags & KDBUS_MAKE_ACCESS_WORLD)
- b->node.mode |= S_IROTH | S_IXOTH;
-
- b->id = atomic64_inc_return(&domain->last_id);
- b->bus_flags = flags;
- b->attach_flags_req = attach_recv;
- b->attach_flags_owner = attach_owner;
- generate_random_uuid(b->id128);
- b->bloom = *bloom;
- b->domain = kdbus_domain_ref(domain);
-
- kdbus_policy_db_init(&b->policy_db);
-
- init_rwsem(&b->conn_rwlock);
- hash_init(b->conn_hash);
- INIT_LIST_HEAD(&b->monitors_list);
-
- INIT_LIST_HEAD(&b->notify_list);
- spin_lock_init(&b->notify_lock);
- mutex_init(&b->notify_flush_lock);
-
- ret = kdbus_node_link(&b->node, &domain->node, name);
- if (ret < 0)
- goto exit_unref;
-
- /* cache the metadata/credentials of the creator */
- b->creator_meta = kdbus_meta_proc_new();
- if (IS_ERR(b->creator_meta)) {
- ret = PTR_ERR(b->creator_meta);
- b->creator_meta = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_proc_collect(b->creator_meta,
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_EXE |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_AUDIT);
- if (ret < 0)
- goto exit_unref;
-
- b->name_registry = kdbus_name_registry_new();
- if (IS_ERR(b->name_registry)) {
- ret = PTR_ERR(b->name_registry);
- b->name_registry = NULL;
- goto exit_unref;
- }
-
- /*
- * Bus-limits of the creator are accounted on its real UID, just like
- * all other per-user limits.
- */
- b->creator = kdbus_user_lookup(domain, current_uid());
- if (IS_ERR(b->creator)) {
- ret = PTR_ERR(b->creator);
- b->creator = NULL;
- goto exit_unref;
- }
-
- return b;
-
-exit_unref:
- kdbus_node_deactivate(&b->node);
- kdbus_node_unref(&b->node);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_bus_ref() - increase the reference counter of a kdbus_bus
- * @bus: The bus to reference
- *
- * Every user of a bus, except for its creator, must add a reference to the
- * kdbus_bus using this function.
- *
- * Return: the bus itself
- */
-struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus)
-{
- if (bus)
- kdbus_node_ref(&bus->node);
- return bus;
-}
-
-/**
- * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus
- * @bus: The bus to unref
- *
- * Release a reference. If the reference count drops to 0, the bus will be
- * freed.
- *
- * Return: NULL
- */
-struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus)
-{
- if (bus)
- kdbus_node_unref(&bus->node);
- return NULL;
-}
-
-/**
- * kdbus_bus_find_conn_by_id() - find a connection with a given id
- * @bus: The bus to look for the connection
- * @id: The 64-bit connection id
- *
- * Looks up a connection with a given id. The returned connection
- * is ref'ed, and needs to be unref'ed by the user. Returns NULL if
- * the connection can't be found.
- */
-struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id)
-{
- struct kdbus_conn *conn, *found = NULL;
-
- down_read(&bus->conn_rwlock);
- hash_for_each_possible(bus->conn_hash, conn, hentry, id)
- if (conn->id == id) {
- found = kdbus_conn_ref(conn);
- break;
- }
- up_read(&bus->conn_rwlock);
-
- return found;
-}
-
-/**
- * kdbus_bus_broadcast() - send a message to all subscribed connections
- * @bus: The bus the connections are connected to
- * @conn_src: The source connection, may be %NULL for kernel notifications
- * @kmsg: The message to send.
- *
- * Send @kmsg to all connections that are currently active on the bus.
- * Connections must still have matches installed in order to let the message
- * pass.
- *
- * The caller must hold the name-registry lock of @bus.
- */
-void kdbus_bus_broadcast(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_kmsg *kmsg)
-{
- struct kdbus_conn *conn_dst;
- unsigned int i;
- int ret;
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- /*
- * Make sure broadcast are queued on monitors before we send it out to
- * anyone else. Otherwise, connections might react to broadcasts before
- * the monitor gets the broadcast queued. In the worst case, the
- * monitor sees a reaction to the broadcast before the broadcast itself.
- * We don't give ordering guarantees across connections (and monitors
- * can re-construct order via sequence numbers), but we should at least
- * try to avoid re-ordering for monitors.
- */
- kdbus_bus_eavesdrop(bus, conn_src, kmsg);
-
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, conn_dst, hentry) {
- if (conn_dst->id == kmsg->msg.src_id)
- continue;
- if (!kdbus_conn_is_ordinary(conn_dst))
- continue;
-
- /*
- * Check if there is a match for the kmsg object in
- * the destination connection match db
- */
- if (!kdbus_match_db_match_kmsg(conn_dst->match_db, conn_src,
- kmsg))
- continue;
-
- if (conn_src) {
- u64 attach_flags;
-
- /*
- * Anyone can send broadcasts, as they have no
- * destination. But a receiver needs TALK access to
- * the sender in order to receive broadcasts.
- */
- if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
- continue;
-
- attach_flags = kdbus_meta_calc_attach_flags(conn_src,
- conn_dst);
-
- /*
- * Keep sending messages even if we cannot acquire the
- * requested metadata. It's up to the receiver to drop
- * messages that lack expected metadata.
- */
- if (!conn_src->faked_meta)
- kdbus_meta_proc_collect(kmsg->proc_meta,
- attach_flags);
- kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
- attach_flags);
- } else {
- /*
- * Check if there is a policy db that prevents the
- * destination connection from receiving this kernel
- * notification
- */
- if (!kdbus_conn_policy_see_notification(conn_dst, NULL,
- kmsg))
- continue;
- }
-
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
- if (ret < 0)
- kdbus_conn_lost_message(conn_dst);
- }
- up_read(&bus->conn_rwlock);
-}
-
-/**
- * kdbus_bus_eavesdrop() - send a message to all subscribed monitors
- * @bus: The bus the monitors are connected to
- * @conn_src: The source connection, may be %NULL for kernel notifications
- * @kmsg: The message to send.
- *
- * Send @kmsg to all monitors that are currently active on the bus. Monitors
- * must still have matches installed in order to let the message pass.
- *
- * The caller must hold the name-registry lock of @bus.
- */
-void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_kmsg *kmsg)
-{
- struct kdbus_conn *conn_dst;
- int ret;
-
- /*
- * Monitor connections get all messages; ignore possible errors
- * when sending messages to monitor connections.
- */
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- down_read(&bus->conn_rwlock);
- list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) {
- /*
- * Collect metadata requested by the destination connection.
- * Ignore errors, as receivers need to check metadata
- * availability, anyway. So it's still better to send messages
- * that lack data, than to skip it entirely.
- */
- if (conn_src) {
- u64 attach_flags;
-
- attach_flags = kdbus_meta_calc_attach_flags(conn_src,
- conn_dst);
- if (!conn_src->faked_meta)
- kdbus_meta_proc_collect(kmsg->proc_meta,
- attach_flags);
- kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
- attach_flags);
- }
-
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
- if (ret < 0)
- kdbus_conn_lost_message(conn_dst);
- }
- up_read(&bus->conn_rwlock);
-}
-
-/**
- * kdbus_cmd_bus_make() - handle KDBUS_CMD_BUS_MAKE
- * @domain: domain to operate on
- * @argp: command payload
- *
- * Return: Newly created bus on success, ERR_PTR on failure.
- */
-struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
- void __user *argp)
-{
- struct kdbus_bus *bus = NULL;
- struct kdbus_cmd *cmd;
- struct kdbus_ep *ep = NULL;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true },
- { .type = KDBUS_ITEM_BLOOM_PARAMETER, .mandatory = true },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV },
- };
- 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;
-
- bus = kdbus_bus_new(domain,
- argv[1].item->str, &argv[2].item->bloom_parameter,
- argv[3].item ? argv[3].item->data64 : NULL,
- argv[4].item ? argv[4].item->data64 : NULL,
- cmd->flags, current_euid(), current_egid());
- if (IS_ERR(bus)) {
- ret = PTR_ERR(bus);
- bus = NULL;
- goto exit;
- }
-
- if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) {
- atomic_dec(&bus->creator->buses);
- ret = -EMFILE;
- goto exit;
- }
-
- if (!kdbus_node_activate(&bus->node)) {
- atomic_dec(&bus->creator->buses);
- ret = -ESHUTDOWN;
- goto exit;
- }
-
- ep = kdbus_ep_new(bus, "bus", cmd->flags, bus->node.uid, bus->node.gid,
- false);
- if (IS_ERR(ep)) {
- ret = PTR_ERR(ep);
- ep = NULL;
- goto exit;
- }
-
- if (!kdbus_node_activate(&ep->node)) {
- ret = -ESHUTDOWN;
- goto exit;
- }
-
- /*
- * Drop our own reference, effectively causing the endpoint to be
- * deactivated and released when the parent bus is.
- */
- ep = kdbus_ep_unref(ep);
-
-exit:
- ret = kdbus_args_clear(&args, ret);
- if (ret < 0) {
- if (ep) {
- kdbus_node_deactivate(&ep->node);
- kdbus_ep_unref(ep);
- }
- if (bus) {
- kdbus_node_deactivate(&bus->node);
- kdbus_bus_unref(bus);
- }
- return ERR_PTR(ret);
- }
- return bus;
-}
-
-/**
- * kdbus_cmd_bus_creator_info() - handle KDBUS_CMD_BUS_CREATOR_INFO
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_info *cmd;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_item_header item_hdr;
- struct kdbus_info info = {};
- size_t meta_size, name_len;
- struct kvec kvec[5];
- u64 hdr_size = 0;
- u64 attach_flags;
- size_t cnt = 0;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- 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_sanitize_attach_flags(cmd->attach_flags, &attach_flags);
- if (ret < 0)
- goto exit;
-
- attach_flags &= bus->attach_flags_owner;
-
- ret = kdbus_meta_export_prepare(bus->creator_meta, NULL,
- &attach_flags, &meta_size);
- if (ret < 0)
- goto exit;
-
- name_len = strlen(bus->node.name) + 1;
- info.id = bus->id;
- info.flags = bus->bus_flags;
- item_hdr.type = KDBUS_ITEM_MAKE_NAME;
- item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &hdr_size);
- kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &hdr_size);
- kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &hdr_size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &hdr_size);
-
- slice = kdbus_pool_slice_alloc(conn->pool, hdr_size + meta_size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit;
- }
-
- ret = kdbus_meta_export(bus->creator_meta, NULL, attach_flags,
- slice, hdr_size, &meta_size);
- if (ret < 0)
- goto exit;
-
- info.size = hdr_size + meta_size;
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, hdr_size);
- if (ret < 0)
- goto exit;
-
- kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size);
-
- if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
- kdbus_member_set_user(&cmd->info_size, argp,
- typeof(*cmd), info_size))
- ret = -EFAULT;
-
-exit:
- kdbus_pool_slice_release(slice);
-
- return kdbus_args_clear(&args, ret);
-}
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __KDBUS_BUS_H
-#define __KDBUS_BUS_H
-
-#include <linux/hashtable.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/spinlock.h>
-#include <uapi/linux/kdbus.h>
-
-#include "metadata.h"
-#include "names.h"
-#include "node.h"
-#include "policy.h"
-
-struct kdbus_conn;
-struct kdbus_domain;
-struct kdbus_kmsg;
-struct kdbus_user;
-
-/**
- * struct kdbus_bus - bus in a domain
- * @node: kdbus_node
- * @id: ID of this bus in the domain
- * @bus_flags: Simple pass-through flags from userspace to userspace
- * @attach_flags_req: KDBUS_ATTACH_* flags required by connecting peers
- * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other
- * connections can see or query
- * @id128: Unique random 128 bit ID of this bus
- * @bloom: Bloom parameters
- * @domain: Domain of this bus
- * @creator: Creator of the bus
- * @creator_meta: Meta information about the bus creator
- * @policy_db: Policy database for this bus
- * @name_registry: Name registry of this bus
- * @conn_rwlock: Read/Write lock for all lists of child connections
- * @conn_hash: Map of connection IDs
- * @monitors_list: Connections that monitor this bus
- * @notify_list: List of pending kernel-generated messages
- * @notify_lock: Notification list lock
- * @notify_flush_lock: Notification flushing lock
- */
-struct kdbus_bus {
- struct kdbus_node node;
-
- /* static */
- u64 id;
- u64 bus_flags;
- u64 attach_flags_req;
- u64 attach_flags_owner;
- u8 id128[16];
- struct kdbus_bloom_parameter bloom;
- struct kdbus_domain *domain;
- struct kdbus_user *creator;
- struct kdbus_meta_proc *creator_meta;
-
- /* protected by own locks */
- struct kdbus_policy_db policy_db;
- struct kdbus_name_registry *name_registry;
-
- /* protected by conn_rwlock */
- struct rw_semaphore conn_rwlock;
- DECLARE_HASHTABLE(conn_hash, 8);
- struct list_head monitors_list;
-
- /* protected by notify_lock */
- struct list_head notify_list;
- spinlock_t notify_lock;
- struct mutex notify_flush_lock;
-};
-
-struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus);
-struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus);
-
-struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id);
-void kdbus_bus_broadcast(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_kmsg *kmsg);
-void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_kmsg *kmsg);
-
-struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
- void __user *argp);
-int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp);
-
-#endif
+++ /dev/null
-/*
- * 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 "bus.h"
-#include "domain.h"
-#include "handle.h"
-#include "item.h"
-#include "limits.h"
-#include "util.h"
-
-static void kdbus_domain_control_free(struct kdbus_node *node)
-{
- kfree(node);
-}
-
-static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain,
- unsigned int access)
-{
- struct kdbus_node *node;
- int ret;
-
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (!node)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(node, KDBUS_NODE_CONTROL);
-
- node->free_cb = kdbus_domain_control_free;
- node->mode = domain->node.mode;
- node->mode = S_IRUSR | S_IWUSR;
- if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- node->mode |= S_IRGRP | S_IWGRP;
- if (access & KDBUS_MAKE_ACCESS_WORLD)
- node->mode |= S_IROTH | S_IWOTH;
-
- ret = kdbus_node_link(node, &domain->node, "control");
- if (ret < 0)
- goto exit_free;
-
- return node;
-
-exit_free:
- kdbus_node_deactivate(node);
- kdbus_node_unref(node);
- return ERR_PTR(ret);
-}
-
-static void kdbus_domain_free(struct kdbus_node *node)
-{
- struct kdbus_domain *domain =
- container_of(node, struct kdbus_domain, node);
-
- put_user_ns(domain->user_namespace);
- ida_destroy(&domain->user_ida);
- idr_destroy(&domain->user_idr);
- kfree(domain);
-}
-
-/**
- * kdbus_domain_new() - create a new domain
- * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*)
- *
- * Return: a new kdbus_domain on success, ERR_PTR on failure
- */
-struct kdbus_domain *kdbus_domain_new(unsigned int access)
-{
- struct kdbus_domain *d;
- int ret;
-
- d = kzalloc(sizeof(*d), GFP_KERNEL);
- if (!d)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN);
-
- d->node.free_cb = kdbus_domain_free;
- d->node.mode = S_IRUSR | S_IXUSR;
- if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- d->node.mode |= S_IRGRP | S_IXGRP;
- if (access & KDBUS_MAKE_ACCESS_WORLD)
- d->node.mode |= S_IROTH | S_IXOTH;
-
- mutex_init(&d->lock);
- idr_init(&d->user_idr);
- ida_init(&d->user_ida);
-
- /* Pin user namespace so we can guarantee domain-unique bus * names. */
- d->user_namespace = get_user_ns(current_user_ns());
-
- ret = kdbus_node_link(&d->node, NULL, NULL);
- if (ret < 0)
- goto exit_unref;
-
- return d;
-
-exit_unref:
- kdbus_node_deactivate(&d->node);
- kdbus_node_unref(&d->node);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_domain_ref() - take a domain reference
- * @domain: Domain
- *
- * Return: the domain itself
- */
-struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain)
-{
- if (domain)
- kdbus_node_ref(&domain->node);
- return domain;
-}
-
-/**
- * kdbus_domain_unref() - drop a domain reference
- * @domain: Domain
- *
- * When the last reference is dropped, the domain internal structure
- * is freed.
- *
- * Return: NULL
- */
-struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain)
-{
- if (domain)
- kdbus_node_unref(&domain->node);
- return NULL;
-}
-
-/**
- * kdbus_domain_populate() - populate static domain nodes
- * @domain: domain to populate
- * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes
- *
- * Allocate and activate static sub-nodes of the given domain. This will fail if
- * you call it on a non-active node or if the domain was already populated.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access)
-{
- struct kdbus_node *control;
-
- /*
- * Create a control-node for this domain. We drop our own reference
- * immediately, effectively causing the node to be deactivated and
- * released when the parent domain is.
- */
- control = kdbus_domain_control_new(domain, access);
- if (IS_ERR(control))
- return PTR_ERR(control);
-
- kdbus_node_activate(control);
- kdbus_node_unref(control);
- return 0;
-}
-
-/**
- * kdbus_user_lookup() - lookup a kdbus_user object
- * @domain: domain of the user
- * @uid: uid of the user; INVALID_UID for an anon user
- *
- * Lookup the kdbus user accounting object for the given domain. If INVALID_UID
- * is passed, a new anonymous user is created which is private to the caller.
- *
- * Return: The user object is returned, ERR_PTR on failure.
- */
-struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid)
-{
- struct kdbus_user *u = NULL, *old = NULL;
- int ret;
-
- mutex_lock(&domain->lock);
-
- if (uid_valid(uid)) {
- old = idr_find(&domain->user_idr, __kuid_val(uid));
- /*
- * If the object is about to be destroyed, ignore it and
- * replace the slot in the IDR later on.
- */
- if (old && kref_get_unless_zero(&old->kref)) {
- mutex_unlock(&domain->lock);
- return old;
- }
- }
-
- u = kzalloc(sizeof(*u), GFP_KERNEL);
- if (!u) {
- ret = -ENOMEM;
- goto exit;
- }
-
- kref_init(&u->kref);
- u->domain = kdbus_domain_ref(domain);
- u->uid = uid;
- atomic_set(&u->buses, 0);
- atomic_set(&u->connections, 0);
-
- if (uid_valid(uid)) {
- if (old) {
- idr_replace(&domain->user_idr, u, __kuid_val(uid));
- old->uid = INVALID_UID; /* mark old as removed */
- } else {
- ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid),
- __kuid_val(uid) + 1, GFP_KERNEL);
- if (ret < 0)
- goto exit;
- }
- }
-
- /*
- * Allocate the smallest possible index for this user; used
- * in arrays for accounting user quota in receiver queues.
- */
- ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL);
- if (ret < 0)
- goto exit;
-
- u->id = ret;
- mutex_unlock(&domain->lock);
- return u;
-
-exit:
- if (u) {
- if (uid_valid(u->uid))
- idr_remove(&domain->user_idr, __kuid_val(u->uid));
- kdbus_domain_unref(u->domain);
- kfree(u);
- }
- mutex_unlock(&domain->lock);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_user_free(struct kref *kref)
-{
- struct kdbus_user *user = container_of(kref, struct kdbus_user, kref);
-
- WARN_ON(atomic_read(&user->buses) > 0);
- WARN_ON(atomic_read(&user->connections) > 0);
-
- mutex_lock(&user->domain->lock);
- ida_simple_remove(&user->domain->user_ida, user->id);
- if (uid_valid(user->uid))
- idr_remove(&user->domain->user_idr, __kuid_val(user->uid));
- mutex_unlock(&user->domain->lock);
-
- kdbus_domain_unref(user->domain);
- kfree(user);
-}
-
-/**
- * kdbus_user_ref() - take a user reference
- * @u: User
- *
- * Return: @u is returned
- */
-struct kdbus_user *kdbus_user_ref(struct kdbus_user *u)
-{
- if (u)
- kref_get(&u->kref);
- return u;
-}
-
-/**
- * kdbus_user_unref() - drop a user reference
- * @u: User
- *
- * Return: NULL
- */
-struct kdbus_user *kdbus_user_unref(struct kdbus_user *u)
-{
- if (u)
- kref_put(&u->kref, __kdbus_user_free);
- return NULL;
-}
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __KDBUS_DOMAIN_H
-#define __KDBUS_DOMAIN_H
-
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kref.h>
-#include <linux/user_namespace.h>
-
-#include "node.h"
-
-/**
- * struct kdbus_domain - domain for buses
- * @node: Underlying API node
- * @lock: Domain data lock
- * @last_id: Last used object id
- * @user_idr: Set of all users indexed by UID
- * @user_ida: Set of all users to compute small indices
- * @user_namespace: User namespace, pinned at creation time
- * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs)
- */
-struct kdbus_domain {
- struct kdbus_node node;
- struct mutex lock;
- atomic64_t last_id;
- struct idr user_idr;
- struct ida user_ida;
- struct user_namespace *user_namespace;
- struct dentry *dentry;
-};
-
-/**
- * struct kdbus_user - resource accounting for users
- * @kref: Reference counter
- * @domain: Domain of the user
- * @id: Index of this user
- * @uid: UID of the user
- * @buses: Number of buses the user has created
- * @connections: Number of connections the user has created
- */
-struct kdbus_user {
- struct kref kref;
- struct kdbus_domain *domain;
- unsigned int id;
- kuid_t uid;
- atomic_t buses;
- atomic_t connections;
-};
-
-#define kdbus_domain_from_node(_node) \
- container_of((_node), struct kdbus_domain, node)
-
-struct kdbus_domain *kdbus_domain_new(unsigned int access);
-struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain);
-struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain);
-int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access);
-
-#define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */
-
-struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid);
-struct kdbus_user *kdbus_user_ref(struct kdbus_user *u);
-struct kdbus_user *kdbus_user_unref(struct kdbus_user *u);
-
-#endif
+++ /dev/null
-/*
- * 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 enpoint 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_deactivate(&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_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE
- * @bus: bus to operate on
- * @argp: command payload
- *
- * Return: 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_deactivate(&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: Newly created endpoint on success, ERR_PTR 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);
-}
+++ /dev/null
-/*
- * 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.
- */
-
-#ifndef __KDBUS_ENDPOINT_H
-#define __KDBUS_ENDPOINT_H
-
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/uidgid.h>
-#include "node.h"
-#include "policy.h"
-
-struct kdbus_bus;
-struct kdbus_user;
-
-/**
- * struct kdbus_ep - enpoint to access a bus
- * @node: The kdbus node
- * @lock: Endpoint data lock
- * @bus: Bus behind this endpoint
- * @user: Custom enpoints account against an anonymous user
- * @policy_db: Uploaded policy
- * @conn_list: Connections of this endpoint
- *
- * An enpoint offers access to a bus; the default endpoint node name is "bus".
- * Additional custom endpoints to the same bus can be created and they can
- * carry their own policies/filters.
- */
-struct kdbus_ep {
- struct kdbus_node node;
- struct mutex lock;
-
- /* static */
- struct kdbus_bus *bus;
- struct kdbus_user *user;
-
- /* protected by own locks */
- struct kdbus_policy_db policy_db;
-
- /* protected by ep->lock */
- struct list_head conn_list;
-};
-
-#define kdbus_ep_from_node(_node) \
- container_of((_node), struct kdbus_ep, node)
-
-struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name,
- unsigned int access, kuid_t uid, kgid_t gid,
- bool policy);
-struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep);
-struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
-
-struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp);
-int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp);
-
-#endif