summaryrefslogtreecommitdiff
path: root/ipc
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-22 01:12:47 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-22 01:12:47 -0300
commit6d461a4fe7896faa1aec5a5417888cf179e46b9f (patch)
tree2e0f1a0b7a5418189c8d53592d33a44d0b356fc9 /ipc
parent5c545e1fb127a4b11ddc5f1a5ed066b853dd1a1a (diff)
Linux-libre 4.4.2-gnupck-4.4.2-gnu
Diffstat (limited to 'ipc')
-rw-r--r--ipc/Makefile1
-rw-r--r--ipc/kdbus/Makefile33
-rw-r--r--ipc/kdbus/bus.c514
-rw-r--r--ipc/kdbus/bus.h101
-rw-r--r--ipc/kdbus/connection.c2227
-rw-r--r--ipc/kdbus/connection.h260
-rw-r--r--ipc/kdbus/domain.c296
-rw-r--r--ipc/kdbus/domain.h77
-rw-r--r--ipc/kdbus/endpoint.c303
-rw-r--r--ipc/kdbus/endpoint.h70
-rw-r--r--ipc/kdbus/fs.c508
-rw-r--r--ipc/kdbus/fs.h28
-rw-r--r--ipc/kdbus/handle.c691
-rw-r--r--ipc/kdbus/handle.h103
-rw-r--r--ipc/kdbus/item.c293
-rw-r--r--ipc/kdbus/item.h61
-rw-r--r--ipc/kdbus/limits.h61
-rw-r--r--ipc/kdbus/main.c111
-rw-r--r--ipc/kdbus/match.c546
-rw-r--r--ipc/kdbus/match.h35
-rw-r--r--ipc/kdbus/message.c1040
-rw-r--r--ipc/kdbus/message.h120
-rw-r--r--ipc/kdbus/metadata.c1347
-rw-r--r--ipc/kdbus/metadata.h86
-rw-r--r--ipc/kdbus/names.c854
-rw-r--r--ipc/kdbus/names.h105
-rw-r--r--ipc/kdbus/node.c948
-rw-r--r--ipc/kdbus/node.h87
-rw-r--r--ipc/kdbus/notify.c204
-rw-r--r--ipc/kdbus/notify.h30
-rw-r--r--ipc/kdbus/policy.c489
-rw-r--r--ipc/kdbus/policy.h51
-rw-r--r--ipc/kdbus/pool.c728
-rw-r--r--ipc/kdbus/pool.h46
-rw-r--r--ipc/kdbus/queue.c363
-rw-r--r--ipc/kdbus/queue.h84
-rw-r--r--ipc/kdbus/reply.c252
-rw-r--r--ipc/kdbus/reply.h68
-rw-r--r--ipc/kdbus/util.c156
-rw-r--r--ipc/kdbus/util.h73
40 files changed, 0 insertions, 13450 deletions
diff --git a/ipc/Makefile b/ipc/Makefile
index 68ec4167d..61eeb1624 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -9,4 +9,3 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
obj-$(CONFIG_IPC_NS) += namespace.o
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
-obj-$(CONFIG_KDBUS) += kdbus/
diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile
deleted file mode 100644
index 66663a124..000000000
--- a/ipc/kdbus/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# By setting KDBUS_EXT=2, the kdbus module will be built as kdbus2.ko, and
-# KBUILD_MODNAME=kdbus2. This has the effect that all exported objects have
-# different names than usually (kdbus2fs, /sys/fs/kdbus2/) and you can run
-# your test-infrastructure against the kdbus2.ko, while running your system
-# on kdbus.ko.
-#
-# To just build the module, use:
-# make KDBUS_EXT=2 M=ipc/kdbus
-#
-
-kdbus$(KDBUS_EXT)-y := \
- bus.o \
- connection.o \
- endpoint.o \
- fs.o \
- handle.o \
- item.o \
- main.o \
- match.o \
- message.o \
- metadata.o \
- names.o \
- node.o \
- notify.o \
- domain.o \
- policy.o \
- pool.o \
- reply.o \
- queue.o \
- util.o
-
-obj-$(CONFIG_KDBUS) += kdbus$(KDBUS_EXT).o
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
deleted file mode 100644
index e636d3478..000000000
--- a/ipc/kdbus/bus.c
+++ /dev/null
@@ -1,514 +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
- *
- * 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,
- u64 flags, kuid_t uid, kgid_t gid)
-{
- struct kdbus_bus *b;
- u64 attach_owner;
- 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_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_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_drain(&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
- * @staging: Staging object containing the message to send
- *
- * Send message 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_staging *staging)
-{
- 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, staging);
-
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, conn_dst, hentry) {
- 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_msg(conn_dst->match_db, conn_src,
- staging))
- continue;
-
- if (conn_src) {
- /*
- * 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;
- } 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,
- staging->msg))
- continue;
- }
-
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging,
- NULL, 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
- * @staging: Staging object containing the message to send
- *
- * Send message 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_staging *staging)
-{
- 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) {
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging,
- NULL, 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: NULL or 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 },
- };
- 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,
- 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_drain(&ep->node);
- kdbus_ep_unref(ep);
- }
- if (bus) {
- kdbus_node_drain(&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 *meta_items = NULL;
- struct kdbus_item_header item_hdr;
- struct kdbus_info info = {};
- size_t meta_size, name_len, cnt = 0;
- struct kvec kvec[6];
- u64 attach_flags, size = 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_emit(bus->creator_meta, NULL, NULL, conn,
- attach_flags, &meta_items, &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), &size);
- kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &size);
- kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- if (meta_size > 0) {
- kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- }
-
- info.size = size;
-
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, 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);
- kfree(meta_items);
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h
deleted file mode 100644
index 8c2acaed6..000000000
--- a/ipc/kdbus/bus.h
+++ /dev/null
@@ -1,101 +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.
- */
-
-#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_staging;
-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_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
- * @last_message_id: Last used message id
- * @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_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 */
- atomic64_t last_message_id;
- 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_staging *staging);
-void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_staging *staging);
-
-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
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
deleted file mode 100644
index ef63d6533..000000000
--- a/ipc/kdbus/connection.c
+++ /dev/null
@@ -1,2227 +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/audit.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fs_struct.h>
-#include <linux/hashtable.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/math64.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/path.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "match.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "domain.h"
-#include "item.h"
-#include "notify.h"
-#include "policy.h"
-#include "pool.h"
-#include "reply.h"
-#include "util.h"
-#include "queue.h"
-
-#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2)
-#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1)
-
-static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
- struct file *file,
- struct kdbus_cmd_hello *hello,
- const char *name,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel,
- const char *conn_description)
-{
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- static struct lock_class_key __key;
-#endif
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_bus *bus = ep->bus;
- struct kdbus_conn *conn;
- u64 attach_flags_send;
- u64 attach_flags_recv;
- u64 items_size = 0;
- bool is_policy_holder;
- bool is_activator;
- bool is_monitor;
- bool privileged;
- bool owner;
- struct kvec kvec;
- int ret;
-
- struct {
- u64 size;
- u64 type;
- struct kdbus_bloom_parameter bloom;
- } bloom_item;
-
- privileged = kdbus_ep_is_privileged(ep, file);
- owner = kdbus_ep_is_owner(ep, file);
-
- is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
- is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
- is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER;
-
- if (!hello->pool_size || !IS_ALIGNED(hello->pool_size, PAGE_SIZE))
- return ERR_PTR(-EINVAL);
- if (is_monitor + is_activator + is_policy_holder > 1)
- return ERR_PTR(-EINVAL);
- if (name && !is_activator && !is_policy_holder)
- return ERR_PTR(-EINVAL);
- if (!name && (is_activator || is_policy_holder))
- return ERR_PTR(-EINVAL);
- if (name && !kdbus_name_is_valid(name, true))
- return ERR_PTR(-EINVAL);
- if (is_monitor && ep->user)
- return ERR_PTR(-EOPNOTSUPP);
- if (!owner && (is_activator || is_policy_holder || is_monitor))
- return ERR_PTR(-EPERM);
- if (!owner && (creds || pids || seclabel))
- return ERR_PTR(-EPERM);
-
- ret = kdbus_sanitize_attach_flags(hello->attach_flags_send,
- &attach_flags_send);
- if (ret < 0)
- return ERR_PTR(ret);
-
- ret = kdbus_sanitize_attach_flags(hello->attach_flags_recv,
- &attach_flags_recv);
- if (ret < 0)
- return ERR_PTR(ret);
-
- conn = kzalloc(sizeof(*conn), GFP_KERNEL);
- if (!conn)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&conn->kref);
- atomic_set(&conn->active, KDBUS_CONN_ACTIVE_NEW);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- lockdep_init_map(&conn->dep_map, "s_active", &__key, 0);
-#endif
- mutex_init(&conn->lock);
- INIT_LIST_HEAD(&conn->names_list);
- INIT_LIST_HEAD(&conn->reply_list);
- atomic_set(&conn->request_count, 0);
- atomic_set(&conn->lost_count, 0);
- INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
- conn->cred = get_cred(file->f_cred);
- conn->pid = get_pid(task_pid(current));
- get_fs_root(current->fs, &conn->root_path);
- init_waitqueue_head(&conn->wait);
- kdbus_queue_init(&conn->queue);
- conn->privileged = privileged;
- conn->owner = owner;
- conn->ep = kdbus_ep_ref(ep);
- conn->id = atomic64_inc_return(&bus->domain->last_id);
- conn->flags = hello->flags;
- atomic64_set(&conn->attach_flags_send, attach_flags_send);
- atomic64_set(&conn->attach_flags_recv, attach_flags_recv);
- INIT_LIST_HEAD(&conn->monitor_entry);
-
- if (conn_description) {
- conn->description = kstrdup(conn_description, GFP_KERNEL);
- if (!conn->description) {
- ret = -ENOMEM;
- goto exit_unref;
- }
- }
-
- conn->pool = kdbus_pool_new(conn->description, hello->pool_size);
- if (IS_ERR(conn->pool)) {
- ret = PTR_ERR(conn->pool);
- conn->pool = NULL;
- goto exit_unref;
- }
-
- conn->match_db = kdbus_match_db_new();
- if (IS_ERR(conn->match_db)) {
- ret = PTR_ERR(conn->match_db);
- conn->match_db = NULL;
- goto exit_unref;
- }
-
- /* return properties of this connection to the caller */
- hello->bus_flags = bus->bus_flags;
- hello->id = conn->id;
-
- BUILD_BUG_ON(sizeof(bus->id128) != sizeof(hello->id128));
- memcpy(hello->id128, bus->id128, sizeof(hello->id128));
-
- /* privileged processes can impersonate somebody else */
- if (creds || pids || seclabel) {
- conn->meta_fake = kdbus_meta_fake_new();
- if (IS_ERR(conn->meta_fake)) {
- ret = PTR_ERR(conn->meta_fake);
- conn->meta_fake = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_fake_collect(conn->meta_fake,
- creds, pids, seclabel);
- if (ret < 0)
- goto exit_unref;
- } else {
- conn->meta_proc = kdbus_meta_proc_new();
- if (IS_ERR(conn->meta_proc)) {
- ret = PTR_ERR(conn->meta_proc);
- conn->meta_proc = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_proc_collect(conn->meta_proc,
- 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;
- }
-
- /*
- * Account the connection against the current user (UID), or for
- * custom endpoints use the anonymous user assigned to the endpoint.
- * Note that limits are always accounted against the real UID, not
- * the effective UID (cred->user always points to the accounting of
- * cred->uid, not cred->euid).
- * In case the caller is privileged, we allow changing the accounting
- * to the faked user.
- */
- if (ep->user) {
- conn->user = kdbus_user_ref(ep->user);
- } else {
- kuid_t uid;
-
- if (conn->meta_fake && uid_valid(conn->meta_fake->uid) &&
- conn->privileged)
- uid = conn->meta_fake->uid;
- else
- uid = conn->cred->uid;
-
- conn->user = kdbus_user_lookup(ep->bus->domain, uid);
- if (IS_ERR(conn->user)) {
- ret = PTR_ERR(conn->user);
- conn->user = NULL;
- goto exit_unref;
- }
- }
-
- if (atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) {
- /* decremented by destructor as conn->user is valid */
- ret = -EMFILE;
- goto exit_unref;
- }
-
- bloom_item.size = sizeof(bloom_item);
- bloom_item.type = KDBUS_ITEM_BLOOM_PARAMETER;
- bloom_item.bloom = bus->bloom;
- kdbus_kvec_set(&kvec, &bloom_item, bloom_item.size, &items_size);
-
- slice = kdbus_pool_slice_alloc(conn->pool, items_size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, items_size);
- if (ret < 0)
- goto exit_unref;
-
- kdbus_pool_slice_publish(slice, &hello->offset, &hello->items_size);
- kdbus_pool_slice_release(slice);
-
- return conn;
-
-exit_unref:
- kdbus_pool_slice_release(slice);
- kdbus_conn_unref(conn);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_conn_free(struct kref *kref)
-{
- struct kdbus_conn *conn = container_of(kref, struct kdbus_conn, kref);
-
- WARN_ON(kdbus_conn_active(conn));
- WARN_ON(delayed_work_pending(&conn->work));
- WARN_ON(!list_empty(&conn->queue.msg_list));
- WARN_ON(!list_empty(&conn->names_list));
- WARN_ON(!list_empty(&conn->reply_list));
-
- if (conn->user) {
- atomic_dec(&conn->user->connections);
- kdbus_user_unref(conn->user);
- }
-
- kdbus_meta_fake_free(conn->meta_fake);
- kdbus_meta_proc_unref(conn->meta_proc);
- kdbus_match_db_free(conn->match_db);
- kdbus_pool_free(conn->pool);
- kdbus_ep_unref(conn->ep);
- path_put(&conn->root_path);
- put_pid(conn->pid);
- put_cred(conn->cred);
- kfree(conn->description);
- kfree(conn->quota);
- kfree(conn);
-}
-
-/**
- * kdbus_conn_ref() - take a connection reference
- * @conn: Connection, may be %NULL
- *
- * Return: the connection itself
- */
-struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn)
-{
- if (conn)
- kref_get(&conn->kref);
- return conn;
-}
-
-/**
- * kdbus_conn_unref() - drop a connection reference
- * @conn: Connection (may be NULL)
- *
- * When the last reference is dropped, the connection's internal structure
- * is freed.
- *
- * Return: NULL
- */
-struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn)
-{
- if (conn)
- kref_put(&conn->kref, __kdbus_conn_free);
- return NULL;
-}
-
-/**
- * kdbus_conn_active() - connection is not disconnected
- * @conn: Connection to check
- *
- * Return true if the connection was not disconnected, yet. Note that a
- * connection might be disconnected asynchronously, unless you hold the
- * connection lock. If that's not suitable for you, see kdbus_conn_acquire() to
- * suppress connection shutdown for a short period.
- *
- * Return: true if the connection is still active
- */
-bool kdbus_conn_active(const struct kdbus_conn *conn)
-{
- return atomic_read(&conn->active) >= 0;
-}
-
-/**
- * kdbus_conn_acquire() - acquire an active connection reference
- * @conn: Connection
- *
- * Users can close a connection via KDBUS_BYEBYE (or by destroying the
- * endpoint/bus/...) at any time. Whenever this happens, we should deny any
- * user-visible action on this connection and signal ECONNRESET instead.
- * To avoid testing for connection availability everytime you take the
- * connection-lock, you can acquire a connection for short periods.
- *
- * By calling kdbus_conn_acquire(), you gain an "active reference" to the
- * connection. You must also hold a regular reference at any time! As long as
- * you hold the active-ref, the connection will not be shut down. However, if
- * the connection was shut down, you can never acquire an active-ref again.
- *
- * kdbus_conn_disconnect() disables the connection and then waits for all active
- * references to be dropped. It will also wake up any pending operation.
- * However, you must not sleep for an indefinite period while holding an
- * active-reference. Otherwise, kdbus_conn_disconnect() might stall. If you need
- * to sleep for an indefinite period, either release the reference and try to
- * acquire it again after waking up, or make kdbus_conn_disconnect() wake up
- * your wait-queue.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_conn_acquire(struct kdbus_conn *conn)
-{
- if (!atomic_inc_unless_negative(&conn->active))
- return -ECONNRESET;
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_);
-#endif
-
- return 0;
-}
-
-/**
- * kdbus_conn_release() - release an active connection reference
- * @conn: Connection
- *
- * This releases an active reference that has been acquired via
- * kdbus_conn_acquire(). If the connection was already disabled and this is the
- * last active-ref that is dropped, the disconnect-waiter will be woken up and
- * properly close the connection.
- */
-void kdbus_conn_release(struct kdbus_conn *conn)
-{
- int v;
-
- if (!conn)
- return;
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_release(&conn->dep_map, 1, _RET_IP_);
-#endif
-
- v = atomic_dec_return(&conn->active);
- if (v != KDBUS_CONN_ACTIVE_BIAS)
- return;
-
- wake_up_all(&conn->wait);
-}
-
-static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name)
-{
- struct kdbus_ep *ep = conn->ep;
- struct kdbus_bus *bus = ep->bus;
- int ret;
-
- if (WARN_ON(atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_NEW))
- return -EALREADY;
-
- /* make sure the ep-node is active while we add our connection */
- if (!kdbus_node_acquire(&ep->node))
- return -ESHUTDOWN;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- mutex_lock(&ep->lock);
- down_write(&bus->conn_rwlock);
-
- /* link into monitor list */
- if (kdbus_conn_is_monitor(conn))
- list_add_tail(&conn->monitor_entry, &bus->monitors_list);
-
- /* link into bus and endpoint */
- list_add_tail(&conn->ep_entry, &ep->conn_list);
- hash_add(bus->conn_hash, &conn->hentry, conn->id);
-
- /* enable lookups and acquire active ref */
- atomic_set(&conn->active, 1);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_);
-#endif
-
- up_write(&bus->conn_rwlock);
- mutex_unlock(&ep->lock);
-
- kdbus_node_release(&ep->node);
-
- /*
- * Notify subscribers about the new active connection, unless it is
- * a monitor. Monitors are invisible on the bus, can't be addressed
- * directly, and won't cause any notifications.
- */
- if (!kdbus_conn_is_monitor(conn)) {
- ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD,
- conn->id, conn->flags);
- if (ret < 0)
- goto exit_disconnect;
- }
-
- if (kdbus_conn_is_activator(conn)) {
- u64 flags = KDBUS_NAME_ACTIVATOR;
-
- if (WARN_ON(!name)) {
- ret = -EINVAL;
- goto exit_disconnect;
- }
-
- ret = kdbus_name_acquire(bus->name_registry, conn, name,
- flags, NULL);
- if (ret < 0)
- goto exit_disconnect;
- }
-
- kdbus_conn_release(conn);
- kdbus_notify_flush(bus);
- return 0;
-
-exit_disconnect:
- kdbus_conn_release(conn);
- kdbus_conn_disconnect(conn, false);
- return ret;
-}
-
-/**
- * kdbus_conn_disconnect() - disconnect a connection
- * @conn: The connection to disconnect
- * @ensure_queue_empty: Flag to indicate if the call should fail in
- * case the connection's message list is not
- * empty
- *
- * If @ensure_msg_list_empty is true, and the connection has pending messages,
- * -EBUSY is returned.
- *
- * Return: 0 on success, negative errno on failure
- */
-int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
-{
- struct kdbus_queue_entry *entry, *tmp;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kdbus_reply *r, *r_tmp;
- struct kdbus_conn *c;
- int i, v;
-
- mutex_lock(&conn->lock);
- v = atomic_read(&conn->active);
- if (v == KDBUS_CONN_ACTIVE_NEW) {
- /* was never connected */
- mutex_unlock(&conn->lock);
- return 0;
- }
- if (v < 0) {
- /* already dead */
- mutex_unlock(&conn->lock);
- return -ECONNRESET;
- }
- if (ensure_queue_empty && !list_empty(&conn->queue.msg_list)) {
- /* still busy */
- mutex_unlock(&conn->lock);
- return -EBUSY;
- }
-
- atomic_add(KDBUS_CONN_ACTIVE_BIAS, &conn->active);
- mutex_unlock(&conn->lock);
-
- wake_up_interruptible(&conn->wait);
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire(&conn->dep_map, 0, 0, _RET_IP_);
- if (atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_BIAS)
- lock_contended(&conn->dep_map, _RET_IP_);
-#endif
-
- wait_event(conn->wait,
- atomic_read(&conn->active) == KDBUS_CONN_ACTIVE_BIAS);
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- lock_acquired(&conn->dep_map, _RET_IP_);
- rwsem_release(&conn->dep_map, 1, _RET_IP_);
-#endif
-
- cancel_delayed_work_sync(&conn->work);
- kdbus_policy_remove_owner(&conn->ep->bus->policy_db, conn);
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- mutex_lock(&conn->ep->lock);
- down_write(&bus->conn_rwlock);
-
- /* remove from bus and endpoint */
- hash_del(&conn->hentry);
- list_del(&conn->monitor_entry);
- list_del(&conn->ep_entry);
-
- up_write(&bus->conn_rwlock);
- mutex_unlock(&conn->ep->lock);
-
- /*
- * Remove all names associated with this connection; this possibly
- * moves queued messages back to the activator connection.
- */
- kdbus_name_release_all(bus->name_registry, conn);
-
- /* if we die while other connections wait for our reply, notify them */
- mutex_lock(&conn->lock);
- list_for_each_entry_safe(entry, tmp, &conn->queue.msg_list, entry) {
- if (entry->reply)
- kdbus_notify_reply_dead(bus,
- entry->reply->reply_dst->id,
- entry->reply->cookie);
- kdbus_queue_entry_free(entry);
- }
-
- list_for_each_entry_safe(r, r_tmp, &conn->reply_list, entry)
- kdbus_reply_unlink(r);
- mutex_unlock(&conn->lock);
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, c, hentry) {
- mutex_lock(&c->lock);
- list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
- if (r->reply_src != conn)
- continue;
-
- if (r->sync)
- kdbus_sync_reply_wakeup(r, -EPIPE);
- else
- /* send a 'connection dead' notification */
- kdbus_notify_reply_dead(bus, c->id, r->cookie);
-
- kdbus_reply_unlink(r);
- }
- mutex_unlock(&c->lock);
- }
- up_read(&bus->conn_rwlock);
-
- if (!kdbus_conn_is_monitor(conn))
- kdbus_notify_id_change(bus, KDBUS_ITEM_ID_REMOVE,
- conn->id, conn->flags);
-
- kdbus_notify_flush(bus);
-
- return 0;
-}
-
-/**
- * kdbus_conn_has_name() - check if a connection owns a name
- * @conn: Connection
- * @name: Well-know name to check for
- *
- * The caller must hold the registry lock of conn->ep->bus.
- *
- * Return: true if the name is currently owned by the connection
- */
-bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name)
-{
- struct kdbus_name_owner *owner;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (!(owner->flags & KDBUS_NAME_IN_QUEUE) &&
- !strcmp(name, owner->name->name))
- return true;
-
- return false;
-}
-
-struct kdbus_quota {
- u32 memory;
- u16 msgs;
- u8 fds;
-};
-
-/**
- * kdbus_conn_quota_inc() - increase quota accounting
- * @c: connection owning the quota tracking
- * @u: user to account for (or NULL for kernel accounting)
- * @memory: size of memory to account for
- * @fds: number of FDs to account for
- *
- * This call manages the quotas on resource @c. That is, it's used if other
- * users want to use the resources of connection @c, which so far only concerns
- * the receive queue of the destination.
- *
- * This increases the quota-accounting for user @u by @memory bytes and @fds
- * file descriptors. If the user has already reached the quota limits, this call
- * will not do any accounting but return a negative error code indicating the
- * failure.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds)
-{
- struct kdbus_quota *quota;
- size_t available, accounted;
- unsigned int id;
-
- /*
- * Pool Layout:
- * 50% of a pool is always owned by the connection. It is reserved for
- * kernel queries, handling received messages and other tasks that are
- * under control of the pool owner. The other 50% of the pool are used
- * as incoming queue.
- * As we optionally support user-space based policies, we need fair
- * allocation schemes. Furthermore, resource utilization should be
- * maximized, so only minimal resources stay reserved. However, we need
- * to adapt to a dynamic number of users, as we cannot know how many
- * users will talk to a connection. Therefore, the current allocation
- * works like this:
- * We limit the number of bytes in a destination's pool per sending
- * user. The space available for a user is 33% of the unused pool space
- * (whereas the space used by the user itself is also treated as
- * 'unused'). This way, we favor users coming first, but keep enough
- * pool space available for any following users. Given that messages are
- * dequeued in FIFO order, this should balance nicely if the number of
- * users grows. At the same time, this algorithm guarantees that the
- * space available to a connection is reduced dynamically, the more
- * concurrent users talk to a connection.
- */
-
- /* per user-accounting is expensive, so we keep state small */
- BUILD_BUG_ON(sizeof(quota->memory) != 4);
- BUILD_BUG_ON(sizeof(quota->msgs) != 2);
- BUILD_BUG_ON(sizeof(quota->fds) != 1);
- BUILD_BUG_ON(KDBUS_CONN_MAX_MSGS > U16_MAX);
- BUILD_BUG_ON(KDBUS_CONN_MAX_FDS_PER_USER > U8_MAX);
-
- id = u ? u->id : KDBUS_USER_KERNEL_ID;
- if (id >= c->n_quota) {
- unsigned int users;
-
- users = max(KDBUS_ALIGN8(id) + 8, id);
- quota = krealloc(c->quota, users * sizeof(*quota),
- GFP_KERNEL | __GFP_ZERO);
- if (!quota)
- return -ENOMEM;
-
- c->n_quota = users;
- c->quota = quota;
- }
-
- quota = &c->quota[id];
- kdbus_pool_accounted(c->pool, &available, &accounted);
-
- /* half the pool is _always_ reserved for the pool owner */
- available /= 2;
-
- /*
- * Pool owner slices are un-accounted slices; they can claim more
- * than 50% of the queue. However, the slices we're dealing with here
- * belong to the incoming queue, hence they are 'accounted' slices
- * to which the 50%-limit applies.
- */
- if (available < accounted)
- return -ENOBUFS;
-
- /* 1/3 of the remaining space (including your own memory) */
- available = (available - accounted + quota->memory) / 3;
-
- if (available < quota->memory ||
- available - quota->memory < memory ||
- quota->memory + memory > U32_MAX)
- return -ENOBUFS;
- if (quota->msgs >= KDBUS_CONN_MAX_MSGS)
- return -ENOBUFS;
- if (quota->fds + fds < quota->fds ||
- quota->fds + fds > KDBUS_CONN_MAX_FDS_PER_USER)
- return -EMFILE;
-
- quota->memory += memory;
- quota->fds += fds;
- ++quota->msgs;
- return 0;
-}
-
-/**
- * kdbus_conn_quota_dec() - decrease quota accounting
- * @c: connection owning the quota tracking
- * @u: user which was accounted for (or NULL for kernel accounting)
- * @memory: size of memory which was accounted for
- * @fds: number of FDs which were accounted for
- *
- * This does the reverse of kdbus_conn_quota_inc(). You have to release any
- * accounted resources that you called kdbus_conn_quota_inc() for. However, you
- * must not call kdbus_conn_quota_dec() if the accounting failed (that is,
- * kdbus_conn_quota_inc() failed).
- */
-void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds)
-{
- struct kdbus_quota *quota;
- unsigned int id;
-
- id = u ? u->id : KDBUS_USER_KERNEL_ID;
- if (WARN_ON(id >= c->n_quota))
- return;
-
- quota = &c->quota[id];
-
- if (!WARN_ON(quota->msgs == 0))
- --quota->msgs;
- if (!WARN_ON(quota->memory < memory))
- quota->memory -= memory;
- if (!WARN_ON(quota->fds < fds))
- quota->fds -= fds;
-}
-
-/**
- * kdbus_conn_lost_message() - handle lost messages
- * @c: connection that lost a message
- *
- * kdbus is reliable. That means, we try hard to never lose messages. However,
- * memory is limited, so we cannot rely on transmissions to never fail.
- * Therefore, we use quota-limits to let callers know if their unicast message
- * cannot be transmitted to a peer. This works fine for unicasts, but for
- * broadcasts we cannot make the caller handle the transmission failure.
- * Instead, we must let the destination know that it couldn't receive a
- * broadcast.
- * As this is an unlikely scenario, we keep it simple. A single lost-counter
- * remembers the number of lost messages since the last call to RECV. The next
- * message retrieval will notify the connection that it lost messages since the
- * last message retrieval and thus should resync its state.
- */
-void kdbus_conn_lost_message(struct kdbus_conn *c)
-{
- if (atomic_inc_return(&c->lost_count) == 1)
- wake_up_interruptible(&c->wait);
-}
-
-/* Callers should take the conn_dst lock */
-static struct kdbus_queue_entry *
-kdbus_conn_entry_make(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging)
-{
- /* The remote connection was disconnected */
- if (!kdbus_conn_active(conn_dst))
- return ERR_PTR(-ECONNRESET);
-
- /*
- * If the connection does not accept file descriptors but the message
- * has some attached, refuse it.
- *
- * If this is a monitor connection, accept the message. In that
- * case, all file descriptors will be set to -1 at receive time.
- */
- if (!kdbus_conn_is_monitor(conn_dst) &&
- !(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
- staging->gaps && staging->gaps->n_fds > 0)
- return ERR_PTR(-ECOMM);
-
- return kdbus_queue_entry_new(conn_src, conn_dst, staging);
-}
-
-/*
- * Synchronously responding to a message, allocate a queue entry
- * and attach it to the reply tracking object.
- * The connection's queue will never get to see it.
- */
-static int kdbus_conn_entry_sync_attach(struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply_wake)
-{
- struct kdbus_queue_entry *entry;
- int remote_ret, ret = 0;
-
- mutex_lock(&reply_wake->reply_dst->lock);
-
- /*
- * If we are still waiting then proceed, allocate a queue
- * entry and attach it to the reply object
- */
- if (reply_wake->waiting) {
- entry = kdbus_conn_entry_make(reply_wake->reply_src, conn_dst,
- staging);
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- /* Attach the entry to the reply object */
- reply_wake->queue_entry = entry;
- } else {
- ret = -ECONNRESET;
- }
-
- /*
- * Update the reply object and wake up remote peer only
- * on appropriate return codes
- *
- * * -ECOMM: if the replying connection failed with -ECOMM
- * then wakeup remote peer with -EREMOTEIO
- *
- * We do this to differenciate between -ECOMM errors
- * from the original sender perspective:
- * -ECOMM error during the sync send and
- * -ECOMM error during the sync reply, this last
- * one is rewritten to -EREMOTEIO
- *
- * * Wake up on all other return codes.
- */
- remote_ret = ret;
-
- if (ret == -ECOMM)
- remote_ret = -EREMOTEIO;
-
- kdbus_sync_reply_wakeup(reply_wake, remote_ret);
- kdbus_reply_unlink(reply_wake);
- mutex_unlock(&reply_wake->reply_dst->lock);
-
- return ret;
-}
-
-/**
- * kdbus_conn_entry_insert() - enqueue a message into the receiver's pool
- * @conn_src: The sending connection
- * @conn_dst: The connection to queue into
- * @staging: Message to send
- * @reply: The reply tracker to attach to the queue entry
- * @name: Destination name this msg is sent to, or NULL
- *
- * Return: 0 on success. negative error otherwise.
- */
-int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply,
- const struct kdbus_name_entry *name)
-{
- struct kdbus_queue_entry *entry;
- int ret;
-
- kdbus_conn_lock2(conn_src, conn_dst);
-
- entry = kdbus_conn_entry_make(conn_src, conn_dst, staging);
- if (IS_ERR(entry)) {
- ret = PTR_ERR(entry);
- goto exit_unlock;
- }
-
- if (reply) {
- kdbus_reply_link(reply);
- if (!reply->sync)
- schedule_delayed_work(&conn_src->work, 0);
- }
-
- /*
- * Record the sequence number of the registered name; it will
- * be remembered by the queue, in case messages addressed to a
- * name need to be moved from or to an activator.
- */
- if (name)
- entry->dst_name_id = name->name_id;
-
- kdbus_queue_entry_enqueue(entry, reply);
- wake_up_interruptible(&conn_dst->wait);
-
- ret = 0;
-
-exit_unlock:
- kdbus_conn_unlock2(conn_src, conn_dst);
- return ret;
-}
-
-static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
- struct kdbus_cmd_send *cmd_send,
- struct file *ioctl_file,
- struct file *cancel_fd,
- struct kdbus_reply *reply_wait,
- ktime_t expire)
-{
- struct kdbus_queue_entry *entry;
- struct poll_wqueues pwq = {};
- int ret;
-
- if (WARN_ON(!reply_wait))
- return -EIO;
-
- /*
- * Block until the reply arrives. reply_wait is left untouched
- * by the timeout scans that might be conducted for other,
- * asynchronous replies of conn_src.
- */
-
- poll_initwait(&pwq);
- poll_wait(ioctl_file, &conn_src->wait, &pwq.pt);
-
- for (;;) {
- /*
- * Any of the following conditions will stop our synchronously
- * blocking SEND command:
- *
- * a) The origin sender closed its connection
- * b) The remote peer answered, setting reply_wait->waiting = 0
- * c) The cancel FD was written to
- * d) A signal was received
- * e) The specified timeout was reached, and none of the above
- * conditions kicked in.
- */
-
- /*
- * We have already acquired an active reference when
- * entering here, but another thread may call
- * KDBUS_CMD_BYEBYE which does not acquire an active
- * reference, therefore kdbus_conn_disconnect() will
- * not wait for us.
- */
- if (!kdbus_conn_active(conn_src)) {
- ret = -ECONNRESET;
- break;
- }
-
- /*
- * After the replying peer unset the waiting variable
- * it will wake up us.
- */
- if (!reply_wait->waiting) {
- ret = reply_wait->err;
- break;
- }
-
- if (cancel_fd) {
- unsigned int r;
-
- r = cancel_fd->f_op->poll(cancel_fd, &pwq.pt);
- if (r & POLLIN) {
- ret = -ECANCELED;
- break;
- }
- }
-
- if (signal_pending(current)) {
- ret = -EINTR;
- break;
- }
-
- if (!poll_schedule_timeout(&pwq, TASK_INTERRUPTIBLE,
- &expire, 0)) {
- ret = -ETIMEDOUT;
- break;
- }
-
- /*
- * Reset the poll worker func, so the waitqueues are not
- * added to the poll table again. We just reuse what we've
- * collected earlier for further iterations.
- */
- init_poll_funcptr(&pwq.pt, NULL);
- }
-
- poll_freewait(&pwq);
-
- if (ret == -EINTR) {
- /*
- * Interrupted system call. Unref the reply object, and pass
- * the return value down the chain. Mark the reply as
- * interrupted, so the cleanup work can remove it, but do not
- * unlink it from the list. Once the syscall restarts, we'll
- * pick it up and wait on it again.
- */
- mutex_lock(&conn_src->lock);
- reply_wait->interrupted = true;
- schedule_delayed_work(&conn_src->work, 0);
- mutex_unlock(&conn_src->lock);
-
- return -ERESTARTSYS;
- }
-
- mutex_lock(&conn_src->lock);
- reply_wait->waiting = false;
- entry = reply_wait->queue_entry;
- if (entry) {
- ret = kdbus_queue_entry_install(entry,
- &cmd_send->reply.return_flags,
- true);
- kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset,
- &cmd_send->reply.msg_size);
- kdbus_queue_entry_free(entry);
- }
- kdbus_reply_unlink(reply_wait);
- mutex_unlock(&conn_src->lock);
-
- return ret;
-}
-
-static int kdbus_pin_dst(struct kdbus_bus *bus,
- struct kdbus_staging *staging,
- struct kdbus_name_entry **out_name,
- struct kdbus_conn **out_dst)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_owner *owner = NULL;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_conn *dst = NULL;
- int ret;
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- if (!staging->dst_name) {
- dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id);
- if (!dst)
- return -ENXIO;
-
- if (!kdbus_conn_is_ordinary(dst)) {
- ret = -ENXIO;
- goto error;
- }
- } else {
- name = kdbus_name_lookup_unlocked(bus->name_registry,
- staging->dst_name);
- if (name)
- owner = kdbus_name_get_owner(name);
- if (!owner)
- return -ESRCH;
-
- /*
- * If both a name and a connection ID are given as destination
- * of a message, check that the currently owning connection of
- * the name matches the specified ID.
- * This way, we allow userspace to send the message to a
- * specific connection by ID only if the connection currently
- * owns the given name.
- */
- if (msg->dst_id != KDBUS_DST_ID_NAME &&
- msg->dst_id != owner->conn->id)
- return -EREMCHG;
-
- if ((msg->flags & KDBUS_MSG_NO_AUTO_START) &&
- kdbus_conn_is_activator(owner->conn))
- return -EADDRNOTAVAIL;
-
- dst = kdbus_conn_ref(owner->conn);
- }
-
- *out_name = name;
- *out_dst = dst;
- return 0;
-
-error:
- kdbus_conn_unref(dst);
- return ret;
-}
-
-static int kdbus_conn_reply(struct kdbus_conn *src,
- struct kdbus_staging *staging)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *reply, *wake = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- int ret;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(msg->flags & KDBUS_MSG_EXPECT_REPLY) ||
- WARN_ON(msg->flags & KDBUS_MSG_SIGNAL))
- return -EINVAL;
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- mutex_lock(&dst->lock);
- reply = kdbus_reply_find(src, dst, msg->cookie_reply);
- if (reply) {
- if (reply->sync)
- wake = kdbus_reply_ref(reply);
- kdbus_reply_unlink(reply);
- }
- mutex_unlock(&dst->lock);
-
- if (!reply) {
- ret = -EBADSLT;
- goto exit;
- }
-
- /* send message */
-
- kdbus_bus_eavesdrop(bus, src, staging);
-
- if (wake)
- ret = kdbus_conn_entry_sync_attach(dst, staging, wake);
- else
- ret = kdbus_conn_entry_insert(src, dst, staging, NULL, name);
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_reply_unref(wake);
- kdbus_conn_unref(dst);
- return ret;
-}
-
-static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src,
- struct kdbus_staging *staging,
- ktime_t exp)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *wait = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- int ret;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(msg->flags & KDBUS_MSG_SIGNAL) ||
- WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY)))
- return ERR_PTR(-EINVAL);
-
- /* resume previous wait-context, if available */
-
- mutex_lock(&src->lock);
- wait = kdbus_reply_find(NULL, src, msg->cookie);
- if (wait) {
- if (wait->interrupted) {
- kdbus_reply_ref(wait);
- wait->interrupted = false;
- } else {
- wait = NULL;
- }
- }
- mutex_unlock(&src->lock);
-
- if (wait)
- return wait;
-
- if (ktime_compare(ktime_get(), exp) >= 0)
- return ERR_PTR(-ETIMEDOUT);
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- if (!kdbus_conn_policy_talk(src, current_cred(), dst)) {
- ret = -EPERM;
- goto exit;
- }
-
- wait = kdbus_reply_new(dst, src, msg, name, true);
- if (IS_ERR(wait)) {
- ret = PTR_ERR(wait);
- wait = NULL;
- goto exit;
- }
-
- /* send message */
-
- kdbus_bus_eavesdrop(bus, src, staging);
-
- ret = kdbus_conn_entry_insert(src, dst, staging, wait, name);
- if (ret < 0)
- goto exit;
-
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- if (ret < 0) {
- kdbus_reply_unref(wait);
- wait = ERR_PTR(ret);
- }
- kdbus_conn_unref(dst);
- return wait;
-}
-
-static int kdbus_conn_unicast(struct kdbus_conn *src,
- struct kdbus_staging *staging)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *wait = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- bool is_signal = (msg->flags & KDBUS_MSG_SIGNAL);
- int ret = 0;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY) &&
- msg->cookie_reply != 0))
- return -EINVAL;
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- if (is_signal) {
- /* like broadcasts we eavesdrop even if the msg is dropped */
- kdbus_bus_eavesdrop(bus, src, staging);
-
- /* drop silently if peer is not interested or not privileged */
- if (!kdbus_match_db_match_msg(dst->match_db, src, staging) ||
- !kdbus_conn_policy_talk(dst, NULL, src))
- goto exit;
- } else if (!kdbus_conn_policy_talk(src, current_cred(), dst)) {
- ret = -EPERM;
- goto exit;
- } else if (msg->flags & KDBUS_MSG_EXPECT_REPLY) {
- wait = kdbus_reply_new(dst, src, msg, name, false);
- if (IS_ERR(wait)) {
- ret = PTR_ERR(wait);
- wait = NULL;
- goto exit;
- }
- }
-
- /* send message */
-
- if (!is_signal)
- kdbus_bus_eavesdrop(bus, src, staging);
-
- ret = kdbus_conn_entry_insert(src, dst, staging, wait, name);
- if (ret < 0 && !is_signal)
- goto exit;
-
- /* signals are treated like broadcasts, recv-errors are ignored */
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_reply_unref(wait);
- kdbus_conn_unref(dst);
- return ret;
-}
-
-/**
- * kdbus_conn_move_messages() - move messages from one connection to another
- * @conn_dst: Connection to copy to
- * @conn_src: Connection to copy from
- * @name_id: Filter for the sequence number of the registered
- * name, 0 means no filtering.
- *
- * Move all messages from one connection to another. This is used when
- * an implementer connection is taking over/giving back a well-known name
- * from/to an activator connection.
- */
-void kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
- struct kdbus_conn *conn_src,
- u64 name_id)
-{
- struct kdbus_queue_entry *e, *e_tmp;
- struct kdbus_reply *r, *r_tmp;
- struct kdbus_bus *bus;
- struct kdbus_conn *c;
- LIST_HEAD(msg_list);
- int i, ret = 0;
-
- if (WARN_ON(conn_src == conn_dst))
- return;
-
- bus = conn_src->ep->bus;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, c, hentry) {
- if (c == conn_src || c == conn_dst)
- continue;
-
- mutex_lock(&c->lock);
- list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
- if (r->reply_src != conn_src)
- continue;
-
- /* filter messages for a specific name */
- if (name_id > 0 && r->name_id != name_id)
- continue;
-
- kdbus_conn_unref(r->reply_src);
- r->reply_src = kdbus_conn_ref(conn_dst);
- }
- mutex_unlock(&c->lock);
- }
- up_read(&bus->conn_rwlock);
-
- kdbus_conn_lock2(conn_src, conn_dst);
- list_for_each_entry_safe(e, e_tmp, &conn_src->queue.msg_list, entry) {
- /* filter messages for a specific name */
- if (name_id > 0 && e->dst_name_id != name_id)
- continue;
-
- if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
- e->gaps && e->gaps->n_fds > 0) {
- kdbus_conn_lost_message(conn_dst);
- kdbus_queue_entry_free(e);
- continue;
- }
-
- ret = kdbus_queue_entry_move(e, conn_dst);
- if (ret < 0) {
- kdbus_conn_lost_message(conn_dst);
- kdbus_queue_entry_free(e);
- continue;
- }
- }
- kdbus_conn_unlock2(conn_src, conn_dst);
-
- /* wake up poll() */
- wake_up_interruptible(&conn_dst->wait);
-}
-
-/* query the policy-database for all names of @whom */
-static bool kdbus_conn_policy_query_all(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_policy_db *db,
- struct kdbus_conn *whom,
- unsigned int access)
-{
- struct kdbus_name_owner *owner;
- bool pass = false;
- int res;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- down_read(&db->entries_rwlock);
- mutex_lock(&whom->lock);
-
- list_for_each_entry(owner, &whom->names_list, conn_entry) {
- if (owner->flags & KDBUS_NAME_IN_QUEUE)
- continue;
-
- res = kdbus_policy_query_unlocked(db,
- conn_creds ? : conn->cred,
- owner->name->name,
- kdbus_strhash(owner->name->name));
- if (res >= (int)access) {
- pass = true;
- break;
- }
- }
-
- mutex_unlock(&whom->lock);
- up_read(&db->entries_rwlock);
-
- return pass;
-}
-
-/**
- * kdbus_conn_policy_own_name() - verify a connection can own the given name
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @name: Name
- *
- * This verifies that @conn is allowed to acquire the well-known name @name.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- unsigned int hash = kdbus_strhash(name);
- int res;
-
- if (!conn_creds)
- conn_creds = conn->cred;
-
- if (conn->ep->user) {
- res = kdbus_policy_query(&conn->ep->policy_db, conn_creds,
- name, hash);
- if (res < KDBUS_POLICY_OWN)
- return false;
- }
-
- if (conn->owner)
- return true;
-
- res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds,
- name, hash);
- return res >= KDBUS_POLICY_OWN;
-}
-
-/**
- * kdbus_conn_policy_talk() - verify a connection can talk to a given peer
- * @conn: Connection that tries to talk
- * @conn_creds: Credentials of @conn to use for policy check
- * @to: Connection that is talked to
- *
- * This verifies that @conn is allowed to talk to @to.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *to)
-{
- if (!conn_creds)
- conn_creds = conn->cred;
-
- if (conn->ep->user &&
- !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db,
- to, KDBUS_POLICY_TALK))
- return false;
-
- if (conn->owner)
- return true;
- if (uid_eq(conn_creds->euid, to->cred->uid))
- return true;
-
- return kdbus_conn_policy_query_all(conn, conn_creds,
- &conn->ep->bus->policy_db, to,
- KDBUS_POLICY_TALK);
-}
-
-/**
- * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given
- * name
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @name: Name
- *
- * This verifies that @conn is allowed to see the well-known name @name. Caller
- * must hold policy-lock.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- int res;
-
- /*
- * By default, all names are visible on a bus. SEE policies can only be
- * installed on custom endpoints, where by default no name is visible.
- */
- if (!conn->ep->user)
- return true;
-
- res = kdbus_policy_query_unlocked(&conn->ep->policy_db,
- conn_creds ? : conn->cred,
- name, kdbus_strhash(name));
- return res >= KDBUS_POLICY_SEE;
-}
-
-static bool kdbus_conn_policy_see_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- bool res;
-
- down_read(&conn->ep->policy_db.entries_rwlock);
- res = kdbus_conn_policy_see_name_unlocked(conn, conn_creds, name);
- up_read(&conn->ep->policy_db.entries_rwlock);
-
- return res;
-}
-
-static bool kdbus_conn_policy_see(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *whom)
-{
- /*
- * By default, all names are visible on a bus, so a connection can
- * always see other connections. SEE policies can only be installed on
- * custom endpoints, where by default no name is visible and we hide
- * peers from each other, unless you see at least _one_ name of the
- * peer.
- */
- return !conn->ep->user ||
- kdbus_conn_policy_query_all(conn, conn_creds,
- &conn->ep->policy_db, whom,
- KDBUS_POLICY_SEE);
-}
-
-/**
- * kdbus_conn_policy_see_notification() - verify a connection is allowed to
- * receive a given kernel notification
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @msg: Notification message
- *
- * This checks whether @conn is allowed to see the kernel notification.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const struct kdbus_msg *msg)
-{
- /*
- * Depending on the notification type, broadcasted kernel notifications
- * have to be filtered:
- *
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}: This notification is forwarded
- * to a peer if, and only if, that peer can see the name this
- * notification is for.
- *
- * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are
- * broadcast to everyone, to allow tracking peers.
- */
-
- switch (msg->items[0].type) {
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- return kdbus_conn_policy_see_name(conn, conn_creds,
- msg->items[0].name_change.name);
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- return true;
-
- default:
- WARN(1, "Invalid type for notification broadcast: %llu\n",
- (unsigned long long)msg->items[0].type);
- return false;
- }
-}
-
-/**
- * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO
- * @ep: Endpoint to operate on
- * @file: File this connection is opened on
- * @argp: Command payload
- *
- * Return: NULL or newly created connection on success, ERR_PTR on failure.
- */
-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
- void __user *argp)
-{
- struct kdbus_cmd_hello *cmd;
- struct kdbus_conn *c = NULL;
- const char *item_name;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME },
- { .type = KDBUS_ITEM_CREDS },
- { .type = KDBUS_ITEM_PIDS },
- { .type = KDBUS_ITEM_SECLABEL },
- { .type = KDBUS_ITEM_CONN_DESCRIPTION },
- { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_HELLO_ACCEPT_FD |
- KDBUS_HELLO_ACTIVATOR |
- KDBUS_HELLO_POLICY_HOLDER |
- KDBUS_HELLO_MONITOR,
- .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_name = argv[1].item ? argv[1].item->str : NULL;
-
- c = kdbus_conn_new(ep, file, cmd, item_name,
- argv[2].item ? &argv[2].item->creds : NULL,
- argv[3].item ? &argv[3].item->pids : NULL,
- argv[4].item ? argv[4].item->str : NULL,
- argv[5].item ? argv[5].item->str : NULL);
- if (IS_ERR(c)) {
- ret = PTR_ERR(c);
- c = NULL;
- goto exit;
- }
-
- ret = kdbus_conn_connect(c, item_name);
- if (ret < 0)
- goto exit;
-
- if (kdbus_conn_is_activator(c) || kdbus_conn_is_policy_holder(c)) {
- ret = kdbus_conn_acquire(c);
- if (ret < 0)
- goto exit;
-
- ret = kdbus_policy_set(&c->ep->bus->policy_db, args.items,
- args.items_size, 1,
- kdbus_conn_is_policy_holder(c), c);
- kdbus_conn_release(c);
- if (ret < 0)
- goto exit;
- }
-
- if (copy_to_user(argp, cmd, sizeof(*cmd)))
- ret = -EFAULT;
-
-exit:
- ret = kdbus_args_clear(&args, ret);
- if (ret < 0) {
- if (c) {
- kdbus_conn_disconnect(c, false);
- kdbus_conn_unref(c);
- }
- return ERR_PTR(ret);
- }
- return c;
-}
-
-/**
- * kdbus_cmd_byebye_unlocked() - handle KDBUS_CMD_BYEBYE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * The caller must not hold any active reference to @conn or this will deadlock.
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd *cmd;
- 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),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_conn_disconnect(conn, true);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_conn_info() - handle KDBUS_CMD_CONN_INFO
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_meta_conn *conn_meta = NULL;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_name_entry *entry = NULL;
- struct kdbus_name_owner *owner = NULL;
- struct kdbus_conn *owner_conn = NULL;
- struct kdbus_item *meta_items = NULL;
- struct kdbus_info info = {};
- struct kdbus_cmd_info *cmd;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kvec kvec[3];
- size_t meta_size, cnt = 0;
- const char *name;
- u64 attach_flags, size = 0;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME },
- };
- 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;
-
- /* registry must be held throughout lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags);
- if (ret < 0)
- goto exit;
-
- name = argv[1].item ? argv[1].item->str : NULL;
-
- if (name) {
- entry = kdbus_name_lookup_unlocked(bus->name_registry, name);
- if (entry)
- owner = kdbus_name_get_owner(entry);
- if (!owner ||
- !kdbus_conn_policy_see_name(conn, current_cred(), name) ||
- (cmd->id != 0 && owner->conn->id != cmd->id)) {
- /* pretend a name doesn't exist if you cannot see it */
- ret = -ESRCH;
- goto exit;
- }
-
- owner_conn = kdbus_conn_ref(owner->conn);
- } else if (cmd->id > 0) {
- owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id);
- if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(),
- owner_conn)) {
- /* pretend an id doesn't exist if you cannot see it */
- ret = -ENXIO;
- goto exit;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
-
- attach_flags &= atomic64_read(&owner_conn->attach_flags_send);
-
- conn_meta = kdbus_meta_conn_new();
- if (IS_ERR(conn_meta)) {
- ret = PTR_ERR(conn_meta);
- conn_meta = NULL;
- goto exit;
- }
-
- ret = kdbus_meta_conn_collect(conn_meta, owner_conn, 0, attach_flags);
- if (ret < 0)
- goto exit;
-
- ret = kdbus_meta_emit(owner_conn->meta_proc, owner_conn->meta_fake,
- conn_meta, conn, attach_flags,
- &meta_items, &meta_size);
- if (ret < 0)
- goto exit;
-
- info.id = owner_conn->id;
- info.flags = owner_conn->flags;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size);
- if (meta_size > 0) {
- kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- }
-
- info.size = size;
-
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, 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;
- goto exit;
- }
-
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_pool_slice_release(slice);
- kfree(meta_items);
- kdbus_meta_conn_unref(conn_meta);
- kdbus_conn_unref(owner_conn);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_update() - handle KDBUS_CMD_UPDATE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_item *item_policy;
- u64 *item_attach_send = NULL;
- u64 *item_attach_recv = NULL;
- struct kdbus_cmd *cmd;
- u64 attach_send;
- u64 attach_recv;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV },
- { .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;
-
- item_attach_send = argv[1].item ? &argv[1].item->data64[0] : NULL;
- item_attach_recv = argv[2].item ? &argv[2].item->data64[0] : NULL;
- item_policy = argv[3].item ? : argv[4].item;
-
- if (item_attach_send) {
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- ret = kdbus_sanitize_attach_flags(*item_attach_send,
- &attach_send);
- if (ret < 0)
- goto exit;
- }
-
- if (item_attach_recv) {
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- ret = kdbus_sanitize_attach_flags(*item_attach_recv,
- &attach_recv);
- if (ret < 0)
- goto exit;
- }
-
- if (item_policy && !kdbus_conn_is_policy_holder(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- /* now that we verified the input, update the connection */
-
- if (item_policy) {
- ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items,
- KDBUS_ITEMS_SIZE(cmd, items),
- 1, true, conn);
- if (ret < 0)
- goto exit;
- }
-
- if (item_attach_send)
- atomic64_set(&conn->attach_flags_send, attach_send);
-
- if (item_attach_recv)
- atomic64_set(&conn->attach_flags_recv, attach_recv);
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_send() - handle KDBUS_CMD_SEND
- * @conn: connection to operate on
- * @f: file this command was called on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp)
-{
- struct kdbus_cmd_send *cmd;
- struct kdbus_staging *staging = NULL;
- struct kdbus_msg *msg = NULL;
- struct file *cancel_fd = NULL;
- int ret, ret2;
-
- /* command arguments */
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_CANCEL_FD },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_SEND_SYNC_REPLY,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- /* message arguments */
- struct kdbus_arg msg_argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_PAYLOAD_VEC, .multiple = true },
- { .type = KDBUS_ITEM_PAYLOAD_MEMFD, .multiple = true },
- { .type = KDBUS_ITEM_FDS },
- { .type = KDBUS_ITEM_BLOOM_FILTER },
- { .type = KDBUS_ITEM_DST_NAME },
- };
- struct kdbus_args msg_args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MSG_EXPECT_REPLY |
- KDBUS_MSG_NO_AUTO_START |
- KDBUS_MSG_SIGNAL,
- .argv = msg_argv,
- .argc = ARRAY_SIZE(msg_argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- /* make sure to parse both, @cmd and @msg on negotiation */
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret < 0)
- goto exit;
- else if (ret > 0 && !cmd->msg_address) /* negotiation without msg */
- goto exit;
-
- ret2 = kdbus_args_parse_msg(&msg_args, KDBUS_PTR(cmd->msg_address),
- &msg);
- if (ret2 < 0) { /* cannot parse message */
- ret = ret2;
- goto exit;
- } else if (ret2 > 0 && !ret) { /* msg-negot implies cmd-negot */
- ret = -EINVAL;
- goto exit;
- } else if (ret > 0) { /* negotiation */
- goto exit;
- }
-
- /* here we parsed both, @cmd and @msg, and neither wants negotiation */
-
- cmd->reply.return_flags = 0;
- kdbus_pool_publish_empty(conn->pool, &cmd->reply.offset,
- &cmd->reply.msg_size);
-
- if (argv[1].item) {
- cancel_fd = fget(argv[1].item->fds[0]);
- if (!cancel_fd) {
- ret = -EBADF;
- goto exit;
- }
-
- if (!cancel_fd->f_op->poll) {
- ret = -EINVAL;
- goto exit;
- }
- }
-
- /* patch-in the source of this message */
- if (msg->src_id > 0 && msg->src_id != conn->id) {
- ret = -EINVAL;
- goto exit;
- }
- msg->src_id = conn->id;
-
- staging = kdbus_staging_new_user(conn->ep->bus, cmd, msg);
- if (IS_ERR(staging)) {
- ret = PTR_ERR(staging);
- staging = NULL;
- goto exit;
- }
-
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST) {
- down_read(&conn->ep->bus->name_registry->rwlock);
- kdbus_bus_broadcast(conn->ep->bus, conn, staging);
- up_read(&conn->ep->bus->name_registry->rwlock);
- } else if (cmd->flags & KDBUS_SEND_SYNC_REPLY) {
- struct kdbus_reply *r;
- ktime_t exp;
-
- exp = ns_to_ktime(msg->timeout_ns);
- r = kdbus_conn_call(conn, staging, exp);
- if (IS_ERR(r)) {
- ret = PTR_ERR(r);
- goto exit;
- }
-
- ret = kdbus_conn_wait_reply(conn, cmd, f, cancel_fd, r, exp);
- kdbus_reply_unref(r);
- if (ret < 0)
- goto exit;
- } else if ((msg->flags & KDBUS_MSG_EXPECT_REPLY) ||
- msg->cookie_reply == 0) {
- ret = kdbus_conn_unicast(conn, staging);
- if (ret < 0)
- goto exit;
- } else {
- ret = kdbus_conn_reply(conn, staging);
- if (ret < 0)
- goto exit;
- }
-
- if (kdbus_member_set_user(&cmd->reply, argp, typeof(*cmd), reply))
- ret = -EFAULT;
-
-exit:
- if (cancel_fd)
- fput(cancel_fd);
- kdbus_staging_free(staging);
- ret = kdbus_args_clear(&msg_args, ret);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_recv() - handle KDBUS_CMD_RECV
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_queue_entry *entry;
- struct kdbus_cmd_recv *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_RECV_PEEK |
- KDBUS_RECV_DROP |
- KDBUS_RECV_USE_PRIORITY,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- cmd->dropped_msgs = 0;
- cmd->msg.return_flags = 0;
- kdbus_pool_publish_empty(conn->pool, &cmd->msg.offset,
- &cmd->msg.msg_size);
-
- /* DROP+priority is not realiably, so prevent it */
- if ((cmd->flags & KDBUS_RECV_DROP) &&
- (cmd->flags & KDBUS_RECV_USE_PRIORITY)) {
- ret = -EINVAL;
- goto exit;
- }
-
- mutex_lock(&conn->lock);
-
- entry = kdbus_queue_peek(&conn->queue, cmd->priority,
- cmd->flags & KDBUS_RECV_USE_PRIORITY);
- if (!entry) {
- mutex_unlock(&conn->lock);
- ret = -EAGAIN;
- } else if (cmd->flags & KDBUS_RECV_DROP) {
- struct kdbus_reply *reply = kdbus_reply_ref(entry->reply);
-
- kdbus_queue_entry_free(entry);
-
- mutex_unlock(&conn->lock);
-
- if (reply) {
- mutex_lock(&reply->reply_dst->lock);
- if (!list_empty(&reply->entry)) {
- kdbus_reply_unlink(reply);
- if (reply->sync)
- kdbus_sync_reply_wakeup(reply, -EPIPE);
- else
- kdbus_notify_reply_dead(conn->ep->bus,
- reply->reply_dst->id,
- reply->cookie);
- }
- mutex_unlock(&reply->reply_dst->lock);
- kdbus_notify_flush(conn->ep->bus);
- }
-
- kdbus_reply_unref(reply);
- } else {
- bool install_fds;
-
- /*
- * PEEK just returns the location of the next message. Do not
- * install FDs nor memfds nor anything else. The only
- * information of interest should be the message header and
- * metadata. Any FD numbers in the payload is undefined for
- * PEEK'ed messages.
- * Also make sure to never install fds into a connection that
- * has refused to receive any. Ordinary connections will not get
- * messages with FDs queued (the receiver will get -ECOMM), but
- * eavesdroppers might.
- */
- install_fds = (conn->flags & KDBUS_HELLO_ACCEPT_FD) &&
- !(cmd->flags & KDBUS_RECV_PEEK);
-
- ret = kdbus_queue_entry_install(entry,
- &cmd->msg.return_flags,
- install_fds);
- if (ret < 0) {
- mutex_unlock(&conn->lock);
- goto exit;
- }
-
- kdbus_pool_slice_publish(entry->slice, &cmd->msg.offset,
- &cmd->msg.msg_size);
-
- if (!(cmd->flags & KDBUS_RECV_PEEK))
- kdbus_queue_entry_free(entry);
-
- mutex_unlock(&conn->lock);
- }
-
- cmd->dropped_msgs = atomic_xchg(&conn->lost_count, 0);
- if (cmd->dropped_msgs > 0)
- cmd->return_flags |= KDBUS_RECV_RETURN_DROPPED_MSGS;
-
- if (kdbus_member_set_user(&cmd->msg, argp, typeof(*cmd), msg) ||
- kdbus_member_set_user(&cmd->dropped_msgs, argp, typeof(*cmd),
- dropped_msgs))
- ret = -EFAULT;
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_free() - handle KDBUS_CMD_FREE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_free *cmd;
- 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),
- };
-
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_pool_release_offset(conn->pool, cmd->offset);
-
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h
deleted file mode 100644
index 1ad082014..000000000
--- a/ipc/kdbus/connection.h
+++ /dev/null
@@ -1,260 +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
- *
- * 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_CONNECTION_H
-#define __KDBUS_CONNECTION_H
-
-#include <linux/atomic.h>
-#include <linux/kref.h>
-#include <linux/lockdep.h>
-#include <linux/path.h>
-
-#include "limits.h"
-#include "metadata.h"
-#include "pool.h"
-#include "queue.h"
-#include "util.h"
-
-#define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \
- KDBUS_HELLO_POLICY_HOLDER | \
- KDBUS_HELLO_MONITOR)
-
-struct kdbus_name_entry;
-struct kdbus_quota;
-struct kdbus_staging;
-
-/**
- * struct kdbus_conn - connection to a bus
- * @kref: Reference count
- * @active: Active references to the connection
- * @id: Connection ID
- * @flags: KDBUS_HELLO_* flags
- * @attach_flags_send: KDBUS_ATTACH_* flags for sending
- * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving
- * @description: Human-readable connection description, used for
- * debugging. This field is only set when the
- * connection is created.
- * @ep: The endpoint this connection belongs to
- * @lock: Connection data lock
- * @hentry: Entry in ID <-> connection map
- * @ep_entry: Entry in endpoint
- * @monitor_entry: Entry in monitor, if the connection is a monitor
- * @reply_list: List of connections this connection should
- * reply to
- * @work: Delayed work to handle timeouts
- * activator for
- * @match_db: Subscription filter to broadcast messages
- * @meta_proc: Process metadata of connection creator, or NULL
- * @meta_fake: Faked metadata, or NULL
- * @pool: The user's buffer to receive messages
- * @user: Owner of the connection
- * @cred: The credentials of the connection at creation time
- * @pid: Pid at creation time
- * @root_path: Root path at creation time
- * @request_count: Number of pending requests issued by this
- * connection that are waiting for replies from
- * other peers
- * @lost_count: Number of lost broadcast messages
- * @wait: Wake up this endpoint
- * @queue: The message queue associated with this connection
- * @quota: Array of per-user quota indexed by user->id
- * @n_quota: Number of elements in quota array
- * @names_list: List of well-known names
- * @name_count: Number of owned well-known names
- * @privileged: Whether this connection is privileged on the domain
- * @owner: Owned by the same user as the bus owner
- */
-struct kdbus_conn {
- struct kref kref;
- atomic_t active;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- struct lockdep_map dep_map;
-#endif
- u64 id;
- u64 flags;
- atomic64_t attach_flags_send;
- atomic64_t attach_flags_recv;
- const char *description;
- struct kdbus_ep *ep;
- struct mutex lock;
- struct hlist_node hentry;
- struct list_head ep_entry;
- struct list_head monitor_entry;
- struct list_head reply_list;
- struct delayed_work work;
- struct kdbus_match_db *match_db;
- struct kdbus_meta_proc *meta_proc;
- struct kdbus_meta_fake *meta_fake;
- struct kdbus_pool *pool;
- struct kdbus_user *user;
- const struct cred *cred;
- struct pid *pid;
- struct path root_path;
- atomic_t request_count;
- atomic_t lost_count;
- wait_queue_head_t wait;
- struct kdbus_queue queue;
-
- struct kdbus_quota *quota;
- unsigned int n_quota;
-
- /* protected by registry->rwlock */
- struct list_head names_list;
- unsigned int name_count;
-
- bool privileged:1;
- bool owner:1;
-};
-
-struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn);
-struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn);
-bool kdbus_conn_active(const struct kdbus_conn *conn);
-int kdbus_conn_acquire(struct kdbus_conn *conn);
-void kdbus_conn_release(struct kdbus_conn *conn);
-int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty);
-bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name);
-int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds);
-void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds);
-void kdbus_conn_lost_message(struct kdbus_conn *c);
-int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply,
- const struct kdbus_name_entry *name);
-void kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
- struct kdbus_conn *conn_src,
- u64 name_id);
-
-/* policy */
-bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name);
-bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *to);
-bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
- const struct cred *curr_creds,
- const char *name);
-bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
- const struct cred *curr_creds,
- const struct kdbus_msg *msg);
-
-/* command dispatcher */
-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
- void __user *argp);
-int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp);
-int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp);
-
-/**
- * kdbus_conn_is_ordinary() - Check if connection is ordinary
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is an ordinary connection
- */
-static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn)
-{
- return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN);
-}
-
-/**
- * kdbus_conn_is_activator() - Check if connection is an activator
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is an activator
- */
-static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_ACTIVATOR;
-}
-
-/**
- * kdbus_conn_is_policy_holder() - Check if connection is a policy holder
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is a policy holder
- */
-static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_POLICY_HOLDER;
-}
-
-/**
- * kdbus_conn_is_monitor() - Check if connection is a monitor
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is a monitor
- */
-static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_MONITOR;
-}
-
-/**
- * kdbus_conn_lock2() - Lock two connections
- * @a: connection A to lock or NULL
- * @b: connection B to lock or NULL
- *
- * Lock two connections at once. As we need to have a stable locking order, we
- * always lock the connection with lower memory address first.
- */
-static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b)
-{
- if (a < b) {
- if (a)
- mutex_lock(&a->lock);
- if (b && b != a)
- mutex_lock_nested(&b->lock, !!a);
- } else {
- if (b)
- mutex_lock(&b->lock);
- if (a && a != b)
- mutex_lock_nested(&a->lock, !!b);
- }
-}
-
-/**
- * kdbus_conn_unlock2() - Unlock two connections
- * @a: connection A to unlock or NULL
- * @b: connection B to unlock or NULL
- *
- * Unlock two connections at once. See kdbus_conn_lock2().
- */
-static inline void kdbus_conn_unlock2(struct kdbus_conn *a,
- struct kdbus_conn *b)
-{
- if (a)
- mutex_unlock(&a->lock);
- if (b && b != a)
- mutex_unlock(&b->lock);
-}
-
-/**
- * kdbus_conn_assert_active() - lockdep assert on active lock
- * @conn: connection that shall be active
- *
- * This verifies via lockdep that the caller holds an active reference to the
- * given connection.
- */
-static inline void kdbus_conn_assert_active(struct kdbus_conn *conn)
-{
- lockdep_assert_held(conn);
-}
-
-#endif
diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c
deleted file mode 100644
index 5d52d009d..000000000
--- a/ipc/kdbus/domain.c
+++ /dev/null
@@ -1,296 +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 "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_drain(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_drain(&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;
-}
diff --git a/ipc/kdbus/domain.h b/ipc/kdbus/domain.h
deleted file mode 100644
index 447a2bd4d..000000000
--- a/ipc/kdbus/domain.h
+++ /dev/null
@@ -1,77 +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.
- */
-
-#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
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);
-}
diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h
deleted file mode 100644
index e0da59f01..000000000
--- a/ipc/kdbus/endpoint.h
+++ /dev/null
@@ -1,70 +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.
- */
-
-#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 - endpoint 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 endpoint 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);
-
-bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file);
-bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file);
-
-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
diff --git a/ipc/kdbus/fs.c b/ipc/kdbus/fs.c
deleted file mode 100644
index 6330c61e5..000000000
--- a/ipc/kdbus/fs.c
+++ /dev/null
@@ -1,508 +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
- *
- * 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/dcache.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/init.h>
-#include <linux/ipc_namespace.h>
-#include <linux/magic.h>
-#include <linux/module.h>
-#include <linux/mount.h>
-#include <linux/mutex.h>
-#include <linux/namei.h>
-#include <linux/pagemap.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include "bus.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "node.h"
-
-#define kdbus_node_from_dentry(_dentry) \
- ((struct kdbus_node *)(_dentry)->d_fsdata)
-
-static struct inode *fs_inode_get(struct super_block *sb,
- struct kdbus_node *node);
-
-/*
- * Directory Management
- */
-
-static inline unsigned char kdbus_dt_type(struct kdbus_node *node)
-{
- switch (node->type) {
- case KDBUS_NODE_DOMAIN:
- case KDBUS_NODE_BUS:
- return DT_DIR;
- case KDBUS_NODE_CONTROL:
- case KDBUS_NODE_ENDPOINT:
- return DT_REG;
- }
-
- return DT_UNKNOWN;
-}
-
-static int fs_dir_fop_iterate(struct file *file, struct dir_context *ctx)
-{
- struct dentry *dentry = file->f_path.dentry;
- struct kdbus_node *parent = kdbus_node_from_dentry(dentry);
- struct kdbus_node *old, *next = file->private_data;
-
- /*
- * kdbusfs directory iterator (modelled after sysfs/kernfs)
- * When iterating kdbusfs directories, we iterate all children of the
- * parent kdbus_node object. We use ctx->pos to store the hash of the
- * child and file->private_data to store a reference to the next node
- * object. If ctx->pos is not modified via llseek while you iterate a
- * directory, then we use the file->private_data node pointer to
- * directly access the next node in the tree.
- * However, if you directly seek on the directory, we have to find the
- * closest node to that position and cannot use our node pointer. This
- * means iterating the rb-tree to find the closest match and start over
- * from there.
- * Note that hash values are not necessarily unique. Therefore, llseek
- * is not guaranteed to seek to the same node that you got when you
- * retrieved the position. Seeking to 0, 1, 2 and >=INT_MAX is safe,
- * though. We could use the inode-number as position, but this would
- * require another rb-tree for fast access. Kernfs and others already
- * ignore those conflicts, so we should be fine, too.
- */
-
- if (!dir_emit_dots(file, ctx))
- return 0;
-
- /* acquire @next; if deactivated, or seek detected, find next node */
- old = next;
- if (next && ctx->pos == next->hash) {
- if (kdbus_node_acquire(next))
- kdbus_node_ref(next);
- else
- next = kdbus_node_next_child(parent, next);
- } else {
- next = kdbus_node_find_closest(parent, ctx->pos);
- }
- kdbus_node_unref(old);
-
- while (next) {
- /* emit @next */
- file->private_data = next;
- ctx->pos = next->hash;
-
- kdbus_node_release(next);
-
- if (!dir_emit(ctx, next->name, strlen(next->name), next->id,
- kdbus_dt_type(next)))
- return 0;
-
- /* find next node after @next */
- old = next;
- next = kdbus_node_next_child(parent, next);
- kdbus_node_unref(old);
- }
-
- file->private_data = NULL;
- ctx->pos = INT_MAX;
-
- return 0;
-}
-
-static loff_t fs_dir_fop_llseek(struct file *file, loff_t offset, int whence)
-{
- struct inode *inode = file_inode(file);
- loff_t ret;
-
- /* protect f_off against fop_iterate */
- mutex_lock(&inode->i_mutex);
- ret = generic_file_llseek(file, offset, whence);
- mutex_unlock(&inode->i_mutex);
-
- return ret;
-}
-
-static int fs_dir_fop_release(struct inode *inode, struct file *file)
-{
- kdbus_node_unref(file->private_data);
- return 0;
-}
-
-static const struct file_operations fs_dir_fops = {
- .read = generic_read_dir,
- .iterate = fs_dir_fop_iterate,
- .llseek = fs_dir_fop_llseek,
- .release = fs_dir_fop_release,
-};
-
-static struct dentry *fs_dir_iop_lookup(struct inode *dir,
- struct dentry *dentry,
- unsigned int flags)
-{
- struct dentry *dnew = NULL;
- struct kdbus_node *parent;
- struct kdbus_node *node;
- struct inode *inode;
-
- parent = kdbus_node_from_dentry(dentry->d_parent);
- if (!kdbus_node_acquire(parent))
- return NULL;
-
- /* returns reference to _acquired_ child node */
- node = kdbus_node_find_child(parent, dentry->d_name.name);
- if (node) {
- dentry->d_fsdata = node;
- inode = fs_inode_get(dir->i_sb, node);
- if (IS_ERR(inode))
- dnew = ERR_CAST(inode);
- else
- dnew = d_splice_alias(inode, dentry);
-
- kdbus_node_release(node);
- }
-
- kdbus_node_release(parent);
- return dnew;
-}
-
-static const struct inode_operations fs_dir_iops = {
- .permission = generic_permission,
- .lookup = fs_dir_iop_lookup,
-};
-
-/*
- * Inode Management
- */
-
-static const struct inode_operations fs_inode_iops = {
- .permission = generic_permission,
-};
-
-static struct inode *fs_inode_get(struct super_block *sb,
- struct kdbus_node *node)
-{
- struct inode *inode;
-
- inode = iget_locked(sb, node->id);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- if (!(inode->i_state & I_NEW))
- return inode;
-
- inode->i_private = kdbus_node_ref(node);
- inode->i_mapping->a_ops = &empty_aops;
- inode->i_mode = node->mode & S_IALLUGO;
- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- inode->i_uid = node->uid;
- inode->i_gid = node->gid;
-
- switch (node->type) {
- case KDBUS_NODE_DOMAIN:
- case KDBUS_NODE_BUS:
- inode->i_mode |= S_IFDIR;
- inode->i_op = &fs_dir_iops;
- inode->i_fop = &fs_dir_fops;
- set_nlink(inode, 2);
- break;
- case KDBUS_NODE_CONTROL:
- case KDBUS_NODE_ENDPOINT:
- inode->i_mode |= S_IFREG;
- inode->i_op = &fs_inode_iops;
- inode->i_fop = &kdbus_handle_ops;
- break;
- }
-
- unlock_new_inode(inode);
-
- return inode;
-}
-
-/*
- * Superblock Management
- */
-
-static int fs_super_dop_revalidate(struct dentry *dentry, unsigned int flags)
-{
- struct kdbus_node *node;
-
- /* Force lookup on negatives */
- if (!dentry->d_inode)
- return 0;
-
- node = kdbus_node_from_dentry(dentry);
-
- /* see whether the node has been removed */
- if (!kdbus_node_is_active(node))
- return 0;
-
- return 1;
-}
-
-static void fs_super_dop_release(struct dentry *dentry)
-{
- kdbus_node_unref(dentry->d_fsdata);
-}
-
-static const struct dentry_operations fs_super_dops = {
- .d_revalidate = fs_super_dop_revalidate,
- .d_release = fs_super_dop_release,
-};
-
-static void fs_super_sop_evict_inode(struct inode *inode)
-{
- struct kdbus_node *node = kdbus_node_from_inode(inode);
-
- truncate_inode_pages_final(&inode->i_data);
- clear_inode(inode);
- kdbus_node_unref(node);
-}
-
-static const struct super_operations fs_super_sops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
- .evict_inode = fs_super_sop_evict_inode,
-};
-
-static int fs_super_fill(struct super_block *sb)
-{
- struct kdbus_domain *domain = sb->s_fs_info;
- struct inode *inode;
- int ret;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = KDBUS_SUPER_MAGIC;
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_op = &fs_super_sops;
- sb->s_time_gran = 1;
-
- inode = fs_inode_get(sb, &domain->node);
- if (IS_ERR(inode))
- return PTR_ERR(inode);
-
- sb->s_root = d_make_root(inode);
- if (!sb->s_root) {
- /* d_make_root iput()s the inode on failure */
- return -ENOMEM;
- }
-
- /* sb holds domain reference */
- sb->s_root->d_fsdata = &domain->node;
- sb->s_d_op = &fs_super_dops;
-
- /* sb holds root reference */
- domain->dentry = sb->s_root;
-
- if (!kdbus_node_activate(&domain->node))
- return -ESHUTDOWN;
-
- ret = kdbus_domain_populate(domain, KDBUS_MAKE_ACCESS_WORLD);
- if (ret < 0)
- return ret;
-
- sb->s_flags |= MS_ACTIVE;
- return 0;
-}
-
-static void fs_super_kill(struct super_block *sb)
-{
- struct kdbus_domain *domain = sb->s_fs_info;
-
- if (domain) {
- kdbus_node_drain(&domain->node);
- domain->dentry = NULL;
- }
-
- kill_anon_super(sb);
- kdbus_domain_unref(domain);
-}
-
-static int fs_super_set(struct super_block *sb, void *data)
-{
- int ret;
-
- ret = set_anon_super(sb, data);
- if (!ret)
- sb->s_fs_info = data;
-
- return ret;
-}
-
-static struct dentry *fs_super_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data)
-{
- struct kdbus_domain *domain;
- struct super_block *sb;
- int ret;
-
- domain = kdbus_domain_new(KDBUS_MAKE_ACCESS_WORLD);
- if (IS_ERR(domain))
- return ERR_CAST(domain);
-
- sb = sget(fs_type, NULL, fs_super_set, flags, domain);
- if (IS_ERR(sb)) {
- kdbus_node_drain(&domain->node);
- kdbus_domain_unref(domain);
- return ERR_CAST(sb);
- }
-
- WARN_ON(sb->s_fs_info != domain);
- WARN_ON(sb->s_root);
-
- ret = fs_super_fill(sb);
- if (ret < 0) {
- /* calls into ->kill_sb() when done */
- deactivate_locked_super(sb);
- return ERR_PTR(ret);
- }
-
- return dget(sb->s_root);
-}
-
-static struct file_system_type fs_type = {
- .name = KBUILD_MODNAME "fs",
- .owner = THIS_MODULE,
- .mount = fs_super_mount,
- .kill_sb = fs_super_kill,
- .fs_flags = FS_USERNS_MOUNT,
-};
-
-/**
- * kdbus_fs_init() - register kdbus filesystem
- *
- * This registers a filesystem with the VFS layer. The filesystem is called
- * `KBUILD_MODNAME "fs"', which usually resolves to `kdbusfs'. The nameing
- * scheme allows to set KBUILD_MODNAME to "kdbus2" and you will get an
- * independent filesystem for developers.
- *
- * Each mount of the kdbusfs filesystem has an kdbus_domain attached.
- * Operations on this mount will only affect the attached domain. On each mount
- * a new domain is automatically created and used for this mount exclusively.
- * If you want to share a domain across multiple mounts, you need to bind-mount
- * it.
- *
- * Mounts of kdbusfs (with a different domain each) are unrelated to each other
- * and will never have any effect on any domain but their own.
- *
- * Return: 0 on success, negative error otherwise.
- */
-int kdbus_fs_init(void)
-{
- return register_filesystem(&fs_type);
-}
-
-/**
- * kdbus_fs_exit() - unregister kdbus filesystem
- *
- * This does the reverse to kdbus_fs_init(). It unregisters the kdbusfs
- * filesystem from VFS and cleans up any allocated resources.
- */
-void kdbus_fs_exit(void)
-{
- unregister_filesystem(&fs_type);
-}
-
-/* acquire domain of @node, making sure all ancestors are active */
-static struct kdbus_domain *fs_acquire_domain(struct kdbus_node *node)
-{
- struct kdbus_domain *domain;
- struct kdbus_node *iter;
-
- /* caller must guarantee that @node is linked */
- for (iter = node; iter->parent; iter = iter->parent)
- if (!kdbus_node_is_active(iter->parent))
- return NULL;
-
- /* root nodes are always domains */
- if (WARN_ON(iter->type != KDBUS_NODE_DOMAIN))
- return NULL;
-
- domain = kdbus_domain_from_node(iter);
- if (!kdbus_node_acquire(&domain->node))
- return NULL;
-
- return domain;
-}
-
-/**
- * kdbus_fs_flush() - flush dcache entries of a node
- * @node: Node to flush entries of
- *
- * This flushes all VFS filesystem cache entries for a node and all its
- * children. This should be called whenever a node is destroyed during
- * runtime. It will flush the cache entries so the linked objects can be
- * deallocated.
- *
- * This is a no-op if you call it on active nodes (they really should stay in
- * cache) or on nodes with deactivated parents (flushing the parent is enough).
- * Furthermore, there is no need to call it on nodes whose lifetime is bound to
- * their parents'. In those cases, the parent-flush will always also flush the
- * children.
- */
-void kdbus_fs_flush(struct kdbus_node *node)
-{
- struct dentry *dentry, *parent_dentry = NULL;
- struct kdbus_domain *domain;
- struct qstr name;
-
- /* active nodes should remain in cache */
- if (!kdbus_node_is_deactivated(node))
- return;
-
- /* nodes that were never linked were never instantiated */
- if (!node->parent)
- return;
-
- /* acquire domain and verify all ancestors are active */
- domain = fs_acquire_domain(node);
- if (!domain)
- return;
-
- switch (node->type) {
- case KDBUS_NODE_ENDPOINT:
- if (WARN_ON(!node->parent || !node->parent->name))
- goto exit;
-
- name.name = node->parent->name;
- name.len = strlen(node->parent->name);
- parent_dentry = d_hash_and_lookup(domain->dentry, &name);
- if (IS_ERR_OR_NULL(parent_dentry))
- goto exit;
-
- /* fallthrough */
- case KDBUS_NODE_BUS:
- if (WARN_ON(!node->name))
- goto exit;
-
- name.name = node->name;
- name.len = strlen(node->name);
- dentry = d_hash_and_lookup(parent_dentry ? : domain->dentry,
- &name);
- if (!IS_ERR_OR_NULL(dentry)) {
- d_invalidate(dentry);
- dput(dentry);
- }
-
- dput(parent_dentry);
- break;
-
- default:
- /* all other types are bound to their parent lifetime */
- break;
- }
-
-exit:
- kdbus_node_release(&domain->node);
-}
diff --git a/ipc/kdbus/fs.h b/ipc/kdbus/fs.h
deleted file mode 100644
index 62f7d6abf..000000000
--- a/ipc/kdbus/fs.h
+++ /dev/null
@@ -1,28 +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
- *
- * 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 __KDBUSFS_H
-#define __KDBUSFS_H
-
-#include <linux/kernel.h>
-
-struct kdbus_node;
-
-int kdbus_fs_init(void);
-void kdbus_fs_exit(void);
-void kdbus_fs_flush(struct kdbus_node *node);
-
-#define kdbus_node_from_inode(_inode) \
- ((struct kdbus_node *)(_inode)->i_private)
-
-#endif
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
deleted file mode 100644
index 2f82c2a32..000000000
--- a/ipc/kdbus/handle.c
+++ /dev/null
@@ -1,691 +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/file.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/kdev_t.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/syscalls.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-#include "domain.h"
-#include "policy.h"
-
-static int kdbus_args_verify(struct kdbus_args *args)
-{
- struct kdbus_item *item;
- size_t i;
- int ret;
-
- KDBUS_ITEMS_FOREACH(item, args->items, args->items_size) {
- struct kdbus_arg *arg = NULL;
-
- if (!KDBUS_ITEM_VALID(item, args->items, args->items_size))
- return -EINVAL;
-
- for (i = 0; i < args->argc; ++i)
- if (args->argv[i].type == item->type)
- break;
- if (i >= args->argc)
- return -EINVAL;
-
- arg = &args->argv[i];
-
- ret = kdbus_item_validate(item);
- if (ret < 0)
- return ret;
-
- if (arg->item && !arg->multiple)
- return -EINVAL;
-
- arg->item = item;
- }
-
- if (!KDBUS_ITEMS_END(item, args->items, args->items_size))
- return -EINVAL;
-
- return 0;
-}
-
-static int kdbus_args_negotiate(struct kdbus_args *args)
-{
- struct kdbus_item __user *user;
- struct kdbus_item *negotiation;
- size_t i, j, num;
-
- /*
- * If KDBUS_FLAG_NEGOTIATE is set, we overwrite the flags field with
- * the set of supported flags. Furthermore, if an KDBUS_ITEM_NEGOTIATE
- * item is passed, we iterate its payload (array of u64, each set to an
- * item type) and clear all unsupported item-types to 0.
- * The caller might do this recursively, if other flags or objects are
- * embedded in the payload itself.
- */
-
- if (args->cmd->flags & KDBUS_FLAG_NEGOTIATE) {
- if (put_user(args->allowed_flags & ~KDBUS_FLAG_NEGOTIATE,
- &args->user->flags))
- return -EFAULT;
- }
-
- if (args->argc < 1 || args->argv[0].type != KDBUS_ITEM_NEGOTIATE ||
- !args->argv[0].item)
- return 0;
-
- negotiation = args->argv[0].item;
- user = (struct kdbus_item __user *)
- ((u8 __user *)args->user +
- ((u8 *)negotiation - (u8 *)args->cmd));
- num = KDBUS_ITEM_PAYLOAD_SIZE(negotiation) / sizeof(u64);
-
- for (i = 0; i < num; ++i) {
- for (j = 0; j < args->argc; ++j)
- if (negotiation->data64[i] == args->argv[j].type)
- break;
-
- if (j < args->argc)
- continue;
-
- /* this item is not supported, clear it out */
- negotiation->data64[i] = 0;
- if (put_user(negotiation->data64[i], &user->data64[i]))
- return -EFAULT;
- }
-
- return 0;
-}
-
-/**
- * __kdbus_args_parse() - parse payload of kdbus command
- * @args: object to parse data into
- * @is_cmd: whether this is a command or msg payload
- * @argp: user-space location of command payload to parse
- * @type_size: overall size of command payload to parse
- * @items_offset: offset of items array in command payload
- * @out: output variable to store pointer to copied payload
- *
- * This parses the ioctl payload at user-space location @argp into @args. @args
- * must be pre-initialized by the caller to reflect the supported flags and
- * items of this command. This parser will then copy the command payload into
- * kernel-space, verify correctness and consistency and cache pointers to parsed
- * items and other data in @args.
- *
- * If this function succeeded, you must call kdbus_args_clear() to release
- * allocated resources before destroying @args.
- *
- * This can also be used to import kdbus_msg objects. In that case, @is_cmd must
- * be set to 'false' and the 'return_flags' field will not be touched (as it
- * doesn't exist on kdbus_msg).
- *
- * Return: On failure a negative error code is returned. Otherwise, 1 is
- * returned if negotiation was requested, 0 if not.
- */
-int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp,
- size_t type_size, size_t items_offset, void **out)
-{
- u64 user_size;
- int ret, i;
-
- ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size));
- if (ret < 0)
- return ret;
-
- if (user_size < type_size)
- return -EINVAL;
- if (user_size > KDBUS_CMD_MAX_SIZE)
- return -EMSGSIZE;
-
- if (user_size <= sizeof(args->cmd_buf)) {
- if (copy_from_user(args->cmd_buf, argp, user_size))
- return -EFAULT;
- args->cmd = (void*)args->cmd_buf;
- } else {
- args->cmd = memdup_user(argp, user_size);
- if (IS_ERR(args->cmd))
- return PTR_ERR(args->cmd);
- }
-
- if (args->cmd->size != user_size) {
- ret = -EINVAL;
- goto error;
- }
-
- if (is_cmd)
- args->cmd->return_flags = 0;
- args->user = argp;
- args->items = (void *)((u8 *)args->cmd + items_offset);
- args->items_size = args->cmd->size - items_offset;
- args->is_cmd = is_cmd;
-
- if (args->cmd->flags & ~args->allowed_flags) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = kdbus_args_verify(args);
- if (ret < 0)
- goto error;
-
- ret = kdbus_args_negotiate(args);
- if (ret < 0)
- goto error;
-
- /* mandatory items must be given (but not on negotiation) */
- if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) {
- for (i = 0; i < args->argc; ++i)
- if (args->argv[i].mandatory && !args->argv[i].item) {
- ret = -EINVAL;
- goto error;
- }
- }
-
- *out = args->cmd;
- return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE);
-
-error:
- return kdbus_args_clear(args, ret);
-}
-
-/**
- * kdbus_args_clear() - release allocated command resources
- * @args: object to release resources of
- * @ret: return value of this command
- *
- * This frees all allocated resources on @args and copies the command result
- * flags into user-space. @ret is usually returned unchanged by this function,
- * so it can be used in the final 'return' statement of the command handler.
- *
- * Return: -EFAULT if return values cannot be copied into user-space, otherwise
- * @ret is returned unchanged.
- */
-int kdbus_args_clear(struct kdbus_args *args, int ret)
-{
- if (!args)
- return ret;
-
- if (!IS_ERR_OR_NULL(args->cmd)) {
- if (args->is_cmd && put_user(args->cmd->return_flags,
- &args->user->return_flags))
- ret = -EFAULT;
- if (args->cmd != (void*)args->cmd_buf)
- kfree(args->cmd);
- args->cmd = NULL;
- }
-
- return ret;
-}
-
-/**
- * enum kdbus_handle_type - type an handle can be of
- * @KDBUS_HANDLE_NONE: no type set, yet
- * @KDBUS_HANDLE_BUS_OWNER: bus owner
- * @KDBUS_HANDLE_EP_OWNER: endpoint owner
- * @KDBUS_HANDLE_CONNECTED: endpoint connection after HELLO
- */
-enum kdbus_handle_type {
- KDBUS_HANDLE_NONE,
- KDBUS_HANDLE_BUS_OWNER,
- KDBUS_HANDLE_EP_OWNER,
- KDBUS_HANDLE_CONNECTED,
-};
-
-/**
- * struct kdbus_handle - handle to the kdbus system
- * @lock: handle lock
- * @type: type of this handle (KDBUS_HANDLE_*)
- * @bus_owner: bus this handle owns
- * @ep_owner: endpoint this handle owns
- * @conn: connection this handle owns
- */
-struct kdbus_handle {
- struct mutex lock;
-
- enum kdbus_handle_type type;
- union {
- struct kdbus_bus *bus_owner;
- struct kdbus_ep *ep_owner;
- struct kdbus_conn *conn;
- };
-};
-
-static int kdbus_handle_open(struct inode *inode, struct file *file)
-{
- struct kdbus_handle *handle;
- struct kdbus_node *node;
- int ret;
-
- node = kdbus_node_from_inode(inode);
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
- ret = -ENOMEM;
- goto exit;
- }
-
- mutex_init(&handle->lock);
- handle->type = KDBUS_HANDLE_NONE;
-
- file->private_data = handle;
- ret = 0;
-
-exit:
- kdbus_node_release(node);
- return ret;
-}
-
-static int kdbus_handle_release(struct inode *inode, struct file *file)
-{
- struct kdbus_handle *handle = file->private_data;
-
- switch (handle->type) {
- case KDBUS_HANDLE_BUS_OWNER:
- if (handle->bus_owner) {
- kdbus_node_drain(&handle->bus_owner->node);
- kdbus_bus_unref(handle->bus_owner);
- }
- break;
- case KDBUS_HANDLE_EP_OWNER:
- if (handle->ep_owner) {
- kdbus_node_drain(&handle->ep_owner->node);
- kdbus_ep_unref(handle->ep_owner);
- }
- break;
- case KDBUS_HANDLE_CONNECTED:
- kdbus_conn_disconnect(handle->conn, false);
- kdbus_conn_unref(handle->conn);
- break;
- case KDBUS_HANDLE_NONE:
- /* nothing to clean up */
- break;
- }
-
- kfree(handle);
-
- return 0;
-}
-
-static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd,
- void __user *argp)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = file_inode(file)->i_private;
- struct kdbus_domain *domain;
- int ret = 0;
-
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- /*
- * The parent of control-nodes is always a domain, make sure to pin it
- * so the parent is actually valid.
- */
- domain = kdbus_domain_from_node(node->parent);
- if (!kdbus_node_acquire(&domain->node)) {
- kdbus_node_release(node);
- return -ESHUTDOWN;
- }
-
- switch (cmd) {
- case KDBUS_CMD_BUS_MAKE: {
- struct kdbus_bus *bus;
-
- bus = kdbus_cmd_bus_make(domain, argp);
- if (IS_ERR_OR_NULL(bus)) {
- ret = PTR_ERR_OR_ZERO(bus);
- break;
- }
-
- handle->bus_owner = bus;
- ret = KDBUS_HANDLE_BUS_OWNER;
- break;
- }
-
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(&domain->node);
- kdbus_node_release(node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
- void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = file_inode(file)->i_private;
- struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node);
- struct kdbus_bus *bus = file_ep->bus;
- struct kdbus_conn *conn;
- int ret = 0;
-
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- switch (cmd) {
- case KDBUS_CMD_ENDPOINT_MAKE: {
- /* creating custom endpoints is a privileged operation */
- if (!kdbus_ep_is_owner(file_ep, file)) {
- ret = -EPERM;
- break;
- }
-
- ep = kdbus_cmd_ep_make(bus, buf);
- if (IS_ERR_OR_NULL(ep)) {
- ret = PTR_ERR_OR_ZERO(ep);
- break;
- }
-
- handle->ep_owner = ep;
- ret = KDBUS_HANDLE_EP_OWNER;
- break;
- }
-
- case KDBUS_CMD_HELLO:
- conn = kdbus_cmd_hello(file_ep, file, buf);
- if (IS_ERR_OR_NULL(conn)) {
- ret = PTR_ERR_OR_ZERO(conn);
- break;
- }
-
- handle->conn = conn;
- ret = KDBUS_HANDLE_CONNECTED;
- break;
-
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_ep_owner(struct file *file, unsigned int command,
- void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_ep *ep = handle->ep_owner;
- int ret;
-
- if (!kdbus_node_acquire(&ep->node))
- return -ESHUTDOWN;
-
- switch (command) {
- case KDBUS_CMD_ENDPOINT_UPDATE:
- ret = kdbus_cmd_ep_update(ep, buf);
- break;
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(&ep->node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_connected(struct file *file,
- unsigned int command, void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_conn *conn = handle->conn;
- struct kdbus_conn *release_conn = NULL;
- int ret;
-
- release_conn = conn;
- ret = kdbus_conn_acquire(release_conn);
- if (ret < 0)
- return ret;
-
- switch (command) {
- case KDBUS_CMD_BYEBYE:
- /*
- * BYEBYE is special; we must not acquire a connection when
- * calling into kdbus_conn_disconnect() or we will deadlock,
- * because kdbus_conn_disconnect() will wait for all acquired
- * references to be dropped.
- */
- kdbus_conn_release(release_conn);
- release_conn = NULL;
- ret = kdbus_cmd_byebye_unlocked(conn, buf);
- break;
- case KDBUS_CMD_NAME_ACQUIRE:
- ret = kdbus_cmd_name_acquire(conn, buf);
- break;
- case KDBUS_CMD_NAME_RELEASE:
- ret = kdbus_cmd_name_release(conn, buf);
- break;
- case KDBUS_CMD_LIST:
- ret = kdbus_cmd_list(conn, buf);
- break;
- case KDBUS_CMD_CONN_INFO:
- ret = kdbus_cmd_conn_info(conn, buf);
- break;
- case KDBUS_CMD_BUS_CREATOR_INFO:
- ret = kdbus_cmd_bus_creator_info(conn, buf);
- break;
- case KDBUS_CMD_UPDATE:
- ret = kdbus_cmd_update(conn, buf);
- break;
- case KDBUS_CMD_MATCH_ADD:
- ret = kdbus_cmd_match_add(conn, buf);
- break;
- case KDBUS_CMD_MATCH_REMOVE:
- ret = kdbus_cmd_match_remove(conn, buf);
- break;
- case KDBUS_CMD_SEND:
- ret = kdbus_cmd_send(conn, file, buf);
- break;
- case KDBUS_CMD_RECV:
- ret = kdbus_cmd_recv(conn, buf);
- break;
- case KDBUS_CMD_FREE:
- ret = kdbus_cmd_free(conn, buf);
- break;
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_conn_release(release_conn);
- return ret;
-}
-
-static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = kdbus_node_from_inode(file_inode(file));
- void __user *argp = (void __user *)arg;
- long ret = -EBADFD;
-
- switch (cmd) {
- case KDBUS_CMD_BUS_MAKE:
- case KDBUS_CMD_ENDPOINT_MAKE:
- case KDBUS_CMD_HELLO:
- mutex_lock(&handle->lock);
- if (handle->type == KDBUS_HANDLE_NONE) {
- if (node->type == KDBUS_NODE_CONTROL)
- ret = kdbus_handle_ioctl_control(file, cmd,
- argp);
- else if (node->type == KDBUS_NODE_ENDPOINT)
- ret = kdbus_handle_ioctl_ep(file, cmd, argp);
-
- if (ret > 0) {
- /*
- * The data given via open() is not sufficient
- * to setup a kdbus handle. Hence, we require
- * the user to perform a setup ioctl. This setup
- * can only be performed once and defines the
- * type of the handle. The different setup
- * ioctls are locked against each other so they
- * cannot race. Once the handle type is set,
- * the type-dependent ioctls are enabled. To
- * improve performance, we don't lock those via
- * handle->lock. Instead, we issue a
- * write-barrier before performing the
- * type-change, which pairs with smp_rmb() in
- * all handlers that access the type field. This
- * guarantees the handle is fully setup, if
- * handle->type is set. If handle->type is
- * unset, you must not make any assumptions
- * without taking handle->lock.
- * Note that handle->type is only set once. It
- * will never change afterwards.
- */
- smp_wmb();
- handle->type = ret;
- }
- }
- mutex_unlock(&handle->lock);
- break;
-
- case KDBUS_CMD_ENDPOINT_UPDATE:
- case KDBUS_CMD_BYEBYE:
- case KDBUS_CMD_NAME_ACQUIRE:
- case KDBUS_CMD_NAME_RELEASE:
- case KDBUS_CMD_LIST:
- case KDBUS_CMD_CONN_INFO:
- case KDBUS_CMD_BUS_CREATOR_INFO:
- case KDBUS_CMD_UPDATE:
- case KDBUS_CMD_MATCH_ADD:
- case KDBUS_CMD_MATCH_REMOVE:
- case KDBUS_CMD_SEND:
- case KDBUS_CMD_RECV:
- case KDBUS_CMD_FREE: {
- enum kdbus_handle_type type;
-
- /*
- * This read-barrier pairs with smp_wmb() of the handle setup.
- * it guarantees the handle is fully written, in case the
- * type has been set. It allows us to access the handle without
- * taking handle->lock, given the guarantee that the type is
- * only ever set once, and stays constant afterwards.
- * Furthermore, the handle object itself is not modified in any
- * way after the type is set. That is, the type-field is the
- * last field that is written on any handle. If it has not been
- * set, we must not access the handle here.
- */
- type = handle->type;
- smp_rmb();
-
- if (type == KDBUS_HANDLE_EP_OWNER)
- ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp);
- else if (type == KDBUS_HANDLE_CONNECTED)
- ret = kdbus_handle_ioctl_connected(file, cmd, argp);
-
- break;
- }
- default:
- ret = -ENOTTY;
- break;
- }
-
- return ret < 0 ? ret : 0;
-}
-
-static unsigned int kdbus_handle_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct kdbus_handle *handle = file->private_data;
- enum kdbus_handle_type type;
- unsigned int mask = POLLOUT | POLLWRNORM;
-
- /*
- * This pairs with smp_wmb() during handle setup. It guarantees that
- * _iff_ the handle type is set, handle->conn is valid. Furthermore,
- * _iff_ the type is set, the handle object is constant and never
- * changed again. If it's not set, we must not access the handle but
- * bail out. We also must assume no setup has taken place, yet.
- */
- type = handle->type;
- smp_rmb();
-
- /* Only a connected endpoint can read/write data */
- if (type != KDBUS_HANDLE_CONNECTED)
- return POLLERR | POLLHUP;
-
- poll_wait(file, &handle->conn->wait, wait);
-
- /*
- * Verify the connection hasn't been deactivated _after_ adding the
- * wait-queue. This guarantees, that if the connection is deactivated
- * after we checked it, the waitqueue is signaled and we're called
- * again.
- */
- if (!kdbus_conn_active(handle->conn))
- return POLLERR | POLLHUP;
-
- if (!list_empty(&handle->conn->queue.msg_list) ||
- atomic_read(&handle->conn->lost_count) > 0)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct kdbus_handle *handle = file->private_data;
- enum kdbus_handle_type type;
- int ret = -EBADFD;
-
- /*
- * This pairs with smp_wmb() during handle setup. It guarantees that
- * _iff_ the handle type is set, handle->conn is valid. Furthermore,
- * _iff_ the type is set, the handle object is constant and never
- * changed again. If it's not set, we must not access the handle but
- * bail out. We also must assume no setup has taken place, yet.
- */
- type = handle->type;
- smp_rmb();
-
- /* Only connected handles have a pool we can map */
- if (type == KDBUS_HANDLE_CONNECTED)
- ret = kdbus_pool_mmap(handle->conn->pool, vma);
-
- return ret;
-}
-
-const struct file_operations kdbus_handle_ops = {
- .owner = THIS_MODULE,
- .open = kdbus_handle_open,
- .release = kdbus_handle_release,
- .poll = kdbus_handle_poll,
- .llseek = noop_llseek,
- .unlocked_ioctl = kdbus_handle_ioctl,
- .mmap = kdbus_handle_mmap,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = kdbus_handle_ioctl,
-#endif
-};
diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
deleted file mode 100644
index 5dde2c10b..000000000
--- a/ipc/kdbus/handle.h
+++ /dev/null
@@ -1,103 +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
- *
- * 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_HANDLE_H
-#define __KDBUS_HANDLE_H
-
-#include <linux/fs.h>
-#include <uapi/linux/kdbus.h>
-
-extern const struct file_operations kdbus_handle_ops;
-
-/**
- * kdbus_arg - information and state of a single ioctl command item
- * @type: item type
- * @item: set by the parser to the first found item of this type
- * @multiple: whether multiple items of this type are allowed
- * @mandatory: whether at least one item of this type is required
- *
- * This structure describes a single item in an ioctl command payload. The
- * caller has to pre-fill the type and flags, the parser will then use this
- * information to verify the ioctl payload. @item is set by the parser to point
- * to the first occurrence of the item.
- */
-struct kdbus_arg {
- u64 type;
- struct kdbus_item *item;
- bool multiple : 1;
- bool mandatory : 1;
-};
-
-/**
- * kdbus_args - information and state of ioctl command parser
- * @allowed_flags: set of flags this command supports
- * @argc: number of items in @argv
- * @argv: array of items this command supports
- * @user: set by parser to user-space location of current command
- * @cmd: set by parser to kernel copy of command payload
- * @cmd_buf: inline buf to avoid kmalloc() on small cmds
- * @items: points to item array in @cmd
- * @items_size: size of @items in bytes
- * @is_cmd: whether this is a command-payload or msg-payload
- *
- * This structure is used to parse ioctl command payloads on each invocation.
- * The ioctl handler has to pre-fill the flags and allowed items before passing
- * the object to kdbus_args_parse(). The parser will copy the command payload
- * into kernel-space and verify the correctness of the data.
- *
- * We use a 256 bytes buffer for small command payloads, to be allocated on
- * stack on syscall entrance.
- */
-struct kdbus_args {
- u64 allowed_flags;
- size_t argc;
- struct kdbus_arg *argv;
-
- struct kdbus_cmd __user *user;
- struct kdbus_cmd *cmd;
- u8 cmd_buf[256];
-
- struct kdbus_item *items;
- size_t items_size;
- bool is_cmd : 1;
-};
-
-int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp,
- size_t type_size, size_t items_offset, void **out);
-int kdbus_args_clear(struct kdbus_args *args, int ret);
-
-#define kdbus_args_parse(_args, _argp, _v) \
- ({ \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \
- offsetof(struct kdbus_cmd, size)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \
- offsetof(struct kdbus_cmd, flags)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \
- offsetof(struct kdbus_cmd, return_flags)); \
- __kdbus_args_parse((_args), 1, (_argp), sizeof(**(_v)), \
- offsetof(typeof(**(_v)), items), \
- (void **)(_v)); \
- })
-
-#define kdbus_args_parse_msg(_args, _argp, _v) \
- ({ \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \
- offsetof(struct kdbus_cmd, size)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \
- offsetof(struct kdbus_cmd, flags)); \
- __kdbus_args_parse((_args), 0, (_argp), sizeof(**(_v)), \
- offsetof(typeof(**(_v)), items), \
- (void **)(_v)); \
- })
-
-#endif
diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c
deleted file mode 100644
index ce78dba03..000000000
--- a/ipc/kdbus/item.c
+++ /dev/null
@@ -1,293 +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/ctype.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-
-#include "item.h"
-#include "limits.h"
-#include "util.h"
-
-/*
- * This verifies the string at position @str with size @size is properly
- * zero-terminated and does not contain a 0-byte but at the end.
- */
-static bool kdbus_str_valid(const char *str, size_t size)
-{
- return size > 0 && memchr(str, '\0', size) == str + size - 1;
-}
-
-/**
- * kdbus_item_validate_name() - validate an item containing a name
- * @item: Item to validate
- *
- * Return: zero on success or an negative error code on failure
- */
-int kdbus_item_validate_name(const struct kdbus_item *item)
-{
- const char *name = item->str;
- unsigned int i;
- size_t len;
-
- if (item->size < KDBUS_ITEM_HEADER_SIZE + 2)
- return -EINVAL;
-
- if (item->size > KDBUS_ITEM_HEADER_SIZE +
- KDBUS_SYSNAME_MAX_LEN + 1)
- return -ENAMETOOLONG;
-
- if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item)))
- return -EINVAL;
-
- len = strlen(name);
- if (len == 0)
- return -EINVAL;
-
- for (i = 0; i < len; i++) {
- if (isalpha(name[i]))
- continue;
- if (isdigit(name[i]))
- continue;
- if (name[i] == '_')
- continue;
- if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.'))
- continue;
-
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * kdbus_item_validate() - validate a single item
- * @item: item to validate
- *
- * Return: 0 if item is valid, negative error code if not.
- */
-int kdbus_item_validate(const struct kdbus_item *item)
-{
- size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item);
- size_t l;
- int ret;
-
- BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE !=
- sizeof(struct kdbus_item_header));
-
- if (item->size < KDBUS_ITEM_HEADER_SIZE)
- return -EINVAL;
-
- switch (item->type) {
- case KDBUS_ITEM_NEGOTIATE:
- if (payload_size % sizeof(u64) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_PAYLOAD_VEC:
- case KDBUS_ITEM_PAYLOAD_OFF:
- if (payload_size != sizeof(struct kdbus_vec))
- return -EINVAL;
- if (item->vec.size == 0 || item->vec.size > SIZE_MAX)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- if (payload_size != sizeof(struct kdbus_memfd))
- return -EINVAL;
- if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX)
- return -EINVAL;
- if (item->memfd.fd < 0)
- return -EBADF;
- break;
-
- case KDBUS_ITEM_FDS:
- if (payload_size % sizeof(int) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CANCEL_FD:
- if (payload_size != sizeof(int))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_PARAMETER:
- if (payload_size != sizeof(struct kdbus_bloom_parameter))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_FILTER:
- /* followed by the bloom-mask, depends on the bloom-size */
- if (payload_size < sizeof(struct kdbus_bloom_filter))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_MASK:
- /* size depends on bloom-size of bus */
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- case KDBUS_ITEM_MAKE_NAME:
- ret = kdbus_item_validate_name(item);
- if (ret < 0)
- return ret;
- break;
-
- case KDBUS_ITEM_ATTACH_FLAGS_SEND:
- case KDBUS_ITEM_ATTACH_FLAGS_RECV:
- case KDBUS_ITEM_ID:
- case KDBUS_ITEM_DST_ID:
- if (payload_size != sizeof(u64))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_TIMESTAMP:
- if (payload_size != sizeof(struct kdbus_timestamp))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CREDS:
- if (payload_size != sizeof(struct kdbus_creds))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
- if (payload_size % sizeof(u32) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_NAME:
- case KDBUS_ITEM_DST_NAME:
- case KDBUS_ITEM_PID_COMM:
- case KDBUS_ITEM_TID_COMM:
- case KDBUS_ITEM_EXE:
- case KDBUS_ITEM_CMDLINE:
- case KDBUS_ITEM_CGROUP:
- case KDBUS_ITEM_SECLABEL:
- if (!kdbus_str_valid(item->str, payload_size))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CAPS:
- if (payload_size < sizeof(u32))
- return -EINVAL;
- if (payload_size < sizeof(u32) +
- 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_AUDIT:
- if (payload_size != sizeof(struct kdbus_audit))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_POLICY_ACCESS:
- if (payload_size != sizeof(struct kdbus_policy_access))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- if (payload_size < sizeof(struct kdbus_notify_name_change))
- return -EINVAL;
- l = payload_size - offsetof(struct kdbus_notify_name_change,
- name);
- if (l > 0 && !kdbus_str_valid(item->name_change.name, l))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- if (payload_size != sizeof(struct kdbus_notify_id_change))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_REPLY_TIMEOUT:
- case KDBUS_ITEM_REPLY_DEAD:
- if (payload_size != 0)
- return -EINVAL;
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/**
- * kdbus_items_validate() - validate items passed by user-space
- * @items: items to validate
- * @items_size: number of items
- *
- * This verifies that the passed items pointer is consistent and valid.
- * Furthermore, each item is checked for:
- * - valid "size" value
- * - payload is of expected type
- * - payload is fully included in the item
- * - string payloads are zero-terminated
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_items_validate(const struct kdbus_item *items, size_t items_size)
-{
- const struct kdbus_item *item;
- int ret;
-
- KDBUS_ITEMS_FOREACH(item, items, items_size) {
- if (!KDBUS_ITEM_VALID(item, items, items_size))
- return -EINVAL;
-
- ret = kdbus_item_validate(item);
- if (ret < 0)
- return ret;
- }
-
- if (!KDBUS_ITEMS_END(item, items, items_size))
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * kdbus_item_set() - Set item content
- * @item: The item to modify
- * @type: The item type to set (KDBUS_ITEM_*)
- * @data: Data to copy to item->data, may be %NULL
- * @len: Number of bytes in @data
- *
- * This sets type, size and data fields of an item. If @data is NULL, the data
- * memory is cleared.
- *
- * Note that you must align your @data memory to 8 bytes. Trailing padding (in
- * case @len is not 8byte aligned) is cleared by this call.
- *
- * Returns: Pointer to the following item.
- */
-struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type,
- const void *data, size_t len)
-{
- item->type = type;
- item->size = KDBUS_ITEM_HEADER_SIZE + len;
-
- if (data) {
- memcpy(item->data, data, len);
- memset(item->data + len, 0, KDBUS_ALIGN8(len) - len);
- } else {
- memset(item->data, 0, KDBUS_ALIGN8(len));
- }
-
- return KDBUS_ITEM_NEXT(item);
-}
diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h
deleted file mode 100644
index 3a7e6ccc2..000000000
--- a/ipc/kdbus/item.h
+++ /dev/null
@@ -1,61 +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.
- */
-
-#ifndef __KDBUS_ITEM_H
-#define __KDBUS_ITEM_H
-
-#include <linux/kernel.h>
-#include <uapi/linux/kdbus.h>
-
-#include "util.h"
-
-/* generic access and iterators over a stream of items */
-#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size))
-#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is))
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s))
-#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE)
-
-#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \
- for ((_i) = (_is); \
- ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \
- ((u8 *)(_i) >= (u8 *)(_is)); \
- (_i) = KDBUS_ITEM_NEXT(_i))
-
-#define KDBUS_ITEM_VALID(_i, _is, _s) \
- ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \
- (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \
- (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \
- (u8 *)(_i) >= (u8 *)(_is))
-
-#define KDBUS_ITEMS_END(_i, _is, _s) \
- ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
-
-/**
- * struct kdbus_item_header - Describes the fix part of an item
- * @size: The total size of the item
- * @type: The item type, one of KDBUS_ITEM_*
- */
-struct kdbus_item_header {
- u64 size;
- u64 type;
-};
-
-int kdbus_item_validate_name(const struct kdbus_item *item);
-int kdbus_item_validate(const struct kdbus_item *item);
-int kdbus_items_validate(const struct kdbus_item *items, size_t items_size);
-struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type,
- const void *data, size_t len);
-
-#endif
diff --git a/ipc/kdbus/limits.h b/ipc/kdbus/limits.h
deleted file mode 100644
index bd47119cd..000000000
--- a/ipc/kdbus/limits.h
+++ /dev/null
@@ -1,61 +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
- *
- * 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_DEFAULTS_H
-#define __KDBUS_DEFAULTS_H
-
-#include <linux/kernel.h>
-
-/* maximum size of message header and items */
-#define KDBUS_MSG_MAX_SIZE SZ_8K
-
-/* maximum number of memfd items per message */
-#define KDBUS_MSG_MAX_MEMFD_ITEMS 16
-
-/* max size of ioctl command data */
-#define KDBUS_CMD_MAX_SIZE SZ_32K
-
-/* maximum number of inflight fds in a target queue per user */
-#define KDBUS_CONN_MAX_FDS_PER_USER 16
-
-/* maximum message payload size */
-#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M
-
-/* maximum size of bloom bit field in bytes */
-#define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K
-
-/* maximum length of well-known bus name */
-#define KDBUS_NAME_MAX_LEN 255
-
-/* maximum length of bus, domain, ep name */
-#define KDBUS_SYSNAME_MAX_LEN 63
-
-/* maximum number of matches per connection */
-#define KDBUS_MATCH_MAX 4096
-
-/* maximum number of queued messages from the same individual user */
-#define KDBUS_CONN_MAX_MSGS 256
-
-/* maximum number of well-known names per connection */
-#define KDBUS_CONN_MAX_NAMES 256
-
-/* maximum number of queued requests waiting for a reply */
-#define KDBUS_CONN_MAX_REQUESTS_PENDING 128
-
-/* maximum number of connections per user in one domain */
-#define KDBUS_USER_MAX_CONN 1024
-
-/* maximum number of buses per user in one domain */
-#define KDBUS_USER_MAX_BUSES 16
-
-#endif
diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c
deleted file mode 100644
index c2117ea53..000000000
--- a/ipc/kdbus/main.c
+++ /dev/null
@@ -1,111 +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
- *
- * 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.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include "util.h"
-#include "fs.h"
-#include "handle.h"
-#include "metadata.h"
-#include "node.h"
-
-/*
- * This is a simplified outline of the internal kdbus object relations, for
- * those interested in the inner life of the driver implementation.
- *
- * From a mount point's (domain's) perspective:
- *
- * struct kdbus_domain
- * |» struct kdbus_user *user (many, owned)
- * '» struct kdbus_node node (embedded)
- * |» struct kdbus_node children (many, referenced)
- * |» struct kdbus_node *parent (pinned)
- * '» struct kdbus_bus (many, pinned)
- * |» struct kdbus_node node (embedded)
- * '» struct kdbus_ep (many, pinned)
- * |» struct kdbus_node node (embedded)
- * |» struct kdbus_bus *bus (pinned)
- * |» struct kdbus_conn conn_list (many, pinned)
- * | |» struct kdbus_ep *ep (pinned)
- * | |» struct kdbus_name_entry *activator_of (owned)
- * | |» struct kdbus_match_db *match_db (owned)
- * | |» struct kdbus_meta *meta (owned)
- * | |» struct kdbus_match_db *match_db (owned)
- * | | '» struct kdbus_match_entry (many, owned)
- * | |
- * | |» struct kdbus_pool *pool (owned)
- * | | '» struct kdbus_pool_slice *slices (many, owned)
- * | | '» struct kdbus_pool *pool (pinned)
- * | |
- * | |» struct kdbus_user *user (pinned)
- * | `» struct kdbus_queue_entry entries (many, embedded)
- * | |» struct kdbus_pool_slice *slice (pinned)
- * | |» struct kdbus_conn_reply *reply (owned)
- * | '» struct kdbus_user *user (pinned)
- * |
- * '» struct kdbus_user *user (pinned)
- * '» struct kdbus_policy_db policy_db (embedded)
- * |» struct kdbus_policy_db_entry (many, owned)
- * | |» struct kdbus_conn (pinned)
- * | '» struct kdbus_ep (pinned)
- * |
- * '» struct kdbus_policy_db_cache_entry (many, owned)
- * '» struct kdbus_conn (pinned)
- *
- * For the life-time of a file descriptor derived from calling open() on a file
- * inside the mount point:
- *
- * struct kdbus_handle
- * |» struct kdbus_meta *meta (owned)
- * |» struct kdbus_ep *ep (pinned)
- * |» struct kdbus_conn *conn (owned)
- * '» struct kdbus_ep *ep (owned)
- */
-
-static int __init kdbus_init(void)
-{
- int ret;
-
- ret = sysfs_create_mount_point(fs_kobj, KBUILD_MODNAME);
- if (ret)
- return ret;
-
- ret = kdbus_fs_init();
- if (ret < 0) {
- pr_err("cannot register filesystem: %d\n", ret);
- goto exit_dir;
- }
-
- pr_info("initialized\n");
- return 0;
-
-exit_dir:
- sysfs_remove_mount_point(fs_kobj, KBUILD_MODNAME);
- return ret;
-}
-
-static void __exit kdbus_exit(void)
-{
- kdbus_fs_exit();
- sysfs_remove_mount_point(fs_kobj, KBUILD_MODNAME);
- ida_destroy(&kdbus_node_ida);
-}
-
-module_init(kdbus_init);
-module_exit(kdbus_exit);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication");
-MODULE_ALIAS_FS(KBUILD_MODNAME "fs");
diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c
deleted file mode 100644
index 4ee6a1f2e..000000000
--- a/ipc/kdbus/match.c
+++ /dev/null
@@ -1,546 +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/hash.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-
-/**
- * struct kdbus_match_db - message filters
- * @entries_list: List of matches
- * @mdb_rwlock: Match data lock
- * @entries_count: Number of entries in database
- */
-struct kdbus_match_db {
- struct list_head entries_list;
- struct rw_semaphore mdb_rwlock;
- unsigned int entries_count;
-};
-
-/**
- * struct kdbus_match_entry - a match database entry
- * @cookie: User-supplied cookie to lookup the entry
- * @list_entry: The list entry element for the db list
- * @rules_list: The list head for tracking rules of this entry
- */
-struct kdbus_match_entry {
- u64 cookie;
- struct list_head list_entry;
- struct list_head rules_list;
-};
-
-/**
- * struct kdbus_bloom_mask - mask to match against filter
- * @generations: Number of generations carried
- * @data: Array of bloom bit fields
- */
-struct kdbus_bloom_mask {
- u64 generations;
- u64 *data;
-};
-
-/**
- * struct kdbus_match_rule - a rule appended to a match entry
- * @type: An item type to match against
- * @bloom_mask: Bloom mask to match a message's filter against, used
- * with KDBUS_ITEM_BLOOM_MASK
- * @name: Name to match against, used with KDBUS_ITEM_NAME,
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
- * @old_id: ID to match against, used with
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
- * KDBUS_ITEM_ID_REMOVE
- * @new_id: ID to match against, used with
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
- * KDBUS_ITEM_ID_REMOVE
- * @src_id: ID to match against, used with KDBUS_ITEM_ID
- * @dst_id: Message destination ID, used with KDBUS_ITEM_DST_ID
- * @rules_entry: Entry in the entry's rules list
- */
-struct kdbus_match_rule {
- u64 type;
- union {
- struct kdbus_bloom_mask bloom_mask;
- struct {
- char *name;
- u64 old_id;
- u64 new_id;
- };
- u64 src_id;
- u64 dst_id;
- };
- struct list_head rules_entry;
-};
-
-static void kdbus_match_rule_free(struct kdbus_match_rule *rule)
-{
- if (!rule)
- return;
-
- switch (rule->type) {
- case KDBUS_ITEM_BLOOM_MASK:
- kfree(rule->bloom_mask.data);
- break;
-
- case KDBUS_ITEM_NAME:
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- kfree(rule->name);
- break;
-
- case KDBUS_ITEM_ID:
- case KDBUS_ITEM_DST_ID:
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- break;
-
- default:
- BUG();
- }
-
- list_del(&rule->rules_entry);
- kfree(rule);
-}
-
-static void kdbus_match_entry_free(struct kdbus_match_entry *entry)
-{
- struct kdbus_match_rule *r, *tmp;
-
- if (!entry)
- return;
-
- list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry)
- kdbus_match_rule_free(r);
-
- list_del(&entry->list_entry);
- kfree(entry);
-}
-
-/**
- * kdbus_match_db_free() - free match db resources
- * @mdb: The match database
- */
-void kdbus_match_db_free(struct kdbus_match_db *mdb)
-{
- struct kdbus_match_entry *entry, *tmp;
-
- if (!mdb)
- return;
-
- list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
- kdbus_match_entry_free(entry);
-
- kfree(mdb);
-}
-
-/**
- * kdbus_match_db_new() - create a new match database
- *
- * Return: a new kdbus_match_db on success, ERR_PTR on failure.
- */
-struct kdbus_match_db *kdbus_match_db_new(void)
-{
- struct kdbus_match_db *d;
-
- d = kzalloc(sizeof(*d), GFP_KERNEL);
- if (!d)
- return ERR_PTR(-ENOMEM);
-
- init_rwsem(&d->mdb_rwlock);
- INIT_LIST_HEAD(&d->entries_list);
-
- return d;
-}
-
-static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter,
- const struct kdbus_bloom_mask *mask,
- const struct kdbus_conn *conn)
-{
- size_t n = conn->ep->bus->bloom.size / sizeof(u64);
- const u64 *m;
- size_t i;
-
- /*
- * The message's filter carries a generation identifier, the
- * match's mask possibly carries an array of multiple generations
- * of the mask. Select the mask with the closest match of the
- * filter's generation.
- */
- m = mask->data + (min(filter->generation, mask->generations - 1) * n);
-
- /*
- * The message's filter contains the messages properties,
- * the match's mask contains the properties to look for in the
- * message. Check the mask bit field against the filter bit field,
- * if the message possibly carries the properties the connection
- * has subscribed to.
- */
- for (i = 0; i < n; i++)
- if ((filter->data[i] & m[i]) != m[i])
- return false;
-
- return true;
-}
-
-static bool kdbus_match_rule_conn(const struct kdbus_match_rule *r,
- struct kdbus_conn *c,
- const struct kdbus_staging *s)
-{
- lockdep_assert_held(&c->ep->bus->name_registry->rwlock);
-
- switch (r->type) {
- case KDBUS_ITEM_BLOOM_MASK:
- return kdbus_match_bloom(s->bloom_filter, &r->bloom_mask, c);
- case KDBUS_ITEM_ID:
- return r->src_id == c->id || r->src_id == KDBUS_MATCH_ID_ANY;
- case KDBUS_ITEM_DST_ID:
- return r->dst_id == s->msg->dst_id ||
- r->dst_id == KDBUS_MATCH_ID_ANY;
- case KDBUS_ITEM_NAME:
- return kdbus_conn_has_name(c, r->name);
- default:
- return false;
- }
-}
-
-static bool kdbus_match_rule_kernel(const struct kdbus_match_rule *r,
- const struct kdbus_staging *s)
-{
- struct kdbus_item *n = s->notify;
-
- if (WARN_ON(!n) || n->type != r->type)
- return false;
-
- switch (r->type) {
- case KDBUS_ITEM_ID_ADD:
- return r->new_id == KDBUS_MATCH_ID_ANY ||
- r->new_id == n->id_change.id;
- case KDBUS_ITEM_ID_REMOVE:
- return r->old_id == KDBUS_MATCH_ID_ANY ||
- r->old_id == n->id_change.id;
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_CHANGE:
- case KDBUS_ITEM_NAME_REMOVE:
- return (r->old_id == KDBUS_MATCH_ID_ANY ||
- r->old_id == n->name_change.old_id.id) &&
- (r->new_id == KDBUS_MATCH_ID_ANY ||
- r->new_id == n->name_change.new_id.id) &&
- (!r->name || !strcmp(r->name, n->name_change.name));
- default:
- return false;
- }
-}
-
-static bool kdbus_match_rules(const struct kdbus_match_entry *entry,
- struct kdbus_conn *c,
- const struct kdbus_staging *s)
-{
- struct kdbus_match_rule *r;
-
- list_for_each_entry(r, &entry->rules_list, rules_entry)
- if ((c && !kdbus_match_rule_conn(r, c, s)) ||
- (!c && !kdbus_match_rule_kernel(r, s)))
- return false;
-
- return true;
-}
-
-/**
- * kdbus_match_db_match_msg() - match a msg object agains the database entries
- * @mdb: The match database
- * @conn_src: The connection object originating the message
- * @staging: Staging object containing the message to match against
- *
- * This function will walk through all the database entries previously uploaded
- * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule
- * set, this function will return true.
- *
- * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src
- * is non-NULL.
- *
- * Return: true if there was a matching database entry, false otherwise.
- */
-bool kdbus_match_db_match_msg(struct kdbus_match_db *mdb,
- struct kdbus_conn *conn_src,
- const struct kdbus_staging *staging)
-{
- struct kdbus_match_entry *entry;
- bool matched = false;
-
- down_read(&mdb->mdb_rwlock);
- list_for_each_entry(entry, &mdb->entries_list, list_entry) {
- matched = kdbus_match_rules(entry, conn_src, staging);
- if (matched)
- break;
- }
- up_read(&mdb->mdb_rwlock);
-
- return matched;
-}
-
-static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb,
- u64 cookie)
-{
- struct kdbus_match_entry *entry, *tmp;
- bool found = false;
-
- list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
- if (entry->cookie == cookie) {
- kdbus_match_entry_free(entry);
- --mdb->entries_count;
- found = true;
- }
-
- return found ? 0 : -EBADSLT;
-}
-
-/**
- * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD
- * @conn: connection to operate on
- * @argp: command payload
- *
- * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively,
- * adds one new database entry with n rules attached to it. Each rule is
- * described with an kdbus_item, and an entry is considered matching if all
- * its rules are satisfied.
- *
- * The items attached to a kdbus_cmd_match struct have the following mapping:
- *
- * KDBUS_ITEM_BLOOM_MASK: A bloom mask
- * KDBUS_ITEM_NAME: A connection's source name
- * KDBUS_ITEM_ID: A connection ID
- * KDBUS_ITEM_DST_ID: A connection ID
- * KDBUS_ITEM_NAME_ADD:
- * KDBUS_ITEM_NAME_REMOVE:
- * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry
- * kdbus_notify_name_change
- * KDBUS_ITEM_ID_ADD:
- * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry
- * kdbus_notify_id_change
- *
- * For kdbus_notify_{id,name}_change structs, only the ID and name fields
- * are looked at when adding an entry. The flags are unused.
- *
- * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME, KDBUS_ITEM_ID,
- * and KDBUS_ITEM_DST_ID are used to match messages from userspace, while the
- * others apply to kernel-generated notifications.
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_match_db *mdb = conn->match_db;
- struct kdbus_match_entry *entry = NULL;
- struct kdbus_cmd_match *cmd;
- struct kdbus_item *item;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true },
- { .type = KDBUS_ITEM_NAME, .multiple = true },
- { .type = KDBUS_ITEM_ID, .multiple = true },
- { .type = KDBUS_ITEM_DST_ID, .multiple = true },
- { .type = KDBUS_ITEM_NAME_ADD, .multiple = true },
- { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true },
- { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true },
- { .type = KDBUS_ITEM_ID_ADD, .multiple = true },
- { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MATCH_REPLACE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- ret = -ENOMEM;
- goto exit;
- }
-
- entry->cookie = cmd->cookie;
- INIT_LIST_HEAD(&entry->list_entry);
- INIT_LIST_HEAD(&entry->rules_list);
-
- KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
- struct kdbus_match_rule *rule;
- size_t size = item->size - offsetof(struct kdbus_item, data);
-
- rule = kzalloc(sizeof(*rule), GFP_KERNEL);
- if (!rule) {
- ret = -ENOMEM;
- goto exit;
- }
-
- rule->type = item->type;
- INIT_LIST_HEAD(&rule->rules_entry);
-
- switch (item->type) {
- case KDBUS_ITEM_BLOOM_MASK: {
- u64 bsize = conn->ep->bus->bloom.size;
- u64 generations;
- u64 remainder;
-
- generations = div64_u64_rem(size, bsize, &remainder);
- if (size < bsize || remainder > 0) {
- ret = -EDOM;
- break;
- }
-
- rule->bloom_mask.data = kmemdup(item->data,
- size, GFP_KERNEL);
- if (!rule->bloom_mask.data) {
- ret = -ENOMEM;
- break;
- }
-
- rule->bloom_mask.generations = generations;
- break;
- }
-
- case KDBUS_ITEM_NAME:
- if (!kdbus_name_is_valid(item->str, false)) {
- ret = -EINVAL;
- break;
- }
-
- rule->name = kstrdup(item->str, GFP_KERNEL);
- if (!rule->name)
- ret = -ENOMEM;
-
- break;
-
- case KDBUS_ITEM_ID:
- rule->src_id = item->id;
- break;
-
- case KDBUS_ITEM_DST_ID:
- rule->dst_id = item->id;
- break;
-
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- rule->old_id = item->name_change.old_id.id;
- rule->new_id = item->name_change.new_id.id;
-
- if (size > sizeof(struct kdbus_notify_name_change)) {
- rule->name = kstrdup(item->name_change.name,
- GFP_KERNEL);
- if (!rule->name)
- ret = -ENOMEM;
- }
-
- break;
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- if (item->type == KDBUS_ITEM_ID_ADD)
- rule->new_id = item->id_change.id;
- else
- rule->old_id = item->id_change.id;
-
- break;
- }
-
- if (ret < 0) {
- kdbus_match_rule_free(rule);
- goto exit;
- }
-
- list_add_tail(&rule->rules_entry, &entry->rules_list);
- }
-
- down_write(&mdb->mdb_rwlock);
-
- /* Remove any entry that has the same cookie as the current one. */
- if (cmd->flags & KDBUS_MATCH_REPLACE)
- kdbus_match_db_remove_unlocked(mdb, entry->cookie);
-
- /*
- * If the above removal caught any entry, there will be room for the
- * new one.
- */
- if (++mdb->entries_count > KDBUS_MATCH_MAX) {
- --mdb->entries_count;
- ret = -EMFILE;
- } else {
- list_add_tail(&entry->list_entry, &mdb->entries_list);
- entry = NULL;
- }
-
- up_write(&mdb->mdb_rwlock);
-
-exit:
- kdbus_match_entry_free(entry);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_match_remove() - handle KDBUS_CMD_MATCH_REMOVE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_match *cmd;
- 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),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- down_write(&conn->match_db->mdb_rwlock);
- ret = kdbus_match_db_remove_unlocked(conn->match_db, cmd->cookie);
- up_write(&conn->match_db->mdb_rwlock);
-
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/match.h b/ipc/kdbus/match.h
deleted file mode 100644
index ceb492f8e..000000000
--- a/ipc/kdbus/match.h
+++ /dev/null
@@ -1,35 +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.
- */
-
-#ifndef __KDBUS_MATCH_H
-#define __KDBUS_MATCH_H
-
-struct kdbus_conn;
-struct kdbus_match_db;
-struct kdbus_staging;
-
-struct kdbus_match_db *kdbus_match_db_new(void);
-void kdbus_match_db_free(struct kdbus_match_db *db);
-int kdbus_match_db_add(struct kdbus_conn *conn,
- struct kdbus_cmd_match *cmd);
-int kdbus_match_db_remove(struct kdbus_conn *conn,
- struct kdbus_cmd_match *cmd);
-bool kdbus_match_db_match_msg(struct kdbus_match_db *db,
- struct kdbus_conn *conn_src,
- const struct kdbus_staging *staging);
-
-int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp);
-
-#endif
diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
deleted file mode 100644
index ae565cd34..000000000
--- a/ipc/kdbus/message.c
+++ /dev/null
@@ -1,1040 +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/capability.h>
-#include <linux/cgroup.h>
-#include <linux/cred.h>
-#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <net/sock.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-#include "policy.h"
-
-static const char * const zeros = "\0\0\0\0\0\0\0";
-
-static struct kdbus_gaps *kdbus_gaps_new(size_t n_memfds, size_t n_fds)
-{
- size_t size_offsets, size_memfds, size_fds, size;
- struct kdbus_gaps *gaps;
-
- size_offsets = n_memfds * sizeof(*gaps->memfd_offsets);
- size_memfds = n_memfds * sizeof(*gaps->memfd_files);
- size_fds = n_fds * sizeof(*gaps->fd_files);
- size = sizeof(*gaps) + size_offsets + size_memfds + size_fds;
-
- gaps = kzalloc(size, GFP_KERNEL);
- if (!gaps)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&gaps->kref);
- gaps->n_memfds = 0; /* we reserve n_memfds, but don't enforce them */
- gaps->memfd_offsets = (void *)(gaps + 1);
- gaps->memfd_files = (void *)((u8 *)gaps->memfd_offsets + size_offsets);
- gaps->n_fds = 0; /* we reserve n_fds, but don't enforce them */
- gaps->fd_files = (void *)((u8 *)gaps->memfd_files + size_memfds);
-
- return gaps;
-}
-
-static void kdbus_gaps_free(struct kref *kref)
-{
- struct kdbus_gaps *gaps = container_of(kref, struct kdbus_gaps, kref);
- size_t i;
-
- for (i = 0; i < gaps->n_fds; ++i)
- if (gaps->fd_files[i])
- fput(gaps->fd_files[i]);
- for (i = 0; i < gaps->n_memfds; ++i)
- if (gaps->memfd_files[i])
- fput(gaps->memfd_files[i]);
-
- kfree(gaps);
-}
-
-/**
- * kdbus_gaps_ref() - gain reference
- * @gaps: gaps object
- *
- * Return: @gaps is returned
- */
-struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps)
-{
- if (gaps)
- kref_get(&gaps->kref);
- return gaps;
-}
-
-/**
- * kdbus_gaps_unref() - drop reference
- * @gaps: gaps object
- *
- * Return: NULL
- */
-struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps)
-{
- if (gaps)
- kref_put(&gaps->kref, kdbus_gaps_free);
- return NULL;
-}
-
-/**
- * kdbus_gaps_install() - install file-descriptors
- * @gaps: gaps object, or NULL
- * @slice: pool slice that contains the message
- * @out_incomplete output variable to note incomplete fds
- *
- * This function installs all file-descriptors of @gaps into the current
- * process and copies the file-descriptor numbers into the target pool slice.
- *
- * If the file-descriptors were only partially installed, then @out_incomplete
- * will be set to true. Otherwise, it's set to false.
- *
- * Return: 0 on success, negative error code on failure
- */
-int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice,
- bool *out_incomplete)
-{
- bool incomplete_fds = false;
- struct kvec kvec;
- size_t i, n_fds;
- int ret, *fds;
-
- if (!gaps) {
- /* nothing to do */
- *out_incomplete = incomplete_fds;
- return 0;
- }
-
- n_fds = gaps->n_fds + gaps->n_memfds;
- if (n_fds < 1) {
- /* nothing to do */
- *out_incomplete = incomplete_fds;
- return 0;
- }
-
- fds = kmalloc_array(n_fds, sizeof(*fds), GFP_TEMPORARY);
- n_fds = 0;
- if (!fds)
- return -ENOMEM;
-
- /* 1) allocate fds and copy them over */
-
- if (gaps->n_fds > 0) {
- for (i = 0; i < gaps->n_fds; ++i) {
- int fd;
-
- fd = get_unused_fd_flags(O_CLOEXEC);
- if (fd < 0)
- incomplete_fds = true;
-
- WARN_ON(!gaps->fd_files[i]);
-
- fds[n_fds++] = fd < 0 ? -1 : fd;
- }
-
- /*
- * The file-descriptor array can only be present once per
- * message. Hence, prepare all fds and then copy them over with
- * a single kvec.
- */
-
- WARN_ON(!gaps->fd_offset);
-
- kvec.iov_base = fds;
- kvec.iov_len = gaps->n_fds * sizeof(*fds);
- ret = kdbus_pool_slice_copy_kvec(slice, gaps->fd_offset,
- &kvec, 1, kvec.iov_len);
- if (ret < 0)
- goto exit;
- }
-
- for (i = 0; i < gaps->n_memfds; ++i) {
- int memfd;
-
- memfd = get_unused_fd_flags(O_CLOEXEC);
- if (memfd < 0) {
- incomplete_fds = true;
- /* memfds are initialized to -1, skip copying it */
- continue;
- }
-
- fds[n_fds++] = memfd;
-
- /*
- * memfds have to be copied individually as they each are put
- * into a separate item. This should not be an issue, though,
- * as usually there is no need to send more than one memfd per
- * message.
- */
-
- WARN_ON(!gaps->memfd_offsets[i]);
- WARN_ON(!gaps->memfd_files[i]);
-
- kvec.iov_base = &memfd;
- kvec.iov_len = sizeof(memfd);
- ret = kdbus_pool_slice_copy_kvec(slice, gaps->memfd_offsets[i],
- &kvec, 1, kvec.iov_len);
- if (ret < 0)
- goto exit;
- }
-
- /* 2) install fds now that everything was successful */
-
- for (i = 0; i < gaps->n_fds; ++i)
- if (fds[i] >= 0)
- fd_install(fds[i], get_file(gaps->fd_files[i]));
- for (i = 0; i < gaps->n_memfds; ++i)
- if (fds[gaps->n_fds + i] >= 0)
- fd_install(fds[gaps->n_fds + i],
- get_file(gaps->memfd_files[i]));
-
- ret = 0;
-
-exit:
- if (ret < 0)
- for (i = 0; i < n_fds; ++i)
- put_unused_fd(fds[i]);
- kfree(fds);
- *out_incomplete = incomplete_fds;
- return ret;
-}
-
-static struct file *kdbus_get_fd(int fd)
-{
- struct file *f, *ret;
- struct inode *inode;
- struct socket *sock;
-
- if (fd < 0)
- return ERR_PTR(-EBADF);
-
- f = fget_raw(fd);
- if (!f)
- return ERR_PTR(-EBADF);
-
- inode = file_inode(f);
- sock = S_ISSOCK(inode->i_mode) ? SOCKET_I(inode) : NULL;
-
- if (f->f_mode & FMODE_PATH)
- ret = f; /* O_PATH is always allowed */
- else if (f->f_op == &kdbus_handle_ops)
- ret = ERR_PTR(-EOPNOTSUPP); /* disallow kdbus-fd over kdbus */
- else if (sock && sock->sk && sock->ops && sock->ops->family == PF_UNIX)
- ret = ERR_PTR(-EOPNOTSUPP); /* disallow UDS over kdbus */
- else
- ret = f; /* all other are allowed */
-
- if (f != ret)
- fput(f);
-
- return ret;
-}
-
-static struct file *kdbus_get_memfd(const struct kdbus_memfd *memfd)
-{
- const int m = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL;
- struct file *f, *ret;
- int s;
-
- if (memfd->fd < 0)
- return ERR_PTR(-EBADF);
-
- f = fget(memfd->fd);
- if (!f)
- return ERR_PTR(-EBADF);
-
- s = shmem_get_seals(f);
- if (s < 0)
- ret = ERR_PTR(-EMEDIUMTYPE);
- else if ((s & m) != m)
- ret = ERR_PTR(-ETXTBSY);
- else if (memfd->start + memfd->size > (u64)i_size_read(file_inode(f)))
- ret = ERR_PTR(-EFAULT);
- else
- ret = f;
-
- if (f != ret)
- fput(f);
-
- return ret;
-}
-
-static int kdbus_msg_examine(struct kdbus_msg *msg, struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd, size_t *out_n_memfds,
- size_t *out_n_fds, size_t *out_n_parts)
-{
- struct kdbus_item *item, *fds = NULL, *bloom = NULL, *dstname = NULL;
- u64 n_parts, n_memfds, n_fds, vec_size;
-
- /*
- * Step 1:
- * Validate the message and command parameters.
- */
-
- /* KDBUS_PAYLOAD_KERNEL is reserved to kernel messages */
- if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
- return -EINVAL;
-
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST) {
- /* broadcasts must be marked as signals */
- if (!(msg->flags & KDBUS_MSG_SIGNAL))
- return -EBADMSG;
- /* broadcasts cannot have timeouts */
- if (msg->timeout_ns > 0)
- return -ENOTUNIQ;
- }
-
- if (msg->flags & KDBUS_MSG_EXPECT_REPLY) {
- /* if you expect a reply, you must specify a timeout */
- if (msg->timeout_ns == 0)
- return -EINVAL;
- /* signals cannot have replies */
- if (msg->flags & KDBUS_MSG_SIGNAL)
- return -ENOTUNIQ;
- } else {
- /* must expect reply if sent as synchronous call */
- if (cmd->flags & KDBUS_SEND_SYNC_REPLY)
- return -EINVAL;
- /* cannot mark replies as signal */
- if (msg->cookie_reply && (msg->flags & KDBUS_MSG_SIGNAL))
- return -EINVAL;
- }
-
- /*
- * Step 2:
- * Validate all passed items. While at it, select some statistics that
- * are required to allocate state objects later on.
- *
- * Generic item validation has already been done via
- * kdbus_item_validate(). Furthermore, the number of items is naturally
- * limited by the maximum message size. Hence, only non-generic item
- * checks are performed here (mainly integer overflow tests).
- */
-
- n_parts = 0;
- n_memfds = 0;
- n_fds = 0;
- vec_size = 0;
-
- KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) {
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_VEC: {
- void __force __user *ptr = KDBUS_PTR(item->vec.address);
- u64 size = item->vec.size;
-
- if (vec_size + size < vec_size)
- return -EMSGSIZE;
- if (vec_size + size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
- return -EMSGSIZE;
- if (ptr && unlikely(!access_ok(VERIFY_READ, ptr, size)))
- return -EFAULT;
-
- if (ptr || size % 8) /* data or padding */
- ++n_parts;
- break;
- }
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- u64 start = item->memfd.start;
- u64 size = item->memfd.size;
-
- if (start + size < start)
- return -EMSGSIZE;
- if (n_memfds >= KDBUS_MSG_MAX_MEMFD_ITEMS)
- return -E2BIG;
-
- ++n_memfds;
- if (size % 8) /* vec-padding required */
- ++n_parts;
- break;
- }
- case KDBUS_ITEM_FDS: {
- if (fds)
- return -EEXIST;
-
- fds = item;
- n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int);
- if (n_fds > KDBUS_CONN_MAX_FDS_PER_USER)
- return -EMFILE;
-
- break;
- }
- case KDBUS_ITEM_BLOOM_FILTER: {
- u64 bloom_size;
-
- if (bloom)
- return -EEXIST;
-
- bloom = item;
- bloom_size = KDBUS_ITEM_PAYLOAD_SIZE(item) -
- offsetof(struct kdbus_bloom_filter, data);
- if (!KDBUS_IS_ALIGNED8(bloom_size))
- return -EFAULT;
- if (bloom_size != bus->bloom.size)
- return -EDOM;
-
- break;
- }
- case KDBUS_ITEM_DST_NAME: {
- if (dstname)
- return -EEXIST;
-
- dstname = item;
- if (!kdbus_name_is_valid(item->str, false))
- return -EINVAL;
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
- return -EBADMSG;
-
- break;
- }
- default:
- return -EINVAL;
- }
- }
-
- /*
- * Step 3:
- * Validate that required items were actually passed, and that no item
- * contradicts the message flags.
- */
-
- /* bloom filters must be attached _iff_ it's a signal */
- if (!(msg->flags & KDBUS_MSG_SIGNAL) != !bloom)
- return -EBADMSG;
- /* destination name is required if no ID is given */
- if (msg->dst_id == KDBUS_DST_ID_NAME && !dstname)
- return -EDESTADDRREQ;
- /* cannot send file-descriptors attached to broadcasts */
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST && fds)
- return -ENOTUNIQ;
-
- *out_n_memfds = n_memfds;
- *out_n_fds = n_fds;
- *out_n_parts = n_parts;
-
- return 0;
-}
-
-static bool kdbus_staging_merge_vecs(struct kdbus_staging *staging,
- struct kdbus_item **prev_item,
- struct iovec **prev_vec,
- const struct kdbus_item *merge)
-{
- void __user *ptr = (void __user *)KDBUS_PTR(merge->vec.address);
- u64 padding = merge->vec.size % 8;
- struct kdbus_item *prev = *prev_item;
- struct iovec *vec = *prev_vec;
-
- /* XXX: merging is disabled so far */
- if (0 && prev && prev->type == KDBUS_ITEM_PAYLOAD_OFF &&
- !merge->vec.address == !prev->vec.address) {
- /*
- * If we merge two VECs, we can always drop the second
- * PAYLOAD_VEC item. Hence, include its size in the previous
- * one.
- */
- prev->vec.size += merge->vec.size;
-
- if (ptr) {
- /*
- * If we merge two data VECs, we need two iovecs to copy
- * the data. But the items can be easily merged by
- * summing their lengths.
- */
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = merge->vec.size;
- vec->iov_base = ptr;
- staging->n_payload += vec->iov_len;
- } else if (padding) {
- /*
- * If we merge two 0-vecs with the second 0-vec
- * requiring padding, we need to insert an iovec to copy
- * the 0-padding. We try merging it with the previous
- * 0-padding iovec. This might end up with an
- * iov_len==0, in which case we simply drop the iovec.
- */
- if (vec) {
- staging->n_payload -= vec->iov_len;
- vec->iov_len = prev->vec.size % 8;
- if (!vec->iov_len) {
- --staging->n_parts;
- vec = NULL;
- } else {
- staging->n_payload += vec->iov_len;
- }
- } else {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = padding;
- vec->iov_base = (char __user *)zeros;
- staging->n_payload += vec->iov_len;
- }
- } else {
- /*
- * If we merge two 0-vecs with the second 0-vec having
- * no padding, we know the padding of the first stays
- * the same. Hence, @vec needs no adjustment.
- */
- }
-
- /* successfully merged with previous item */
- merge = prev;
- } else {
- /*
- * If we cannot merge the payload item with the previous one,
- * we simply insert a new iovec for the data/padding.
- */
- if (ptr) {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = merge->vec.size;
- vec->iov_base = ptr;
- staging->n_payload += vec->iov_len;
- } else if (padding) {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = padding;
- vec->iov_base = (char __user *)zeros;
- staging->n_payload += vec->iov_len;
- } else {
- vec = NULL;
- }
- }
-
- *prev_item = (struct kdbus_item *)merge;
- *prev_vec = vec;
-
- return merge == prev;
-}
-
-static int kdbus_staging_import(struct kdbus_staging *staging)
-{
- struct kdbus_item *it, *item, *last, *prev_payload;
- struct kdbus_gaps *gaps = staging->gaps;
- struct kdbus_msg *msg = staging->msg;
- struct iovec *part, *prev_part;
- bool drop_item;
-
- drop_item = false;
- last = NULL;
- prev_payload = NULL;
- prev_part = NULL;
-
- /*
- * We modify msg->items along the way; make sure to use @item as offset
- * to the next item (instead of the iterator @it).
- */
- for (it = item = msg->items;
- it >= msg->items &&
- (u8 *)it < (u8 *)msg + msg->size &&
- (u8 *)it + it->size <= (u8 *)msg + msg->size; ) {
- /*
- * If we dropped items along the way, move current item to
- * front. We must not access @it afterwards, but use @item
- * instead!
- */
- if (it != item)
- memmove(item, it, it->size);
- it = (void *)((u8 *)it + KDBUS_ALIGN8(item->size));
-
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_VEC: {
- size_t offset = staging->n_payload;
-
- if (kdbus_staging_merge_vecs(staging, &prev_payload,
- &prev_part, item)) {
- drop_item = true;
- } else if (item->vec.address) {
- /* real offset is patched later on */
- item->type = KDBUS_ITEM_PAYLOAD_OFF;
- item->vec.offset = offset;
- } else {
- item->type = KDBUS_ITEM_PAYLOAD_OFF;
- item->vec.offset = ~0ULL;
- }
-
- break;
- }
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- struct file *f;
-
- f = kdbus_get_memfd(&item->memfd);
- if (IS_ERR(f))
- return PTR_ERR(f);
-
- gaps->memfd_files[gaps->n_memfds] = f;
- gaps->memfd_offsets[gaps->n_memfds] =
- (u8 *)&item->memfd.fd - (u8 *)msg;
- ++gaps->n_memfds;
-
- /* memfds cannot be merged */
- prev_payload = item;
- prev_part = NULL;
-
- /* insert padding to make following VECs aligned */
- if (item->memfd.size % 8) {
- part = &staging->parts[staging->n_parts++];
- part->iov_len = item->memfd.size % 8;
- part->iov_base = (char __user *)zeros;
- staging->n_payload += part->iov_len;
- }
-
- break;
- }
- case KDBUS_ITEM_FDS: {
- size_t i, n_fds;
-
- n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int);
- for (i = 0; i < n_fds; ++i) {
- struct file *f;
-
- f = kdbus_get_fd(item->fds[i]);
- if (IS_ERR(f))
- return PTR_ERR(f);
-
- gaps->fd_files[gaps->n_fds++] = f;
- }
-
- gaps->fd_offset = (u8 *)item->fds - (u8 *)msg;
-
- break;
- }
- case KDBUS_ITEM_BLOOM_FILTER:
- staging->bloom_filter = &item->bloom_filter;
- break;
- case KDBUS_ITEM_DST_NAME:
- staging->dst_name = item->str;
- break;
- }
-
- /* drop item if we merged it with a previous one */
- if (drop_item) {
- drop_item = false;
- } else {
- last = item;
- item = KDBUS_ITEM_NEXT(item);
- }
- }
-
- /* adjust message size regarding dropped items */
- msg->size = offsetof(struct kdbus_msg, items);
- if (last)
- msg->size += ((u8 *)last - (u8 *)msg->items) + last->size;
-
- return 0;
-}
-
-static void kdbus_staging_reserve(struct kdbus_staging *staging)
-{
- struct iovec *part;
-
- part = &staging->parts[staging->n_parts++];
- part->iov_base = (void __user *)zeros;
- part->iov_len = 0;
-}
-
-static struct kdbus_staging *kdbus_staging_new(struct kdbus_bus *bus,
- size_t n_parts,
- size_t msg_extra_size)
-{
- const size_t reserved_parts = 5; /* see below for explanation */
- struct kdbus_staging *staging;
- int ret;
-
- n_parts += reserved_parts;
-
- staging = kzalloc(sizeof(*staging) + n_parts * sizeof(*staging->parts) +
- msg_extra_size, GFP_TEMPORARY);
- if (!staging)
- return ERR_PTR(-ENOMEM);
-
- staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id);
- staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */
- staging->parts = (void *)(staging + 1);
-
- if (msg_extra_size) /* if requested, allocate message, too */
- staging->msg = (void *)((u8 *)staging->parts +
- n_parts * sizeof(*staging->parts));
-
- staging->meta_proc = kdbus_meta_proc_new();
- if (IS_ERR(staging->meta_proc)) {
- ret = PTR_ERR(staging->meta_proc);
- staging->meta_proc = NULL;
- goto error;
- }
-
- staging->meta_conn = kdbus_meta_conn_new();
- if (IS_ERR(staging->meta_conn)) {
- ret = PTR_ERR(staging->meta_conn);
- staging->meta_conn = NULL;
- goto error;
- }
-
- /*
- * Prepare iovecs to copy the message into the target pool. We use the
- * following iovecs:
- * * iovec to copy "kdbus_msg.size"
- * * iovec to copy "struct kdbus_msg" (minus size) plus items
- * * iovec for possible padding after the items
- * * iovec for metadata items
- * * iovec for possible padding after the items
- *
- * Make sure to update @reserved_parts if you add more parts here.
- */
-
- kdbus_staging_reserve(staging); /* msg.size */
- kdbus_staging_reserve(staging); /* msg (minus msg.size) plus items */
- kdbus_staging_reserve(staging); /* msg padding */
- kdbus_staging_reserve(staging); /* meta */
- kdbus_staging_reserve(staging); /* meta padding */
-
- return staging;
-
-error:
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
-}
-
-struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus,
- u64 dst, u64 cookie_timeout,
- size_t it_size, size_t it_type)
-{
- struct kdbus_staging *staging;
- size_t size;
-
- size = offsetof(struct kdbus_msg, items) +
- KDBUS_ITEM_HEADER_SIZE + it_size;
-
- staging = kdbus_staging_new(bus, 0, KDBUS_ALIGN8(size));
- if (IS_ERR(staging))
- return ERR_CAST(staging);
-
- staging->msg->size = size;
- staging->msg->flags = (dst == KDBUS_DST_ID_BROADCAST) ?
- KDBUS_MSG_SIGNAL : 0;
- staging->msg->dst_id = dst;
- staging->msg->src_id = KDBUS_SRC_ID_KERNEL;
- staging->msg->payload_type = KDBUS_PAYLOAD_KERNEL;
- staging->msg->cookie_reply = cookie_timeout;
- staging->notify = staging->msg->items;
- staging->notify->size = KDBUS_ITEM_HEADER_SIZE + it_size;
- staging->notify->type = it_type;
-
- return staging;
-}
-
-struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd,
- struct kdbus_msg *msg)
-{
- const size_t reserved_parts = 1; /* see below for explanation */
- size_t n_memfds, n_fds, n_parts;
- struct kdbus_staging *staging;
- int ret;
-
- /*
- * Examine user-supplied message and figure out how many resources we
- * need to allocate in our staging area. This requires us to iterate
- * the message twice, but saves us from re-allocating our resources
- * all the time.
- */
-
- ret = kdbus_msg_examine(msg, bus, cmd, &n_memfds, &n_fds, &n_parts);
- if (ret < 0)
- return ERR_PTR(ret);
-
- n_parts += reserved_parts;
-
- /*
- * Allocate staging area with the number of required resources. Make
- * sure that we have enough iovecs for all required parts pre-allocated
- * so this will hopefully be the only memory allocation for this
- * message transaction.
- */
-
- staging = kdbus_staging_new(bus, n_parts, 0);
- if (IS_ERR(staging))
- return ERR_CAST(staging);
-
- staging->msg = msg;
-
- /*
- * If the message contains memfds or fd items, we need to remember some
- * state so we can fill in the requested information at RECV time.
- * File-descriptors cannot be passed at SEND time. Hence, allocate a
- * gaps-object to remember that state. That gaps object is linked to
- * from the staging area, but will also be linked to from the message
- * queue of each peer. Hence, each receiver owns a reference to it, and
- * it will later be used to fill the 'gaps' in message that couldn't be
- * filled at SEND time.
- * Note that the 'gaps' object is read-only once the staging-allocator
- * returns. There might be connections receiving a queued message while
- * the sender still broadcasts the message to other receivers.
- */
-
- if (n_memfds > 0 || n_fds > 0) {
- staging->gaps = kdbus_gaps_new(n_memfds, n_fds);
- if (IS_ERR(staging->gaps)) {
- ret = PTR_ERR(staging->gaps);
- staging->gaps = NULL;
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
- }
- }
-
- /*
- * kdbus_staging_new() already reserves parts for message setup. For
- * user-supplied messages, we add the following iovecs:
- * ... variable number of iovecs for payload ...
- * * final iovec for possible padding of payload
- *
- * Make sure to update @reserved_parts if you add more parts here.
- */
-
- ret = kdbus_staging_import(staging); /* payload */
- kdbus_staging_reserve(staging); /* payload padding */
-
- if (ret < 0)
- goto error;
-
- return staging;
-
-error:
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
-}
-
-struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging)
-{
- if (!staging)
- return NULL;
-
- kdbus_meta_conn_unref(staging->meta_conn);
- kdbus_meta_proc_unref(staging->meta_proc);
- kdbus_gaps_unref(staging->gaps);
- kfree(staging);
-
- return NULL;
-}
-
-static int kdbus_staging_collect_metadata(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst,
- u64 *out_attach)
-{
- u64 attach;
- int ret;
-
- if (src)
- attach = kdbus_meta_msg_mask(src, dst);
- else
- attach = KDBUS_ATTACH_TIMESTAMP; /* metadata for kernel msgs */
-
- if (src && !src->meta_fake) {
- ret = kdbus_meta_proc_collect(staging->meta_proc, attach);
- if (ret < 0)
- return ret;
- }
-
- ret = kdbus_meta_conn_collect(staging->meta_conn, src,
- staging->msg_seqnum, attach);
- if (ret < 0)
- return ret;
-
- *out_attach = attach;
- return 0;
-}
-
-/**
- * kdbus_staging_emit() - emit linearized message in target pool
- * @staging: staging object to create message from
- * @src: sender of the message (or NULL)
- * @dst: target connection to allocate message for
- *
- * This allocates a pool-slice for @dst and copies the message provided by
- * @staging into it. The new slice is then returned to the caller for further
- * processing. It's not linked into any queue, yet.
- *
- * Return: Newly allocated slice or ERR_PTR on failure.
- */
-struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst)
-{
- struct kdbus_item *item, *meta_items = NULL;
- struct kdbus_pool_slice *slice = NULL;
- size_t off, size, meta_size;
- struct iovec *v;
- u64 attach, msg_size;
- int ret;
-
- /*
- * Step 1:
- * Collect metadata from @src depending on the attach-flags allowed for
- * @dst. Translate it into the namespaces pinned by @dst.
- */
-
- ret = kdbus_staging_collect_metadata(staging, src, dst, &attach);
- if (ret < 0)
- goto error;
-
- ret = kdbus_meta_emit(staging->meta_proc, NULL, staging->meta_conn,
- dst, attach, &meta_items, &meta_size);
- if (ret < 0)
- goto error;
-
- /*
- * Step 2:
- * Setup iovecs for the message. See kdbus_staging_new() for allocation
- * of those iovecs. All reserved iovecs have been initialized with
- * iov_len=0 + iov_base=zeros. Furthermore, the iovecs to copy the
- * actual message payload have already been initialized and need not be
- * touched.
- */
-
- v = staging->parts;
- msg_size = staging->msg->size;
-
- /* msg.size */
- v->iov_len = sizeof(msg_size);
- v->iov_base = (void __user *)&msg_size;
- ++v;
-
- /* msg (after msg.size) plus items */
- v->iov_len = staging->msg->size - sizeof(staging->msg->size);
- v->iov_base = (void __user *)((u8 *)staging->msg +
- sizeof(staging->msg->size));
- ++v;
-
- /* padding after msg */
- v->iov_len = KDBUS_ALIGN8(staging->msg->size) - staging->msg->size;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- if (meta_size > 0) {
- /* metadata items */
- v->iov_len = meta_size;
- v->iov_base = (void __user *)meta_items;
- ++v;
-
- /* padding after metadata */
- v->iov_len = KDBUS_ALIGN8(meta_size) - meta_size;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- msg_size = KDBUS_ALIGN8(msg_size) + meta_size;
- } else {
- /* metadata items */
- v->iov_len = 0;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- /* padding after metadata */
- v->iov_len = 0;
- v->iov_base = (void __user *)zeros;
- ++v;
- }
-
- /* ... payload iovecs are already filled in ... */
-
- /* compute overall size and fill in padding after payload */
- size = KDBUS_ALIGN8(msg_size);
-
- if (staging->n_payload > 0) {
- size += staging->n_payload;
-
- v = &staging->parts[staging->n_parts - 1];
- v->iov_len = KDBUS_ALIGN8(size) - size;
- v->iov_base = (void __user *)zeros;
-
- size = KDBUS_ALIGN8(size);
- }
-
- /*
- * Step 3:
- * The PAYLOAD_OFF items in the message contain a relative 'offset'
- * field that tells the receiver where to find the actual payload. This
- * offset is relative to the start of the message, and as such depends
- * on the size of the metadata items we inserted. This size is variable
- * and changes for each peer we send the message to. Hence, we remember
- * the last relative offset that was used to calculate the 'offset'
- * fields. For each message, we re-calculate it and patch all items, in
- * case it changed.
- */
-
- off = KDBUS_ALIGN8(msg_size);
-
- if (off != staging->i_payload) {
- KDBUS_ITEMS_FOREACH(item, staging->msg->items,
- KDBUS_ITEMS_SIZE(staging->msg, items)) {
- if (item->type != KDBUS_ITEM_PAYLOAD_OFF)
- continue;
-
- item->vec.offset -= staging->i_payload;
- item->vec.offset += off;
- }
-
- staging->i_payload = off;
- }
-
- /*
- * Step 4:
- * Allocate pool slice and copy over all data. Make sure to properly
- * account on user quota.
- */
-
- ret = kdbus_conn_quota_inc(dst, src ? src->user : NULL, size,
- staging->gaps ? staging->gaps->n_fds : 0);
- if (ret < 0)
- goto error;
-
- slice = kdbus_pool_slice_alloc(dst->pool, size, true);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto error;
- }
-
- WARN_ON(kdbus_pool_slice_size(slice) != size);
-
- ret = kdbus_pool_slice_copy_iovec(slice, 0, staging->parts,
- staging->n_parts, size);
- if (ret < 0)
- goto error;
-
- /* all done, return slice to caller */
- goto exit;
-
-error:
- if (slice)
- kdbus_conn_quota_dec(dst, src ? src->user : NULL, size,
- staging->gaps ? staging->gaps->n_fds : 0);
- kdbus_pool_slice_release(slice);
- slice = ERR_PTR(ret);
-exit:
- kfree(meta_items);
- return slice;
-}
diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h
deleted file mode 100644
index 298f9c99d..000000000
--- a/ipc/kdbus/message.h
+++ /dev/null
@@ -1,120 +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
- *
- * 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_MESSAGE_H
-#define __KDBUS_MESSAGE_H
-
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <uapi/linux/kdbus.h>
-
-struct kdbus_bus;
-struct kdbus_conn;
-struct kdbus_meta_conn;
-struct kdbus_meta_proc;
-struct kdbus_pool_slice;
-
-/**
- * struct kdbus_gaps - gaps in message to be filled later
- * @kref: Reference counter
- * @n_memfd_offs: Number of memfds
- * @memfd_offs: Offsets of kdbus_memfd items in target slice
- * @n_fds: Number of fds
- * @fds: Array of sent fds
- * @fds_offset: Offset of fd-array in target slice
- *
- * The 'gaps' object is used to track data that is needed to fill gaps in a
- * message at RECV time. Usually, we try to compile the whole message at SEND
- * time. This has the advantage, that we don't have to cache any information and
- * can keep the memory consumption small. Furthermore, all copy operations can
- * be combined into a single function call, which speeds up transactions
- * considerably.
- * However, things like file-descriptors can only be fully installed at RECV
- * time. The gaps object tracks this data and pins it until a message is
- * received. The gaps object is shared between all receivers of the same
- * message.
- */
-struct kdbus_gaps {
- struct kref kref;
-
- /* state tracking for KDBUS_ITEM_PAYLOAD_MEMFD entries */
- size_t n_memfds;
- u64 *memfd_offsets;
- struct file **memfd_files;
-
- /* state tracking for KDBUS_ITEM_FDS */
- size_t n_fds;
- struct file **fd_files;
- u64 fd_offset;
-};
-
-struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps);
-struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps);
-int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice,
- bool *out_incomplete);
-
-/**
- * struct kdbus_staging - staging area to import messages
- * @msg: User-supplied message
- * @gaps: Gaps-object created during import (or NULL if empty)
- * @msg_seqnum: Message sequence number
- * @notify_entry: Entry into list of kernel-generated notifications
- * @i_payload: Current relative index of start of payload
- * @n_payload: Total number of bytes needed for payload
- * @n_parts: Number of parts
- * @parts: Array of iovecs that make up the whole message
- * @meta_proc: Process metadata of the sender (or NULL if empty)
- * @meta_conn: Connection metadata of the sender (or NULL if empty)
- * @bloom_filter: Pointer to the bloom-item in @msg, or NULL
- * @dst_name: Pointer to the dst-name-item in @msg, or NULL
- * @notify: Pointer to the notification item in @msg, or NULL
- *
- * The kdbus_staging object is a temporary staging area to import user-supplied
- * messages into the kernel. It is only used during SEND and dropped once the
- * message is queued. Any data that cannot be collected during SEND, is
- * collected in a kdbus_gaps object and attached to the message queue.
- */
-struct kdbus_staging {
- struct kdbus_msg *msg;
- struct kdbus_gaps *gaps;
- u64 msg_seqnum;
- struct list_head notify_entry;
-
- /* crafted iovecs to copy the message */
- size_t i_payload;
- size_t n_payload;
- size_t n_parts;
- struct iovec *parts;
-
- /* metadata state */
- struct kdbus_meta_proc *meta_proc;
- struct kdbus_meta_conn *meta_conn;
-
- /* cached pointers into @msg */
- const struct kdbus_bloom_filter *bloom_filter;
- const char *dst_name;
- struct kdbus_item *notify;
-};
-
-struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus,
- u64 dst, u64 cookie_timeout,
- size_t it_size, size_t it_type);
-struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd,
- struct kdbus_msg *msg);
-struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging);
-struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst);
-
-#endif
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
deleted file mode 100644
index 71ca475a8..000000000
--- a/ipc/kdbus/metadata.c
+++ /dev/null
@@ -1,1347 +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/audit.h>
-#include <linux/capability.h>
-#include <linux/cgroup.h>
-#include <linux/cred.h>
-#include <linux/file.h>
-#include <linux/fs_struct.h>
-#include <linux/init.h>
-#include <linux/kref.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/security.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uidgid.h>
-#include <linux/uio.h>
-#include <linux/user_namespace.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "item.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-
-/**
- * struct kdbus_meta_proc - Process metadata
- * @kref: Reference counting
- * @lock: Object lock
- * @collected: Bitmask of collected items
- * @valid: Bitmask of collected and valid items
- * @cred: Credentials
- * @pid: PID of process
- * @tgid: TGID of process
- * @ppid: PPID of process
- * @tid_comm: TID comm line
- * @pid_comm: PID comm line
- * @exe_path: Executable path
- * @root_path: Root-FS path
- * @cmdline: Command-line
- * @cgroup: Full cgroup path
- * @seclabel: Seclabel
- * @audit_loginuid: Audit login-UID
- * @audit_sessionid: Audit session-ID
- */
-struct kdbus_meta_proc {
- struct kref kref;
- struct mutex lock;
- u64 collected;
- u64 valid;
-
- /* KDBUS_ITEM_CREDS */
- /* KDBUS_ITEM_AUXGROUPS */
- /* KDBUS_ITEM_CAPS */
- const struct cred *cred;
-
- /* KDBUS_ITEM_PIDS */
- struct pid *pid;
- struct pid *tgid;
- struct pid *ppid;
-
- /* KDBUS_ITEM_TID_COMM */
- char tid_comm[TASK_COMM_LEN];
- /* KDBUS_ITEM_PID_COMM */
- char pid_comm[TASK_COMM_LEN];
-
- /* KDBUS_ITEM_EXE */
- struct path exe_path;
- struct path root_path;
-
- /* KDBUS_ITEM_CMDLINE */
- char *cmdline;
-
- /* KDBUS_ITEM_CGROUP */
- char *cgroup;
-
- /* KDBUS_ITEM_SECLABEL */
- char *seclabel;
-
- /* KDBUS_ITEM_AUDIT */
- kuid_t audit_loginuid;
- unsigned int audit_sessionid;
-};
-
-/**
- * struct kdbus_meta_conn
- * @kref: Reference counting
- * @lock: Object lock
- * @collected: Bitmask of collected items
- * @valid: Bitmask of collected and valid items
- * @ts: Timestamp values
- * @owned_names_items: Serialized items for owned names
- * @owned_names_size: Size of @owned_names_items
- * @conn_description: Connection description
- */
-struct kdbus_meta_conn {
- struct kref kref;
- struct mutex lock;
- u64 collected;
- u64 valid;
-
- /* KDBUS_ITEM_TIMESTAMP */
- struct kdbus_timestamp ts;
-
- /* KDBUS_ITEM_OWNED_NAME */
- struct kdbus_item *owned_names_items;
- size_t owned_names_size;
-
- /* KDBUS_ITEM_CONN_DESCRIPTION */
- char *conn_description;
-};
-
-/* fixed size equivalent of "kdbus_caps" */
-struct kdbus_meta_caps {
- u32 last_cap;
- struct {
- u32 caps[_KERNEL_CAPABILITY_U32S];
- } set[4];
-};
-
-/**
- * kdbus_meta_proc_new() - Create process metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_proc *kdbus_meta_proc_new(void)
-{
- struct kdbus_meta_proc *mp;
-
- mp = kzalloc(sizeof(*mp), GFP_KERNEL);
- if (!mp)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&mp->kref);
- mutex_init(&mp->lock);
-
- return mp;
-}
-
-static void kdbus_meta_proc_free(struct kref *kref)
-{
- struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc,
- kref);
-
- path_put(&mp->exe_path);
- path_put(&mp->root_path);
- if (mp->cred)
- put_cred(mp->cred);
- put_pid(mp->ppid);
- put_pid(mp->tgid);
- put_pid(mp->pid);
-
- kfree(mp->seclabel);
- kfree(mp->cmdline);
- kfree(mp->cgroup);
- kfree(mp);
-}
-
-/**
- * kdbus_meta_proc_ref() - Gain reference
- * @mp: Process metadata object
- *
- * Return: @mp is returned
- */
-struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp)
-{
- if (mp)
- kref_get(&mp->kref);
- return mp;
-}
-
-/**
- * kdbus_meta_proc_unref() - Drop reference
- * @mp: Process metadata object
- *
- * Return: NULL
- */
-struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp)
-{
- if (mp)
- kref_put(&mp->kref, kdbus_meta_proc_free);
- return NULL;
-}
-
-static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp)
-{
- struct task_struct *parent;
-
- mp->pid = get_pid(task_pid(current));
- mp->tgid = get_pid(task_tgid(current));
-
- rcu_read_lock();
- parent = rcu_dereference(current->real_parent);
- mp->ppid = get_pid(task_tgid(parent));
- rcu_read_unlock();
-
- mp->valid |= KDBUS_ATTACH_PIDS;
-}
-
-static void kdbus_meta_proc_collect_tid_comm(struct kdbus_meta_proc *mp)
-{
- get_task_comm(mp->tid_comm, current);
- mp->valid |= KDBUS_ATTACH_TID_COMM;
-}
-
-static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp)
-{
- get_task_comm(mp->pid_comm, current->group_leader);
- mp->valid |= KDBUS_ATTACH_PID_COMM;
-}
-
-static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
-{
- struct file *exe_file;
-
- rcu_read_lock();
- exe_file = rcu_dereference(current->mm->exe_file);
- if (exe_file) {
- mp->exe_path = exe_file->f_path;
- path_get(&mp->exe_path);
- get_fs_root(current->fs, &mp->root_path);
- mp->valid |= KDBUS_ATTACH_EXE;
- }
- rcu_read_unlock();
-}
-
-static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp)
-{
- struct mm_struct *mm = current->mm;
- char *cmdline;
-
- if (!mm->arg_end)
- return 0;
-
- cmdline = strndup_user((const char __user *)mm->arg_start,
- mm->arg_end - mm->arg_start);
- if (IS_ERR(cmdline))
- return PTR_ERR(cmdline);
-
- mp->cmdline = cmdline;
- mp->valid |= KDBUS_ATTACH_CMDLINE;
-
- return 0;
-}
-
-static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_CGROUPS
- void *page;
- char *s;
-
- page = (void *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- return -ENOMEM;
-
- s = task_cgroup_path(current, page, PAGE_SIZE);
- if (s) {
- mp->cgroup = kstrdup(s, GFP_KERNEL);
- if (!mp->cgroup) {
- free_page((unsigned long)page);
- return -ENOMEM;
- }
- }
-
- free_page((unsigned long)page);
- mp->valid |= KDBUS_ATTACH_CGROUP;
-#endif
-
- return 0;
-}
-
-static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_SECURITY
- char *ctx = NULL;
- u32 sid, len;
- int ret;
-
- security_task_getsecid(current, &sid);
- ret = security_secid_to_secctx(sid, &ctx, &len);
- if (ret < 0) {
- /*
- * EOPNOTSUPP means no security module is active,
- * lets skip adding the seclabel then. This effectively
- * drops the SECLABEL item.
- */
- return (ret == -EOPNOTSUPP) ? 0 : ret;
- }
-
- mp->seclabel = kstrdup(ctx, GFP_KERNEL);
- security_release_secctx(ctx, len);
- if (!mp->seclabel)
- return -ENOMEM;
-
- mp->valid |= KDBUS_ATTACH_SECLABEL;
-#endif
-
- return 0;
-}
-
-static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_AUDITSYSCALL
- mp->audit_loginuid = audit_get_loginuid(current);
- mp->audit_sessionid = audit_get_sessionid(current);
- mp->valid |= KDBUS_ATTACH_AUDIT;
-#endif
-}
-
-/**
- * kdbus_meta_proc_collect() - Collect process metadata
- * @mp: Process metadata object
- * @what: Attach flags to collect
- *
- * This collects process metadata from current and saves it in @mp.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what)
-{
- int ret;
-
- if (!mp || !(what & (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)))
- return 0;
-
- mutex_lock(&mp->lock);
-
- /* creds, auxgrps and caps share "struct cred" as context */
- {
- const u64 m_cred = KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_CAPS;
-
- if ((what & m_cred) && !(mp->collected & m_cred)) {
- mp->cred = get_current_cred();
- mp->valid |= m_cred;
- mp->collected |= m_cred;
- }
- }
-
- if ((what & KDBUS_ATTACH_PIDS) &&
- !(mp->collected & KDBUS_ATTACH_PIDS)) {
- kdbus_meta_proc_collect_pids(mp);
- mp->collected |= KDBUS_ATTACH_PIDS;
- }
-
- if ((what & KDBUS_ATTACH_TID_COMM) &&
- !(mp->collected & KDBUS_ATTACH_TID_COMM)) {
- kdbus_meta_proc_collect_tid_comm(mp);
- mp->collected |= KDBUS_ATTACH_TID_COMM;
- }
-
- if ((what & KDBUS_ATTACH_PID_COMM) &&
- !(mp->collected & KDBUS_ATTACH_PID_COMM)) {
- kdbus_meta_proc_collect_pid_comm(mp);
- mp->collected |= KDBUS_ATTACH_PID_COMM;
- }
-
- if ((what & KDBUS_ATTACH_EXE) &&
- !(mp->collected & KDBUS_ATTACH_EXE)) {
- kdbus_meta_proc_collect_exe(mp);
- mp->collected |= KDBUS_ATTACH_EXE;
- }
-
- if ((what & KDBUS_ATTACH_CMDLINE) &&
- !(mp->collected & KDBUS_ATTACH_CMDLINE)) {
- ret = kdbus_meta_proc_collect_cmdline(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_CMDLINE;
- }
-
- if ((what & KDBUS_ATTACH_CGROUP) &&
- !(mp->collected & KDBUS_ATTACH_CGROUP)) {
- ret = kdbus_meta_proc_collect_cgroup(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_CGROUP;
- }
-
- if ((what & KDBUS_ATTACH_SECLABEL) &&
- !(mp->collected & KDBUS_ATTACH_SECLABEL)) {
- ret = kdbus_meta_proc_collect_seclabel(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_SECLABEL;
- }
-
- if ((what & KDBUS_ATTACH_AUDIT) &&
- !(mp->collected & KDBUS_ATTACH_AUDIT)) {
- kdbus_meta_proc_collect_audit(mp);
- mp->collected |= KDBUS_ATTACH_AUDIT;
- }
-
- ret = 0;
-
-exit_unlock:
- mutex_unlock(&mp->lock);
- return ret;
-}
-
-/**
- * kdbus_meta_fake_new() - Create fake metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_fake *kdbus_meta_fake_new(void)
-{
- struct kdbus_meta_fake *mf;
-
- mf = kzalloc(sizeof(*mf), GFP_KERNEL);
- if (!mf)
- return ERR_PTR(-ENOMEM);
-
- return mf;
-}
-
-/**
- * kdbus_meta_fake_free() - Free fake metadata object
- * @mf: Fake metadata object
- *
- * Return: NULL
- */
-struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf)
-{
- if (mf) {
- put_pid(mf->ppid);
- put_pid(mf->tgid);
- put_pid(mf->pid);
- kfree(mf->seclabel);
- kfree(mf);
- }
-
- return NULL;
-}
-
-/**
- * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials
- * @mf: Fake metadata object
- * @creds: Creds to set, may be %NULL
- * @pids: PIDs to set, may be %NULL
- * @seclabel: Seclabel to set, may be %NULL
- *
- * This function takes information stored in @creds, @pids and @seclabel and
- * resolves them to kernel-representations, if possible. This call uses the
- * current task's namespaces to resolve the given information.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel)
-{
- if (mf->valid)
- return -EALREADY;
-
- if (creds) {
- struct user_namespace *ns = current_user_ns();
-
- mf->uid = make_kuid(ns, creds->uid);
- mf->euid = make_kuid(ns, creds->euid);
- mf->suid = make_kuid(ns, creds->suid);
- mf->fsuid = make_kuid(ns, creds->fsuid);
-
- mf->gid = make_kgid(ns, creds->gid);
- mf->egid = make_kgid(ns, creds->egid);
- mf->sgid = make_kgid(ns, creds->sgid);
- mf->fsgid = make_kgid(ns, creds->fsgid);
-
- if ((creds->uid != (uid_t)-1 && !uid_valid(mf->uid)) ||
- (creds->euid != (uid_t)-1 && !uid_valid(mf->euid)) ||
- (creds->suid != (uid_t)-1 && !uid_valid(mf->suid)) ||
- (creds->fsuid != (uid_t)-1 && !uid_valid(mf->fsuid)) ||
- (creds->gid != (gid_t)-1 && !gid_valid(mf->gid)) ||
- (creds->egid != (gid_t)-1 && !gid_valid(mf->egid)) ||
- (creds->sgid != (gid_t)-1 && !gid_valid(mf->sgid)) ||
- (creds->fsgid != (gid_t)-1 && !gid_valid(mf->fsgid)))
- return -EINVAL;
-
- mf->valid |= KDBUS_ATTACH_CREDS;
- }
-
- if (pids) {
- mf->pid = get_pid(find_vpid(pids->tid));
- mf->tgid = get_pid(find_vpid(pids->pid));
- mf->ppid = get_pid(find_vpid(pids->ppid));
-
- if ((pids->tid != 0 && !mf->pid) ||
- (pids->pid != 0 && !mf->tgid) ||
- (pids->ppid != 0 && !mf->ppid)) {
- put_pid(mf->pid);
- put_pid(mf->tgid);
- put_pid(mf->ppid);
- mf->pid = NULL;
- mf->tgid = NULL;
- mf->ppid = NULL;
- return -EINVAL;
- }
-
- mf->valid |= KDBUS_ATTACH_PIDS;
- }
-
- if (seclabel) {
- mf->seclabel = kstrdup(seclabel, GFP_KERNEL);
- if (!mf->seclabel)
- return -ENOMEM;
-
- mf->valid |= KDBUS_ATTACH_SECLABEL;
- }
-
- return 0;
-}
-
-/**
- * kdbus_meta_conn_new() - Create connection metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_conn *kdbus_meta_conn_new(void)
-{
- struct kdbus_meta_conn *mc;
-
- mc = kzalloc(sizeof(*mc), GFP_KERNEL);
- if (!mc)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&mc->kref);
- mutex_init(&mc->lock);
-
- return mc;
-}
-
-static void kdbus_meta_conn_free(struct kref *kref)
-{
- struct kdbus_meta_conn *mc =
- container_of(kref, struct kdbus_meta_conn, kref);
-
- kfree(mc->conn_description);
- kfree(mc->owned_names_items);
- kfree(mc);
-}
-
-/**
- * kdbus_meta_conn_ref() - Gain reference
- * @mc: Connection metadata object
- */
-struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc)
-{
- if (mc)
- kref_get(&mc->kref);
- return mc;
-}
-
-/**
- * kdbus_meta_conn_unref() - Drop reference
- * @mc: Connection metadata object
- */
-struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc)
-{
- if (mc)
- kref_put(&mc->kref, kdbus_meta_conn_free);
- return NULL;
-}
-
-static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc,
- u64 msg_seqnum)
-{
- mc->ts.monotonic_ns = ktime_get_ns();
- mc->ts.realtime_ns = ktime_get_real_ns();
-
- if (msg_seqnum)
- mc->ts.seqnum = msg_seqnum;
-
- mc->valid |= KDBUS_ATTACH_TIMESTAMP;
-}
-
-static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn)
-{
- const struct kdbus_name_owner *owner;
- struct kdbus_item *item;
- size_t slen, size;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- size = 0;
- /* open-code length calculation to avoid final padding */
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (!(owner->flags & KDBUS_NAME_IN_QUEUE))
- size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE +
- sizeof(struct kdbus_name) +
- strlen(owner->name->name) + 1;
-
- if (!size)
- return 0;
-
- /* make sure we include zeroed padding for convenience helpers */
- item = kmalloc(KDBUS_ALIGN8(size), GFP_KERNEL);
- if (!item)
- return -ENOMEM;
-
- mc->owned_names_items = item;
- mc->owned_names_size = size;
-
- list_for_each_entry(owner, &conn->names_list, conn_entry) {
- if (owner->flags & KDBUS_NAME_IN_QUEUE)
- continue;
-
- slen = strlen(owner->name->name) + 1;
- kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL,
- sizeof(struct kdbus_name) + slen);
- item->name.flags = owner->flags;
- memcpy(item->name.name, owner->name->name, slen);
- item = KDBUS_ITEM_NEXT(item);
- }
-
- /* sanity check: the buffer should be completely written now */
- WARN_ON((u8 *)item !=
- (u8 *)mc->owned_names_items + KDBUS_ALIGN8(size));
-
- mc->valid |= KDBUS_ATTACH_NAMES;
- return 0;
-}
-
-static int kdbus_meta_conn_collect_description(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn)
-{
- if (!conn->description)
- return 0;
-
- mc->conn_description = kstrdup(conn->description, GFP_KERNEL);
- if (!mc->conn_description)
- return -ENOMEM;
-
- mc->valid |= KDBUS_ATTACH_CONN_DESCRIPTION;
- return 0;
-}
-
-/**
- * kdbus_meta_conn_collect() - Collect connection metadata
- * @mc: Message metadata object
- * @conn: Connection to collect data from
- * @msg_seqnum: Sequence number of the message to send
- * @what: Attach flags to collect
- *
- * This collects connection metadata from @msg_seqnum and @conn and saves it
- * in @mc.
- *
- * If KDBUS_ATTACH_NAMES is set in @what and @conn is non-NULL, the caller must
- * hold the name-registry read-lock of conn->ep->bus->registry.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 msg_seqnum, u64 what)
-{
- int ret;
-
- if (!mc || !(what & (KDBUS_ATTACH_TIMESTAMP |
- KDBUS_ATTACH_NAMES |
- KDBUS_ATTACH_CONN_DESCRIPTION)))
- return 0;
-
- mutex_lock(&mc->lock);
-
- if (msg_seqnum && (what & KDBUS_ATTACH_TIMESTAMP) &&
- !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) {
- kdbus_meta_conn_collect_timestamp(mc, msg_seqnum);
- mc->collected |= KDBUS_ATTACH_TIMESTAMP;
- }
-
- if (conn && (what & KDBUS_ATTACH_NAMES) &&
- !(mc->collected & KDBUS_ATTACH_NAMES)) {
- ret = kdbus_meta_conn_collect_names(mc, conn);
- if (ret < 0)
- goto exit_unlock;
- mc->collected |= KDBUS_ATTACH_NAMES;
- }
-
- if (conn && (what & KDBUS_ATTACH_CONN_DESCRIPTION) &&
- !(mc->collected & KDBUS_ATTACH_CONN_DESCRIPTION)) {
- ret = kdbus_meta_conn_collect_description(mc, conn);
- if (ret < 0)
- goto exit_unlock;
- mc->collected |= KDBUS_ATTACH_CONN_DESCRIPTION;
- }
-
- ret = 0;
-
-exit_unlock:
- mutex_unlock(&mc->lock);
- return ret;
-}
-
-static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
- const struct kdbus_meta_proc *mp,
- struct user_namespace *user_ns)
-{
- struct user_namespace *iter;
- const struct cred *cred = mp->cred;
- bool parent = false, owner = false;
- int i;
-
- /*
- * This translates the effective capabilities of 'cred' into the given
- * user-namespace. If the given user-namespace is a child-namespace of
- * the user-namespace of 'cred', the mask can be copied verbatim. If
- * not, the mask is cleared.
- * There's one exception: If 'cred' is the owner of any user-namespace
- * in the path between the given user-namespace and the user-namespace
- * of 'cred', then it has all effective capabilities set. This means,
- * the user who created a user-namespace always has all effective
- * capabilities in any child namespaces. Note that this is based on the
- * uid of the namespace creator, not the task hierarchy.
- */
- for (iter = user_ns; iter; iter = iter->parent) {
- if (iter == cred->user_ns) {
- parent = true;
- break;
- }
-
- if (iter == &init_user_ns)
- break;
-
- if ((iter->parent == cred->user_ns) &&
- uid_eq(iter->owner, cred->euid)) {
- owner = true;
- break;
- }
- }
-
- out->last_cap = CAP_LAST_CAP;
-
- CAP_FOR_EACH_U32(i) {
- if (parent) {
- out->set[0].caps[i] = cred->cap_inheritable.cap[i];
- out->set[1].caps[i] = cred->cap_permitted.cap[i];
- out->set[2].caps[i] = cred->cap_effective.cap[i];
- out->set[3].caps[i] = cred->cap_bset.cap[i];
- } else if (owner) {
- out->set[0].caps[i] = 0U;
- out->set[1].caps[i] = ~0U;
- out->set[2].caps[i] = ~0U;
- out->set[3].caps[i] = ~0U;
- } else {
- out->set[0].caps[i] = 0U;
- out->set[1].caps[i] = 0U;
- out->set[2].caps[i] = 0U;
- out->set[3].caps[i] = 0U;
- }
- }
-
- /* clear unused bits */
- for (i = 0; i < 4; i++)
- out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
- CAP_LAST_U32_VALID_MASK;
-}
-
-/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */
-static uid_t kdbus_from_kuid_keep(struct user_namespace *ns, kuid_t uid)
-{
- return uid_valid(uid) ? from_kuid_munged(ns, uid) : ((uid_t)-1);
-}
-
-/* This is equivalent to from_kgid_munged(), but maps INVALID_GID to itself */
-static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid)
-{
- return gid_valid(gid) ? from_kgid_munged(ns, gid) : ((gid_t)-1);
-}
-
-struct kdbus_meta_staging {
- const struct kdbus_meta_proc *mp;
- const struct kdbus_meta_fake *mf;
- const struct kdbus_meta_conn *mc;
- const struct kdbus_conn *conn;
- u64 mask;
-
- void *exe;
- const char *exe_path;
-};
-
-static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging)
-{
- const struct kdbus_meta_proc *mp = staging->mp;
- const struct kdbus_meta_fake *mf = staging->mf;
- const struct kdbus_meta_conn *mc = staging->mc;
- const u64 mask = staging->mask;
- size_t size = 0;
-
- /* process metadata */
-
- if (mf && (mask & KDBUS_ATTACH_CREDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
- else if (mp && (mask & KDBUS_ATTACH_CREDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
-
- if (mf && (mask & KDBUS_ATTACH_PIDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids));
- else if (mp && (mask & KDBUS_ATTACH_PIDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids));
-
- if (mp && (mask & KDBUS_ATTACH_AUXGROUPS))
- size += KDBUS_ITEM_SIZE(mp->cred->group_info->ngroups *
- sizeof(u64));
-
- if (mp && (mask & KDBUS_ATTACH_TID_COMM))
- size += KDBUS_ITEM_SIZE(strlen(mp->tid_comm) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_PID_COMM))
- size += KDBUS_ITEM_SIZE(strlen(mp->pid_comm) + 1);
-
- if (staging->exe_path && (mask & KDBUS_ATTACH_EXE))
- size += KDBUS_ITEM_SIZE(strlen(staging->exe_path) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CMDLINE))
- size += KDBUS_ITEM_SIZE(strlen(mp->cmdline) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CGROUP))
- size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CAPS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps));
-
- if (mf && (mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mf->seclabel) + 1);
- else if (mp && (mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_AUDIT))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit));
-
- /* connection metadata */
-
- if (mc && (mask & KDBUS_ATTACH_NAMES))
- size += KDBUS_ALIGN8(mc->owned_names_size);
-
- if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION))
- size += KDBUS_ITEM_SIZE(strlen(mc->conn_description) + 1);
-
- if (mc && (mask & KDBUS_ATTACH_TIMESTAMP))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_timestamp));
-
- return size;
-}
-
-static struct kdbus_item *kdbus_write_head(struct kdbus_item **iter,
- u64 type, u64 size)
-{
- struct kdbus_item *item = *iter;
- size_t padding;
-
- item->type = type;
- item->size = KDBUS_ITEM_HEADER_SIZE + size;
-
- /* clear padding */
- padding = KDBUS_ALIGN8(item->size) - item->size;
- if (padding)
- memset(item->data + size, 0, padding);
-
- *iter = KDBUS_ITEM_NEXT(item);
- return item;
-}
-
-static struct kdbus_item *kdbus_write_full(struct kdbus_item **iter,
- u64 type, u64 size, const void *data)
-{
- struct kdbus_item *item;
-
- item = kdbus_write_head(iter, type, size);
- memcpy(item->data, data, size);
- return item;
-}
-
-static size_t kdbus_meta_write(struct kdbus_meta_staging *staging, void *mem,
- size_t size)
-{
- struct user_namespace *user_ns = staging->conn->cred->user_ns;
- struct pid_namespace *pid_ns = ns_of_pid(staging->conn->pid);
- struct kdbus_item *item = NULL, *items = mem;
- u8 *end, *owned_names_end = NULL;
-
- /* process metadata */
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_CREDS)) {
- const struct kdbus_meta_fake *mf = staging->mf;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_CREDS,
- sizeof(struct kdbus_creds));
- item->creds = (struct kdbus_creds){
- .uid = kdbus_from_kuid_keep(user_ns, mf->uid),
- .euid = kdbus_from_kuid_keep(user_ns, mf->euid),
- .suid = kdbus_from_kuid_keep(user_ns, mf->suid),
- .fsuid = kdbus_from_kuid_keep(user_ns, mf->fsuid),
- .gid = kdbus_from_kgid_keep(user_ns, mf->gid),
- .egid = kdbus_from_kgid_keep(user_ns, mf->egid),
- .sgid = kdbus_from_kgid_keep(user_ns, mf->sgid),
- .fsgid = kdbus_from_kgid_keep(user_ns, mf->fsgid),
- };
- } else if (staging->mp && (staging->mask & KDBUS_ATTACH_CREDS)) {
- const struct cred *c = staging->mp->cred;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_CREDS,
- sizeof(struct kdbus_creds));
- item->creds = (struct kdbus_creds){
- .uid = kdbus_from_kuid_keep(user_ns, c->uid),
- .euid = kdbus_from_kuid_keep(user_ns, c->euid),
- .suid = kdbus_from_kuid_keep(user_ns, c->suid),
- .fsuid = kdbus_from_kuid_keep(user_ns, c->fsuid),
- .gid = kdbus_from_kgid_keep(user_ns, c->gid),
- .egid = kdbus_from_kgid_keep(user_ns, c->egid),
- .sgid = kdbus_from_kgid_keep(user_ns, c->sgid),
- .fsgid = kdbus_from_kgid_keep(user_ns, c->fsgid),
- };
- }
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_PIDS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_PIDS,
- sizeof(struct kdbus_pids));
- item->pids = (struct kdbus_pids){
- .pid = pid_nr_ns(staging->mf->tgid, pid_ns),
- .tid = pid_nr_ns(staging->mf->pid, pid_ns),
- .ppid = pid_nr_ns(staging->mf->ppid, pid_ns),
- };
- } else if (staging->mp && (staging->mask & KDBUS_ATTACH_PIDS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_PIDS,
- sizeof(struct kdbus_pids));
- item->pids = (struct kdbus_pids){
- .pid = pid_nr_ns(staging->mp->tgid, pid_ns),
- .tid = pid_nr_ns(staging->mp->pid, pid_ns),
- .ppid = pid_nr_ns(staging->mp->ppid, pid_ns),
- };
- }
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_AUXGROUPS)) {
- const struct group_info *info = staging->mp->cred->group_info;
- size_t i;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_AUXGROUPS,
- info->ngroups * sizeof(u64));
- for (i = 0; i < info->ngroups; ++i)
- item->data64[i] = from_kgid_munged(user_ns,
- GROUP_AT(info, i));
- }
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_TID_COMM))
- item = kdbus_write_full(&items, KDBUS_ITEM_TID_COMM,
- strlen(staging->mp->tid_comm) + 1,
- staging->mp->tid_comm);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_PID_COMM))
- item = kdbus_write_full(&items, KDBUS_ITEM_PID_COMM,
- strlen(staging->mp->pid_comm) + 1,
- staging->mp->pid_comm);
-
- if (staging->exe_path && (staging->mask & KDBUS_ATTACH_EXE))
- item = kdbus_write_full(&items, KDBUS_ITEM_EXE,
- strlen(staging->exe_path) + 1,
- staging->exe_path);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CMDLINE))
- item = kdbus_write_full(&items, KDBUS_ITEM_CMDLINE,
- strlen(staging->mp->cmdline) + 1,
- staging->mp->cmdline);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CGROUP))
- item = kdbus_write_full(&items, KDBUS_ITEM_CGROUP,
- strlen(staging->mp->cgroup) + 1,
- staging->mp->cgroup);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CAPS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_CAPS,
- sizeof(struct kdbus_meta_caps));
- kdbus_meta_export_caps((void*)&item->caps, staging->mp,
- user_ns);
- }
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_SECLABEL))
- item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
- strlen(staging->mf->seclabel) + 1,
- staging->mf->seclabel);
- else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL))
- item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
- strlen(staging->mp->seclabel) + 1,
- staging->mp->seclabel);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_AUDIT)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_AUDIT,
- sizeof(struct kdbus_audit));
- item->audit = (struct kdbus_audit){
- .loginuid = from_kuid(user_ns,
- staging->mp->audit_loginuid),
- .sessionid = staging->mp->audit_sessionid,
- };
- }
-
- /* connection metadata */
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_NAMES)) {
- memcpy(items, staging->mc->owned_names_items,
- KDBUS_ALIGN8(staging->mc->owned_names_size));
- owned_names_end = (u8 *)items + staging->mc->owned_names_size;
- items = (void *)KDBUS_ALIGN8((unsigned long)owned_names_end);
- }
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_CONN_DESCRIPTION))
- item = kdbus_write_full(&items, KDBUS_ITEM_CONN_DESCRIPTION,
- strlen(staging->mc->conn_description) + 1,
- staging->mc->conn_description);
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_TIMESTAMP))
- item = kdbus_write_full(&items, KDBUS_ITEM_TIMESTAMP,
- sizeof(staging->mc->ts),
- &staging->mc->ts);
-
- /*
- * Return real size (minus trailing padding). In case of 'owned_names'
- * we cannot deduce it from item->size, so treat it special.
- */
-
- if (items == (void *)KDBUS_ALIGN8((unsigned long)owned_names_end))
- end = owned_names_end;
- else if (item)
- end = (u8 *)item + item->size;
- else
- end = mem;
-
- WARN_ON((u8 *)items - (u8 *)mem != size);
- WARN_ON((void *)KDBUS_ALIGN8((unsigned long)end) != (void *)items);
-
- return end - (u8 *)mem;
-}
-
-int kdbus_meta_emit(struct kdbus_meta_proc *mp,
- struct kdbus_meta_fake *mf,
- struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 mask,
- struct kdbus_item **out_items,
- size_t *out_size)
-{
- struct kdbus_meta_staging staging = {};
- struct kdbus_item *items = NULL;
- size_t size = 0;
- int ret;
-
- if (WARN_ON(mf && mp))
- mp = NULL;
-
- staging.mp = mp;
- staging.mf = mf;
- staging.mc = mc;
- staging.conn = conn;
-
- /* get mask of valid items */
- if (mf)
- staging.mask |= mf->valid;
- if (mp) {
- mutex_lock(&mp->lock);
- staging.mask |= mp->valid;
- mutex_unlock(&mp->lock);
- }
- if (mc) {
- mutex_lock(&mc->lock);
- staging.mask |= mc->valid;
- mutex_unlock(&mc->lock);
- }
-
- staging.mask &= mask;
-
- if (!staging.mask) { /* bail out if nothing to do */
- ret = 0;
- goto exit;
- }
-
- /* EXE is special as it needs a temporary page to assemble */
- if (mp && (staging.mask & KDBUS_ATTACH_EXE)) {
- struct path p;
-
- /*
- * XXX: We need access to __d_path() so we can write the path
- * relative to conn->root_path. Once upstream, we need
- * EXPORT_SYMBOL(__d_path) or an equivalent of d_path() that
- * takes the root path directly. Until then, we drop this item
- * if the root-paths differ.
- */
-
- get_fs_root(current->fs, &p);
- if (path_equal(&p, &conn->root_path)) {
- staging.exe = (void *)__get_free_page(GFP_TEMPORARY);
- if (!staging.exe) {
- path_put(&p);
- ret = -ENOMEM;
- goto exit;
- }
-
- staging.exe_path = d_path(&mp->exe_path, staging.exe,
- PAGE_SIZE);
- if (IS_ERR(staging.exe_path)) {
- path_put(&p);
- ret = PTR_ERR(staging.exe_path);
- goto exit;
- }
- }
- path_put(&p);
- }
-
- size = kdbus_meta_measure(&staging);
- if (!size) { /* bail out if nothing to do */
- ret = 0;
- goto exit;
- }
-
- items = kmalloc(size, GFP_KERNEL);
- if (!items) {
- ret = -ENOMEM;
- goto exit;
- }
-
- size = kdbus_meta_write(&staging, items, size);
- if (!size) {
- kfree(items);
- items = NULL;
- }
-
- ret = 0;
-
-exit:
- if (staging.exe)
- free_page((unsigned long)staging.exe);
- if (ret >= 0) {
- *out_items = items;
- *out_size = size;
- }
- return ret;
-}
-
-enum {
- KDBUS_META_PROC_NONE,
- KDBUS_META_PROC_NORMAL,
-};
-
-/**
- * kdbus_proc_permission() - check /proc permissions on target pid
- * @pid_ns: namespace we operate in
- * @cred: credentials of requestor
- * @target: target process
- *
- * This checks whether a process with credentials @cred can access information
- * of @target in the namespace @pid_ns. This tries to follow /proc permissions,
- * but is slightly more restrictive.
- *
- * Return: The /proc access level (KDBUS_META_PROC_*) is returned.
- */
-static unsigned int kdbus_proc_permission(const struct pid_namespace *pid_ns,
- const struct cred *cred,
- struct pid *target)
-{
- if (pid_ns->hide_pid < 1)
- return KDBUS_META_PROC_NORMAL;
-
- /* XXX: we need groups_search() exported for aux-groups */
- if (gid_eq(cred->egid, pid_ns->pid_gid))
- return KDBUS_META_PROC_NORMAL;
-
- /*
- * XXX: If ptrace_may_access(PTRACE_MODE_READ) is granted, you can
- * overwrite hide_pid. However, ptrace_may_access() only supports
- * checking 'current', hence, we cannot use this here. But we
- * simply decide to not support this override, so no need to worry.
- */
-
- return KDBUS_META_PROC_NONE;
-}
-
-/**
- * kdbus_meta_proc_mask() - calculate which metadata would be visible to
- * a connection via /proc
- * @prv_pid: pid of metadata provider
- * @req_pid: pid of metadata requestor
- * @req_cred: credentials of metadata reqeuestor
- * @wanted: metadata that is requested
- *
- * This checks which metadata items of @prv_pid can be read via /proc by the
- * requestor @req_pid.
- *
- * Return: Set of metadata flags the requestor can see (limited by @wanted).
- */
-static u64 kdbus_meta_proc_mask(struct pid *prv_pid,
- struct pid *req_pid,
- const struct cred *req_cred,
- u64 wanted)
-{
- struct pid_namespace *prv_ns, *req_ns;
- unsigned int proc;
-
- prv_ns = ns_of_pid(prv_pid);
- req_ns = ns_of_pid(req_pid);
-
- /*
- * If the sender is not visible in the receiver namespace, then the
- * receiver cannot access the sender via its own procfs. Hence, we do
- * not attach any additional metadata.
- */
- if (!pid_nr_ns(prv_pid, req_ns))
- return 0;
-
- /*
- * If the pid-namespace of the receiver has hide_pid set, it cannot see
- * any process but its own. We shortcut this /proc permission check if
- * provider and requestor are the same. If not, we perform rather
- * expensive /proc permission checks.
- */
- if (prv_pid == req_pid)
- proc = KDBUS_META_PROC_NORMAL;
- else
- proc = kdbus_proc_permission(req_ns, req_cred, prv_pid);
-
- /* you need /proc access to read standard process attributes */
- if (proc < KDBUS_META_PROC_NORMAL)
- wanted &= ~(KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_AUDIT |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_EXE);
-
- /* clear all non-/proc flags */
- return wanted & (KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_AUDIT |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_EXE);
-}
-
-/**
- * kdbus_meta_get_mask() - calculate attach flags mask for metadata request
- * @prv_pid: pid of metadata provider
- * @prv_mask: mask of metadata the provide grants unchecked
- * @req_pid: pid of metadata requestor
- * @req_cred: credentials of metadata requestor
- * @req_mask: mask of metadata that is requested
- *
- * This calculates the metadata items that the requestor @req_pid can access
- * from the metadata provider @prv_pid. This permission check consists of
- * several different parts:
- * - Providers can grant metadata items unchecked. Regardless of their type,
- * they're always granted to the requestor. This mask is passed as @prv_mask.
- * - Basic items (credentials and connection metadata) are granted implicitly
- * to everyone. They're publicly available to any bus-user that can see the
- * provider.
- * - Process credentials that are not granted implicitly follow the same
- * permission checks as /proc. This means, we always assume a requestor
- * process has access to their *own* /proc mount, if they have access to
- * kdbusfs.
- *
- * Return: Mask of metadata that is granted.
- */
-static u64 kdbus_meta_get_mask(struct pid *prv_pid, u64 prv_mask,
- struct pid *req_pid,
- const struct cred *req_cred, u64 req_mask)
-{
- u64 missing, impl_mask, proc_mask = 0;
-
- /*
- * Connection metadata and basic unix process credentials are
- * transmitted implicitly, and cannot be suppressed. Both are required
- * to perform user-space policies on the receiver-side. Furthermore,
- * connection metadata is public state, anyway, and unix credentials
- * are needed for UDS-compatibility. We extend them slightly by
- * auxiliary groups and additional uids/gids/pids.
- */
- impl_mask = /* connection metadata */
- KDBUS_ATTACH_CONN_DESCRIPTION |
- KDBUS_ATTACH_TIMESTAMP |
- KDBUS_ATTACH_NAMES |
- /* credentials and pids */
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS;
-
- /*
- * Calculate the set of metadata that is not granted implicitly nor by
- * the sender, but still requested by the receiver. If any are left,
- * perform rather expensive /proc access checks for them.
- */
- missing = req_mask & ~((prv_mask | impl_mask) & req_mask);
- if (missing)
- proc_mask = kdbus_meta_proc_mask(prv_pid, req_pid, req_cred,
- missing);
-
- return (prv_mask | impl_mask | proc_mask) & req_mask;
-}
-
-/**
- */
-u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask)
-{
- return kdbus_meta_get_mask(conn->pid,
- atomic64_read(&conn->attach_flags_send),
- task_pid(current),
- current_cred(),
- mask);
-}
-
-/**
- */
-u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd,
- const struct kdbus_conn *rcv)
-{
- return kdbus_meta_get_mask(task_pid(current),
- atomic64_read(&snd->attach_flags_send),
- rcv->pid,
- rcv->cred,
- atomic64_read(&rcv->attach_flags_recv));
-}
diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h
deleted file mode 100644
index dba7cc7fd..000000000
--- a/ipc/kdbus/metadata.h
+++ /dev/null
@@ -1,86 +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
- *
- * 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_METADATA_H
-#define __KDBUS_METADATA_H
-
-#include <linux/kernel.h>
-
-struct kdbus_conn;
-struct kdbus_pool_slice;
-
-struct kdbus_meta_proc;
-struct kdbus_meta_conn;
-
-/**
- * struct kdbus_meta_fake - Fake metadata
- * @valid: Bitmask of collected and valid items
- * @uid: UID of process
- * @euid: EUID of process
- * @suid: SUID of process
- * @fsuid: FSUID of process
- * @gid: GID of process
- * @egid: EGID of process
- * @sgid: SGID of process
- * @fsgid: FSGID of process
- * @pid: PID of process
- * @tgid: TGID of process
- * @ppid: PPID of process
- * @seclabel: Seclabel
- */
-struct kdbus_meta_fake {
- u64 valid;
-
- /* KDBUS_ITEM_CREDS */
- kuid_t uid, euid, suid, fsuid;
- kgid_t gid, egid, sgid, fsgid;
-
- /* KDBUS_ITEM_PIDS */
- struct pid *pid, *tgid, *ppid;
-
- /* KDBUS_ITEM_SECLABEL */
- char *seclabel;
-};
-
-struct kdbus_meta_proc *kdbus_meta_proc_new(void);
-struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp);
-struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp);
-int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what);
-
-struct kdbus_meta_fake *kdbus_meta_fake_new(void);
-struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf);
-int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel);
-
-struct kdbus_meta_conn *kdbus_meta_conn_new(void);
-struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc);
-struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc);
-int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 msg_seqnum, u64 what);
-
-int kdbus_meta_emit(struct kdbus_meta_proc *mp,
- struct kdbus_meta_fake *mf,
- struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 mask,
- struct kdbus_item **out_items,
- size_t *out_size);
-u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask);
-u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd,
- const struct kdbus_conn *rcv);
-
-#endif
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
deleted file mode 100644
index bf44ca3f1..000000000
--- a/ipc/kdbus/names.c
+++ /dev/null
@@ -1,854 +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/ctype.h>
-#include <linux/fs.h>
-#include <linux/hash.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "names.h"
-#include "notify.h"
-#include "policy.h"
-
-#define KDBUS_NAME_SAVED_MASK (KDBUS_NAME_ALLOW_REPLACEMENT | \
- KDBUS_NAME_QUEUE)
-
-static bool kdbus_name_owner_is_used(struct kdbus_name_owner *owner)
-{
- return !list_empty(&owner->name_entry) ||
- owner == owner->name->activator;
-}
-
-static struct kdbus_name_owner *
-kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name,
- u64 flags)
-{
- struct kdbus_name_owner *owner;
-
- kdbus_conn_assert_active(conn);
-
- if (conn->name_count >= KDBUS_CONN_MAX_NAMES)
- return ERR_PTR(-E2BIG);
-
- owner = kmalloc(sizeof(*owner), GFP_KERNEL);
- if (!owner)
- return ERR_PTR(-ENOMEM);
-
- owner->flags = flags & KDBUS_NAME_SAVED_MASK;
- owner->conn = conn;
- owner->name = name;
- list_add_tail(&owner->conn_entry, &conn->names_list);
- INIT_LIST_HEAD(&owner->name_entry);
-
- ++conn->name_count;
- return owner;
-}
-
-static void kdbus_name_owner_free(struct kdbus_name_owner *owner)
-{
- if (!owner)
- return;
-
- WARN_ON(kdbus_name_owner_is_used(owner));
- --owner->conn->name_count;
- list_del(&owner->conn_entry);
- kfree(owner);
-}
-
-static struct kdbus_name_owner *
-kdbus_name_owner_find(struct kdbus_name_entry *name, struct kdbus_conn *conn)
-{
- struct kdbus_name_owner *owner;
-
- /*
- * Use conn->names_list over name->queue to make sure boundaries of
- * this linear search are controlled by the connection itself.
- * Furthermore, this will find normal owners as well as activators
- * without any additional code.
- */
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (owner->name == name)
- return owner;
-
- return NULL;
-}
-
-static bool kdbus_name_entry_is_used(struct kdbus_name_entry *name)
-{
- return !list_empty(&name->queue) || name->activator;
-}
-
-static struct kdbus_name_owner *
-kdbus_name_entry_first(struct kdbus_name_entry *name)
-{
- return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
- name_entry);
-}
-
-static struct kdbus_name_entry *
-kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash,
- const char *name_str)
-{
- struct kdbus_name_entry *name;
- size_t namelen;
-
- lockdep_assert_held(&r->rwlock);
-
- namelen = strlen(name_str);
-
- name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL);
- if (!name)
- return ERR_PTR(-ENOMEM);
-
- name->name_id = ++r->name_seq_last;
- name->activator = NULL;
- INIT_LIST_HEAD(&name->queue);
- hash_add(r->entries_hash, &name->hentry, hash);
- memcpy(name->name, name_str, namelen + 1);
-
- return name;
-}
-
-static void kdbus_name_entry_free(struct kdbus_name_entry *name)
-{
- if (!name)
- return;
-
- WARN_ON(kdbus_name_entry_is_used(name));
- hash_del(&name->hentry);
- kfree(name);
-}
-
-static struct kdbus_name_entry *
-kdbus_name_entry_find(struct kdbus_name_registry *r, u32 hash,
- const char *name_str)
-{
- struct kdbus_name_entry *name;
-
- lockdep_assert_held(&r->rwlock);
-
- hash_for_each_possible(r->entries_hash, name, hentry, hash)
- if (!strcmp(name->name, name_str))
- return name;
-
- return NULL;
-}
-
-/**
- * kdbus_name_registry_new() - create a new name registry
- *
- * Return: a new kdbus_name_registry on success, ERR_PTR on failure.
- */
-struct kdbus_name_registry *kdbus_name_registry_new(void)
-{
- struct kdbus_name_registry *r;
-
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r)
- return ERR_PTR(-ENOMEM);
-
- hash_init(r->entries_hash);
- init_rwsem(&r->rwlock);
- r->name_seq_last = 0;
-
- return r;
-}
-
-/**
- * kdbus_name_registry_free() - free name registry
- * @r: name registry to free, or NULL
- *
- * Free a name registry and cleanup all internal objects. This is a no-op if
- * you pass NULL as registry.
- */
-void kdbus_name_registry_free(struct kdbus_name_registry *r)
-{
- if (!r)
- return;
-
- WARN_ON(!hash_empty(r->entries_hash));
- kfree(r);
-}
-
-/**
- * kdbus_name_lookup_unlocked() - lookup name in registry
- * @reg: name registry
- * @name: name to lookup
- *
- * This looks up @name in the given name-registry and returns the
- * kdbus_name_entry object. The caller must hold the registry-lock and must not
- * access the returned object after releasing the lock.
- *
- * Return: Pointer to name-entry, or NULL if not found.
- */
-struct kdbus_name_entry *
-kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name)
-{
- return kdbus_name_entry_find(reg, kdbus_strhash(name), name);
-}
-
-static int kdbus_name_become_activator(struct kdbus_name_owner *owner,
- u64 *return_flags)
-{
- if (kdbus_name_owner_is_used(owner))
- return -EALREADY;
- if (owner->name->activator)
- return -EEXIST;
-
- owner->name->activator = owner;
- owner->flags |= KDBUS_NAME_ACTIVATOR;
-
- if (kdbus_name_entry_first(owner->name)) {
- owner->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- owner->flags |= KDBUS_NAME_PRIMARY;
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_ADD,
- 0, owner->conn->id,
- 0, owner->flags,
- owner->name->name);
- }
-
- if (return_flags)
- *return_flags = owner->flags | KDBUS_NAME_ACQUIRED;
-
- return 0;
-}
-
-static int kdbus_name_update(struct kdbus_name_owner *owner, u64 flags,
- u64 *return_flags)
-{
- struct kdbus_name_owner *primary, *activator;
- struct kdbus_name_entry *name;
- struct kdbus_bus *bus;
- u64 nflags = 0;
- int ret = 0;
-
- name = owner->name;
- bus = owner->conn->ep->bus;
- primary = kdbus_name_entry_first(name);
- activator = name->activator;
-
- /* cannot be activator and acquire a name */
- if (owner == activator)
- return -EUCLEAN;
-
- /* update saved flags */
- owner->flags = flags & KDBUS_NAME_SAVED_MASK;
-
- if (!primary) {
- /*
- * No primary owner (but maybe an activator). Take over the
- * name.
- */
-
- list_add(&owner->name_entry, &name->queue);
- owner->flags |= KDBUS_NAME_PRIMARY;
- nflags |= KDBUS_NAME_ACQUIRED;
-
- /* move messages to new owner on activation */
- if (activator) {
- kdbus_conn_move_messages(owner->conn, activator->conn,
- name->name_id);
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
- activator->conn->id, owner->conn->id,
- activator->flags, owner->flags,
- name->name);
- activator->flags &= ~KDBUS_NAME_PRIMARY;
- activator->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_ADD,
- 0, owner->conn->id,
- 0, owner->flags,
- name->name);
- }
-
- } else if (owner == primary) {
- /*
- * Already the primary owner of the name, flags were already
- * updated. Nothing to do.
- */
-
- owner->flags |= KDBUS_NAME_PRIMARY;
-
- } else if ((primary->flags & KDBUS_NAME_ALLOW_REPLACEMENT) &&
- (flags & KDBUS_NAME_REPLACE_EXISTING)) {
- /*
- * We're not the primary owner but can replace it. Move us
- * ahead of the primary owner and acquire the name (possibly
- * skipping queued owners ahead of us).
- */
-
- list_del_init(&owner->name_entry);
- list_add(&owner->name_entry, &name->queue);
- owner->flags |= KDBUS_NAME_PRIMARY;
- nflags |= KDBUS_NAME_ACQUIRED;
-
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
- primary->conn->id, owner->conn->id,
- primary->flags, owner->flags,
- name->name);
-
- /* requeue old primary, or drop if queueing not wanted */
- if (primary->flags & KDBUS_NAME_QUEUE) {
- primary->flags &= ~KDBUS_NAME_PRIMARY;
- primary->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- list_del_init(&primary->name_entry);
- kdbus_name_owner_free(primary);
- }
-
- } else if (flags & KDBUS_NAME_QUEUE) {
- /*
- * Name is already occupied and we cannot take it over, but
- * queuing is allowed. Put us silently on the queue, if not
- * already there.
- */
-
- owner->flags |= KDBUS_NAME_IN_QUEUE;
- if (!kdbus_name_owner_is_used(owner)) {
- list_add_tail(&owner->name_entry, &name->queue);
- nflags |= KDBUS_NAME_ACQUIRED;
- }
- } else if (kdbus_name_owner_is_used(owner)) {
- /*
- * Already queued on name, but re-queueing was not requested.
- * Make sure to unlink it from the name, the caller is
- * responsible for releasing it.
- */
-
- list_del_init(&owner->name_entry);
- } else {
- /*
- * Name is already claimed and queueing is not requested.
- * Return error to the caller.
- */
-
- ret = -EEXIST;
- }
-
- if (return_flags)
- *return_flags = owner->flags | nflags;
-
- return ret;
-}
-
-int kdbus_name_acquire(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn, const char *name_str,
- u64 flags, u64 *return_flags)
-{
- struct kdbus_name_entry *name = NULL;
- struct kdbus_name_owner *owner = NULL;
- u32 hash;
- int ret;
-
- kdbus_conn_assert_active(conn);
-
- down_write(&reg->rwlock);
-
- /*
- * Verify the connection has access to the name. Do this before testing
- * for double-acquisitions and other errors to make sure we do not leak
- * information about this name through possible custom endpoints.
- */
- if (!kdbus_conn_policy_own_name(conn, current_cred(), name_str)) {
- ret = -EPERM;
- goto exit;
- }
-
- /*
- * Lookup the name entry. If it already exists, search for an owner
- * entry as we might already own that name. If either does not exist,
- * we will allocate a fresh one.
- */
- hash = kdbus_strhash(name_str);
- name = kdbus_name_entry_find(reg, hash, name_str);
- if (name) {
- owner = kdbus_name_owner_find(name, conn);
- } else {
- name = kdbus_name_entry_new(reg, hash, name_str);
- if (IS_ERR(name)) {
- ret = PTR_ERR(name);
- name = NULL;
- goto exit;
- }
- }
-
- /* create name owner object if not already queued */
- if (!owner) {
- owner = kdbus_name_owner_new(conn, name, flags);
- if (IS_ERR(owner)) {
- ret = PTR_ERR(owner);
- owner = NULL;
- goto exit;
- }
- }
-
- if (flags & KDBUS_NAME_ACTIVATOR)
- ret = kdbus_name_become_activator(owner, return_flags);
- else
- ret = kdbus_name_update(owner, flags, return_flags);
- if (ret < 0)
- goto exit;
-
-exit:
- if (owner && !kdbus_name_owner_is_used(owner))
- kdbus_name_owner_free(owner);
- if (name && !kdbus_name_entry_is_used(name))
- kdbus_name_entry_free(name);
- up_write(&reg->rwlock);
- kdbus_notify_flush(conn->ep->bus);
- return ret;
-}
-
-static void kdbus_name_release_unlocked(struct kdbus_name_owner *owner)
-{
- struct kdbus_name_owner *primary, *next;
- struct kdbus_name_entry *name;
-
- name = owner->name;
- primary = kdbus_name_entry_first(name);
-
- list_del_init(&owner->name_entry);
- if (owner == name->activator)
- name->activator = NULL;
-
- if (!primary || owner == primary) {
- next = kdbus_name_entry_first(name);
- if (!next)
- next = name->activator;
-
- if (next) {
- /* hand to next in queue */
- next->flags &= ~KDBUS_NAME_IN_QUEUE;
- next->flags |= KDBUS_NAME_PRIMARY;
- if (next == name->activator)
- kdbus_conn_move_messages(next->conn,
- owner->conn,
- name->name_id);
-
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_CHANGE,
- owner->conn->id, next->conn->id,
- owner->flags, next->flags,
- name->name);
- } else {
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_REMOVE,
- owner->conn->id, 0,
- owner->flags, 0,
- name->name);
- }
- }
-
- kdbus_name_owner_free(owner);
- if (!kdbus_name_entry_is_used(name))
- kdbus_name_entry_free(name);
-}
-
-static int kdbus_name_release(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn,
- const char *name_str)
-{
- struct kdbus_name_owner *owner;
- struct kdbus_name_entry *name;
- int ret = 0;
-
- down_write(&reg->rwlock);
- name = kdbus_name_entry_find(reg, kdbus_strhash(name_str), name_str);
- if (name) {
- owner = kdbus_name_owner_find(name, conn);
- if (owner)
- kdbus_name_release_unlocked(owner);
- else
- ret = -EADDRINUSE;
- } else {
- ret = -ESRCH;
- }
- up_write(&reg->rwlock);
-
- kdbus_notify_flush(conn->ep->bus);
- return ret;
-}
-
-/**
- * kdbus_name_release_all() - remove all name entries of a given connection
- * @reg: name registry
- * @conn: connection
- */
-void kdbus_name_release_all(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn)
-{
- struct kdbus_name_owner *owner;
-
- down_write(&reg->rwlock);
-
- while ((owner = list_first_entry_or_null(&conn->names_list,
- struct kdbus_name_owner,
- conn_entry)))
- kdbus_name_release_unlocked(owner);
-
- up_write(&reg->rwlock);
-
- kdbus_notify_flush(conn->ep->bus);
-}
-
-/**
- * kdbus_name_is_valid() - check if a name is valid
- * @p: The name to check
- * @allow_wildcard: Whether or not to allow a wildcard name
- *
- * A name is valid if all of the following criterias are met:
- *
- * - The name has two or more elements separated by a period ('.') character.
- * - All elements must contain at least one character.
- * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-"
- * and must not begin with a digit.
- * - The name must not exceed KDBUS_NAME_MAX_LEN.
- * - If @allow_wildcard is true, the name may end on '.*'
- */
-bool kdbus_name_is_valid(const char *p, bool allow_wildcard)
-{
- bool dot, found_dot = false;
- const char *q;
-
- for (dot = true, q = p; *q; q++) {
- if (*q == '.') {
- if (dot)
- return false;
-
- found_dot = true;
- dot = true;
- } else {
- bool good;
-
- good = isalpha(*q) || (!dot && isdigit(*q)) ||
- *q == '_' || *q == '-' ||
- (allow_wildcard && dot &&
- *q == '*' && *(q + 1) == '\0');
-
- if (!good)
- return false;
-
- dot = false;
- }
- }
-
- if (q - p > KDBUS_NAME_MAX_LEN)
- return false;
-
- if (dot)
- return false;
-
- if (!found_dot)
- return false;
-
- return true;
-}
-
-/**
- * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
-{
- const char *item_name;
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME, .mandatory = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_NAME_REPLACE_EXISTING |
- KDBUS_NAME_ALLOW_REPLACEMENT |
- KDBUS_NAME_QUEUE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- item_name = argv[1].item->str;
- if (!kdbus_name_is_valid(item_name, false)) {
- ret = -EINVAL;
- goto exit;
- }
-
- ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
- cmd->flags, &cmd->return_flags);
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME, .mandatory = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_name_release(conn->ep->bus->name_registry, conn,
- argv[1].item->str);
- return kdbus_args_clear(&args, ret);
-}
-
-static int kdbus_list_write(struct kdbus_conn *conn,
- struct kdbus_conn *c,
- struct kdbus_pool_slice *slice,
- size_t *pos,
- struct kdbus_name_owner *o,
- bool write)
-{
- struct kvec kvec[4];
- size_t cnt = 0;
- int ret;
-
- /* info header */
- struct kdbus_info info = {
- .size = 0,
- .id = c->id,
- .flags = c->flags,
- };
-
- /* fake the header of a kdbus_name item */
- struct {
- u64 size;
- u64 type;
- u64 flags;
- } h = {};
-
- if (o && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(),
- o->name->name))
- return 0;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
-
- /* append name */
- if (o) {
- size_t slen = strlen(o->name->name) + 1;
-
- h.size = offsetof(struct kdbus_item, name.name) + slen;
- h.type = KDBUS_ITEM_OWNED_NAME;
- h.flags = o->flags;
-
- kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size);
- kdbus_kvec_set(&kvec[cnt++], o->name->name, slen, &info.size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size);
- }
-
- if (write) {
- ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec,
- cnt, info.size);
- if (ret < 0)
- return ret;
- }
-
- *pos += info.size;
- return 0;
-}
-
-static int kdbus_list_all(struct kdbus_conn *conn, u64 flags,
- struct kdbus_pool_slice *slice,
- size_t *pos, bool write)
-{
- struct kdbus_conn *c;
- size_t p = *pos;
- int ret, i;
-
- hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) {
- bool added = false;
-
- /* skip monitors */
- if (kdbus_conn_is_monitor(c))
- continue;
-
- /* all names the connection owns */
- if (flags & (KDBUS_LIST_NAMES |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED)) {
- struct kdbus_name_owner *o;
-
- list_for_each_entry(o, &c->names_list, conn_entry) {
- if (o->flags & KDBUS_NAME_ACTIVATOR) {
- if (!(flags & KDBUS_LIST_ACTIVATORS))
- continue;
-
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- } else if (o->flags & KDBUS_NAME_IN_QUEUE) {
- if (!(flags & KDBUS_LIST_QUEUED))
- continue;
-
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- } else if (flags & KDBUS_LIST_NAMES) {
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- }
- }
- }
-
- /* nothing added so far, just add the unique ID */
- if (!added && (flags & KDBUS_LIST_UNIQUE)) {
- ret = kdbus_list_write(conn, c, slice, &p, NULL, write);
- if (ret < 0)
- return ret;
- }
- }
-
- *pos = p;
- return 0;
-}
-
-/**
- * kdbus_cmd_list() - handle KDBUS_CMD_LIST
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_name_registry *reg = conn->ep->bus->name_registry;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_cmd_list *cmd;
- size_t pos, size;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_LIST_UNIQUE |
- KDBUS_LIST_NAMES |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&reg->rwlock);
- down_read(&conn->ep->bus->conn_rwlock);
- down_read(&conn->ep->policy_db.entries_rwlock);
-
- /* size of records */
- size = 0;
- ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false);
- if (ret < 0)
- goto exit_unlock;
-
- if (size == 0) {
- kdbus_pool_publish_empty(conn->pool, &cmd->offset,
- &cmd->list_size);
- } else {
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit_unlock;
- }
-
- /* copy the records */
- pos = 0;
- ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true);
- if (ret < 0)
- goto exit_unlock;
-
- WARN_ON(pos != size);
- kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size);
- }
-
- if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
- kdbus_member_set_user(&cmd->list_size, argp,
- typeof(*cmd), list_size))
- ret = -EFAULT;
-
-exit_unlock:
- up_read(&conn->ep->policy_db.entries_rwlock);
- up_read(&conn->ep->bus->conn_rwlock);
- up_read(&reg->rwlock);
- kdbus_pool_slice_release(slice);
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h
deleted file mode 100644
index edac59ddd..000000000
--- a/ipc/kdbus/names.h
+++ /dev/null
@@ -1,105 +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.
- */
-
-#ifndef __KDBUS_NAMES_H
-#define __KDBUS_NAMES_H
-
-#include <linux/hashtable.h>
-#include <linux/rwsem.h>
-
-struct kdbus_name_entry;
-struct kdbus_name_owner;
-struct kdbus_name_registry;
-
-/**
- * struct kdbus_name_registry - names registered for a bus
- * @entries_hash: Map of entries
- * @lock: Registry data lock
- * @name_seq_last: Last used sequence number to assign to a name entry
- */
-struct kdbus_name_registry {
- DECLARE_HASHTABLE(entries_hash, 8);
- struct rw_semaphore rwlock;
- u64 name_seq_last;
-};
-
-/**
- * struct kdbus_name_entry - well-know name entry
- * @name_id: sequence number of name entry to be able to uniquely
- * identify a name over its registration lifetime
- * @activator: activator of this name, or NULL
- * @queue: list of queued owners
- * @hentry: entry in registry map
- * @name: well-known name
- */
-struct kdbus_name_entry {
- u64 name_id;
- struct kdbus_name_owner *activator;
- struct list_head queue;
- struct hlist_node hentry;
- char name[];
-};
-
-/**
- * struct kdbus_name_owner - owner of a well-known name
- * @flags: KDBUS_NAME_* flags of this owner
- * @conn: connection owning the name
- * @name: name that is owned
- * @conn_entry: link into @conn
- * @name_entry: link into @name
- */
-struct kdbus_name_owner {
- u64 flags;
- struct kdbus_conn *conn;
- struct kdbus_name_entry *name;
- struct list_head conn_entry;
- struct list_head name_entry;
-};
-
-bool kdbus_name_is_valid(const char *p, bool allow_wildcard);
-
-struct kdbus_name_registry *kdbus_name_registry_new(void);
-void kdbus_name_registry_free(struct kdbus_name_registry *reg);
-
-struct kdbus_name_entry *
-kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name);
-
-int kdbus_name_acquire(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn, const char *name,
- u64 flags, u64 *return_flags);
-void kdbus_name_release_all(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn);
-
-int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp);
-
-/**
- * kdbus_name_get_owner() - get current owner of a name
- * @name: name to get current owner of
- *
- * This returns a pointer to the current owner of a name (or its activator if
- * there is no owner). The caller must make sure @name is valid and does not
- * vanish.
- *
- * Return: Pointer to current owner or NULL if there is none.
- */
-static inline struct kdbus_name_owner *
-kdbus_name_get_owner(struct kdbus_name_entry *name)
-{
- return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
- name_entry) ? : name->activator;
-}
-
-#endif
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
deleted file mode 100644
index 986aca39c..000000000
--- a/ipc/kdbus/node.c
+++ /dev/null
@@ -1,948 +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
- *
- * 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/atomic.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kdev_t.h>
-#include <linux/rbtree.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-
-#include "bus.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "node.h"
-#include "util.h"
-
-/**
- * DOC: kdbus nodes
- *
- * Nodes unify lifetime management across exposed kdbus objects and provide a
- * hierarchy. Each kdbus object, that might be exposed to user-space, has a
- * kdbus_node object embedded and is linked into the hierarchy. Each node can
- * have any number (0-n) of child nodes linked. Each child retains a reference
- * to its parent node. For root-nodes, the parent is NULL.
- *
- * Each node object goes through a bunch of states during it's lifetime:
- * * NEW
- * * LINKED (can be skipped by NEW->FREED transition)
- * * ACTIVE (can be skipped by LINKED->INACTIVE transition)
- * * INACTIVE
- * * DRAINED
- * * FREED
- *
- * Each node is allocated by the caller and initialized via kdbus_node_init().
- * This never fails and sets the object into state NEW. From now on, ref-counts
- * on the node manage its lifetime. During init, the ref-count is set to 1. Once
- * it drops to 0, the node goes to state FREED and the node->free_cb() callback
- * is called to deallocate any memory.
- *
- * After initializing a node, you usually link it into the hierarchy. You need
- * to provide a parent node and a name. The node will be linked as child to the
- * parent and a globally unique ID is assigned to the child. The name of the
- * child must be unique for all children of this parent. Otherwise, linking the
- * child will fail with -EEXIST.
- * Note that the child is not marked active, yet. Admittedly, it prevents any
- * other node from being linked with the same name (thus, it reserves that
- * name), but any child-lookup (via name or unique ID) will never return this
- * child unless it has been marked active.
- *
- * Once successfully linked, you can use kdbus_node_activate() to activate a
- * child. This will mark the child active. This state can be skipped by directly
- * deactivating the child via kdbus_node_deactivate() (see below).
- * By activating a child, you enable any lookups on this child to succeed from
- * now on. Furthermore, any code that got its hands on a reference to the node,
- * can from now on "acquire" the node.
- *
- * Active References (or: 'acquiring' and 'releasing' a node)
- * Additionally to normal object references, nodes support something we call
- * "active references". An active reference can be acquired via
- * kdbus_node_acquire() and released via kdbus_node_release(). A caller
- * _must_ own a normal object reference whenever calling those functions.
- * Unlike object references, acquiring an active reference can fail (by
- * returning 'false' from kdbus_node_acquire()). An active reference can
- * only be acquired if the node is marked active. If it is not marked
- * active, yet, or if it was already deactivated, no more active references
- * can be acquired, ever!
- * Active references are used to track tasks working on a node. Whenever a
- * task enters kernel-space to perform an action on a node, it acquires an
- * active reference, performs the action and releases the reference again.
- * While holding an active reference, the node is guaranteed to stay active.
- * If the node is deactivated in parallel, the node is marked as
- * deactivated, then we wait for all active references to be dropped, before
- * we finally proceed with any cleanups. That is, if you hold an active
- * reference to a node, any resources that are bound to the "active" state
- * are guaranteed to stay accessible until you release your reference.
- *
- * Active-references are very similar to rw-locks, where acquiring a node is
- * equal to try-read-lock and releasing to read-unlock. Deactivating a node
- * means write-lock and never releasing it again.
- * Unlike rw-locks, the 'active reference' concept is more versatile and
- * avoids unusual rw-lock usage (never releasing a write-lock..).
- *
- * It is safe to acquire multiple active-references recursively. But you
- * need to check the return value of kdbus_node_acquire() on _each_ call. It
- * may stop granting references at _any_ time.
- *
- * You're free to perform any operations you want while holding an active
- * reference, except sleeping for an indefinite period. Sleeping for a fixed
- * amount of time is fine, but you usually should not wait on wait-queues
- * without a timeout.
- * For example, if you wait for I/O to happen, you should gather all data
- * and schedule the I/O operation, then release your active reference and
- * wait for it to complete. Then try to acquire a new reference. If it
- * fails, perform any cleanup (the node is now dead). Otherwise, you can
- * finish your operation.
- *
- * All nodes can be deactivated via kdbus_node_deactivate() at any time. You can
- * call this multiple times, even in parallel or on nodes that were never
- * linked, and it will just work. Furthermore, all children will be deactivated
- * recursively as well. If a node is deactivated, there might still be active
- * references that were acquired before calling kdbus_node_deactivate(). The
- * owner of an object must call kdbus_node_drain() (which is a superset of
- * kdbus_node_deactivate()) before dropping their reference. This will
- * deactivate the node and also synchronously wait for all active references to
- * be dropped. Hence, once kdbus_node_drain() returns, the node is fully
- * released and no active references exist, anymore.
- * kdbus_node_drain() can be called at any times, multiple times, and in
- * parallel on multiple threads. All calls are synchronized internally and will
- * return only once the node is fully drained. The only restriction is, you
- * must not hold an active reference when calling kdbus_node_drain() (unlike
- * deactivation, which allows the caller to hold an active reference).
- *
- * When a node is activated, we acquire a normal object reference to the node.
- * This reference is dropped after deactivation is fully done (and only if the
- * node really was activated). This allows callers to link+activate a child node
- * and then drop all refs. This has the effect that nobody owns a reference to
- * the node, except for the parent node. Hence, if the parent is deactivated
- * (and thus all children are deactivated, too), this will automatically
- * release the child node.
- *
- * Currently, nodes provide a bunch of resources that external code can use
- * directly. This includes:
- *
- * * node->waitq: Each node has its own wait-queue that is used to manage
- * the 'active' state. When a node is deactivated, we wait on
- * this queue until all active refs are dropped. Analogously,
- * when you release an active reference on a deactivated
- * node, and the active ref-count drops to 0, we wake up a
- * single thread on this queue. Furthermore, once the
- * ->release_cb() callback finished, we wake up all waiters.
- * The node-owner is free to re-use this wait-queue for other
- * purposes. As node-management uses this queue only during
- * deactivation, it is usually totally fine to re-use the
- * queue for other, preferably low-overhead, use-cases.
- *
- * * node->type: This field defines the type of the owner of this node. It
- * must be set during node initialization and must remain
- * constant. The node management never looks at this value,
- * but external users might use to gain access to the owner
- * object of a node.
- * It is totally up to the owner of the node to define what
- * their type means. Usually it means you can access the
- * parent structure via container_of(), as long as you hold an
- * active reference to the node.
- *
- * * node->free_cb: callback after all references are dropped
- * node->release_cb: callback during node deactivation
- * These fields must be set by the node owner during
- * node initialization. They must remain constant. If
- * NULL, they're skipped.
- *
- * * node->mode: filesystem access modes
- * node->uid: filesystem owner uid
- * node->gid: filesystem owner gid
- * These fields must be set by the node owner during node
- * initialization. They must remain constant and may be
- * accessed by other callers to properly initialize
- * filesystem nodes.
- *
- * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is
- * always kept as small as possible during allocation and is
- * globally unique across all nodes allocated by this module. 0
- * is reserved as "not assigned" and is the default.
- * The ID is assigned during kdbus_node_link() and is kept until
- * the object is freed. Thus, the ID surpasses the active
- * lifetime of a node. As long as you hold an object reference
- * to a node (and the node was linked once), the ID is valid and
- * unique.
- *
- * * node->name: name of this node
- * node->hash: 31bit hash-value of @name (range [2..INT_MAX-1])
- * These values follow the same lifetime rules as node->id.
- * They're initialized when the node is linked and then remain
- * constant until the last object reference is dropped.
- * Unlike the id, the name is only unique across all siblings
- * and only until the node is deactivated. Currently, the name
- * is even unique if linked but not activated, yet. This might
- * change in the future, though. Code should not rely on this.
- *
- * * node->lock: lock to protect node->children, node->rb, node->parent
- * * node->parent: Reference to parent node. This is set during LINK time
- * and is dropped during destruction. You can freely access
- * this field, but it may be NULL (root node).
- * * node->children: rb-tree of all linked children of this node. You must
- * not access this directly, but use one of the iterator
- * or lookup helpers.
- */
-
-/*
- * Bias values track states of "active references". They're all negative. If a
- * node is active, its active-ref-counter is >=0 and tracks all active
- * references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the
- * counter is now negative but still counts the active references. Once it drops
- * to exactly NODE_BIAS, we know all active references were dropped. Exactly one
- * thread will change it to NODE_RELEASE now, perform cleanup and then put it
- * into NODE_DRAINED. Once drained, all other threads that tried deactivating
- * the node will now be woken up (thus, they wait until the node is fully done).
- * The initial state during node-setup is NODE_NEW. If a node is directly
- * deactivated without having ever been active, it is put into
- * NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state
- * across node-deactivation. The task putting it into NODE_RELEASE now knows
- * whether the node was active before or not.
- *
- * Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN
- * to avoid overflows if multiplied by -1.
- */
-#define KDBUS_NODE_BIAS (INT_MIN + 5)
-#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1)
-#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2)
-#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3)
-#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4)
-
-/* global unique ID mapping for kdbus nodes */
-DEFINE_IDA(kdbus_node_ida);
-
-/**
- * kdbus_node_name_hash() - hash a name
- * @name: The string to hash
- *
- * This computes the hash of @name. It is guaranteed to be in the range
- * [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved
- * for the filesystem code.
- *
- * Return: hash value of the passed string
- */
-static unsigned int kdbus_node_name_hash(const char *name)
-{
- unsigned int hash;
-
- /* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */
- hash = kdbus_strhash(name) & INT_MAX;
- if (hash < 2)
- hash += 2;
- if (hash >= INT_MAX)
- hash = INT_MAX - 1;
-
- return hash;
-}
-
-/**
- * kdbus_node_name_compare() - compare a name with a node's name
- * @hash: hash of the string to compare the node with
- * @name: name to compare the node with
- * @node: node to compare the name with
- *
- * This compares a query string against a kdbus node. If the kdbus node has the
- * given name, this returns 0. Otherwise, this returns >0 / <0 depending
- * whether the query string is greater / less than the node.
- *
- * Note: If @node is drained but has the name @name, this returns 1. The
- * reason for this is that we treat drained nodes as "renamed". The
- * slot of such nodes is no longer occupied and new nodes can claim it.
- * Obviously, this has the side-effect that you cannot match drained
- * nodes, as they will never return 0 on name-matches. But this is
- * intentional, as there is no reason why anyone would ever want to match
- * on drained nodes.
- *
- * Return: 0 if @name and @hash exactly match the information in @node, or
- * an integer less than or greater than zero if @name is found, respectively,
- * to be less than or be greater than the string stored in @node.
- */
-static int kdbus_node_name_compare(unsigned int hash, const char *name,
- const struct kdbus_node *node)
-{
- int ret;
-
- if (hash != node->hash)
- return hash - node->hash;
-
- ret = strcmp(name, node->name);
- if (ret != 0)
- return ret;
-
- return atomic_read(&node->active) == KDBUS_NODE_DRAINED;
-}
-
-/**
- * kdbus_node_init() - initialize a kdbus_node
- * @node: Pointer to the node to initialize
- * @type: The type the node will have (KDBUS_NODE_*)
- *
- * The caller is responsible of allocating @node and initializating it to zero.
- * Once this call returns, you must use the node_ref() and node_unref()
- * functions to manage this node.
- */
-void kdbus_node_init(struct kdbus_node *node, unsigned int type)
-{
- atomic_set(&node->refcnt, 1);
- mutex_init(&node->lock);
- node->id = 0;
- node->type = type;
- RB_CLEAR_NODE(&node->rb);
- node->children = RB_ROOT;
- init_waitqueue_head(&node->waitq);
- atomic_set(&node->active, KDBUS_NODE_NEW);
-}
-
-/**
- * kdbus_node_link() - link a node into the nodes system
- * @node: Pointer to the node to initialize
- * @parent: Pointer to a parent node, may be %NULL
- * @name: The name of the node (or NULL if root node)
- *
- * This links a node into the hierarchy. This must not be called multiple times.
- * If @parent is NULL, the node becomes a new root node.
- *
- * This call will fail if @name is not unique across all its siblings or if no
- * ID could be allocated. You must not activate a node if linking failed! It is
- * safe to deactivate it, though.
- *
- * Once you linked a node, you must call kdbus_node_drain() before you drop
- * the last reference (even if you never activate the node).
- *
- * Return: 0 on success. negative error otherwise.
- */
-int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
- const char *name)
-{
- int ret;
-
- if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent))
- return -EINVAL;
-
- if (WARN_ON(parent && !name))
- return -EINVAL;
-
- if (name) {
- node->name = kstrdup(name, GFP_KERNEL);
- if (!node->name)
- return -ENOMEM;
-
- node->hash = kdbus_node_name_hash(name);
- }
-
- ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL);
- if (ret < 0)
- return ret;
-
- node->id = ret;
- ret = 0;
-
- if (parent) {
- struct rb_node **n, *prev;
-
- if (!kdbus_node_acquire(parent))
- return -ESHUTDOWN;
-
- mutex_lock(&parent->lock);
-
- n = &parent->children.rb_node;
- prev = NULL;
-
- while (*n) {
- struct kdbus_node *pos;
- int result;
-
- pos = kdbus_node_from_rb(*n);
- prev = *n;
- result = kdbus_node_name_compare(node->hash,
- node->name,
- pos);
- if (result == 0) {
- ret = -EEXIST;
- goto exit_unlock;
- }
-
- if (result < 0)
- n = &pos->rb.rb_left;
- else
- n = &pos->rb.rb_right;
- }
-
- /* add new node and rebalance the tree */
- rb_link_node(&node->rb, prev, n);
- rb_insert_color(&node->rb, &parent->children);
- node->parent = kdbus_node_ref(parent);
-
-exit_unlock:
- mutex_unlock(&parent->lock);
- kdbus_node_release(parent);
- }
-
- return ret;
-}
-
-/**
- * kdbus_node_ref() - Acquire object reference
- * @node: node to acquire reference to (or NULL)
- *
- * This acquires a new reference to @node. You must already own a reference when
- * calling this!
- * If @node is NULL, this is a no-op.
- *
- * Return: @node is returned
- */
-struct kdbus_node *kdbus_node_ref(struct kdbus_node *node)
-{
- if (node)
- atomic_inc(&node->refcnt);
- return node;
-}
-
-/**
- * kdbus_node_unref() - Drop object reference
- * @node: node to drop reference to (or NULL)
- *
- * This drops an object reference to @node. You must not access the node if you
- * no longer own a reference.
- * If the ref-count drops to 0, the object will be destroyed (->free_cb will be
- * called).
- *
- * If you linked or activated the node, you must deactivate the node before you
- * drop your last reference! If you didn't link or activate the node, you can
- * drop any reference you want.
- *
- * Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb()
- * callbacks must not acquire any outer locks, though. So you can safely drop
- * references while holding locks (apart from node->parent->lock).
- *
- * If @node is NULL, this is a no-op.
- *
- * Return: This always returns NULL
- */
-struct kdbus_node *kdbus_node_unref(struct kdbus_node *node)
-{
- if (node && atomic_dec_and_test(&node->refcnt)) {
- struct kdbus_node safe = *node;
-
- WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED);
-
- if (node->parent) {
- mutex_lock(&node->parent->lock);
- if (!RB_EMPTY_NODE(&node->rb)) {
- rb_erase(&node->rb,
- &node->parent->children);
- RB_CLEAR_NODE(&node->rb);
- }
- mutex_unlock(&node->parent->lock);
- }
-
- if (node->free_cb)
- node->free_cb(node);
- if (safe.id > 0)
- ida_simple_remove(&kdbus_node_ida, safe.id);
-
- kfree(safe.name);
- kdbus_node_unref(safe.parent);
- }
-
- return NULL;
-}
-
-/**
- * kdbus_node_is_active() - test whether a node is active
- * @node: node to test
- *
- * This checks whether @node is active. That means, @node was linked and
- * activated by the node owner and hasn't been deactivated, yet. If, and only
- * if, a node is active, kdbus_node_acquire() will be able to acquire active
- * references.
- *
- * Note that this function does not give any lifetime guarantees. After this
- * call returns, the node might be deactivated immediately. Normally, what you
- * want is to acquire a real active reference via kdbus_node_acquire().
- *
- * Return: true if @node is active, false otherwise
- */
-bool kdbus_node_is_active(struct kdbus_node *node)
-{
- return atomic_read(&node->active) >= 0;
-}
-
-/**
- * kdbus_node_is_deactivated() - test whether a node was already deactivated
- * @node: node to test
- *
- * This checks whether kdbus_node_deactivate() was called on @node. Note that
- * this might be true even if you never deactivated the node directly, but only
- * one of its ancestors.
- *
- * Note that even if this returns 'false', the node might get deactivated
- * immediately after the call returns.
- *
- * Return: true if @node was already deactivated, false if not
- */
-bool kdbus_node_is_deactivated(struct kdbus_node *node)
-{
- int v;
-
- v = atomic_read(&node->active);
- return v != KDBUS_NODE_NEW && v < 0;
-}
-
-/**
- * kdbus_node_activate() - activate a node
- * @node: node to activate
- *
- * This marks @node as active if, and only if, the node wasn't activated nor
- * deactivated, yet, and the parent is still active. Any but the first call to
- * kdbus_node_activate() is a no-op.
- * If you called kdbus_node_deactivate() before, then even the first call to
- * kdbus_node_activate() will be a no-op.
- *
- * This call doesn't give any lifetime guarantees. The node might get
- * deactivated immediately after this call returns. Or the parent might already
- * be deactivated, which will make this call a no-op.
- *
- * If this call successfully activated a node, it will take an object reference
- * to it. This reference is dropped after the node is deactivated. Therefore,
- * the object owner can safely drop their reference to @node iff they know that
- * its parent node will get deactivated at some point. Once the parent node is
- * deactivated, it will deactivate all its child and thus drop this reference
- * again.
- *
- * Return: True if this call successfully activated the node, otherwise false.
- * Note that this might return false, even if the node is still active
- * (eg., if you called this a second time).
- */
-bool kdbus_node_activate(struct kdbus_node *node)
-{
- bool res = false;
-
- mutex_lock(&node->lock);
- if (atomic_read(&node->active) == KDBUS_NODE_NEW) {
- atomic_sub(KDBUS_NODE_NEW, &node->active);
- /* activated nodes have ref +1 */
- kdbus_node_ref(node);
- res = true;
- }
- mutex_unlock(&node->lock);
-
- return res;
-}
-
-/**
- * kdbus_node_recurse_unlock() - advance iterator on a tree
- * @start: node at which the iteration started
- * @node: previously visited node
- *
- * This helper advances an iterator by one, when traversing a node tree. It is
- * supposed to be used like this:
- *
- * struct kdbus_node *n;
- *
- * n = start;
- * while (n) {
- * mutex_lock(&n->lock);
- * ... visit @n ...
- * n = kdbus_node_recurse_unlock(start, n);
- * }
- *
- * This helpers takes as input the start-node of the iteration and the current
- * position. It returns a pointer to the next node to visit. The caller must
- * hold a reference to @start during the whole iteration. Furthermore, @node
- * must be locked when entering this helper. On return, the lock is released.
- *
- * The order of visit is pre-order traversal.
- *
- * If @node is deactivated before recursing its children, then it is guaranteed
- * that all children will be visited. If @node is still active, new nodes might
- * be inserted during traversal, and thus might be missed.
- *
- * Also note that the node-locks are released while traversing children. You
- * must not rely on the locks to be held during the whole traversal. Each node
- * that is visited is pinned by this helper, so the caller can rely on owning a
- * reference. It is dropped, once all of the children of the node have been
- * visited (recursively).
- *
- * You *must not* bail out of a traversal early, otherwise you'll leak
- * ref-counts to all nodes in the current depth-path.
- *
- * Return: Reference to next node, or NULL.
- */
-static struct kdbus_node *kdbus_node_recurse_unlock(struct kdbus_node *start,
- struct kdbus_node *node)
-{
- struct kdbus_node *t, *prev = NULL;
- struct rb_node *rb;
-
- lockdep_assert_held(&node->lock);
-
- rb = rb_first(&node->children);
- if (!rb) {
- do {
- mutex_unlock(&node->lock);
- kdbus_node_unref(prev);
-
- if (node == start)
- return NULL;
-
- prev = node;
- node = node->parent;
-
- mutex_lock(&node->lock);
- rb = rb_next(&prev->rb);
- } while (!rb);
- }
-
- t = kdbus_node_ref(kdbus_node_from_rb(rb));
- mutex_unlock(&node->lock);
- kdbus_node_unref(prev);
- return t;
-}
-
-/**
- * kdbus_node_deactivate() - deactivate a node
- * @node: node to deactivate
- *
- * This recursively deactivates the passed node and all its children. The nodes
- * are marked as deactivated, but they're not drained. Hence, even after this
- * call returns, there might still be someone holding an active reference to
- * any of the nodes. However, no new active references can be acquired after
- * this returns.
- *
- * It is safe to call this multiple times (even in parallel). Each call is
- * guaranteed to only return after _all_ nodes have been deactivated.
- */
-void kdbus_node_deactivate(struct kdbus_node *node)
-{
- struct kdbus_node *pos;
- int v;
-
- pos = node;
- while (pos) {
- mutex_lock(&pos->lock);
-
- /*
- * Add BIAS to pos->active to mark it as inactive. If it was
- * never active before, immediately mark it as RELEASE_INACTIVE
- * so that this case can be detected later on.
- * If the node was already deactivated, make sure to still
- * recurse into the children. Otherwise, we might return before
- * a racing thread finished deactivating all children. But we
- * want to guarantee that the whole tree is deactivated once
- * this returns.
- */
- v = atomic_read(&pos->active);
- if (v >= 0)
- atomic_add_return(KDBUS_NODE_BIAS, &pos->active);
- else if (v == KDBUS_NODE_NEW)
- atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT);
-
- pos = kdbus_node_recurse_unlock(node, pos);
- }
-}
-
-/**
- * kdbus_node_drain() - drain a node
- * @node: node to drain
- *
- * This function recursively deactivates this node and all its children and
- * then waits for all active references to be dropped. This function is a
- * superset of kdbus_node_deactivate(), as it additionally drains all nodes. It
- * returns only once all children and the node itself were recursively drained
- * (even if you call this function multiple times in parallel).
- *
- * It is safe to call this function on _any_ node that was initialized _any_
- * number of times.
- *
- * This call may sleep, as it waits for all active references to be dropped.
- */
-void kdbus_node_drain(struct kdbus_node *node)
-{
- struct kdbus_node *pos;
- int v;
-
- kdbus_node_deactivate(node);
-
- pos = node;
- while (pos) {
- /* wait until all active references were dropped */
- wait_event(pos->waitq,
- atomic_read(&pos->active) <= KDBUS_NODE_BIAS);
-
- /* mark object as RELEASE */
- mutex_lock(&pos->lock);
- v = atomic_read(&pos->active);
- if (v == KDBUS_NODE_BIAS || v == KDBUS_NODE_RELEASE_DIRECT)
- atomic_set(&pos->active, KDBUS_NODE_RELEASE);
- mutex_unlock(&pos->lock);
-
- /*
- * If this is the thread that marked the object as RELEASE, we
- * perform the actual release. Otherwise, we wait until the
- * release is done and the node is marked as DRAINED.
- */
- if (v == KDBUS_NODE_BIAS || v == KDBUS_NODE_RELEASE_DIRECT) {
- if (pos->release_cb)
- pos->release_cb(pos, v == KDBUS_NODE_BIAS);
-
- /* mark as DRAINED */
- atomic_set(&pos->active, KDBUS_NODE_DRAINED);
- wake_up_all(&pos->waitq);
-
- /* drop VFS cache */
- kdbus_fs_flush(pos);
-
- /*
- * If the node was activated and someone subtracted BIAS
- * from it to deactivate it, we, and only us, are
- * responsible to release the extra ref-count that was
- * taken once in kdbus_node_activate().
- * If the node was never activated, no-one ever
- * subtracted BIAS, but instead skipped that state and
- * immediately went to NODE_RELEASE_DIRECT. In that case
- * we must not drop the reference.
- */
- if (v == KDBUS_NODE_BIAS)
- kdbus_node_unref(pos);
- } else {
- /* wait until object is DRAINED */
- wait_event(pos->waitq,
- atomic_read(&pos->active) == KDBUS_NODE_DRAINED);
- }
-
- mutex_lock(&pos->lock);
- pos = kdbus_node_recurse_unlock(node, pos);
- }
-}
-
-/**
- * kdbus_node_acquire() - Acquire an active ref on a node
- * @node: The node
- *
- * This acquires an active-reference to @node. This will only succeed if the
- * node is active. You must release this active reference via
- * kdbus_node_release() again.
- *
- * See the introduction to "active references" for more details.
- *
- * Return: %true if @node was non-NULL and active
- */
-bool kdbus_node_acquire(struct kdbus_node *node)
-{
- return node && atomic_inc_unless_negative(&node->active);
-}
-
-/**
- * kdbus_node_release() - Release an active ref on a node
- * @node: The node
- *
- * This releases an active reference that was previously acquired via
- * kdbus_node_acquire(). See kdbus_node_acquire() for details.
- */
-void kdbus_node_release(struct kdbus_node *node)
-{
- if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS)
- wake_up(&node->waitq);
-}
-
-/**
- * kdbus_node_find_child() - Find child by name
- * @node: parent node to search through
- * @name: name of child node
- *
- * This searches through all children of @node for a child-node with name @name.
- * If not found, or if the child is deactivated, NULL is returned. Otherwise,
- * the child is acquired and a new reference is returned.
- *
- * If you're done with the child, you need to release it and drop your
- * reference.
- *
- * This function does not acquire the parent node. However, if the parent was
- * already deactivated, then kdbus_node_deactivate() will, at some point, also
- * deactivate the child. Therefore, we can rely on the explicit ordering during
- * deactivation.
- *
- * Return: Reference to acquired child node, or NULL if not found / not active.
- */
-struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node,
- const char *name)
-{
- struct kdbus_node *child;
- struct rb_node *rb;
- unsigned int hash;
- int ret;
-
- hash = kdbus_node_name_hash(name);
-
- mutex_lock(&node->lock);
- rb = node->children.rb_node;
- while (rb) {
- child = kdbus_node_from_rb(rb);
- ret = kdbus_node_name_compare(hash, name, child);
- if (ret < 0)
- rb = rb->rb_left;
- else if (ret > 0)
- rb = rb->rb_right;
- else
- break;
- }
- if (rb && kdbus_node_acquire(child))
- kdbus_node_ref(child);
- else
- child = NULL;
- mutex_unlock(&node->lock);
-
- return child;
-}
-
-static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node,
- unsigned int hash,
- const char *name)
-{
- struct kdbus_node *n, *pos = NULL;
- struct rb_node *rb;
- int res;
-
- /*
- * Find the closest child with ``node->hash >= hash'', or, if @name is
- * valid, ``node->name >= name'' (where '>=' is the lex. order).
- */
-
- rb = node->children.rb_node;
- while (rb) {
- n = kdbus_node_from_rb(rb);
-
- if (name)
- res = kdbus_node_name_compare(hash, name, n);
- else
- res = hash - n->hash;
-
- if (res <= 0) {
- rb = rb->rb_left;
- pos = n;
- } else { /* ``hash > n->hash'', ``name > n->name'' */
- rb = rb->rb_right;
- }
- }
-
- return pos;
-}
-
-/**
- * kdbus_node_find_closest() - Find closest child-match
- * @node: parent node to search through
- * @hash: hash value to find closest match for
- *
- * Find the closest child of @node with a hash greater than or equal to @hash.
- * The closest match is the left-most child of @node with this property. Which
- * means, it is the first child with that hash returned by
- * kdbus_node_next_child(), if you'd iterate the whole parent node.
- *
- * Return: Reference to acquired child, or NULL if none found.
- */
-struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node,
- unsigned int hash)
-{
- struct kdbus_node *child;
- struct rb_node *rb;
-
- mutex_lock(&node->lock);
-
- child = node_find_closest_unlocked(node, hash, NULL);
- while (child && !kdbus_node_acquire(child)) {
- rb = rb_next(&child->rb);
- if (rb)
- child = kdbus_node_from_rb(rb);
- else
- child = NULL;
- }
- kdbus_node_ref(child);
-
- mutex_unlock(&node->lock);
-
- return child;
-}
-
-/**
- * kdbus_node_next_child() - Acquire next child
- * @node: parent node
- * @prev: previous child-node position or NULL
- *
- * This function returns a reference to the next active child of @node, after
- * the passed position @prev. If @prev is NULL, a reference to the first active
- * child is returned. If no more active children are found, NULL is returned.
- *
- * This function acquires the next child it returns. If you're done with the
- * returned pointer, you need to release _and_ unref it.
- *
- * The passed in pointer @prev is not modified by this function, and it does
- * *not* have to be active. If @prev was acquired via different means, or if it
- * was unlinked from its parent before you pass it in, then this iterator will
- * still return the next active child (it will have to search through the
- * rb-tree based on the node-name, though).
- * However, @prev must not be linked to a different parent than @node!
- *
- * Return: Reference to next acquired child, or NULL if at the end.
- */
-struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node,
- struct kdbus_node *prev)
-{
- struct kdbus_node *pos = NULL;
- struct rb_node *rb;
-
- mutex_lock(&node->lock);
-
- if (!prev) {
- /*
- * New iteration; find first node in rb-tree and try to acquire
- * it. If we got it, directly return it as first element.
- * Otherwise, the loop below will find the next active node.
- */
- rb = rb_first(&node->children);
- if (!rb)
- goto exit;
- pos = kdbus_node_from_rb(rb);
- if (kdbus_node_acquire(pos))
- goto exit;
- } else {
- /*
- * The current iterator is still linked to the parent. Set it
- * as current position and use the loop below to find the next
- * active element.
- */
- pos = prev;
- }
-
- /* @pos was already returned or is inactive; find next active node */
- do {
- rb = rb_next(&pos->rb);
- if (rb)
- pos = kdbus_node_from_rb(rb);
- else
- pos = NULL;
- } while (pos && !kdbus_node_acquire(pos));
-
-exit:
- /* @pos is NULL or acquired. Take ref if non-NULL and return it */
- kdbus_node_ref(pos);
- mutex_unlock(&node->lock);
- return pos;
-}
diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h
deleted file mode 100644
index 16c6fd574..000000000
--- a/ipc/kdbus/node.h
+++ /dev/null
@@ -1,87 +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
- *
- * 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_NODE_H
-#define __KDBUS_NODE_H
-
-#include <linux/atomic.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-
-struct kdbus_node;
-
-enum kdbus_node_type {
- KDBUS_NODE_DOMAIN,
- KDBUS_NODE_CONTROL,
- KDBUS_NODE_BUS,
- KDBUS_NODE_ENDPOINT,
-};
-
-typedef void (*kdbus_node_free_t) (struct kdbus_node *node);
-typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active);
-
-struct kdbus_node {
- struct mutex lock;
- atomic_t refcnt;
- atomic_t active;
- wait_queue_head_t waitq;
-
- /* static members */
- unsigned int type;
- kdbus_node_free_t free_cb;
- kdbus_node_release_t release_cb;
- umode_t mode;
- kuid_t uid;
- kgid_t gid;
-
- /* valid once linked */
- char *name;
- unsigned int hash;
- unsigned int id;
- struct kdbus_node *parent; /* may be NULL */
- struct rb_node rb;
-
- /* dynamic list of children */
- struct rb_root children;
-};
-
-#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb)
-
-extern struct ida kdbus_node_ida;
-
-void kdbus_node_init(struct kdbus_node *node, unsigned int type);
-
-int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
- const char *name);
-
-struct kdbus_node *kdbus_node_ref(struct kdbus_node *node);
-struct kdbus_node *kdbus_node_unref(struct kdbus_node *node);
-
-bool kdbus_node_is_active(struct kdbus_node *node);
-bool kdbus_node_is_deactivated(struct kdbus_node *node);
-bool kdbus_node_activate(struct kdbus_node *node);
-void kdbus_node_deactivate(struct kdbus_node *node);
-void kdbus_node_drain(struct kdbus_node *node);
-
-bool kdbus_node_acquire(struct kdbus_node *node);
-void kdbus_node_release(struct kdbus_node *node);
-
-struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node,
- const char *name);
-struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node,
- unsigned int hash);
-struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node,
- struct kdbus_node *prev);
-
-#endif
diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c
deleted file mode 100644
index 375758c48..000000000
--- a/ipc/kdbus/notify.c
+++ /dev/null
@@ -1,204 +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/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "item.h"
-#include "message.h"
-#include "notify.h"
-
-static inline void kdbus_notify_add_tail(struct kdbus_staging *staging,
- struct kdbus_bus *bus)
-{
- spin_lock(&bus->notify_lock);
- list_add_tail(&staging->notify_entry, &bus->notify_list);
- spin_unlock(&bus->notify_lock);
-}
-
-static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id,
- u64 cookie, u64 msg_type)
-{
- struct kdbus_staging *s;
-
- s = kdbus_staging_new_kernel(bus, id, cookie, 0, msg_type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_reply_timeout() - queue a timeout reply
- * @bus: Bus which queues the messages
- * @id: The destination's connection ID
- * @cookie: The cookie to set in the reply.
- *
- * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached.
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie)
-{
- return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT);
-}
-
-/**
- * kdbus_notify_reply_dead() - queue a 'dead' reply
- * @bus: Bus which queues the messages
- * @id: The destination's connection ID
- * @cookie: The cookie to set in the reply.
- *
- * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached.
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie)
-{
- return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD);
-}
-
-/**
- * kdbus_notify_name_change() - queue a notification about a name owner change
- * @bus: Bus which queues the messages
- * @type: The type if the notification; KDBUS_ITEM_NAME_ADD,
- * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE
- * @old_id: The id of the connection that used to own the name
- * @new_id: The id of the new owner connection
- * @old_flags: The flags to pass in the KDBUS_ITEM flags field for
- * the old owner
- * @new_flags: The flags to pass in the KDBUS_ITEM flags field for
- * the new owner
- * @name: The name that was removed or assigned to a new owner
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
- u64 old_id, u64 new_id,
- u64 old_flags, u64 new_flags,
- const char *name)
-{
- size_t name_len, extra_size;
- struct kdbus_staging *s;
-
- name_len = strlen(name) + 1;
- extra_size = sizeof(struct kdbus_notify_name_change) + name_len;
-
- s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0,
- extra_size, type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- s->notify->name_change.old_id.id = old_id;
- s->notify->name_change.old_id.flags = old_flags;
- s->notify->name_change.new_id.id = new_id;
- s->notify->name_change.new_id.flags = new_flags;
- memcpy(s->notify->name_change.name, name, name_len);
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_id_change() - queue a notification about a unique ID change
- * @bus: Bus which queues the messages
- * @type: The type if the notification; KDBUS_ITEM_ID_ADD or
- * KDBUS_ITEM_ID_REMOVE
- * @id: The id of the connection that was added or removed
- * @flags: The flags to pass in the KDBUS_ITEM flags field
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags)
-{
- struct kdbus_staging *s;
- size_t extra_size;
-
- extra_size = sizeof(struct kdbus_notify_id_change);
- s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0,
- extra_size, type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- s->notify->id_change.id = id;
- s->notify->id_change.flags = flags;
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_flush() - send a list of collected messages
- * @bus: Bus which queues the messages
- *
- * The list is empty after sending the messages.
- */
-void kdbus_notify_flush(struct kdbus_bus *bus)
-{
- LIST_HEAD(notify_list);
- struct kdbus_staging *s, *tmp;
-
- mutex_lock(&bus->notify_flush_lock);
- down_read(&bus->name_registry->rwlock);
-
- spin_lock(&bus->notify_lock);
- list_splice_init(&bus->notify_list, &notify_list);
- spin_unlock(&bus->notify_lock);
-
- list_for_each_entry_safe(s, tmp, &notify_list, notify_entry) {
- if (s->msg->dst_id != KDBUS_DST_ID_BROADCAST) {
- struct kdbus_conn *conn;
-
- conn = kdbus_bus_find_conn_by_id(bus, s->msg->dst_id);
- if (conn) {
- kdbus_bus_eavesdrop(bus, NULL, s);
- kdbus_conn_entry_insert(NULL, conn, s, NULL,
- NULL);
- kdbus_conn_unref(conn);
- }
- } else {
- kdbus_bus_broadcast(bus, NULL, s);
- }
-
- list_del(&s->notify_entry);
- kdbus_staging_free(s);
- }
-
- up_read(&bus->name_registry->rwlock);
- mutex_unlock(&bus->notify_flush_lock);
-}
-
-/**
- * kdbus_notify_free() - free a list of collected messages
- * @bus: Bus which queues the messages
- */
-void kdbus_notify_free(struct kdbus_bus *bus)
-{
- struct kdbus_staging *s, *tmp;
-
- list_for_each_entry_safe(s, tmp, &bus->notify_list, notify_entry) {
- list_del(&s->notify_entry);
- kdbus_staging_free(s);
- }
-}
diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h
deleted file mode 100644
index 03df464cb..000000000
--- a/ipc/kdbus/notify.h
+++ /dev/null
@@ -1,30 +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.
- */
-
-#ifndef __KDBUS_NOTIFY_H
-#define __KDBUS_NOTIFY_H
-
-struct kdbus_bus;
-
-int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags);
-int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie);
-int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie);
-int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
- u64 old_id, u64 new_id,
- u64 old_flags, u64 new_flags,
- const char *name);
-void kdbus_notify_flush(struct kdbus_bus *bus);
-void kdbus_notify_free(struct kdbus_bus *bus);
-
-#endif
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 <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/dcache.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#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;
-}
diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h
deleted file mode 100644
index 15dd7bc12..000000000
--- a/ipc/kdbus/policy.h
+++ /dev/null
@@ -1,51 +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
- *
- * 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_POLICY_H
-#define __KDBUS_POLICY_H
-
-#include <linux/hashtable.h>
-#include <linux/rwsem.h>
-
-struct kdbus_conn;
-struct kdbus_item;
-
-/**
- * struct kdbus_policy_db - policy database
- * @entries_hash: Hashtable of entries
- * @entries_rwlock: Mutex to protect the database's access entries
- */
-struct kdbus_policy_db {
- DECLARE_HASHTABLE(entries_hash, 6);
- struct rw_semaphore entries_rwlock;
-};
-
-void kdbus_policy_db_init(struct kdbus_policy_db *db);
-void kdbus_policy_db_clear(struct kdbus_policy_db *db);
-
-int kdbus_policy_query_unlocked(struct kdbus_policy_db *db,
- const struct cred *cred, const char *name,
- unsigned int hash);
-int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred,
- const char *name, unsigned int hash);
-
-void kdbus_policy_remove_owner(struct kdbus_policy_db *db,
- const void *owner);
-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);
-
-#endif
diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c
deleted file mode 100644
index c65043e8c..000000000
--- a/ipc/kdbus/pool.c
+++ /dev/null
@@ -1,728 +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/aio.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/rbtree.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "pool.h"
-#include "util.h"
-
-/**
- * struct kdbus_pool - the receiver's buffer
- * @f: The backing shmem file
- * @size: The size of the file
- * @accounted_size: Currently accounted memory in bytes
- * @lock: Pool data lock
- * @slices: All slices sorted by address
- * @slices_busy: Tree of allocated slices
- * @slices_free: Tree of free slices
- *
- * The receiver's buffer, managed as a pool of allocated and free
- * slices containing the queued messages.
- *
- * Messages sent with KDBUS_CMD_SEND are copied directly by the
- * sending process into the receiver's pool.
- *
- * Messages received with KDBUS_CMD_RECV just return the offset
- * to the data placed in the pool.
- *
- * The internally allocated memory needs to be returned by the receiver
- * with KDBUS_CMD_FREE.
- */
-struct kdbus_pool {
- struct file *f;
- size_t size;
- size_t accounted_size;
- struct mutex lock;
-
- struct list_head slices;
- struct rb_root slices_busy;
- struct rb_root slices_free;
-};
-
-/**
- * struct kdbus_pool_slice - allocated element in kdbus_pool
- * @pool: Pool this slice belongs to
- * @off: Offset of slice in the shmem file
- * @size: Size of slice
- * @entry: Entry in "all slices" list
- * @rb_node: Entry in free or busy list
- * @free: Unused slice
- * @accounted: Accounted as queue slice
- * @ref_kernel: Kernel holds a reference
- * @ref_user: Userspace holds a reference
- *
- * The pool has one or more slices, always spanning the entire size of the
- * pool.
- *
- * Every slice is an element in a list sorted by the buffer address, to
- * provide access to the next neighbor slice.
- *
- * Every slice is member in either the busy or the free tree. The free
- * tree is organized by slice size, the busy tree organized by buffer
- * offset.
- */
-struct kdbus_pool_slice {
- struct kdbus_pool *pool;
- size_t off;
- size_t size;
-
- struct list_head entry;
- struct rb_node rb_node;
-
- bool free:1;
- bool accounted:1;
- bool ref_kernel:1;
- bool ref_user:1;
-};
-
-static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool,
- size_t off, size_t size)
-{
- struct kdbus_pool_slice *slice;
-
- slice = kzalloc(sizeof(*slice), GFP_KERNEL);
- if (!slice)
- return NULL;
-
- slice->pool = pool;
- slice->off = off;
- slice->size = size;
- slice->free = true;
- return slice;
-}
-
-/* insert a slice into the free tree */
-static void kdbus_pool_add_free_slice(struct kdbus_pool *pool,
- struct kdbus_pool_slice *slice)
-{
- struct rb_node **n;
- struct rb_node *pn = NULL;
-
- n = &pool->slices_free.rb_node;
- while (*n) {
- struct kdbus_pool_slice *pslice;
-
- pn = *n;
- pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
- if (slice->size < pslice->size)
- n = &pn->rb_left;
- else
- n = &pn->rb_right;
- }
-
- rb_link_node(&slice->rb_node, pn, n);
- rb_insert_color(&slice->rb_node, &pool->slices_free);
-}
-
-/* insert a slice into the busy tree */
-static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool,
- struct kdbus_pool_slice *slice)
-{
- struct rb_node **n;
- struct rb_node *pn = NULL;
-
- n = &pool->slices_busy.rb_node;
- while (*n) {
- struct kdbus_pool_slice *pslice;
-
- pn = *n;
- pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
- if (slice->off < pslice->off)
- n = &pn->rb_left;
- else if (slice->off > pslice->off)
- n = &pn->rb_right;
- else
- BUG();
- }
-
- rb_link_node(&slice->rb_node, pn, n);
- rb_insert_color(&slice->rb_node, &pool->slices_busy);
-}
-
-static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool,
- size_t off)
-{
- struct rb_node *n;
-
- n = pool->slices_busy.rb_node;
- while (n) {
- struct kdbus_pool_slice *s;
-
- s = rb_entry(n, struct kdbus_pool_slice, rb_node);
- if (off < s->off)
- n = n->rb_left;
- else if (off > s->off)
- n = n->rb_right;
- else
- return s;
- }
-
- return NULL;
-}
-
-/**
- * kdbus_pool_slice_alloc() - allocate memory from a pool
- * @pool: The receiver's pool
- * @size: The number of bytes to allocate
- * @accounted: Whether this slice should be accounted for
- *
- * The returned slice is used for kdbus_pool_slice_release() to
- * free the allocated memory. If either @kvec or @iovec is non-NULL, the data
- * will be copied from kernel or userspace memory into the new slice at
- * offset 0.
- *
- * Return: the allocated slice on success, ERR_PTR on failure.
- */
-struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
- size_t size, bool accounted)
-{
- size_t slice_size = KDBUS_ALIGN8(size);
- struct rb_node *n, *found = NULL;
- struct kdbus_pool_slice *s;
- int ret = 0;
-
- if (WARN_ON(!size))
- return ERR_PTR(-EINVAL);
-
- /* search a free slice with the closest matching size */
- mutex_lock(&pool->lock);
- n = pool->slices_free.rb_node;
- while (n) {
- s = rb_entry(n, struct kdbus_pool_slice, rb_node);
- if (slice_size < s->size) {
- found = n;
- n = n->rb_left;
- } else if (slice_size > s->size) {
- n = n->rb_right;
- } else {
- found = n;
- break;
- }
- }
-
- /* no slice with the minimum size found in the pool */
- if (!found) {
- ret = -EXFULL;
- goto exit_unlock;
- }
-
- /* no exact match, use the closest one */
- if (!n) {
- struct kdbus_pool_slice *s_new;
-
- s = rb_entry(found, struct kdbus_pool_slice, rb_node);
-
- /* split-off the remainder of the size to its own slice */
- s_new = kdbus_pool_slice_new(pool, s->off + slice_size,
- s->size - slice_size);
- if (!s_new) {
- ret = -ENOMEM;
- goto exit_unlock;
- }
-
- list_add(&s_new->entry, &s->entry);
- kdbus_pool_add_free_slice(pool, s_new);
-
- /* adjust our size now that we split-off another slice */
- s->size = slice_size;
- }
-
- /* move slice from free to the busy tree */
- rb_erase(found, &pool->slices_free);
- kdbus_pool_add_busy_slice(pool, s);
-
- WARN_ON(s->ref_kernel || s->ref_user);
-
- s->ref_kernel = true;
- s->free = false;
- s->accounted = accounted;
- if (accounted)
- pool->accounted_size += s->size;
- mutex_unlock(&pool->lock);
-
- return s;
-
-exit_unlock:
- mutex_unlock(&pool->lock);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
-{
- struct kdbus_pool *pool = slice->pool;
-
- /* don't free the slice if either has a reference */
- if (slice->ref_kernel || slice->ref_user)
- return;
-
- if (WARN_ON(slice->free))
- return;
-
- rb_erase(&slice->rb_node, &pool->slices_busy);
-
- /* merge with the next free slice */
- if (!list_is_last(&slice->entry, &pool->slices)) {
- struct kdbus_pool_slice *s;
-
- s = list_entry(slice->entry.next,
- struct kdbus_pool_slice, entry);
- if (s->free) {
- rb_erase(&s->rb_node, &pool->slices_free);
- list_del(&s->entry);
- slice->size += s->size;
- kfree(s);
- }
- }
-
- /* merge with previous free slice */
- if (pool->slices.next != &slice->entry) {
- struct kdbus_pool_slice *s;
-
- s = list_entry(slice->entry.prev,
- struct kdbus_pool_slice, entry);
- if (s->free) {
- rb_erase(&s->rb_node, &pool->slices_free);
- list_del(&slice->entry);
- s->size += slice->size;
- kfree(slice);
- slice = s;
- }
- }
-
- slice->free = true;
- kdbus_pool_add_free_slice(pool, slice);
-}
-
-/**
- * kdbus_pool_slice_release() - drop kernel-reference on allocated slice
- * @slice: Slice allocated from the pool
- *
- * This releases the kernel-reference on the given slice. If the
- * kernel-reference and the user-reference on a slice are dropped, the slice is
- * returned to the pool.
- *
- * So far, we do not implement full ref-counting on slices. Each, kernel and
- * user-space can have exactly one reference to a slice. If both are dropped at
- * the same time, the slice is released.
- */
-void kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
-{
- struct kdbus_pool *pool;
-
- if (!slice)
- return;
-
- /* @slice may be freed, so keep local ptr to @pool */
- pool = slice->pool;
-
- mutex_lock(&pool->lock);
- /* kernel must own a ref to @slice to drop it */
- WARN_ON(!slice->ref_kernel);
- slice->ref_kernel = false;
- /* no longer kernel-owned, de-account slice */
- if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size))
- pool->accounted_size -= slice->size;
- __kdbus_pool_slice_release(slice);
- mutex_unlock(&pool->lock);
-}
-
-/**
- * kdbus_pool_release_offset() - release a public offset
- * @pool: pool to operate on
- * @off: offset to release
- *
- * This should be called whenever user-space frees a slice given to them. It
- * verifies the slice is available and public, and then drops it. It ensures
- * correct locking and barriers against queues.
- *
- * Return: 0 on success, ENXIO if the offset is invalid or not public.
- */
-int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off)
-{
- struct kdbus_pool_slice *slice;
- int ret = 0;
-
- /* 'pool->size' is used as dummy offset for empty slices */
- if (off == pool->size)
- return 0;
-
- mutex_lock(&pool->lock);
- slice = kdbus_pool_find_slice(pool, off);
- if (slice && slice->ref_user) {
- slice->ref_user = false;
- __kdbus_pool_slice_release(slice);
- } else {
- ret = -ENXIO;
- }
- mutex_unlock(&pool->lock);
-
- return ret;
-}
-
-/**
- * kdbus_pool_publish_empty() - publish empty slice to user-space
- * @pool: pool to operate on
- * @off: output storage for offset, or NULL
- * @size: output storage for size, or NULL
- *
- * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with
- * size 0. The returned offset points to the end of the pool and is never
- * returned on real slices.
- */
-void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size)
-{
- if (off)
- *off = pool->size;
- if (size)
- *size = 0;
-}
-
-/**
- * kdbus_pool_slice_publish() - publish slice to user-space
- * @slice: The slice
- * @out_offset: Output storage for offset, or NULL
- * @out_size: Output storage for size, or NULL
- *
- * This prepares a slice to be published to user-space.
- *
- * This call combines the following operations:
- * * the memory region is flushed so the user's memory view is consistent
- * * the slice is marked as referenced by user-space, so user-space has to
- * call KDBUS_CMD_FREE to release it
- * * the offset and size of the slice are written to the given output
- * arguments, if non-NULL
- */
-void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
- u64 *out_offset, u64 *out_size)
-{
- mutex_lock(&slice->pool->lock);
- /* kernel must own a ref to @slice to gain a user-space ref */
- WARN_ON(!slice->ref_kernel);
- slice->ref_user = true;
- mutex_unlock(&slice->pool->lock);
-
- if (out_offset)
- *out_offset = slice->off;
- if (out_size)
- *out_size = slice->size;
-}
-
-/**
- * kdbus_pool_slice_offset() - Get a slice's offset inside the pool
- * @slice: Slice to return the offset of
- *
- * Return: The internal offset @slice inside the pool.
- */
-off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice)
-{
- return slice->off;
-}
-
-/**
- * kdbus_pool_slice_size() - get size of a pool slice
- * @slice: slice to query
- *
- * Return: size of the given slice
- */
-size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice)
-{
- return slice->size;
-}
-
-/**
- * kdbus_pool_new() - create a new pool
- * @name: Name of the (deleted) file which shows up in
- * /proc, used for debugging
- * @size: Maximum size of the pool
- *
- * Return: a new kdbus_pool on success, ERR_PTR on failure.
- */
-struct kdbus_pool *kdbus_pool_new(const char *name, size_t size)
-{
- struct kdbus_pool_slice *s;
- struct kdbus_pool *p;
- struct file *f;
- char *n = NULL;
- int ret;
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p)
- return ERR_PTR(-ENOMEM);
-
- if (name) {
- n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name);
- if (!n) {
- ret = -ENOMEM;
- goto exit_free;
- }
- }
-
- f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0, 0);
- kfree(n);
-
- if (IS_ERR(f)) {
- ret = PTR_ERR(f);
- goto exit_free;
- }
-
- ret = get_write_access(file_inode(f));
- if (ret < 0)
- goto exit_put_shmem;
-
- /* allocate first slice spanning the entire pool */
- s = kdbus_pool_slice_new(p, 0, size);
- if (!s) {
- ret = -ENOMEM;
- goto exit_put_write;
- }
-
- p->f = f;
- p->size = size;
- p->slices_free = RB_ROOT;
- p->slices_busy = RB_ROOT;
- mutex_init(&p->lock);
-
- INIT_LIST_HEAD(&p->slices);
- list_add(&s->entry, &p->slices);
-
- kdbus_pool_add_free_slice(p, s);
- return p;
-
-exit_put_write:
- put_write_access(file_inode(f));
-exit_put_shmem:
- fput(f);
-exit_free:
- kfree(p);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_pool_free() - destroy pool
- * @pool: The receiver's pool
- */
-void kdbus_pool_free(struct kdbus_pool *pool)
-{
- struct kdbus_pool_slice *s, *tmp;
-
- if (!pool)
- return;
-
- list_for_each_entry_safe(s, tmp, &pool->slices, entry) {
- list_del(&s->entry);
- kfree(s);
- }
-
- put_write_access(file_inode(pool->f));
- fput(pool->f);
- kfree(pool);
-}
-
-/**
- * kdbus_pool_accounted() - retrieve accounting information
- * @pool: pool to query
- * @size: output for overall pool size
- * @acc: output for currently accounted size
- *
- * This returns accounting information of the pool. Note that the data might
- * change after the function returns, as the pool lock is dropped. You need to
- * protect the data via other means, if you need reliable accounting.
- */
-void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc)
-{
- mutex_lock(&pool->lock);
- if (size)
- *size = pool->size;
- if (acc)
- *acc = pool->accounted_size;
- mutex_unlock(&pool->lock);
-}
-
-/**
- * kdbus_pool_slice_copy_iovec() - copy user memory to a slice
- * @slice: The slice to write to
- * @off: Offset in the slice to write to
- * @iov: iovec array, pointing to data to copy
- * @iov_len: Number of elements in @iov
- * @total_len: Total number of bytes described in members of @iov
- *
- * User memory referenced by @iov will be copied into @slice at offset @off.
- *
- * Return: the numbers of bytes copied, negative errno on failure.
- */
-ssize_t
-kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off,
- struct iovec *iov, size_t iov_len, size_t total_len)
-{
- struct iov_iter iter;
- ssize_t len;
-
- if (WARN_ON(off + total_len > slice->size))
- return -EFAULT;
-
- off += slice->off;
- iov_iter_init(&iter, WRITE, iov, iov_len, total_len);
- len = vfs_iter_write(slice->pool->f, &iter, &off);
-
- return (len >= 0 && len != total_len) ? -EFAULT : len;
-}
-
-/**
- * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice
- * @slice: The slice to write to
- * @off: Offset in the slice to write to
- * @kvec: kvec array, pointing to data to copy
- * @kvec_len: Number of elements in @kvec
- * @total_len: Total number of bytes described in members of @kvec
- *
- * Kernel memory referenced by @kvec will be copied into @slice at offset @off.
- *
- * Return: the numbers of bytes copied, negative errno on failure.
- */
-ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
- loff_t off, struct kvec *kvec,
- size_t kvec_len, size_t total_len)
-{
- struct iov_iter iter;
- mm_segment_t old_fs;
- ssize_t len;
-
- if (WARN_ON(off + total_len > slice->size))
- return -EFAULT;
-
- off += slice->off;
- iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len);
-
- old_fs = get_fs();
- set_fs(get_ds());
- len = vfs_iter_write(slice->pool->f, &iter, &off);
- set_fs(old_fs);
-
- return (len >= 0 && len != total_len) ? -EFAULT : len;
-}
-
-/**
- * kdbus_pool_slice_copy() - copy data from one slice into another
- * @slice_dst: destination slice
- * @slice_src: source slice
- *
- * Return: 0 on success, negative error number on failure.
- */
-int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
- const struct kdbus_pool_slice *slice_src)
-{
- struct file *f_src = slice_src->pool->f;
- struct file *f_dst = slice_dst->pool->f;
- struct inode *i_dst = file_inode(f_dst);
- struct address_space *mapping_dst = f_dst->f_mapping;
- const struct address_space_operations *aops = mapping_dst->a_ops;
- unsigned long len = slice_src->size;
- loff_t off_src = slice_src->off;
- loff_t off_dst = slice_dst->off;
- mm_segment_t old_fs;
- int ret = 0;
-
- if (WARN_ON(slice_src->size != slice_dst->size) ||
- WARN_ON(slice_src->free || slice_dst->free))
- return -EINVAL;
-
- mutex_lock(&i_dst->i_mutex);
- old_fs = get_fs();
- set_fs(get_ds());
- while (len > 0) {
- unsigned long page_off;
- unsigned long copy_len;
- char __user *kaddr;
- struct page *page;
- ssize_t n_read;
- void *fsdata;
- long status;
-
- page_off = off_dst & (PAGE_CACHE_SIZE - 1);
- copy_len = min_t(unsigned long,
- PAGE_CACHE_SIZE - page_off, len);
-
- status = aops->write_begin(f_dst, mapping_dst, off_dst,
- copy_len, 0, &page, &fsdata);
- if (unlikely(status < 0)) {
- ret = status;
- break;
- }
-
- kaddr = (char __force __user *)kmap(page) + page_off;
- n_read = __vfs_read(f_src, kaddr, copy_len, &off_src);
- kunmap(page);
- mark_page_accessed(page);
- flush_dcache_page(page);
-
- if (unlikely(n_read != copy_len)) {
- ret = -EFAULT;
- break;
- }
-
- status = aops->write_end(f_dst, mapping_dst, off_dst,
- copy_len, copy_len, page, fsdata);
- if (unlikely(status != copy_len)) {
- ret = -EFAULT;
- break;
- }
-
- off_dst += copy_len;
- len -= copy_len;
- }
- set_fs(old_fs);
- mutex_unlock(&i_dst->i_mutex);
-
- return ret;
-}
-
-/**
- * kdbus_pool_mmap() - map the pool into the process
- * @pool: The receiver's pool
- * @vma: passed by mmap() syscall
- *
- * Return: the result of the mmap() call, negative errno on failure.
- */
-int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma)
-{
- /* deny write access to the pool */
- if (vma->vm_flags & VM_WRITE)
- return -EPERM;
- vma->vm_flags &= ~VM_MAYWRITE;
-
- /* do not allow to map more than the size of the file */
- if ((vma->vm_end - vma->vm_start) > pool->size)
- return -EFAULT;
-
- /* replace the connection file with our shmem file */
- if (vma->vm_file)
- fput(vma->vm_file);
- vma->vm_file = get_file(pool->f);
-
- return pool->f->f_op->mmap(pool->f, vma);
-}
diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h
deleted file mode 100644
index a9038213a..000000000
--- a/ipc/kdbus/pool.h
+++ /dev/null
@@ -1,46 +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.
- */
-
-#ifndef __KDBUS_POOL_H
-#define __KDBUS_POOL_H
-
-#include <linux/uio.h>
-
-struct kdbus_pool;
-struct kdbus_pool_slice;
-
-struct kdbus_pool *kdbus_pool_new(const char *name, size_t size);
-void kdbus_pool_free(struct kdbus_pool *pool);
-void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc);
-int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma);
-int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off);
-void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size);
-
-struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
- size_t size, bool accounted);
-void kdbus_pool_slice_release(struct kdbus_pool_slice *slice);
-void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
- u64 *out_offset, u64 *out_size);
-off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice);
-size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice);
-int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
- const struct kdbus_pool_slice *slice_src);
-ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
- loff_t off, struct kvec *kvec,
- size_t kvec_count, size_t total_len);
-ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice,
- loff_t off, struct iovec *iov,
- size_t iov_count, size_t total_len);
-
-#endif
diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c
deleted file mode 100644
index f9c44d7ba..000000000
--- a/ipc/kdbus/queue.c
+++ /dev/null
@@ -1,363 +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/audit.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/hashtable.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/math64.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/uio.h>
-
-#include "util.h"
-#include "domain.h"
-#include "connection.h"
-#include "item.h"
-#include "message.h"
-#include "metadata.h"
-#include "queue.h"
-#include "reply.h"
-
-/**
- * kdbus_queue_init() - initialize data structure related to a queue
- * @queue: The queue to initialize
- */
-void kdbus_queue_init(struct kdbus_queue *queue)
-{
- INIT_LIST_HEAD(&queue->msg_list);
- queue->msg_prio_queue = RB_ROOT;
-}
-
-/**
- * kdbus_queue_peek() - Retrieves an entry from a queue
- * @queue: The queue
- * @priority: The minimum priority of the entry to peek
- * @use_priority: Boolean flag whether or not to peek by priority
- *
- * Look for a entry in a queue, either by priority, or the oldest one (FIFO).
- * The entry is not freed, put off the queue's lists or anything else.
- *
- * Return: the peeked queue entry on success, NULL if no suitable msg is found
- */
-struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue,
- s64 priority, bool use_priority)
-{
- struct kdbus_queue_entry *e;
-
- if (list_empty(&queue->msg_list))
- return NULL;
-
- if (use_priority) {
- /* get next entry with highest priority */
- e = rb_entry(queue->msg_prio_highest,
- struct kdbus_queue_entry, prio_node);
-
- /* no entry with the requested priority */
- if (e->priority > priority)
- return NULL;
- } else {
- /* ignore the priority, return the next entry in the entry */
- e = list_first_entry(&queue->msg_list,
- struct kdbus_queue_entry, entry);
- }
-
- return e;
-}
-
-static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry)
-{
- struct kdbus_queue *queue = &entry->conn->queue;
- struct rb_node **n, *pn = NULL;
- bool highest = true;
-
- lockdep_assert_held(&entry->conn->lock);
- if (WARN_ON(!list_empty(&entry->entry)))
- return;
-
- /* sort into priority entry tree */
- n = &queue->msg_prio_queue.rb_node;
- while (*n) {
- struct kdbus_queue_entry *e;
-
- pn = *n;
- e = rb_entry(pn, struct kdbus_queue_entry, prio_node);
-
- /* existing node for this priority, add to its list */
- if (likely(entry->priority == e->priority)) {
- list_add_tail(&entry->prio_entry, &e->prio_entry);
- goto prio_done;
- }
-
- if (entry->priority < e->priority) {
- n = &pn->rb_left;
- } else {
- n = &pn->rb_right;
- highest = false;
- }
- }
-
- /* cache highest-priority entry */
- if (highest)
- queue->msg_prio_highest = &entry->prio_node;
-
- /* new node for this priority */
- rb_link_node(&entry->prio_node, pn, n);
- rb_insert_color(&entry->prio_node, &queue->msg_prio_queue);
- INIT_LIST_HEAD(&entry->prio_entry);
-
-prio_done:
- /* add to unsorted fifo list */
- list_add_tail(&entry->entry, &queue->msg_list);
-}
-
-static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry)
-{
- struct kdbus_queue *queue = &entry->conn->queue;
-
- lockdep_assert_held(&entry->conn->lock);
- if (list_empty(&entry->entry))
- return;
-
- list_del_init(&entry->entry);
-
- if (list_empty(&entry->prio_entry)) {
- /*
- * Single entry for this priority, update cached
- * highest-priority entry, remove the tree node.
- */
- if (queue->msg_prio_highest == &entry->prio_node)
- queue->msg_prio_highest = rb_next(&entry->prio_node);
-
- rb_erase(&entry->prio_node, &queue->msg_prio_queue);
- } else {
- struct kdbus_queue_entry *q;
-
- /*
- * Multiple entries for this priority entry, get next one in
- * the list. Update cached highest-priority entry, store the
- * new one as the tree node.
- */
- q = list_first_entry(&entry->prio_entry,
- struct kdbus_queue_entry, prio_entry);
- list_del(&entry->prio_entry);
-
- if (queue->msg_prio_highest == &entry->prio_node)
- queue->msg_prio_highest = &q->prio_node;
-
- rb_replace_node(&entry->prio_node, &q->prio_node,
- &queue->msg_prio_queue);
- }
-}
-
-/**
- * kdbus_queue_entry_new() - allocate a queue entry
- * @src: source connection, or NULL
- * @dst: destination connection
- * @s: staging object carrying the message
- *
- * Allocates a queue entry based on a given msg and allocate space for
- * the message payload and the requested metadata in the connection's pool.
- * The entry is not actually added to the queue's lists at this point.
- *
- * Return: the allocated entry on success, or an ERR_PTR on failures.
- */
-struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src,
- struct kdbus_conn *dst,
- struct kdbus_staging *s)
-{
- struct kdbus_queue_entry *entry;
- int ret;
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&entry->entry);
- entry->priority = s->msg->priority;
- entry->conn = kdbus_conn_ref(dst);
- entry->gaps = kdbus_gaps_ref(s->gaps);
-
- entry->slice = kdbus_staging_emit(s, src, dst);
- if (IS_ERR(entry->slice)) {
- ret = PTR_ERR(entry->slice);
- entry->slice = NULL;
- goto error;
- }
-
- entry->user = src ? kdbus_user_ref(src->user) : NULL;
- return entry;
-
-error:
- kdbus_queue_entry_free(entry);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_queue_entry_free() - free resources of an entry
- * @entry: The entry to free
- *
- * Removes resources allocated by a queue entry, along with the entry itself.
- * Note that the entry's slice is not freed at this point.
- */
-void kdbus_queue_entry_free(struct kdbus_queue_entry *entry)
-{
- if (!entry)
- return;
-
- lockdep_assert_held(&entry->conn->lock);
-
- kdbus_queue_entry_unlink(entry);
- kdbus_reply_unref(entry->reply);
-
- if (entry->slice) {
- kdbus_conn_quota_dec(entry->conn, entry->user,
- kdbus_pool_slice_size(entry->slice),
- entry->gaps ? entry->gaps->n_fds : 0);
- kdbus_pool_slice_release(entry->slice);
- }
-
- kdbus_user_unref(entry->user);
- kdbus_gaps_unref(entry->gaps);
- kdbus_conn_unref(entry->conn);
- kfree(entry);
-}
-
-/**
- * kdbus_queue_entry_install() - install message components into the
- * receiver's process
- * @entry: The queue entry to install
- * @return_flags: Pointer to store the return flags for userspace
- * @install_fds: Whether or not to install associated file descriptors
- *
- * Return: 0 on success.
- */
-int kdbus_queue_entry_install(struct kdbus_queue_entry *entry,
- u64 *return_flags, bool install_fds)
-{
- bool incomplete_fds = false;
- int ret;
-
- lockdep_assert_held(&entry->conn->lock);
-
- ret = kdbus_gaps_install(entry->gaps, entry->slice, &incomplete_fds);
- if (ret < 0)
- return ret;
-
- if (incomplete_fds)
- *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS;
- return 0;
-}
-
-/**
- * kdbus_queue_entry_enqueue() - enqueue an entry
- * @entry: entry to enqueue
- * @reply: reply to link to this entry (or NULL if none)
- *
- * This enqueues an unqueued entry into the message queue of the linked
- * connection. It also binds a reply object to the entry so we can remember it
- * when the message is moved.
- *
- * Once this call returns (and the connection lock is released), this entry can
- * be dequeued by the target connection. Note that the entry will not be removed
- * from the queue until it is destroyed.
- */
-void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry,
- struct kdbus_reply *reply)
-{
- lockdep_assert_held(&entry->conn->lock);
-
- if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry)))
- return;
-
- entry->reply = kdbus_reply_ref(reply);
- kdbus_queue_entry_link(entry);
-}
-
-/**
- * kdbus_queue_entry_move() - move queue entry
- * @e: queue entry to move
- * @dst: destination connection to queue the entry on
- *
- * This moves a queue entry onto a different connection. It allocates a new
- * slice on the target connection and copies the message over. If the copy
- * succeeded, we move the entry from @src to @dst.
- *
- * On failure, the entry is left untouched.
- *
- * The queue entry must be queued right now, and after the call succeeds it will
- * be queued on the destination, but no longer on the source.
- *
- * The caller must hold the connection lock of the source *and* destination.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_queue_entry_move(struct kdbus_queue_entry *e,
- struct kdbus_conn *dst)
-{
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_conn *src = e->conn;
- size_t size, fds;
- int ret;
-
- lockdep_assert_held(&src->lock);
- lockdep_assert_held(&dst->lock);
-
- if (WARN_ON(list_empty(&e->entry)))
- return -EINVAL;
- if (src == dst)
- return 0;
-
- size = kdbus_pool_slice_size(e->slice);
- fds = e->gaps ? e->gaps->n_fds : 0;
-
- ret = kdbus_conn_quota_inc(dst, e->user, size, fds);
- if (ret < 0)
- return ret;
-
- slice = kdbus_pool_slice_alloc(dst->pool, size, true);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto error;
- }
-
- ret = kdbus_pool_slice_copy(slice, e->slice);
- if (ret < 0)
- goto error;
-
- kdbus_queue_entry_unlink(e);
- kdbus_conn_quota_dec(src, e->user, size, fds);
- kdbus_pool_slice_release(e->slice);
- kdbus_conn_unref(e->conn);
-
- e->slice = slice;
- e->conn = kdbus_conn_ref(dst);
- kdbus_queue_entry_link(e);
-
- return 0;
-
-error:
- kdbus_pool_slice_release(slice);
- kdbus_conn_quota_dec(dst, e->user, size, fds);
- return ret;
-}
diff --git a/ipc/kdbus/queue.h b/ipc/kdbus/queue.h
deleted file mode 100644
index bf686d182..000000000
--- a/ipc/kdbus/queue.h
+++ /dev/null
@@ -1,84 +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.
- */
-
-#ifndef __KDBUS_QUEUE_H
-#define __KDBUS_QUEUE_H
-
-#include <linux/list.h>
-#include <linux/rbtree.h>
-
-struct kdbus_conn;
-struct kdbus_pool_slice;
-struct kdbus_reply;
-struct kdbus_staging;
-struct kdbus_user;
-
-/**
- * struct kdbus_queue - a connection's message queue
- * @msg_list: List head for kdbus_queue_entry objects
- * @msg_prio_queue: RB tree root for messages, sorted by priority
- * @msg_prio_highest: Link to the RB node referencing the message with the
- * highest priority in the tree.
- */
-struct kdbus_queue {
- struct list_head msg_list;
- struct rb_root msg_prio_queue;
- struct rb_node *msg_prio_highest;
-};
-
-/**
- * struct kdbus_queue_entry - messages waiting to be read
- * @entry: Entry in the connection's list
- * @prio_node: Entry in the priority queue tree
- * @prio_entry: Queue tree node entry in the list of one priority
- * @priority: Message priority
- * @dst_name_id: The sequence number of the name this message is
- * addressed to, 0 for messages sent to an ID
- * @conn: Connection this entry is queued on
- * @gaps: Gaps object to fill message gaps at RECV time
- * @user: User used for accounting
- * @slice: Slice in the receiver's pool for the message
- * @reply: The reply block if a reply to this message is expected
- */
-struct kdbus_queue_entry {
- struct list_head entry;
- struct rb_node prio_node;
- struct list_head prio_entry;
-
- s64 priority;
- u64 dst_name_id;
-
- struct kdbus_conn *conn;
- struct kdbus_gaps *gaps;
- struct kdbus_user *user;
- struct kdbus_pool_slice *slice;
- struct kdbus_reply *reply;
-};
-
-void kdbus_queue_init(struct kdbus_queue *queue);
-struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue,
- s64 priority, bool use_priority);
-
-struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src,
- struct kdbus_conn *dst,
- struct kdbus_staging *s);
-void kdbus_queue_entry_free(struct kdbus_queue_entry *entry);
-int kdbus_queue_entry_install(struct kdbus_queue_entry *entry,
- u64 *return_flags, bool install_fds);
-void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry,
- struct kdbus_reply *reply);
-int kdbus_queue_entry_move(struct kdbus_queue_entry *entry,
- struct kdbus_conn *dst);
-
-#endif /* __KDBUS_QUEUE_H */
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
deleted file mode 100644
index e6791d86e..000000000
--- a/ipc/kdbus/reply.c
+++ /dev/null
@@ -1,252 +0,0 @@
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "domain.h"
-#include "item.h"
-#include "notify.h"
-#include "policy.h"
-#include "reply.h"
-#include "util.h"
-
-/**
- * kdbus_reply_new() - Allocate and set up a new kdbus_reply object
- * @reply_src: The connection a reply is expected from
- * @reply_dst: The connection this reply object belongs to
- * @msg: Message associated with the reply
- * @name_entry: Name entry used to send the message
- * @sync: Whether or not to make this reply synchronous
- *
- * Allocate and fill a new kdbus_reply object.
- *
- * Return: New kdbus_conn object on success, ERR_PTR on error.
- */
-struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
- struct kdbus_conn *reply_dst,
- const struct kdbus_msg *msg,
- struct kdbus_name_entry *name_entry,
- bool sync)
-{
- struct kdbus_reply *r;
- int ret;
-
- if (atomic_inc_return(&reply_dst->request_count) >
- KDBUS_CONN_MAX_REQUESTS_PENDING) {
- ret = -EMLINK;
- goto exit_dec_request_count;
- }
-
- r = kzalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- ret = -ENOMEM;
- goto exit_dec_request_count;
- }
-
- kref_init(&r->kref);
- INIT_LIST_HEAD(&r->entry);
- r->reply_src = kdbus_conn_ref(reply_src);
- r->reply_dst = kdbus_conn_ref(reply_dst);
- r->cookie = msg->cookie;
- r->name_id = name_entry ? name_entry->name_id : 0;
- r->deadline_ns = msg->timeout_ns;
-
- if (sync) {
- r->sync = true;
- r->waiting = true;
- }
-
- return r;
-
-exit_dec_request_count:
- atomic_dec(&reply_dst->request_count);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_reply_free(struct kref *kref)
-{
- struct kdbus_reply *reply =
- container_of(kref, struct kdbus_reply, kref);
-
- atomic_dec(&reply->reply_dst->request_count);
- kdbus_conn_unref(reply->reply_src);
- kdbus_conn_unref(reply->reply_dst);
- kfree(reply);
-}
-
-/**
- * kdbus_reply_ref() - Increase reference on kdbus_reply
- * @r: The reply, may be %NULL
- *
- * Return: The reply object with an extra reference
- */
-struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r)
-{
- if (r)
- kref_get(&r->kref);
- return r;
-}
-
-/**
- * kdbus_reply_unref() - Decrease reference on kdbus_reply
- * @r: The reply, may be %NULL
- *
- * Return: NULL
- */
-struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r)
-{
- if (r)
- kref_put(&r->kref, __kdbus_reply_free);
- return NULL;
-}
-
-/**
- * kdbus_reply_link() - Link reply object into target connection
- * @r: Reply to link
- */
-void kdbus_reply_link(struct kdbus_reply *r)
-{
- if (WARN_ON(!list_empty(&r->entry)))
- return;
-
- list_add(&r->entry, &r->reply_dst->reply_list);
- kdbus_reply_ref(r);
-}
-
-/**
- * kdbus_reply_unlink() - Unlink reply object from target connection
- * @r: Reply to unlink
- */
-void kdbus_reply_unlink(struct kdbus_reply *r)
-{
- if (!list_empty(&r->entry)) {
- list_del_init(&r->entry);
- kdbus_reply_unref(r);
- }
-}
-
-/**
- * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply
- * @reply: The reply object
- * @err: Error code to set on the remote side
- *
- * Wake up remote peer (method origin) with the appropriate synchronous reply
- * code.
- */
-void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err)
-{
- if (WARN_ON(!reply->sync))
- return;
-
- reply->waiting = false;
- reply->err = err;
- wake_up_interruptible(&reply->reply_dst->wait);
-}
-
-/**
- * kdbus_reply_find() - Find the corresponding reply object
- * @replying: The replying connection or NULL
- * @reply_dst: The connection the reply will be sent to
- * (method origin)
- * @cookie: The cookie of the requesting message
- *
- * Lookup a reply object that should be sent as a reply by
- * @replying to @reply_dst with the given cookie.
- *
- * Callers must take the @reply_dst lock.
- *
- * Return: the corresponding reply object or NULL if not found
- */
-struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
- struct kdbus_conn *reply_dst,
- u64 cookie)
-{
- struct kdbus_reply *r;
-
- list_for_each_entry(r, &reply_dst->reply_list, entry) {
- if (r->cookie == cookie &&
- (!replying || r->reply_src == replying))
- return r;
- }
-
- return NULL;
-}
-
-/**
- * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a
- * connection for exceeded timeouts
- * @work: Work struct of the connection to scan
- *
- * Walk the list of replies stored with a connection and look for entries
- * that have exceeded their timeout. If such an entry is found, a timeout
- * notification is sent to the waiting peer, and the reply is removed from
- * the list.
- *
- * The work is rescheduled to the nearest timeout found during the list
- * iteration.
- */
-void kdbus_reply_list_scan_work(struct work_struct *work)
-{
- struct kdbus_conn *conn =
- container_of(work, struct kdbus_conn, work.work);
- struct kdbus_reply *reply, *reply_tmp;
- u64 deadline = ~0ULL;
- u64 now;
-
- now = ktime_get_ns();
-
- mutex_lock(&conn->lock);
- if (!kdbus_conn_active(conn)) {
- mutex_unlock(&conn->lock);
- return;
- }
-
- list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) {
- /*
- * If the reply block is waiting for synchronous I/O,
- * the timeout is handled by wait_event_*_timeout(),
- * so we don't have to care for it here.
- */
- if (reply->sync && !reply->interrupted)
- continue;
-
- WARN_ON(reply->reply_dst != conn);
-
- if (reply->deadline_ns > now) {
- /* remember next timeout */
- if (deadline > reply->deadline_ns)
- deadline = reply->deadline_ns;
-
- continue;
- }
-
- /*
- * A zero deadline means the connection died, was
- * cleaned up already and the notification was sent.
- * Don't send notifications for reply trackers that were
- * left in an interrupted syscall state.
- */
- if (reply->deadline_ns != 0 && !reply->interrupted)
- kdbus_notify_reply_timeout(conn->ep->bus, conn->id,
- reply->cookie);
-
- kdbus_reply_unlink(reply);
- }
-
- /* rearm delayed work with next timeout */
- if (deadline != ~0ULL)
- schedule_delayed_work(&conn->work,
- nsecs_to_jiffies(deadline - now));
-
- mutex_unlock(&conn->lock);
-
- kdbus_notify_flush(conn->ep->bus);
-}
diff --git a/ipc/kdbus/reply.h b/ipc/kdbus/reply.h
deleted file mode 100644
index 68d52321a..000000000
--- a/ipc/kdbus/reply.h
+++ /dev/null
@@ -1,68 +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.
- */
-
-#ifndef __KDBUS_REPLY_H
-#define __KDBUS_REPLY_H
-
-/**
- * struct kdbus_reply - an entry of kdbus_conn's list of replies
- * @kref: Ref-count of this object
- * @entry: The entry of the connection's reply_list
- * @reply_src: The connection the reply will be sent from
- * @reply_dst: The connection the reply will be sent to
- * @queue_entry: The queue entry item that is prepared by the replying
- * connection
- * @deadline_ns: The deadline of the reply, in nanoseconds
- * @cookie: The cookie of the requesting message
- * @name_id: ID of the well-known name the original msg was sent to
- * @sync: The reply block is waiting for synchronous I/O
- * @waiting: The condition to synchronously wait for
- * @interrupted: The sync reply was left in an interrupted state
- * @err: The error code for the synchronous reply
- */
-struct kdbus_reply {
- struct kref kref;
- struct list_head entry;
- struct kdbus_conn *reply_src;
- struct kdbus_conn *reply_dst;
- struct kdbus_queue_entry *queue_entry;
- u64 deadline_ns;
- u64 cookie;
- u64 name_id;
- bool sync:1;
- bool waiting:1;
- bool interrupted:1;
- int err;
-};
-
-struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
- struct kdbus_conn *reply_dst,
- const struct kdbus_msg *msg,
- struct kdbus_name_entry *name_entry,
- bool sync);
-
-struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r);
-struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r);
-
-void kdbus_reply_link(struct kdbus_reply *r);
-void kdbus_reply_unlink(struct kdbus_reply *r);
-
-struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
- struct kdbus_conn *reply_dst,
- u64 cookie);
-
-void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err);
-void kdbus_reply_list_scan_work(struct work_struct *work);
-
-#endif /* __KDBUS_REPLY_H */
diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c
deleted file mode 100644
index 72b188330..000000000
--- a/ipc/kdbus/util.c
+++ /dev/null
@@ -1,156 +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/capability.h>
-#include <linux/cred.h>
-#include <linux/ctype.h>
-#include <linux/err.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-#include <linux/user_namespace.h>
-
-#include "limits.h"
-#include "util.h"
-
-/**
- * kdbus_copy_from_user() - copy aligned data from user-space
- * @dest: target buffer in kernel memory
- * @user_ptr: user-provided source buffer
- * @size: memory size to copy from user
- *
- * This copies @size bytes from @user_ptr into the kernel, just like
- * copy_from_user() does. But we enforce an 8-byte alignment and reject any
- * unaligned user-space pointers.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size)
-{
- if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr))
- return -EFAULT;
-
- if (copy_from_user(dest, user_ptr, size))
- return -EFAULT;
-
- return 0;
-}
-
-/**
- * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name
- * @name: user-supplied name to verify
- * @user_ns: user-namespace to act in
- * @kuid: Kernel internal uid of user
- *
- * This verifies that the user-supplied name @name has their UID as prefix. This
- * is the default name-spacing policy we enforce on user-supplied names for
- * public kdbus entities like buses and endpoints.
- *
- * The user must supply names prefixed with "<UID>-", whereas the UID is
- * interpreted in the user-namespace of the domain. If the user fails to supply
- * such a prefixed name, we reject it.
- *
- * Return: 0 on success, negative error code on failure
- */
-int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns,
- kuid_t kuid)
-{
- uid_t uid;
- char prefix[16];
-
- /*
- * The kuid must have a mapping into the userns of the domain
- * otherwise do not allow creation of buses nor endpoints.
- */
- uid = from_kuid(user_ns, kuid);
- if (uid == (uid_t) -1)
- return -EINVAL;
-
- snprintf(prefix, sizeof(prefix), "%u-", uid);
- if (strncmp(name, prefix, strlen(prefix)) != 0)
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space
- * @flags: Attach flags provided by userspace
- * @attach_flags: A pointer where to store the valid attach flags
- *
- * Convert attach-flags provided by user-space into a valid mask. If the mask
- * is invalid, an error is returned. The sanitized attach flags are stored in
- * the output parameter.
- *
- * Return: 0 on success, negative error on failure.
- */
-int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags)
-{
- /* 'any' degrades to 'all' for compatibility */
- if (flags == _KDBUS_ATTACH_ANY)
- flags = _KDBUS_ATTACH_ALL;
-
- /* reject unknown attach flags */
- if (flags & ~_KDBUS_ATTACH_ALL)
- return -EINVAL;
-
- *attach_flags = flags;
- return 0;
-}
-
-/**
- * kdbus_kvec_set - helper utility to assemble kvec arrays
- * @kvec: kvec entry to use
- * @src: Source address to set in @kvec
- * @len: Number of bytes in @src
- * @total_len: Pointer to total length variable
- *
- * Set @src and @len in @kvec, and increase @total_len by @len.
- */
-void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len)
-{
- kvec->iov_base = src;
- kvec->iov_len = len;
- *total_len += len;
-}
-
-static const char * const zeros = "\0\0\0\0\0\0\0";
-
-/**
- * kdbus_kvec_pad - conditionally write a padding kvec
- * @kvec: kvec entry to use
- * @len: Total length used for kvec array
- *
- * Check if the current total byte length of the array in @len is aligned to
- * 8 bytes. If it isn't, fill @kvec with padding information and increase @len
- * by the number of bytes stored in @kvec.
- *
- * Return: the number of added padding bytes.
- */
-size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len)
-{
- size_t pad = KDBUS_ALIGN8(*len) - *len;
-
- if (!pad)
- return 0;
-
- kvec->iov_base = (void *)zeros;
- kvec->iov_len = pad;
-
- *len += pad;
-
- return pad;
-}
diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h
deleted file mode 100644
index 529716669..000000000
--- a/ipc/kdbus/util.h
+++ /dev/null
@@ -1,73 +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.
- */
-
-#ifndef __KDBUS_UTIL_H
-#define __KDBUS_UTIL_H
-
-#include <linux/dcache.h>
-#include <linux/ioctl.h>
-
-#include <uapi/linux/kdbus.h>
-
-/* all exported addresses are 64 bit */
-#define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr))
-
-/* all exported sizes are 64 bit and data aligned to 64 bit */
-#define KDBUS_ALIGN8(s) ALIGN((s), 8)
-#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8))
-
-/**
- * kdbus_member_set_user - write a structure member to user memory
- * @_s: Variable to copy from
- * @_b: Buffer to write to
- * @_t: Structure type
- * @_m: Member name in the passed structure
- *
- * Return: the result of copy_to_user()
- */
-#define kdbus_member_set_user(_s, _b, _t, _m) \
-({ \
- u64 __user *_sz = \
- (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \
- copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \
-})
-
-/**
- * kdbus_strhash - calculate a hash
- * @str: String
- *
- * Return: hash value
- */
-static inline unsigned int kdbus_strhash(const char *str)
-{
- unsigned long hash = init_name_hash();
-
- while (*str)
- hash = partial_name_hash(*str++, hash);
-
- return end_name_hash(hash);
-}
-
-int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns,
- kuid_t kuid);
-int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags);
-
-int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size);
-
-struct kvec;
-
-void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len);
-size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len);
-
-#endif