Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755113AbcJZTYy (ORCPT ); Wed, 26 Oct 2016 15:24:54 -0400 Received: from mail-wm0-f68.google.com ([74.125.82.68]:34727 "EHLO mail-wm0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754315AbcJZTVl (ORCPT ); Wed, 26 Oct 2016 15:21:41 -0400 From: David Herrmann To: linux-kernel@vger.kernel.org Cc: Andy Lutomirski , Jiri Kosina , Greg KH , Hannes Reinecke , Steven Rostedt , Arnd Bergmann , Tom Gundersen , David Herrmann , Josh Triplett , Linus Torvalds , Andrew Morton Subject: [RFC v1 02/14] bus1: provide stub cdev /dev/bus1 Date: Wed, 26 Oct 2016 21:17:58 +0200 Message-Id: <20161026191810.12275-3-dh.herrmann@gmail.com> X-Mailer: git-send-email 2.10.1 In-Reply-To: <20161026191810.12275-1-dh.herrmann@gmail.com> References: <20161026191810.12275-1-dh.herrmann@gmail.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 13013 Lines: 451 From: Tom Gundersen Add the CONFIG_BUS1 option to enable the bus1 kernel messaging bus. If enabled, provide the bus1.ko module with a stub cdev /dev/bus1. So far it does not expose any API, but the full intended uapi is provided in include/uapi/linux/bus1.h already. Signed-off-by: Tom Gundersen Signed-off-by: David Herrmann --- include/uapi/linux/bus1.h | 138 ++++++++++++++++++++++++++++++++++++++++++++++ init/Kconfig | 17 ++++++ ipc/Makefile | 1 + ipc/bus1/Makefile | 6 ++ ipc/bus1/main.c | 80 +++++++++++++++++++++++++++ ipc/bus1/main.h | 74 +++++++++++++++++++++++++ ipc/bus1/tests.c | 19 +++++++ ipc/bus1/tests.h | 32 +++++++++++ 8 files changed, 367 insertions(+) create mode 100644 include/uapi/linux/bus1.h create mode 100644 ipc/bus1/Makefile create mode 100644 ipc/bus1/main.c create mode 100644 ipc/bus1/main.h create mode 100644 ipc/bus1/tests.c create mode 100644 ipc/bus1/tests.h diff --git a/include/uapi/linux/bus1.h b/include/uapi/linux/bus1.h new file mode 100644 index 0000000..8ec3357 --- /dev/null +++ b/include/uapi/linux/bus1.h @@ -0,0 +1,138 @@ +#ifndef _UAPI_LINUX_BUS1_H +#define _UAPI_LINUX_BUS1_H + +/* + * Copyright (C) 2013-2016 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU Lesser General Public License as published by the + * Free Software Foundation; either version 2.1 of the License, or (at + * your option) any later version. + */ + +#include +#include + +#define BUS1_FD_MAX (256) + +#define BUS1_IOCTL_MAGIC 0x96 +#define BUS1_HANDLE_INVALID ((__u64)-1) +#define BUS1_OFFSET_INVALID ((__u64)-1) + +enum { + BUS1_HANDLE_FLAG_MANAGED = 1ULL << 0, + BUS1_HANDLE_FLAG_REMOTE = 1ULL << 1, +}; + +enum { + BUS1_PEER_FLAG_WANT_SECCTX = 1ULL << 0, +}; + +enum { + BUS1_PEER_RESET_FLAG_FLUSH = 1ULL << 0, + BUS1_PEER_RESET_FLAG_FLUSH_SEED = 1ULL << 1, +}; + +struct bus1_cmd_peer_reset { + __u64 flags; + __u64 peer_flags; + __u32 max_slices; + __u32 max_handles; + __u32 max_inflight_bytes; + __u32 max_inflight_fds; +} __attribute__((__aligned__(8))); + +struct bus1_cmd_handle_transfer { + __u64 flags; + __u64 src_handle; + __u64 dst_fd; + __u64 dst_handle; +} __attribute__((__aligned__(8))); + +enum { + BUS1_NODES_DESTROY_FLAG_RELEASE_HANDLES = 1ULL << 0, +}; + +struct bus1_cmd_nodes_destroy { + __u64 flags; + __u64 ptr_nodes; + __u64 n_nodes; +} __attribute__((__aligned__(8))); + +enum { + BUS1_SEND_FLAG_CONTINUE = 1ULL << 0, + BUS1_SEND_FLAG_SEED = 1ULL << 1, +}; + +struct bus1_cmd_send { + __u64 flags; + __u64 ptr_destinations; + __u64 ptr_errors; + __u64 n_destinations; + __u64 ptr_vecs; + __u64 n_vecs; + __u64 ptr_handles; + __u64 n_handles; + __u64 ptr_fds; + __u64 n_fds; +} __attribute__((__aligned__(8))); + +enum { + BUS1_RECV_FLAG_PEEK = 1ULL << 0, + BUS1_RECV_FLAG_SEED = 1ULL << 1, + BUS1_RECV_FLAG_INSTALL_FDS = 1ULL << 2, +}; + +enum { + BUS1_MSG_NONE, + BUS1_MSG_DATA, + BUS1_MSG_NODE_DESTROY, + BUS1_MSG_NODE_RELEASE, +}; + +enum { + BUS1_MSG_FLAG_HAS_SECCTX = 1ULL << 0, + BUS1_MSG_FLAG_CONTINUE = 1ULL << 1, +}; + +struct bus1_cmd_recv { + __u64 flags; + __u64 max_offset; + struct { + __u64 type; + __u64 flags; + __u64 destination; + __u32 uid; + __u32 gid; + __u32 pid; + __u32 tid; + __u64 offset; + __u64 n_bytes; + __u64 n_handles; + __u64 n_fds; + __u64 n_secctx; + } __attribute__((__aligned__(8))) msg; +} __attribute__((__aligned__(8))); + +enum { + BUS1_CMD_PEER_DISCONNECT = _IOWR(BUS1_IOCTL_MAGIC, 0x00, + __u64), + BUS1_CMD_PEER_QUERY = _IOWR(BUS1_IOCTL_MAGIC, 0x01, + struct bus1_cmd_peer_reset), + BUS1_CMD_PEER_RESET = _IOWR(BUS1_IOCTL_MAGIC, 0x02, + struct bus1_cmd_peer_reset), + BUS1_CMD_HANDLE_RELEASE = _IOWR(BUS1_IOCTL_MAGIC, 0x10, + __u64), + BUS1_CMD_HANDLE_TRANSFER = _IOWR(BUS1_IOCTL_MAGIC, 0x11, + struct bus1_cmd_handle_transfer), + BUS1_CMD_NODES_DESTROY = _IOWR(BUS1_IOCTL_MAGIC, 0x20, + struct bus1_cmd_nodes_destroy), + BUS1_CMD_SLICE_RELEASE = _IOWR(BUS1_IOCTL_MAGIC, 0x30, + __u64), + BUS1_CMD_SEND = _IOWR(BUS1_IOCTL_MAGIC, 0x40, + struct bus1_cmd_send), + BUS1_CMD_RECV = _IOWR(BUS1_IOCTL_MAGIC, 0x50, + struct bus1_cmd_recv), +}; + +#endif /* _UAPI_LINUX_BUS1_H */ diff --git a/init/Kconfig b/init/Kconfig index 34407f1..04c7daf 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -273,6 +273,23 @@ config POSIX_MQUEUE_SYSCTL depends on SYSCTL default y +config BUS1 + tristate "Bus1 Kernel Message Bus" + help + The Bus1 Kernel Message Bus defines and implements a distributed + object model. It provides a capability-based IPC system for machine + local communication. + + The Bus1 IPC system is exposed via /dev/bus1. If debugfs is enabled, + bus1 exposes additional debug information there. + +config BUS1_TESTS + bool "Bus1 Self-Tests" + depends on BUS1 + help + Enable and run the bus1 self-tests before loading the module. The + overhead is minimal, so there is generally no harm in enabling it. + config CROSS_MEMORY_ATTACH bool "Enable process_vm_readv/writev syscalls" depends on MMU diff --git a/ipc/Makefile b/ipc/Makefile index 86c7300..eee12d1 100644 --- a/ipc/Makefile +++ b/ipc/Makefile @@ -9,4 +9,5 @@ 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_BUS1) += bus1/ diff --git a/ipc/bus1/Makefile b/ipc/bus1/Makefile new file mode 100644 index 0000000..d3a4491 --- /dev/null +++ b/ipc/bus1/Makefile @@ -0,0 +1,6 @@ +bus1-y := \ + main.o + +obj-$(CONFIG_BUS1) += bus1.o + +bus1-$(CONFIG_BUS1_TESTS) += tests.o diff --git a/ipc/bus1/main.c b/ipc/bus1/main.c new file mode 100644 index 0000000..02412a7 --- /dev/null +++ b/ipc/bus1/main.c @@ -0,0 +1,80 @@ +/* + * Copyright (C) 2013-2016 Red Hat, Inc. + * + * This program 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 +#include +#include +#include +#include +#include +#include "main.h" +#include "tests.h" + +static int bus1_fop_open(struct inode *inode, struct file *file) +{ + return 0; +} + +static int bus1_fop_release(struct inode *inode, struct file *file) +{ + return 0; +} + +const struct file_operations bus1_fops = { + .owner = THIS_MODULE, + .open = bus1_fop_open, + .release = bus1_fop_release, + .llseek = noop_llseek, +}; + +static struct miscdevice bus1_misc = { + .fops = &bus1_fops, + .minor = MISC_DYNAMIC_MINOR, + .name = KBUILD_MODNAME, + .mode = S_IRUGO | S_IWUGO, +}; + +struct dentry *bus1_debugdir; + +static int __init bus1_modinit(void) +{ + int r; + + r = bus1_tests_run(); + if (r < 0) + return r; + + bus1_debugdir = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!bus1_debugdir) + pr_err("cannot create debugfs root\n"); + + r = misc_register(&bus1_misc); + if (r < 0) + goto error; + + pr_info("loaded\n"); + return 0; + +error: + debugfs_remove(bus1_debugdir); + return r; +} + +static void __exit bus1_modexit(void) +{ + misc_deregister(&bus1_misc); + debugfs_remove(bus1_debugdir); + pr_info("unloaded\n"); +} + +module_init(bus1_modinit); +module_exit(bus1_modexit); +MODULE_LICENSE("GPL"); +MODULE_DESCRIPTION("Bus based interprocess communication"); diff --git a/ipc/bus1/main.h b/ipc/bus1/main.h new file mode 100644 index 0000000..76fce66 --- /dev/null +++ b/ipc/bus1/main.h @@ -0,0 +1,74 @@ +#ifndef __BUS1_MAIN_H +#define __BUS1_MAIN_H + +/* + * Copyright (C) 2013-2016 Red Hat, Inc. + * + * This program 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. + */ + +/** + * DOC: Bus1 Overview + * + * bus1 is a local IPC system, which provides a decentralized infrastructure to + * share objects between local peers. The main building blocks are nodes and + * handles. Nodes represent objects of a local peer, while handles represent + * descriptors that point to a node. Nodes can be created and destroyed by any + * peer, and they will always remain owned by their respective creator. Handles, + * on the other hand, are used to refer to nodes and can be passed around with + * messages as auxiliary data. Whenever a handle is transferred, the receiver + * will get its own handle allocated, pointing to the same node as the original + * handle. + * + * Any peer can send messages directed at one of their handles. This will + * transfer the message to the owner of the node the handle points to. If a + * peer does not posess a handle to a given node, it will not be able to send a + * message to that node. That is, handles provide exclusive access management. + * Anyone that somehow acquired a handle to a node is privileged to further + * send this handle to other peers. As such, access management is transitive. + * Once a peer acquired a handle, it cannot be revoked again. However, a node + * owner can, at anytime, destroy a node. This will effectively unbind all + * existing handles to that node on any peer, notifying each one of the + * destruction. + * + * Unlike nodes and handles, peers cannot be addressed directly. In fact, peers + * are completely disconnected entities. A peer is merely an anchor of a set of + * nodes and handles, including an incoming message queue for any of those. + * Whether multiple nodes are all part of the same peer, or part of different + * peers does not affect the remote view of those. Peers solely exist as + * management entity and command dispatcher to local processes. + * + * The set of actors on a system is completely decentralized. There is no + * global component involved that provides a central registry or discovery + * mechanism. Furthermore, communication between peers only involves those + * peers, and does not affect any other peer in any way. No global + * communication lock is taken. However, any communication is still globally + * ordered, including unicasts, multicasts, and notifications. + */ + +struct dentry; +struct file_operations; + +/** + * bus1_fops - file-operations of bus1 character devices + * + * All bus1 peers are backed by a character device with @bus1_fops used as + * file-operations. That is, a file is a bus1 peer if, and only if, its f_op + * pointer contains @bus1_fops. + */ +extern const struct file_operations bus1_fops; + +/** + * bus1_debugdir - debugfs root directory + * + * If debugfs is enabled, this is set to point to the debugfs root directory + * for this module. If debugfs is disabled, or if the root directory could not + * be created, this is set to NULL or ERR_PTR (which debugfs functions can deal + * with seamlessly). + */ +extern struct dentry *bus1_debugdir; + +#endif /* __BUS1_MAIN_H */ diff --git a/ipc/bus1/tests.c b/ipc/bus1/tests.c new file mode 100644 index 0000000..6fd2946 --- /dev/null +++ b/ipc/bus1/tests.c @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2013-2016 Red Hat, Inc. + * + * This program 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 +#include +#include "tests.h" + +int bus1_tests_run(void) +{ + pr_info("run selftests..\n"); + return 0; +} diff --git a/ipc/bus1/tests.h b/ipc/bus1/tests.h new file mode 100644 index 0000000..fb554e2 --- /dev/null +++ b/ipc/bus1/tests.h @@ -0,0 +1,32 @@ +#ifndef __BUS1_TESTS_H +#define __BUS1_TESTS_H + +/* + * Copyright (C) 2013-2016 Red Hat, Inc. + * + * This program 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. + */ + +/** + * Kernel Selftests + * + * These tests are built into the kernel module itself if, and only if, the + * required configuration is selected. On every module load, the selftests will + * be run. On production builds, this option should not be selected. + */ + +#include + +#if IS_ENABLED(CONFIG_BUS1_TESTS) +int bus1_tests_run(void); +#else +static inline int bus1_tests_run(void) +{ + return 0; +} +#endif + +#endif /* __BUS1_TESTS_H */ -- 2.10.1