Skip to contentSkip to conversation

Add kdbus implementation

PATCH Superseded Greg Kroah-Hartman 15 participants 86 messages Jan 16, 2015 – Feb 8, 2015 Page 1 of 2

Subsystems (3)

v3 of 4 Superseded Latest is v4 →

lore
Share & tools
lore
#0 lore raw

v3 cover Add kdbus implementation

kdbus is a kernel-level IPC implementation that aims for resemblance to the the protocol layer with the existing userspace D-Bus daemon while enabling some features that couldn't be implemented before in userspace.

The documentation in the first patch in this series explains the protocol and the API details.

Full details on what has changed from the v2 submission are at the bottom of this email.

Reasons why this should be done in the kernel, instead of userspace as it is currently done today include the following:

- performance: fewer process context switches, fewer copies, fewer syscalls, larger memory chunks via memfd. This is really important for a whole class of userspace programs that are ported from other operating systems that are run on tiny ARM systems that rely on hundreds of thousands of messages passed at boot time, and at "critical" times in their user interaction loops.
- security: the peers which communicate do not have to trust each other, as the only trustworthy compoenent in the game is the kernel which adds metadata and ensures that all data passed as payload is either copied or sealed, so that the receiver can parse the data without having to protect against changing memory while parsing buffers. Also, all the data transfer is controlled by the kernel, so that LSMs can track and control what is going on, without involving userspace. Because of the LSM issue, security people are much happier with this model than the current scheme of having to hook into dbus to mediate things.
- more metadata can be attached to messages than in userspace
- semantics for apps with heavy data payloads (media apps, for instance) with optinal priority message dequeuing, and global message ordering. Some "crazy" people are playing with using kdbus for audio data in the system. I'm not saying that this is the best model for this, but until now, there wasn't any other way to do this without having to create custom "busses", one for each application library.
- being in the kernle closes a lot of races which can't be fixed with the current userspace solutions. For example, with kdbus, there is a way a client can disconnect from a bus, but do so only if no further messages present in its queue, which is crucial for implementing race-free "exit-on-idle" services
- eavesdropping on the kernel level, so privileged users can hook into the message stream without hacking support for that into their userspace processes
- a number of smaller benefits: for example kdbus learned a way to peek full messages without dequeing them, which is really useful for logging metadata when handling bus-activation requests.

Of course, some of the bits above could be implemented in userspace alone, for example with more sophisticated memory management APIs, but this is usually done by losing out on the other details. For example, for many of the memory management APIs, it's hard to not require the communicating peers to fully trust each other. And we _really_ don't want peers to have to trust each other.

Another benefit of having this in the kernel, rather than as a userspace daemon, is that you can now easily use the bus from the initrd, or up to the very end when the system shuts down. On current userspace D-Bus, this is not really possible, as this requires passing the bus instance around between initrd and the "real" system. Such a transition of all fds also requires keeping full state of what has already been read from the connection fds. kdbus makes this much simpler, as we can change the ownership of the bus, just by passing one fd over from one part to the other.

Regarding binder: binder and kdbus follow very different design concepts. Binder implies the use of thread-pools to dispatch incoming method calls. This is a very efficient scheme, and completely natural in programming languages like Java. On most Linux programs, however, there's a much stronger focus on central poll() loops that dispatch all sources a program cares about. kdbus is much more usable in such environments, as it doesn't enforce a threading model, and it is happy with serialized dispatching. In fact, this major difference had an effect on much of the design decisions: binder does not guarantee global message ordering due to the parallel dispatching in the thread-pools, but kdbus does. Moreover, there's also a difference in the way message handling. In kdbus, every message is basically taken and dispatched as one blob, while in binder, continious connections to other peers are created, which are then used to send messages on. Hence, the models are quite different, and they serve different needs. I believe that the D-Bus/kdbus model is more compatible and friendly with how Linux programs are usually implemented.

This can also be found in a git tree, the kdbus branch of char-misc.git at:
https://git.kernel.org/cgit/linux/kernel/git/gregkh/char-misc.git/

Changes since v2:

* Add FS_USERNS_MOUNT to the file system flags, so users can mount their own kdbusfs instances without being root in the parent user-ns. Spotted by Andy Lutomirski.

* Rewrite major parts of the metadata implementation to allow for per-recipient namespace translations. For this, namespaces are now not pinned by domains anymore. Instead, metadata is recorded in kernel scope, and exported into the currently active namespaces at the time of message installing.

* Split PID and TID from KDBUS_ITEM_CREDS into KDBUS_ITEM_PIDS. The starttime is there to detect re-used PIDs, so move it to that new item type as well. Consequently, introduce struct kdbus_pids to accommodate the information. Requested by Andy Lutomirski.

* Add {e,s,fs}{u,g}id to KDBUS_ITEM_CREDS, so users have a way to get more fine-grained credential information.

* Removed KDBUS_CMD_CANCEL. The interface was not usable from threaded userspace implementation due to inherent races. Instead, add an item type CANCEL_FD which can be used to pass a file descriptor to the CMD_SEND ioctl. When the SEND is done synchronously, it will get cancelled as soon as the passed FD signals POLLIN.

* Dropped startttime from KDBUS_ITEM_PIDS

* Restrict names of custom endpoints to names with a "<uid>-" prefix, just like we do for buses.

* Provide module-parameter "kdbus.attach_flags_mask" to specify the a mask of metadata items that is applied on all exported items.

* Monitors are now entirely invisible (IOW, there won't be any notification when they are created) and they don't need to install filters for broadcast messages anymore.

* All information exposed via a connection's pool now also reports the length in addition to the offset. That way, userspace applications can mmap() only parts of the pool on demand.

* Due to the metadata rework, KDBUS_ITEM_PAYLOAD_OFF items now describe the offset relative to the pool, where they used to be relative to the message header.

* Added return_flags bitmask to all kdbus_cmd_* structs, so the kernel can report details of the command processing. This is mostly reserved for future extensions.

* Some fixes in kdbus.txt and tests, spotted by Harald Hoyer, Andy Lutomirski, Michele Curti, Sergei Zviagintsev, Sheng Yong, Torstein Husebø and Hristo Venev.

* Fixed compiler warnings in test-message by Michele Curti

* Unexpected items are now rejected with -EINVAL

* Split signal and broadcast handling. Unicast signals are now supported, and messages have a new KDBUS_MSG_SIGNAL flag.

* KDBUS_CMD_MSG_SEND was renamed to KDBUS_CMD_SEND, and now takes a struct kdbus_cmd_send instead of a kdbus_msg.

* KDBUS_CMD_MSG_RECV was renamed to KDBUS_CMD_RECV.

* Test case memory leak plugged, and various other cleanups and fixes, by Rui Miguel Silva.

* Build fix for s390

* Test case fix for 32bit archs

* The test framework now supports mount, pid and user namespaces.

* The test framework learned a --tap command line parameter to format its output in the "Test Anything Protocol". This format is chosen by default when "make kselftest" is invoked.

* Fixed buses and custom endpoints name validation, reported by Andy Lutomirski.

* copy_from_user() return code issue fixed, reported by Dan Carpenter.

* Avoid signed int overflow on archs without atomic_sub

* Avoid variable size stack items. Fixes a sparse warning in queue.c.

* New test case for kernel notification quota

* Switched back to enums for the list of ioctls. This has advantages for userspace code as gdb, for instance, is able to resolve the numbers into names. Added features can easily be detected with autotools, and new iotcls can get #defines as well. Having #defines for the initial set of ioctls is uncecessary.

Daniel Mack (13):
kdbus: add documentation
kdbus: add header file
kdbus: add driver skeleton, ioctl entry points and utility functions
kdbus: add connection pool implementation
kdbus: add connection, queue handling and message validation code
kdbus: add node and filesystem implementation
kdbus: add code to gather metadata
kdbus: add code for notifications and matches
kdbus: add code for buses, domains and endpoints
kdbus: add name registry implementation
kdbus: add policy database implementation
kdbus: add Makefile, Kconfig and MAINTAINERS entry
kdbus: add selftests

 Documentation/ioctl/ioctl-number.txt              |    1 +
 Documentation/kdbus.txt                           | 2107 +++++++++++++++++++++
 MAINTAINERS                                       |   12 +
 include/uapi/linux/Kbuild                         |    1 +
 include/uapi/linux/kdbus.h                        | 1049 ++++++++++
 include/uapi/linux/magic.h                        |    2 +
 init/Kconfig                                      |   12 +
 ipc/Makefile                                      |    2 +-
 ipc/kdbus/Makefile                                |   22 +
 ipc/kdbus/bus.c                                   |  553 ++++++
 ipc/kdbus/bus.h                                   |  103 +
 ipc/kdbus/connection.c                            | 2004 ++++++++++++++++++++
 ipc/kdbus/connection.h                            |  262 +++
 ipc/kdbus/domain.c                                |  350 ++++
 ipc/kdbus/domain.h                                |   84 +
 ipc/kdbus/endpoint.c                              |  232 +++
 ipc/kdbus/endpoint.h                              |   68 +
 ipc/kdbus/fs.c                                    |  519 +++++
 ipc/kdbus/fs.h                                    |   25 +
 ipc/kdbus/handle.c                                | 1134 +++++++++++
 ipc/kdbus/handle.h                                |   20 +
 ipc/kdbus/item.c                                  |  309 +++
 ipc/kdbus/item.h                                  |   57 +
 ipc/kdbus/limits.h                                |   95 +
 ipc/kdbus/main.c                                  |   72 +
 ipc/kdbus/match.c                                 |  535 ++++++
 ipc/kdbus/match.h                                 |   32 +
 ipc/kdbus/message.c                               |  598 ++++++
 ipc/kdbus/message.h                               |  133 ++
 ipc/kdbus/metadata.c                              | 1066 +++++++++++
 ipc/kdbus/metadata.h                              |   52 +
 ipc/kdbus/names.c                                 |  891 +++++++++
 ipc/kdbus/names.h                                 |   82 +
 ipc/kdbus/node.c                                  |  910 +++++++++
 ipc/kdbus/node.h                                  |   87 +
 ipc/kdbus/notify.c                                |  244 +++
 ipc/kdbus/notify.h                                |   30 +
 ipc/kdbus/policy.c                                |  481 +++++
 ipc/kdbus/policy.h                                |   51 +
 ipc/kdbus/pool.c                                  |  784 ++++++++
 ipc/kdbus/pool.h                                  |   47 +
 ipc/kdbus/queue.c                                 |  505 +++++
 ipc/kdbus/queue.h                                 |  108 ++
 ipc/kdbus/reply.c                                 |  262 +++
 ipc/kdbus/reply.h                                 |   68 +
 ipc/kdbus/util.c                                  |  317 ++++
 ipc/kdbus/util.h                                  |  133 ++
 tools/testing/selftests/Makefile                  |    1 +
 tools/testing/selftests/kdbus/.gitignore          |   11 +
 tools/testing/selftests/kdbus/Makefile            |   46 +
 tools/testing/selftests/kdbus/kdbus-enum.c        |   95 +
 tools/testing/selftests/kdbus/kdbus-enum.h        |   14 +
 tools/testing/selftests/kdbus/kdbus-test.c        |  920 +++++++++
 tools/testing/selftests/kdbus/kdbus-test.h        |   85 +
 tools/testing/selftests/kdbus/kdbus-util.c        | 1646 ++++++++++++++++
 tools/testing/selftests/kdbus/kdbus-util.h        |  216 +++
 tools/testing/selftests/kdbus/test-activator.c    |  319 ++++
 tools/testing/selftests/kdbus/test-attach-flags.c |  751 ++++++++
 tools/testing/selftests/kdbus/test-benchmark.c    |  427 +++++
 tools/testing/selftests/kdbus/test-bus.c          |  174 ++
 tools/testing/selftests/kdbus/test-chat.c         |  123 ++
 tools/testing/selftests/kdbus/test-connection.c   |  611 ++++++
 tools/testing/selftests/kdbus/test-daemon.c       |   66 +
 tools/testing/selftests/kdbus/test-endpoint.c     |  344 ++++
 tools/testing/selftests/kdbus/test-fd.c           |  710 +++++++
 tools/testing/selftests/kdbus/test-free.c         |   36 +
 tools/testing/selftests/kdbus/test-match.c        |  442 +++++
 tools/testing/selftests/kdbus/test-message.c      |  658 +++++++
 tools/testing/selftests/kdbus/test-metadata-ns.c  |  507 +++++
 tools/testing/selftests/kdbus/test-monitor.c      |  158 ++
 tools/testing/selftests/kdbus/test-names.c        |  184 ++
 tools/testing/selftests/kdbus/test-policy-ns.c    |  633 +++++++
 tools/testing/selftests/kdbus/test-policy-priv.c  | 1270 +++++++++++++
 tools/testing/selftests/kdbus/test-policy.c       |   81 +
 tools/testing/selftests/kdbus/test-race.c         |  313 +++
 tools/testing/selftests/kdbus/test-sync.c         |  368 ++++
 tools/testing/selftests/kdbus/test-timeout.c      |   99 +
 77 files changed, 27818 insertions(+), 1 deletion(-)
 create mode 100644 Documentation/kdbus.txt
 create mode 100644 include/uapi/linux/kdbus.h
 create mode 100644 ipc/kdbus/Makefile
 create mode 100644 ipc/kdbus/bus.c
 create mode 100644 ipc/kdbus/bus.h
 create mode 100644 ipc/kdbus/connection.c
 create mode 100644 ipc/kdbus/connection.h
 create mode 100644 ipc/kdbus/domain.c
 create mode 100644 ipc/kdbus/domain.h
 create mode 100644 ipc/kdbus/endpoint.c
 create mode 100644 ipc/kdbus/endpoint.h
 create mode 100644 ipc/kdbus/fs.c
 create mode 100644 ipc/kdbus/fs.h
 create mode 100644 ipc/kdbus/handle.c
 create mode 100644 ipc/kdbus/handle.h
 create mode 100644 ipc/kdbus/item.c
 create mode 100644 ipc/kdbus/item.h
 create mode 100644 ipc/kdbus/limits.h
 create mode 100644 ipc/kdbus/main.c
 create mode 100644 ipc/kdbus/match.c
 create mode 100644 ipc/kdbus/match.h
 create mode 100644 ipc/kdbus/message.c
 create mode 100644 ipc/kdbus/message.h
 create mode 100644 ipc/kdbus/metadata.c
 create mode 100644 ipc/kdbus/metadata.h
 create mode 100644 ipc/kdbus/names.c
 create mode 100644 ipc/kdbus/names.h
 create mode 100644 ipc/kdbus/node.c
 create mode 100644 ipc/kdbus/node.h
 create mode 100644 ipc/kdbus/notify.c
 create mode 100644 ipc/kdbus/notify.h
 create mode 100644 ipc/kdbus/policy.c
 create mode 100644 ipc/kdbus/policy.h
 create mode 100644 ipc/kdbus/pool.c
 create mode 100644 ipc/kdbus/pool.h
 create mode 100644 ipc/kdbus/queue.c
 create mode 100644 ipc/kdbus/queue.h
 create mode 100644 ipc/kdbus/reply.c
 create mode 100644 ipc/kdbus/reply.h
 create mode 100644 ipc/kdbus/util.c
 create mode 100644 ipc/kdbus/util.h
 create mode 100644 tools/testing/selftests/kdbus/.gitignore
 create mode 100644 tools/testing/selftests/kdbus/Makefile
 create mode 100644 tools/testing/selftests/kdbus/kdbus-enum.c
 create mode 100644 tools/testing/selftests/kdbus/kdbus-enum.h
 create mode 100644 tools/testing/selftests/kdbus/kdbus-test.c
 create mode 100644 tools/testing/selftests/kdbus/kdbus-test.h
 create mode 100644 tools/testing/selftests/kdbus/kdbus-util.c
 create mode 100644 tools/testing/selftests/kdbus/kdbus-util.h
 create mode 100644 tools/testing/selftests/kdbus/test-activator.c
 create mode 100644 tools/testing/selftests/kdbus/test-attach-flags.c
 create mode 100644 tools/testing/selftests/kdbus/test-benchmark.c
 create mode 100644 tools/testing/selftests/kdbus/test-bus.c
 create mode 100644 tools/testing/selftests/kdbus/test-chat.c
 create mode 100644 tools/testing/selftests/kdbus/test-connection.c
 create mode 100644 tools/testing/selftests/kdbus/test-daemon.c
 create mode 100644 tools/testing/selftests/kdbus/test-endpoint.c
 create mode 100644 tools/testing/selftests/kdbus/test-fd.c
 create mode 100644 tools/testing/selftests/kdbus/test-free.c
 create mode 100644 tools/testing/selftests/kdbus/test-match.c
 create mode 100644 tools/testing/selftests/kdbus/test-message.c
 create mode 100644 tools/testing/selftests/kdbus/test-metadata-ns.c
 create mode 100644 tools/testing/selftests/kdbus/test-monitor.c
 create mode 100644 tools/testing/selftests/kdbus/test-names.c
 create mode 100644 tools/testing/selftests/kdbus/test-policy-ns.c
 create mode 100644 tools/testing/selftests/kdbus/test-policy-priv.c
 create mode 100644 tools/testing/selftests/kdbus/test-policy.c
 create mode 100644 tools/testing/selftests/kdbus/test-race.c
 create mode 100644 tools/testing/selftests/kdbus/test-sync.c
 create mode 100644 tools/testing/selftests/kdbus/test-timeout.c
#1 lore raw

PATCH v3 1/13 kdbus: add documentation

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

---
 Documentation/kdbus.txt | 2107 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2107 insertions(+)
 create mode 100644 Documentation/kdbus.txt
Documentation/kdbus.txt new file +2107 -0
new file mode 100644
index 000000000000..2592a7e37079
@@ -0,0 +1,2107 @@
+D-Bus is a system for powerful, easy to use interprocess communication (IPC).
+
+The focus of this document is an overview of the low-level, native kernel D-Bus
+transport called kdbus. Kdbus exposes its functionality via files in a
+filesystem called 'kdbusfs'. All communication between processes takes place
+via ioctls on files exposed through the mount point of a kdbusfs. The default
+mount point of kdbusfs is /sys/fs/kdbus.
+
+Please note that kdbus was designed as transport layer for D-Bus, but is in no
+way limited, nor controlled by the D-Bus protocol specification. The D-Bus
+protocol is one possible application layer on top of kdbus.
+
+For the general D-Bus protocol specification, the payload format, the
+marshaling, and the communication semantics, please refer to:
+  http://dbus.freedesktop.org/doc/dbus-specification.html
+
+For a kdbus specific userspace library implementation please refer to:
+  http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-bus.h
+
+Articles about D-Bus and kdbus:
+  http://lwn.net/Articles/580194/
+
+
+1. Terminology
+===============================================================================
+
+  Domain:
+    A domain is created each time a kdbusfs is mounted. Each process that is
+    capable to mount a new instance of a kdbusfs will have its own kdbus
+    hierarchy. Each domain (ie, each mount point) offers its own "control"
+    file to create new buses. Domains have no connection to each other and
+    cannot see nor talk to each other. See section 5 for more details.
+
+  Bus:
+    A bus is a named object inside a domain. Clients exchange messages
+    over a bus. Multiple buses themselves have no connection to each other;
+    messages can only be exchanged on the same bus. The default endpoint of
+    a bus, where clients establish the connection to, is the "bus" file
+    /sys/fs/kdbus/<bus name>/bus.
+    Common operating system setups create one "system bus" per system, and one
+    "user bus" for every logged-in user. Applications or services may create
+    their own private buses.  See section 5 for more details.
+
+  Endpoint:
+    An endpoint provides a file to talk to a bus. Opening an endpoint
+    creates a new connection to the bus to which the endpoint belongs. All
+    endpoints have unique names and are accessible as files underneath the
+    directory of a bus, e.g., /sys/fs/kdbus/<bus>/<endpoint>
+    Every bus has a default endpoint called "bus". A bus can optionally offer
+    additional endpoints with custom names to provide restricted access to the
+    bus. Custom endpoints carry additional policy which can be used to create
+    sandboxes with locked-down, limited, filtered access to a bus.  See
+    section 5 for more details.
+
+  Connection:
+    A connection to a bus is created by opening an endpoint file of a bus and
+    becoming an active client with the HELLO exchange. Every ordinary client
+    connection has a unique identifier on the bus and can address messages to
+    every other connection on the same bus by using the peer's connection id
+    as the destination.  See section 6 for more details.
+
+  Pool:
+    Each connection allocates a piece of shmem-backed memory that is used
+    to receive messages and answers to ioctl commands from the kernel. It is
+    never used to send anything to the kernel. In order to access that memory,
+    userspace must mmap() it into its address space.
+    See section 12 for more details.
+
+  Well-known Name:
+    A connection can, in addition to its implicit unique connection id, request
+    the ownership of a textual well-known name. Well-known names are noted in
+    reverse-domain notation, such as com.example.service1. Connections offering
+    a service on a bus are usually reached by its well-known name. The analogy
+    of connection id and well-known name is an IP address and a DNS name
+    associated with that address.
+
+  Message:
+    Connections can exchange messages with other connections by addressing
+    the peers with their connection id or well-known name. A message consists
+    of a message header with kernel-specific information on how to route the
+    message, and the message payload, which is a logical byte stream of
+    arbitrary size. Messages can carry additional file descriptors to be passed
+    from one connection to another. Every connection can specify which set of
+    metadata the kernel should attach to the message when it is delivered
+    to the receiving connection. Metadata contains information like: system
+    timestamps, uid, gid, tid, proc-starttime, well-known-names, process comm,
+    process exe, process argv, cgroup, capabilities, seclabel, audit session,
+    loginuid and the connection's human-readable name.
+    See section 7 and 13 for more details.
+
+  Item:
+    The API of kdbus implements a notion of items, submitted through and
+    returned by most ioctls, and stored inside data structures in the
+    connection's pool. See section 4 for more details.
+
+  Broadcast and Match:
+    Broadcast messages are potentially sent to all connections of a bus. By
+    default, the connections will not actually receive any of the sent
+    broadcast messages; only after installing a match for specific message
+    properties, a broadcast message passes this filter.
+    See section 10 for more details.
+
+  Policy:
+    A policy is a set of rules that define which connections can see, talk to,
+    or register a well-know name on the bus. A policy is attached to buses and
+    custom endpoints, and modified by policy holder connections or owners of
+    custom endpoints. See section 11 for more details.
+    See section 11 for more details.
+
+  Privileged bus users:
+    A user connecting to the bus is considered privileged if it is either the
+    creator of the bus, or if it has the CAP_IPC_OWNER capability flag set.
+
+
+2. Control Files Layout
+===============================================================================
+
+The kdbus interface is exposed through files in its kdbusfs mount point
+(defaults to /sys/fs/kdbus):
+
+  /sys/fs/kdbus                 (mount point of kdbusfs)
+  |-- control                   (domain control-file)
+  |-- 0-system                  (bus of user uid=0)
+  |   |-- bus                   (default endpoint of bus '0-system')
+  |   `-- ep.apache             (custom endpoint of bus '0-system')
+  |-- 1000-user                 (bus of user uid=1000)
+  |   `-- bus                   (default endpoint of bus '1000-user')
+  `-- 2702-user                 (bus of user uid=2702)
+      |-- bus                   (default endpoint of bus '2702-user')
+      `-- ep.app                (custom endpoint of bus '2702-user')
+
+
+3. Data Structures and flags
+===============================================================================
+
+3.1 Data structures and interconnections
+----------------------------------------
+
+  +--------------------------------------------------------------------------+
+  | Domain (Mount Point)                                                     |
+  | /sys/fs/kdbus/control                                                    |
+  | +----------------------------------------------------------------------+ |
+  | | Bus (System Bus)                                                     | |
+  | | /sys/fs/kdbus/0-system/                                              | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | | Endpoint                      | | Endpoint                       | | |
+  | | | /sys/fs/kdbus/0-system/bus    | | /sys/fs/kdbus/0-system/ep.app  | | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |
+  | | | Connection   | | Connection   | | Connection   | | Connection    | | |
+  | | | :1.22        | | :1.25        | | :1.55        | | :1.81         | | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |
+  | +----------------------------------------------------------------------+ |
+  |                                                                          |
+  | +----------------------------------------------------------------------+ |
+  | | Bus (User Bus for UID 2702)                                          | |
+  | | /sys/fs/kdbus/2702-user/                                             | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | | Endpoint                      | | Endpoint                       | | |
+  | | | /sys/fs/kdbus/2702-user/bus   | | /sys/fs/kdbus/2702-user/ep.app | | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |
+  | | | Connection   | | Connection   | | Connection   | | Connection    | | |
+  | | | :1.22        | | :1.25        | | :1.55        | | :1.81         | | |
+  | | +--------------+ +--------------+ +--------------------------------+ | |
+  | +----------------------------------------------------------------------+ |
+  +--------------------------------------------------------------------------+
+
+The above description uses the D-Bus notation of unique connection names that
+adds a ":1." prefix to the connection's unique ID. kdbus itself doesn't
+use that notation, neither internally nor externally. However, libraries and
+other userspace code that aims for compatibility to D-Bus might.
+
+3.2 Flags
+---------
+
+All ioctls used in the communication with the driver contain three 64-bit
+fields: 'flags', 'kernel_flags' and 'return_flags'. All of them are specific
+to the ioctl used.
+
+In 'flags', the behavior of the command can be tweaked. All bits that are not
+recognized by the kernel in this field are rejected, and the ioctl fails with
+-EINVAL.
+
+In 'kernel_flags', the kernel driver writes back the mask of supported bits
+upon each call, and sets the KDBUS_FLAGS_KERNEL bit. This is a way to probe
+possible kernel features and make userspace code forward and backward
+compatible.
+
+In 'return_flags', the kernel can return results of the command, in addition
+to the actual return value. This is mostly to inform userspace about non-fatal
+conditions that occurred during the execution of the command.
+
+
+4. Items
+===============================================================================
+
+To flexibly augment transport structures, data blobs of type struct kdbus_item
+can be attached to the structs passed into the ioctls. Some ioctls make items
+of certain types mandatory, others are optional. Unsupported items will cause
+the ioctl to fail -EINVAL.
+
+The total size of an item is variable and is in some cases defined by the item
+type. In other cases, they can be of arbitrary length (for instance, a string).
+
+Items are also used for information stored in a connection's pool, such as
+received messages, name lists or requested connection or bus owner information.
+
+Whenever items are used as part of the kdbus kernel API, they are embedded in
+structs that have an overall size of their own, so there can be multiple items
+per ioctl.
+
+The kernel expects all items to be aligned to 8-byte boundaries. Unaligned
+items or such that are unsupported by the ioctl are rejected.
+
+A simple iterator in userspace would iterate over the items until the items
+have reached the embedding structure's overall size. An example implementation
+of such an iterator can be found in tools/testing/selftests/kdbus/kdbus-util.h.
+
+
+5. Creation of new domains, buses and endpoints
+===============================================================================
+
+
+5.1 Domains
+-----------
+
+A domain is a container of buses. Domains themselves do not provide any IPC
+functionality. Their sole purpose is to manage buses allocated in their
+domain. Each time kdbusfs is mounted, a new kdbus domain is created, with its
+own 'control' file. The lifetime of the domain ends once the user has unmounted
+the kdbusfs. If you mount kdbusfs multiple times, each will have its own kdbus
+domain internally. Operations performed on one domain do not affect any
+other domain.
+
+The full kdbusfs hierarchy, any sub-directory, or file can be bind-mounted to
+an external mount point and will remain fully functional. The kdbus domain and
+any linked resources stay available until the original mount and all subsequent
+bind-mounts have been unmounted.
+
+During creation, domains pin the user-namespace of the creator and use
+it as controlling user-namespace for this domain. Any user accounting is done
+relative to that user-namespace.
+
+Newly created kdbus domains do not have any bus pre-created. The only resource
+available is a 'control' file, which is used to manage kdbus domains.
+Currently, 'control' files are exclusively used to create buses via
+KDBUS_CMD_BUS_MAKE, but further ioctls might be added in the future.
+
+
+5.2 Buses
+---------
+
+A bus is a shared resource between connections to transmit messages. Each bus
+is independent and operations on the bus will not have any effect on other
+buses. A bus is a management entity, that controls the addresses of its
+connections, their policies and message transactions performed via this bus.
+
+Each bus is bound to the domain it was created on. It has a custom name that is
+unique across all buses of a domain. In kdbusfs, a bus is presented as a
+directory. No operations can be performed on the bus itself, instead you need
+to perform those on an endpoint associated with the bus. Endpoints are
+accessible as files underneath the bus directory. A default endpoint called
+"bus" is provided on each bus.
+
+Bus names may be chosen freely except for one restriction: the name
+must be prefixed with the numeric UID of the creator and a dash. This
+is required to avoid namespace clashes between different users. When
+creating a bus the name must be passed in properly formatted, or the
+kernel will refuse creation of the bus. Example: "1047-foobar" is an
+OK name for a bus registered by a user with UID 1047. However,
+"1024-foobar" is not, and neither is "foobar".
+The UID must be provided in the user-namespace of the parent domain.
+
+To create a new bus, you need to open the control file of a domain and run the
+KDBUS_CMD_BUS_MAKE ioctl. The control file descriptor that was used to issue
+KDBUS_CMD_BUS_MAKE must not have been used for any other control-ioctl before
+and needs to be kept open for the entire life-time of the created bus. Closing
+it will immediately cleanup the entire bus and all its associated resources and
+endpoints. Every control file descriptor can only be used to create a single
+new bus; from that point on, it is not used for any further communication until
+the final close().
+
+Each bus will generate a random, 128-bit UUID upon creation. It will be
+returned to creators of connections through kdbus_cmd_hello.id128 and can
+be used by userspace to uniquely identify buses, even across different machines
+or containers. The UUID will have its variant bits set to 'DCE', and denote
+version 4 (random).
+
+When creating buses, a variable list of items that must be passed in
+the items array is expected otherwise bus creation will fail.
+
+
+5.3 Endpoints
+-------------
+
+Endpoints are entry points to a bus. By default, each bus has a default
+endpoint called 'bus'. The bus owner has the ability to create custom
+endpoints with specific names, permissions, and policy databases (see below).
+An endpoint is presented as file underneath the directory of the parent bus.
+
+To create a custom endpoint, open the default endpoint ('bus') and use the
+KDBUS_CMD_ENDPOINT_MAKE ioctl with "struct kdbus_cmd_make". Custom endpoints
+always have a policy database that, by default, forbids any operation. You have
+to explicitly install policy entries to allow any operation on this endpoint.
+Once KDBUS_CMD_ENDPOINT_MAKE succeeded, this file descriptor will manage the
+newly created endpoint resource. It cannot be used to manage further resources.
+
+Endpoint names may be chosen freely except for one restriction: the name
+must be prefixed with the numeric UID of the creator and a dash. This
+is required to avoid namespace clashes between different users. When
+creating an endpoint the name must be passed in properly formatted, or the
+kernel will refuse creation of the endpoint. Example: "1047-foobar" is an
+OK name for an endpoint registered by a user with UID 1047. However,
+"1024-foobar" is not, and neither is "foobar".
+The UID must be provided in the user-namespace of the parent domain.
+
+To create connections to a bus, you use KDBUS_CMD_HELLO. See section 6 for
+details. Note that once KDBUS_CMD_HELLO succeeded, this file descriptor manages
+the newly created connection resource. It cannot be used to manage further
+resources.
+
+
+5.4 Creating buses and endpoints
+--------------------------------
+
+KDBUS_CMD_BUS_MAKE, and KDBUS_CMD_ENDPOINT_MAKE take a
+struct kdbus_cmd_make argument.
+
+struct kdbus_cmd_make {
+  __u64 size;
+    The overall size of the struct, including its items.
+
+  __u64 flags;
+    The flags for creation.
+
+    KDBUS_MAKE_ACCESS_GROUP
+      Make the bus or endpoint file group-accessible
+
+    KDBUS_MAKE_ACCESS_WORLD
+      Make the bus or endpoint file world-accessible
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    A list of items that has specific meanings for KDBUS_CMD_BUS_MAKE
+    and KDBUS_CMD_ENDPOINT_MAKE (see above).
+
+    Following items are expected for KDBUS_CMD_BUS_MAKE:
+    KDBUS_ITEM_MAKE_NAME
+      Contains a string to identify the bus name.
+
+    KDBUS_ITEM_BLOOM_PARAMETER
+      Bus-wide bloom parameters passed in a dbus_bloom_parameter struct
+
+    KDBUS_ITEM_ATTACH_FLAGS_RECV
+      An optional item that contains a set of required attach flags
+      that connections must allow. This item is used as a negotiation
+      measure during connection creation. If connections do not satisfy
+      the bus requirements, they are not allowed on the bus.
+      If not set, the bus does not require any metadata to be attached,
+      in this case connections are free to set their own attach flags.
+
+    KDBUS_ITEM_ATTACH_FLAGS_SEND
+      An optional item that contains a set of attach flags that are
+      returned to connections when they query the bus creator metadata.
+      If not set, no metadata is returned.
+
+    Unrecognized items are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+6. Connections
+===============================================================================
+
+
+6.1 Connection IDs and well-known connection names
+--------------------------------------------------
+
+Connections are identified by their connection id, internally implemented as a
+uint64_t counter. The IDs of every newly created bus start at 1, and every new
+connection will increment the counter by 1. The ids are not reused.
+
+In higher level tools, the user visible representation of a connection is
+defined by the D-Bus protocol specification as ":1.<id>".
+
+Messages with a specific uint64_t destination id are directly delivered to
+the connection with the corresponding id. Messages with the special destination
+id KDBUS_DST_ID_BROADCAST are broadcast messages and are potentially delivered
+to all known connections on the bus; clients interested in broadcast messages
+need to subscribe to the specific messages they are interested, though before
+any broadcast message reaches them.
+
+Messages synthesized and sent directly by the kernel will carry the special
+source id KDBUS_SRC_ID_KERNEL (0).
+
+In addition to the unique uint64_t connection id, established connections can
+request the ownership of well-known names, under which they can be found and
+addressed by other bus clients. A well-known name is associated with one and
+only one connection at a time. See section 8 on name acquisition and the
+name registry, and the validity of names.
+
+Messages can specify the special destination id 0 and carry a well-known name
+in the message data. Such a message is delivered to the destination connection
+which owns that well-known name.
+
+  +-------------------------------------------------------------------------+
+  | +---------------+     +---------------------------+                     |
+  | | Connection    |     | Message                   | -----------------+  |
+  | | :1.22         | --> | src: 22                   |                  |  |
+  | |               |     | dst: 25                   |                  |  |
+  | |               |     |                           |                  |  |
+  | |               |     |                           |                  |  |
+  | |               |     +---------------------------+                  |  |
+  | |               |                                                    |  |
+  | |               | <--------------------------------------+           |  |
+  | +---------------+                                        |           |  |
+  |                                                          |           |  |
+  | +---------------+     +---------------------------+      |           |  |
+  | | Connection    |     | Message                   | -----+           |  |
+  | | :1.25         | --> | src: 25                   |                  |  |
+  | |               |     | dst: 0xffffffffffffffff   | -------------+   |  |
+  | |               |     |  (KDBUS_DST_ID_BROADCAST) |              |   |  |
+  | |               |     |                           | ---------+   |   |  |
+  | |               |     +---------------------------+          |   |   |  |
+  | |               |                                            |   |   |  |
+  | |               | <--------------------------------------------------+  |
+  | +---------------+                                            |   |      |
+  |                                                              |   |      |
+  | +---------------+     +---------------------------+          |   |      |
+  | | Connection    |     | Message                   | --+      |   |      |
+  | | :1.55         | --> | src: 55                   |   |      |   |      |
+  | |               |     | dst: 0 / org.foo.bar      |   |      |   |      |
+  | |               |     |                           |   |      |   |      |
+  | |               |     |                           |   |      |   |      |
+  | |               |     +---------------------------+   |      |   |      |
+  | |               |                                     |      |   |      |
+  | |               | <------------------------------------------+   |      |
+  | +---------------+                                     |          |      |
+  |                                                       |          |      |
+  | +---------------+                                     |          |      |
+  | | Connection    |                                     |          |      |
+  | | :1.81         |                                     |          |      |
+  | | org.foo.bar   |                                     |          |      |
+  | |               |                                     |          |      |
+  | |               |                                     |          |      |
+  | |               | <-----------------------------------+          |      |
+  | |               |                                                |      |
+  | |               | <----------------------------------------------+      |
+  | +---------------+                                                       |
+  +-------------------------------------------------------------------------+
+
+
+6.2 Creating connections
+------------------------
+
+A connection to a bus is created by opening an endpoint file of a bus and
+becoming an active client with the KDBUS_CMD_HELLO ioctl. Every connected client
+connection has a unique identifier on the bus and can address messages to every
+other connection on the same bus by using the peer's connection id as the
+destination.
+
+The KDBUS_CMD_HELLO ioctl takes the following struct as argument.
+
+struct kdbus_cmd_hello {
+  __u64 size;
+    The overall size of the struct, including all attached items.
+
+  __u64 flags;
+    Flags to apply to this connection:
+
+    KDBUS_HELLO_ACCEPT_FD
+      When this flag is set, the connection can be sent file descriptors
+      as message payload. If it's not set, any attempt of doing so will
+      result in -ECOMM on the sender's side.
+
+    KDBUS_HELLO_ACTIVATOR
+      Make this connection an activator (see below). With this bit set,
+      an item of type KDBUS_ITEM_NAME has to be attached which describes
+      the well-known name this connection should be an activator for.
+
+    KDBUS_HELLO_POLICY_HOLDER
+      Make this connection a policy holder (see below). With this bit set,
+      an item of type KDBUS_ITEM_NAME has to be attached which describes
+      the well-known name this connection should hold a policy for.
+
+    KDBUS_HELLO_MONITOR
+      Make this connection an eaves-dropping connection. See section 6.8 for
+      more information.
+
+To also receive broadcast messages,
+      the connection has to upload appropriate matches as well.
+      This flag is only valid for privileged bus connections.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  __u64 attach_flags_send;
+      Set the bits for metadata this connection permits to be sent to the
+      receiving peer. Only metadata items that are both allowed to be sent by
+      the sender and that are requested by the receiver will effectively be
+      attached to the message eventually. Note, however, that the bus may
+      optionally enforce some of those bits to be set. If the match fails,
+      -ECONNREFUSED will be returned. In either case, this field will be set
+      to the mask of metadata items that are enforced by the bus. The
+      KDBUS_FLAGS_KERNEL bit will as well be set.
+
+  __u64 attach_flags_recv;
+      Request the attachment of metadata for each message received by this
+      connection. The metadata actually attached may actually augment the list
+      of requested items. See section 13 for more details.
+
+  __u64 bus_flags;
+      Upon successful completion of the ioctl, this member will contain the
+      flags of the bus it connected to.
+
+  __u64 id;
+      Upon successful completion of the ioctl, this member will contain the
+      id of the new connection.
+
+  __u64 pool_size;
+      The size of the communication pool, in bytes. The pool can be accessed
+      by calling mmap() on the file descriptor that was used to issue the
+      KDBUS_CMD_HELLO ioctl.
+
+  __u64 offset;
+      The kernel will return the offset in the pool where returned details
+      will be stored.
+
+  __u8 id128[16];
+      Upon successful completion of the ioctl, this member will contain the
+      128 bit wide UUID of the connected bus.
+
+  struct kdbus_item items[0];
+      Variable list of items to add optional additional information. The
+      following items are currently expected/valid:
+
+      KDBUS_ITEM_CONN_DESCRIPTION
+        Contains a string to describes this connection's name, so it can be
+        identified later.
+
+      KDBUS_ITEM_NAME
+      KDBUS_ITEM_POLICY_ACCESS
+        For activators and policy holders only, combinations of these two
+        items describe policy access entries (see section about policy).
+
+      KDBUS_ITEM_CREDS
+      KDBUS_ITEM_PIDS
+      KDBUS_ITEM_SECLABEL
+        Privileged bus users may submit these types in order to create
+        connections with faked credentials. This information will be returned
+        when peer information is queried by KDBUS_CMD_CONN_INFO. See section
+        13 for more information.
+
+      Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+At the offset returned in the 'offset' field of struct kdbus_cmd_hello, the
+kernel will store items of the following types:
+
+  KDBUS_ITEM_BLOOM_PARAMETER
+      Bloom filter parameter as defined by the bus creator (see below).
+
+The offset in the pool has to be freed with the KDBUS_CMD_FREE ioctl.
+
+6.3 Activator and policy holder connection
+------------------------------------------
+
+An activator connection is a placeholder for a well-known name. Messages sent
+to such a connection can be used by userspace to start an implementer
+connection, which will then get all the messages from the activator copied
+over. An activator connection cannot be used to send any message.
+
+A policy holder connection only installs a policy for one or more names.
+These policy entries are kept active as long as the connection is alive, and
+are removed once it terminates. Such a policy connection type can be used to
+deploy restrictions for names that are not yet active on the bus. A policy
+holder connection cannot be used to send any message.
+
+The creation of activator, policy holder or monitor connections is an operation
+restricted to privileged users on the bus (see section "Terminology").
+
+
+6.4 Retrieving information on a connection
+------------------------------------------
+
+The KDBUS_CMD_CONN_INFO ioctl can be used to retrieve credentials and
+properties of the initial creator of a connection. This ioctl uses the
+following struct:
+
+struct kdbus_cmd_info {
+  __u64 size;
+    The overall size of the struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 flags;
+    Specify which metadata items should be attached to the answer.
+    See section 13 for more details.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  __u64 id;
+    The connection's numerical ID to retrieve information for. If set to
+    non-zero value, the 'name' field is ignored.
+
+  __u64 offset;
+    When the ioctl returns, this value will yield the offset of the connection
+    information inside the caller's pool.
+
+  __u64 info_size;
+    The kernel will return the size of the returned information, so applications
+    can optionally mmap specific parts of the pool.
+
+  struct kdbus_item items[0];
+    The optional item list, containing the well-known name to look up as
+    a KDBUS_ITEM_OWNED_NAME. Only required if the 'id' field is set to 0.
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+After the ioctl returns, the following struct will be stored in the caller's
+pool at 'offset'.
+
+struct kdbus_info {
+  __u64 size;
+    The overall size of the struct, including all its items.
+
+  __u64 id;
+    The connection's unique ID.
+
+  __u64 flags;
+    The connection's flags as specified when it was created.
+
+  struct kdbus_item items[0];
+    Depending on the 'flags' field in struct kdbus_cmd_info, items of
+    types KDBUS_ITEM_OWNED_NAME and KDBUS_ITEM_CONN_DESCRIPTION are followed
+    here.
+};
+
+Once the caller is finished with parsing the return buffer, it needs to call
+KDBUS_CMD_FREE for the offset.
+
+
+6.5 Getting information about a connection's bus creator
+--------------------------------------------------------
+
+The KDBUS_CMD_BUS_CREATOR_INFO ioctl takes the same struct as
+KDBUS_CMD_CONN_INFO but is used to retrieve information about the creator of
+the bus the connection is attached to. The metadata returned by this call is
+collected during the creation of the bus and is never altered afterwards, so
+it provides pristine information on the task that created the bus, at the
+moment when it did so.
+
+In response to this call, a slice in the connection's pool is allocated and
+filled with an object of type struct kdbus_info, pointed to by the ioctl's
+'offset' field.
+
+struct kdbus_info {
+  __u64 size;
+    The overall size of the struct, including all its items.
+
+  __u64 id;
+    The bus ID
+
+  __u64 flags;
+    The bus flags as specified when it was created.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  struct kdbus_item items[0];
+    Metadata information is stored in items here. The item list contains
+    a KDBUS_ITEM_MAKE_NAME item that indicates the bus name of the
+    calling connection.
+};
+
+Once the caller is finished with parsing the return buffer, it needs to call
+KDBUS_CMD_FREE for the offset.
+
+
+6.6 Updating connection details
+-------------------------------
+
+Some of a connection's details can be updated with the KDBUS_CMD_CONN_UPDATE
+ioctl, using the file descriptor that was used to create the connection.
+The update command uses the following struct.
+
+struct kdbus_cmd_update {
+  __u64 size;
+    The overall size of the struct, including all its items.
+
+  __u64 flags;
+    Currently no flags are supported. Reserved for future use.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    Items to describe the connection details to be updated. The following item
+    types are supported:
+
+    KDBUS_ITEM_ATTACH_FLAGS_SEND
+      Supply a new set of items that this connection permits to be sent along
+      with messages.
+
+    KDBUS_ITEM_ATTACH_FLAGS_RECV
+      Supply a new set of items to be attached to each message.
+
+    KDBUS_ITEM_NAME
+    KDBUS_ITEM_POLICY_ACCESS
+      Policy holder connections may supply a new set of policy information
+      with these items. For other connection types, -EOPNOTSUPP is returned.
+
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+6.7 Termination
+---------------
+
+A connection can be terminated by simply closing its file descriptor. All
+pending incoming messages will be discarded, and the memory in the pool will
+be freed.
+
+An alternative way of closing down a connection is calling the KDBUS_CMD_BYEBYE
+ioctl on it, which will only succeed if the message queue of the connection is
+empty at the time of closing, otherwise, -EBUSY is returned.
+
+When this ioctl returns successfully, the connection has been terminated and
+won't accept any new messages from remote peers. This way, a connection can
+be terminated race-free, without losing any messages.
+
+
+6.8 Monitor connections ('eavesdropper')
+----------------------------------------
+
+Eavesdropping connections are created by setting the KDBUS_HELLO_MONITOR flag
+in struct kdbus_hello.flags. Such connections have all properties of any other,
+regular connection, except for the following details:
+
+  * They will get every message sent over the bus, both unicasts and broadcasts
+
+  * Installing matches for broadcast messages is neither necessary nor allowed
+
+  * They cannot send messages or be directly addressed as receiver
+
+  * Their creation and destruction will not cause KDBUS_ITEM_ID_{ADD,REMOVE}
+    notifications to be generated, so other connections cannot detect the
+    presence of an eavesdropper.
+
+
+7. Messages
+===============================================================================
+
+Messages consist of a fixed-size header followed directly by a list of
+variable-sized data 'items'. The overall message size is specified in the
+header of the message. The chain of data items can contain well-defined
+message metadata fields, raw data, references to data, or file descriptors.
+
+
+7.1 Sending messages
+--------------------
+
+Messages are passed to the kernel with the KDBUS_CMD_SEND ioctl. Depending
+on the destination address of the message, the kernel delivers the message to
+the specific destination connection or to all connections on the same bus.
+Sending messages across buses is not possible. Messages are always queued in
+the memory pool of the destination connection (see below).
+
+The KDBUS_CMD_SEND ioctl uses struct kdbus_cmd_send to describe the message
+transfer.
+
+struct kdbus_cmd_send {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    Flags for message delivery:
+
+    KDBUS_SEND_SYNC_REPLY
+      By default, all calls to kdbus are considered asynchronous,
+      non-blocking. However, as there are many use cases that need to wait
+      for a remote peer to answer a method call, there's a way to send a
+      message and wait for a reply in a synchronous fashion. This is what
+      the KDBUS_MSG_SYNC_REPLY controls. The KDBUS_CMD_SEND ioctl will block
+      until the reply has arrived, the timeout limit is reached, in case the
+      remote connection was shut down, or if interrupted by a signal before
+      any reply; see signal(7).
+
+      The offset of the reply message in the sender's pool is stored in in
+      'offset_reply' when the ioctl has returned without error. Hence, there
+      is no need for another KDBUS_CMD_RECV ioctl or anything else to receive
+      the reply.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call of
+    KDBUS_CMD_SEND.
+
+  __u64 kernel_msg_flags;
+    Valid bits for message flags, returned by the kernel upon each call of
+    KDBUS_CMD_SEND.
+
+  __u64 return_flags;
+    Kernel-provided flags, returning non-fatal errors that occurred during
+    send. Currently unused.
+
+  __u64 msg_address;
+    Userspace has to provide a pointer to a message (struct kdbus_msg) to send.
+
+  struct kdbus_msg_info reply;
+    Only used for synchronous replies. See description of struct kdbus_cmd_recv
+    for more details.
+
+  struct kdbus_item items[0];
+    The following items are currently recognized:
+
+    KDBUS_ITEM_CANCEL_FD
+      When this optional item is passed in, and the call is executed as SYNC
+      call, the passed in file descriptor can be used as alternative
+      cancellation point. The kernel will call poll() on this file descriptor,
+      and if it reports any incoming bytes, the blocking send operation will
+      be canceled, and the call will return -ECANCELED. Any type of file
+      descriptor that implements poll() can be used as payload to this item.
+      For asynchronous message sending, this item is accepted but ignored.
+
+    All other items are rejected, and the ioctl will fail with -EINVAL.
+};
+
+The message referenced by 'msg_address' above has the following layout.
+
+struct kdbus_msg {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    KDBUS_MSG_EXPECT_REPLY
+      Expect a reply from the remote peer to this message. With this bit set,
+      the timeout_ns field must be set to a non-zero number of nanoseconds in
+      which the receiving peer is expected to reply. If such a reply is not
+      received in time, the sender will be notified with a timeout message
+      (see below). The value must be an absolute value, in nanoseconds and
+      based on CLOCK_MONOTONIC.
+
+      For a message to be accepted as reply, it must be a direct message to
+      the original sender (not a broadcast), and its kdbus_msg.reply_cookie
+      must match the previous message's kdbus_msg.cookie.
+
+      Expected replies also temporarily open the policy of the sending
+      connection, so the other peer is allowed to respond within the given
+      time window.
+
+    KDBUS_MSG_NO_AUTO_START
+      By default, when a message is sent to an activator connection, the
+      activator notified and will start an implementer. This flag inhibits
+      that behavior. With this bit set, and the remote being an activator,
+      -EADDRNOTAVAIL is returned from the ioctl.
+
+  __s64 priority;
+    The priority of this message. Receiving messages (see below) may
+    optionally be constrained to messages of a minimal priority. This
+    allows for use cases where timing critical data is interleaved with
+    control data on the same connection. If unused, the priority should be
+    set to zero.
+
+  __u64 dst_id;
+    The numeric ID of the destination connection, or KDBUS_DST_ID_BROADCAST
+    (~0ULL) to address every peer on the bus, or KDBUS_DST_ID_NAME (0) to look
+    it up dynamically from the bus' name registry. In the latter case, an item
+    of type KDBUS_ITEM_DST_NAME is mandatory.
+
+  __u64 src_id;
+    Upon return of the ioctl, this member will contain the sending
+    connection's numerical ID. Should be 0 at send time.
+
+  __u64 payload_type;
+    Type of the payload in the actual data records. Currently, only
+    KDBUS_PAYLOAD_DBUS is accepted as input value of this field. When
+    receiving messages that are generated by the kernel (notifications),
+    this field will yield KDBUS_PAYLOAD_KERNEL.
+
+  __u64 cookie;
+    Cookie of this message, for later recognition. Also, when replying
+    to a message (see above), the cookie_reply field must match this value.
+
+  __u64 timeout_ns;
+    If the message sent requires a reply from the remote peer (see above),
+    this field contains the timeout in absolute nanoseconds based on
+    CLOCK_MONOTONIC.
+
+  __u64 cookie_reply;
+    If the message sent is a reply to another message, this field must
+    match the cookie of the formerly received message.
+
+  struct kdbus_item items[0];
+    A dynamically sized list of items to contain additional information.
+    The following items are expected/valid:
+
+    KDBUS_ITEM_PAYLOAD_VEC
+    KDBUS_ITEM_PAYLOAD_MEMFD
+    KDBUS_ITEM_FDS
+      Actual data records containing the payload. See section "Passing of
+      Payload Data".
+
+    KDBUS_ITEM_BLOOM_FILTER
+      Bloom filter for matches (see below).
+
+    KDBUS_ITEM_DST_NAME
+      Well-known name to send this message to. Required if dst_id is set
+      to KDBUS_DST_ID_NAME. If a connection holding the given name can't
+      be found, -ESRCH is returned.
+      For messages to a unique name (ID), this item is optional. If present,
+      the kernel will make sure the name owner matches the given unique name.
+      This allows userspace tie the message sending to the condition that a
+      name is currently owned by a certain unique name.
+};
+
+The message will be augmented by the requested metadata items when queued into
+the receiver's pool. See also section 13.2 ("Metadata and namespaces").
+
+
+7.2 Message layout
+------------------
+
+The layout of a message is shown below.
+
+  +-------------------------------------------------------------------------+
+  | Message                                                                 |
+  | +---------------------------------------------------------------------+ |
+  | | Header                                                              | |
+  | | size:          overall message size, including the data records     | |
+  | | destination:   connection id of the receiver                        | |
+  | | source:        connection id of the sender (set by kernel)          | |
+  | | payload_type:  "DBusDBus" textual identifier stored as uint64_t     | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size (without padding)                        | |
+  | | type:  type of data                                                 | |
+  | | data:  reference to data (address or file descriptor)               | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | padding bytes to the next 8 byte alignment                          | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size (without padding)                        | |
+  | | ...                                                                 | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | padding bytes to the next 8 byte alignment                          | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size                                          | |
+  | | ...                                                                 | |
+  | +---------------------------------------------------------------------+ |
+  |   ... further data records ...                                          |
+  +-------------------------------------------------------------------------+
+
+
+7.3 Passing of Payload Data
+---------------------------
+
+When connecting to the bus, receivers request a memory pool of a given size,
+large enough to carry all backlog of data enqueued for the connection. The
+pool is internally backed by a shared memory file which can be mmap()ed by
+the receiver.
+
+KDBUS_MSG_PAYLOAD_VEC:
+  Messages are directly copied by the sending process into the receiver's pool,
+  that way two peers can exchange data by effectively doing a single-copy from
+  one process to another, the kernel will not buffer the data anywhere else.
+
+KDBUS_MSG_PAYLOAD_MEMFD:
+  Messages can reference memfd files which contain the data.
+  memfd files are tmpfs-backed files that allow sealing of the content of the
+  file, which prevents all writable access to the file content.
+  Only memfds that have (F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL) set
+  are accepted as payload data, which enforces reliable passing of data.
+  The receiver can assume that neither the sender nor anyone else can alter the
+  content after the message is sent.
+  Apart from the sender filling-in the content into memfd files, the data will
+  be passed as zero-copy from one process to another, read-only, shared between
+  the peers.
+
+The sender must not make any assumptions on the type how data is received by the
+remote peer. The kernel is free to re-pack multiple VEC and MEMFD payloads. For
+instance, the kernel may decide to merge multiple VECs into a single VEC, inline
+MEMFD payloads into memory or merge all passed VECs into a single MEMFD.
+However, the kernel preserves the order of passed data. This means, the order of
+all VEC and MEMFD items is not changed in respect to each other.
+
+In other words: All passed VEC and MEMFD data payloads are treated as a single
+stream of data that may be received by the remote peer in a different set of
+hunks than it was sent as.
+
+
+7.4 Receiving messages
+----------------------
+
+Messages are received by the client with the KDBUS_CMD_RECV ioctl. The endpoint
+file of the bus supports poll() to wake up the receiving process when new
+messages are queued up to be received.
+
+With the KDBUS_CMD_RECV ioctl, a struct kdbus_cmd_recv is used.
+
+struct kdbus_cmd_recv {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    Flags to control the receive command.
+
+    KDBUS_RECV_PEEK
+      Just return the location of the next message. Do not install file
+      descriptors or anything else. This is usually used to determine the
+      sender of the next queued message.
+
+    KDBUS_RECV_DROP
+      Drop the next message without doing anything else with it, and free the
+      pool slice. This a short-cut for KDBUS_RECV_PEEK and KDBUS_CMD_FREE.
+
+    KDBUS_RECV_USE_PRIORITY
+      Use the priority field (see below).
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Kernel-provided flags, returning non-fatal errors that occurred during
+    send. Currently unused.
+
+  __s64 priority;
+    With KDBUS_RECV_USE_PRIORITY set in flags, receive the next message in
+    the queue with at least the given priority. If no such message is waiting
+    in the queue, -ENOMSG is returned.
+
+  __u64 dropped_msgs;
+    If the CMD_RECV ioctl fails with EOVERFLOW, this field is filled by
+    the kernel with the number of messages that couldn't be transmitted to
+    this connection. In that case, the @offset member must not be accessed.
+
+  struct kdbus_msg_info msg;
+   Embedded struct to be filled when the command succeeded (see below).
+
+  struct kdbus_item items[0];
+    Items to specify further details for the receive command. Currently unused.
+};
+
+Both 'struct kdbus_cmd_recv' and 'struct kdbus_cmd_send' embed 'struct
+kdbus_msg_info'. For the SEND ioctl, it is used to catch synchronous replies,
+if one was requested, and is unused otherwise.
+
+struct kdbus_msg_info {
+  __u64 offset;
+    Upon return of the ioctl, this field contains the offset in the receiver's
+    memory pool. The memory must be freed with KDBUS_CMD_FREE.
+
+  __u64 msg_size;
+    Upon successful return of the ioctl, this field contains the size of the
+    allocated slice at offset @offset. It is the combination of the size of
+    the stored kdbus_msg object plus all appended VECs. You can use it in
+    combination with @offset to map a single message, instead of mapping the
+    whole pool.
+
+  __u64 return_flags;
+    Kernel-provided return flags. Currently, the following flags are defined.
+
+      KDBUS_RECV_RETURN_INCOMPLETE_FDS
+        The message contained file descriptors which couldn't be installed
+        into the receiver's task. Most probably that happened because the
+        maximum number of file descriptors for that task were exceeded.
+        The message is still delivered, so this is not a fatal condition.
+        File descriptors inside the KDBUS_ITEM_FDS item that could not be
+        installed will be set to -1.
+};
+
+Unless KDBUS_RECV_DROP was passed, and given that the ioctl succeeded, the
+offset field contains the location of the new message inside the receiver's
+pool. The message is stored as struct kdbus_msg at this offset, and can be
+interpreted with the semantics described above.
+
+Also, if the connection allowed for file descriptor to be passed
+(KDBUS_HELLO_ACCEPT_FD), and if the message contained any, they will be
+installed into the receiving process after the KDBUS_CMD_RECV ioctl returns.
+The receiving task is obliged to close all of them appropriately. If
+KDBUS_RECV_PEEK is set, no file descriptors are installed. This allows for
+peeking at a message and dropping it via KDBUS_RECV_DROP, without installing
+the passed file descriptors into the receiving process.
+
+The caller is obliged to call KDBUS_CMD_FREE with the returned offset when
+the memory is no longer needed.
+
+
+8. Name registry
+===============================================================================
+
+Each bus instantiates a name registry to resolve well-known names into unique
+connection IDs for message delivery. The registry will be queried when a
+message is sent with kdbus_msg.dst_id set to KDBUS_DST_ID_NAME, or when a
+registry dump is requested.
+
+All of the below is subject to policy rules for SEE and OWN permissions.
+
+
+8.1 Name validity
+-----------------
+
+A name has to comply to the following rules to be considered valid:
+
+ - 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 contain at least one '.' (period) character
+   (and thus at least two elements)
+ - The name must not begin with a '.' (period) character
+ - The name must not exceed KDBUS_NAME_MAX_LEN (255)
+
+
+8.2 Acquiring a name
+--------------------
+
+To acquire a name, a client uses the KDBUS_CMD_NAME_ACQUIRE ioctl with the
+following data structure.
+
+struct kdbus_cmd_name {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 flags;
+    Flags to control details in the name acquisition.
+
+    KDBUS_NAME_REPLACE_EXISTING
+      Acquiring a name that is already present usually fails, unless this flag
+      is set in the call, and KDBUS_NAME_ALLOW_REPLACEMENT or (see below) was
+      set when the current owner of the name acquired it, or if the current
+      owner is an activator connection (see below).
+
+    KDBUS_NAME_ALLOW_REPLACEMENT
+      Allow other connections to take over this name. When this happens, the
+      former owner of the connection will be notified of the name loss.
+
+    KDBUS_NAME_QUEUE (acquire)
+      A name that is already acquired by a connection, and which wasn't
+      requested with the KDBUS_NAME_ALLOW_REPLACEMENT flag set can not be
+      acquired again. However, a connection can put itself in a queue of
+      connections waiting for the name to be released. Once that happens, the
+      first connection in that queue becomes the new owner and is notified
+      accordingly.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    Items to submit the name. Currently, one item of type KDBUS_ITEM_NAME is
+    expected and allowed, and the contained string must be a valid bus name.
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+8.3 Releasing a name
+--------------------
+
+A connection may release a name explicitly with the KDBUS_CMD_NAME_RELEASE
+ioctl. If the connection was an implementer of an activatable name, its
+pending messages are moved back to the activator. If there are any connections
+queued up as waiters for the name, the oldest one of them will become the new
+owner. The same happens implicitly for all names once a connection terminates.
+
+The KDBUS_CMD_NAME_RELEASE ioctl uses the same data structure as the
+acquisition call, but with slightly different field usage.
+
+struct kdbus_cmd_name {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 flags;
+    Flags to the command. Currently unused.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    Items to submit the name. Currently, one item of type KDBUS_ITEM_NAME is
+    expected and allowed, and the contained string must be a valid bus name.
+};
+
+
+8.4 Dumping the name registry
+-----------------------------
+
+A connection may request a complete or filtered dump of currently active bus
+names with the KDBUS_CMD_NAME_LIST ioctl, which takes a struct
+kdbus_cmd_name_list as argument.
+
+struct kdbus_cmd_name_list {
+  __u64 flags;
+    Any combination of flags to specify which names should be dumped.
+
+    KDBUS_NAME_LIST_UNIQUE
+      List the unique (numeric) IDs of the connection, whether it owns a name
+      or not.
+
+    KDBUS_NAME_LIST_NAMES
+      List well-known names stored in the database which are actively owned by
+      a real connection (not an activator).
+
+    KDBUS_NAME_LIST_ACTIVATORS
+      List names that are owned by an activator.
+
+    KDBUS_NAME_LIST_QUEUED
+      List connections that are not yet owning a name but are waiting for it
+      to become available.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  __u64 offset;
+    When the ioctl returns successfully, the offset to the name registry dump
+    inside the connection's pool will be stored in this field.
+};
+
+The returned list of names is stored in a struct kdbus_name_list that in turn
+contains a dynamic number of struct kdbus_cmd_name that carry the actual
+information. The fields inside that struct kdbus_cmd_name is described next.
+
+struct kdbus_name_info {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 owner_id;
+    The owning connection's unique ID.
+
+  __u64 conn_flags;
+    The flags of the owning connection.
+
+  struct kdbus_item items[0];
+    Items containing the actual name. Currently, one item of type
+    KDBUS_ITEM_OWNED_NAME will be attached, including the name's flags. In that
+    item, the flags field of the name may carry the following bits:
+
+    KDBUS_NAME_ALLOW_REPLACEMENT
+      Other connections are allowed to take over this name from the
+      connection that owns it.
+
+    KDBUS_NAME_IN_QUEUE (list)
+      When retrieving a list of currently acquired name in the registry, this
+      flag indicates whether the connection actually owns the name or is
+      currently waiting for it to become available.
+
+    KDBUS_NAME_ACTIVATOR (list)
+      An activator connection owns a name as a placeholder for an implementer,
+      which is started on demand as soon as the first message arrives. There's
+      some more information on this topic below. In contrast to
+      KDBUS_NAME_REPLACE_EXISTING, when a name is taken over from an activator
+      connection, all the messages that have been queued in the activator
+      connection will be moved over to the new owner. The activator connection
+      will still be tracked for the name and will take control again if the
+      implementer connection terminates.
+      This flag can not be used when acquiring a name, but is implicitly set
+      through KDBUS_CMD_HELLO with KDBUS_HELLO_ACTIVATOR set in
+      kdbus_cmd_hello.conn_flags.
+};
+
+The returned buffer must be freed with the KDBUS_CMD_FREE ioctl when the user
+is finished with it.
+
+
+9. Notifications
+===============================================================================
+
+The kernel will notify its users of the following events.
+
+  * When connection A is terminated while connection B is waiting for a reply
+    from it, connection B is notified with a message with an item of type
+    KDBUS_ITEM_REPLY_DEAD.
+
+  * When connection A does not receive a reply from connection B within the
+    specified timeout window, connection A will receive a message with an item
+    of type KDBUS_ITEM_REPLY_TIMEOUT.
+
+  * When an ordinary connection (not a monitor) is created on or removed from
+    a bus, messages with an item of type KDBUS_ITEM_ID_ADD or
+    KDBUS_ITEM_ID_REMOVE, respectively, are sent to all bus members that match
+    these messages through their match database. Eavesdroppers (monitor
+    connections) do not cause such notifications to be sent. They are invisible
+    on the bus.
+
+  * When a connection gains or loses ownership of a name, messages with an item
+    of type KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE or
+    KDBUS_ITEM_NAME_CHANGE are sent to all bus members that match these
+    messages through their match database.
+
+A kernel notification is a regular kdbus message with the following details.
+
+  * kdbus_msg.src_id == KDBUS_SRC_ID_KERNEL
+  * kdbus_msg.dst_id == KDBUS_DST_ID_BROADCAST
+  * kdbus_msg.payload_type == KDBUS_PAYLOAD_KERNEL
+  * Has exactly one of the aforementioned items attached
+
+Kernel notifications have an item of type KDBUS_ITEM_TIMESTAMP attached.
+
+
+10. Message Matching, Bloom filters
+===============================================================================
+
+10.1 Matches for broadcast messages from other connections
+----------------------------------------------------------
+
+A message addressed at the connection ID KDBUS_DST_ID_BROADCAST (~0ULL) is a
+broadcast message, delivered to all connected peers which installed a rule to
+match certain properties of the message. Without any rules installed in the
+connection, no broadcast message or kernel-side notifications will be delivered
+to the connection. Broadcast messages are subject to policy rules and TALK
+access checks.
+
+See section 11 for details on policies, and section 11.5 for more
+details on implicit policies.
+
+Matches for messages from other connections (not kernel notifications) are
+implemented as bloom filters. The sender adds certain properties of the message
+as elements to a bloom filter bit field, and sends that along with the
+broadcast message.
+
+The connection adds the message properties it is interested as elements to a
+bloom mask bit field, and uploads the mask to the match rules of the
+connection.
+
+The kernel will match the broadcast message's bloom filter against the
+connections bloom mask (simply by &-ing it), and decide whether the message
+should be delivered to the connection.
+
+The kernel has no notion of any specific properties of the message, all it
+sees are the bit fields of the bloom filter and mask to match against. The
+use of bloom filters allows simple and efficient matching, without exposing
+any message properties or internals to the kernel side. Clients need to deal
+with the fact that they might receive broadcasts which they did not subscribe
+to, as the bloom filter might allow false-positives to pass the filter.
+
+To allow the future extension of the set of elements in the bloom filter, the
+filter specifies a "generation" number. A later generation must always contain
+all elements of the set of the previous generation, but can add new elements
+to the set. The match rules mask can carry an array with all previous
+generations of masks individually stored. When the filter and mask are matched
+by the kernel, the mask with the closest matching "generation" is selected
+as the index into the mask array.
+
+
+10.2 Matches for kernel notifications
+------------------------------------
+
+To receive kernel generated notifications (see section 9), a connection must
+install special match rules that are different from the bloom filter matches
+described in the section above. They can be filtered by a sender connection's
+ID, by one of the name the sender connection owns at the time of sending the
+message, or by type of the notification (id/name add/remove/change).
+
+10.3 Adding a match
+-------------------
+
+To add a match, the KDBUS_CMD_MATCH_ADD ioctl is used, which takes a struct
+of the struct described below.
+
+Note that each of the items attached to this command will internally create
+one match 'rule', and the collection of them, which is submitted as one block
+via the ioctl is called a 'match'. To allow a message to pass, all rules of a
+match have to be satisfied. Hence, adding more items to the command will only
+narrow the possibility of a match to effectively let the message pass, and will
+cause the connection's user space process to wake up less likely.
+
+Multiple matches can be installed per connection. As long as one of it has a
+set of rules which allows the message to pass, this one will be decisive.
+
+struct kdbus_cmd_match {
+  __u64 size;
+    The overall size of the struct, including its items.
+
+  __u64 cookie;
+    A cookie which identifies the match, so it can be referred to at removal
+    time.
+
+  __u64 flags;
+    Flags to control the behavior of the ioctl.
+
+    KDBUS_MATCH_REPLACE:
+      Remove all entries with the given cookie before installing the new one.
+      This allows for race-free replacement of matches.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    Items to define the actual rules of the matches. The following item types
+    are expected. Each item will cause one new match rule to be created.
+
+    KDBUS_ITEM_BLOOM_MASK
+      An item that carries the bloom filter mask to match against in its
+      data field. The payload size must match the bloom filter size that
+      was specified when the bus was created.
+      See section 10.4 for more information.
+
+    KDBUS_ITEM_NAME
+      Specify a name that a sending connection must own at a time of sending
+      a broadcast message in order to match this rule.
+
+    KDBUS_ITEM_ID
+      Specify a sender connection's ID that will match this rule.
+
+    KDBUS_ITEM_NAME_ADD
+    KDBUS_ITEM_NAME_REMOVE
+    KDBUS_ITEM_NAME_CHANGE
+      These items request delivery of broadcast messages that describe a name
+      acquisition, loss, or change. The details are stored in the item's
+      kdbus_notify_name_change member. All information specified must be
+      matched in order to make the message pass. Use KDBUS_MATCH_ID_ANY to
+      match against any unique connection ID.
+
+    KDBUS_ITEM_ID_ADD
+    KDBUS_ITEM_ID_REMOVE
+      These items request delivery of broadcast messages that are generated
+      when a connection is created or terminated. struct kdbus_notify_id_change
+      is used to store the actual match information. This item can be used to
+      monitor one particular connection ID, or, when the id field is set to
+      KDBUS_MATCH_ID_ANY, all of them.
+
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+10.4 Bloom filters
+------------------
+
+Bloom filters allow checking whether a given word is present in a dictionary.
+This allows connections to set up a mask for information it is interested in,
+and will be delivered signal messages that have a matching filter.
+
+For general information on bloom filters, see
+
+  https://en.wikipedia.org/wiki/Bloom_filter
+
+The size of the bloom filter is defined per bus when it is created, in
+kdbus_bloom_parameter.size. All bloom filters attached to signals on the bus
+must match this size, and all bloom filter matches uploaded by connections must
+also match the size, or a multiple thereof (see below).
+
+The calculation of the mask has to be done on the userspace side. The kernel
+just checks the bitmasks to decide whether or not to let the message pass. All
+bits in the mask must match the filter in and bit-wise AND logic, but the
+mask may have more bits set than the filter. Consequently, false positive
+matches are expected to happen, and userspace must deal with that fact.
+
+Masks are entities that are always passed to the kernel as part of a match
+(with an item of type KDBUS_ITEM_BLOOM_MASK), and filters can be attached to
+signals, with an item of type KDBUS_ITEM_BLOOM_FILTER.
+
+For a filter to match, all its bits have to be set in the match mask as well.
+For example, consider a bus has a bloom size of 8 bytes, and the following
+mask/filter combinations:
+
+    filter  0x0101010101010101
+    mask    0x0101010101010101
+            -> matches
+
+    filter  0x0303030303030303
+    mask    0x0101010101010101
+            -> doesn't match
+
+    filter  0x0101010101010101
+    mask    0x0303030303030303
+            -> matches
+
+Hence, in order to catch all messages, a mask filled with 0xff bytes can be
+installed as a wildcard match rule.
+
+Uploaded matches may contain multiple masks, each of which in the size of the
+bloom size defined by the bus. Each block of a mask is called a 'generation',
+starting at index 0.
+
+At match time, when a signal is about to be delivered, a bloom mask generation
+is passed, which denotes which of the bloom masks the filter should be matched
+against. This allows userspace to provide backward compatible masks at upload
+time, while older clients can still match against older versions of filters.
+
+
+10.5 Removing a match
+--------------------
+
+Matches can be removed through the KDBUS_CMD_MATCH_REMOVE ioctl, which again
+takes struct kdbus_cmd_match as argument, but its fields are used slightly
+differently.
+
+struct kdbus_cmd_match {
+  __u64 size;
+    The overall size of the struct. As it has no items in this use case, the
+    value should yield 16.
+
+  __u64 cookie;
+    The cookie of the match, as it was passed when the match was added.
+    All matches that have this cookie will be removed.
+
+  __u64 flags;
+    Unused for this use case,
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.
+
+  struct kdbus_item items[0];
+    Unused und not allowed for this use case.
+};
+
+
+11. Policy
+===============================================================================
+
+A policy databases restrict the possibilities of connections to own, see and
+talk to well-known names. It can be associated with a bus (through a policy
+holder connection) or a custom endpoint.
+
+See section 8.1 for more details on the validity of well-known names.
+
+Default endpoints of buses always have a policy database. The default
+policy is to deny all operations except for operations that are covered by
+implicit policies. Custom endpoints always have a policy, and by default,
+a policy database is empty. Therefore, unless policy rules are added, all
+operations will also be denied by default.
+
+See section 11.5 for more details on implicit policies.
+
+A set of policy rules is described by a name and multiple access rules, defined
+by the following struct.
+
+struct kdbus_policy_access {
+  __u64 type;	/* USER, GROUP, WORLD */
+    One of the following.
+
+    KDBUS_POLICY_ACCESS_USER
+      Grant access to a user with the uid stored in the 'id' field.
+
+    KDBUS_POLICY_ACCESS_GROUP
+      Grant access to a user with the gid stored in the 'id' field.
+
+    KDBUS_POLICY_ACCESS_WORLD
+      Grant access to everyone. The 'id' field is ignored.
+
+  __u64 access;	/* OWN, TALK, SEE */
+    The access to grant.
+
+    KDBUS_POLICY_SEE
+      Allow the name to be seen.
+
+    KDBUS_POLICY_TALK
+      Allow the name to be talked to.
+
+    KDBUS_POLICY_OWN
+      Allow the name to be owned.
+
+  __u64 id;
+    For KDBUS_POLICY_ACCESS_USER, stores the uid.
+    For KDBUS_POLICY_ACCESS_GROUP, stores the gid.
+};
+
+Policies are set through KDBUS_CMD_HELLO (when creating a policy holder
+connection), KDBUS_CMD_CONN_UPDATE (when updating a policy holder connection),
+KDBUS_CMD_ENDPOINT_MAKE (creating a custom endpoint) or
+KDBUS_CMD_ENDPOINT_UPDATE (updating a custom endpoint). In all cases, the name
+and policy access information is stored in items of type KDBUS_ITEM_NAME and
+KDBUS_ITEM_POLICY_ACCESS. For this transport, the following rules apply.
+
+  * An item of type KDBUS_ITEM_NAME must be followed by at least one
+    KDBUS_ITEM_POLICY_ACCESS item
+  * An item of type KDBUS_ITEM_NAME can be followed by an arbitrary number of
+    KDBUS_ITEM_POLICY_ACCESS items
+  * An arbitrary number of groups of names and access levels can be passed
+
+uids and gids are internally always stored in the kernel's view of global ids,
+and are translated back and forth on the ioctl level accordingly.
+
+
+11.2 Wildcard names
+-------------------
+
+Policy holder connections may upload names that contain the wild card suffix
+(".*"). That way, a policy can be uploaded that is effective for every
+well-known name that extends the provided name by exactly one more level.
+
+For example, if an item of a set up uploaded policy rules contains the name
+"foo.bar.*", both "foo.bar.baz" and "foo.bar.bazbaz" are valid, but
+"foo.bar.baz.baz" is not.
+
+This allows connections to take control over multiple names that the policy
+holder doesn't need to know about when uploading the policy.
+
+Such wildcard entries are not allowed for custom endpoints.
+
+
+11.3 Policy example
+-------------------
+
+For example, a set of policy rules may look like this:
+
+  KDBUS_ITEM_NAME: str='org.foo.bar'
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, id=1000
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, id=1001
+  KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE
+  KDBUS_ITEM_NAME: str='org.blah.baz'
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, id=0
+  KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK
+
+That means that 'org.foo.bar' may only be owned by uid 1000, but every user on
+the bus is allowed to see the name. However, only uid 1001 may actually send
+a message to the connection and receive a reply from it.
+
+The second rule allows 'org.blah.baz' to be owned by uid 0 only, but every user
+may talk to it.
+
+
+11.4 TALK access and multiple well-known names per connection
+-------------------------------------------------------------
+
+Note that TALK access is checked against all names of a connection.
+For example, if a connection owns both 'org.foo.bar' and 'org.blah.baz', and
+the policy database allows 'org.blah.baz' to be talked to by WORLD, then this
+permission is also granted to 'org.foo.bar'. That might sound illogical, but
+after all, we allow messages to be directed to either the ID or a well-known
+name, and policy is applied to the connection, not the name. In other words,
+the effective TALK policy for a connection is the most permissive of all names
+the connection owns.
+
+For broadcast messages, the receiver needs TALK permissions to the sender to
+receive the broadcast.
+
+If a policy database exists for a bus (because a policy holder created one on
+demand) or for a custom endpoint (which always has one), each one is consulted
+during name registry listing, name owning or message delivery. If either one
+fails, the operation is failed with -EPERM.
+
+For best practices, connections that own names with a restricted TALK
+access should not install matches. This avoids cases where the sent
+message may pass the bloom filter due to false-positives and may also
+satisfy the policy rules.
+
+
+11.5 Implicit policies
+----------------------
+
+Depending on the type of the endpoint, a set of implicit rules that
+override installed policies might be enforced.
+
+On default endpoints, the following set is enforced and checked before
+any user-supplied policy is checked.
+
+  * Privileged connections always override any installed policy. Those
+    connections could easily install their own policies, so there is no
+    reason to enforce installed policies.
+  * Connections can always talk to connections of the same user. This
+    includes broadcast messages.
+
+Custom endpoints have stricter policies. The following rules apply:
+
+  * Policy rules are always enforced, even if the connection is a privileged
+    connection.
+  * Policy rules are always enforced for TALK access, even if both ends are
+    running under the same user. This includes broadcast messages.
+  * To restrict the set of names that can be seen, endpoint policies can
+    install "SEE" policies.
+
+
+12. Pool
+===============================================================================
+
+A pool for data received from the kernel is installed for every connection of
+the bus, and is sized according to the information stored in the
+KDBUS_ITEM_BLOOM_PARAMETER item that is returned by KDBUS_CMD_HELLO.
+
+The pool is written to by the kernel when one of the following ioctls is issued:
+
+  * KDBUS_CMD_HELLO, to receive details about the bus the connection was made to
+  * KDBUS_CMD_RECV, to receive a message
+  * KDBUS_CMD_NAME_LIST, to dump the name registry
+  * KDBUS_CMD_CONN_INFO, to retrieve information on a connection
+
+The offsets returned by either one of the aforementioned ioctls describe offsets
+inside the pool. In order to make the slice available for subsequent calls,
+KDBUS_CMD_FREE has to be called on the offset.
+
+To access the memory, the caller is expected to mmap() it to its task, like
+this:
+
+  /*
+   * POOL_SIZE has to be a multiple of PAGE_SIZE, and it must match the
+   * value that was previously returned through the KDBUS_ITEM_BLOOM_PARAMETER
+   * item field when the KDBUS_CMD_HELLO ioctl returned.
+   */
+
+  buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, conn_fd, 0);
+
+Alternatively, instead of mapping the entire pool buffer, only parts of it can
+be mapped. The length of the response is returned by the kernel along with the
+offset for each of the ioctls listed above.
+
+
+13. Metadata
+===============================================================================
+
+kdbus records data about the system in certain situations. Such metadata can
+refer to the currently active process (creds, PIDs, current user groups, process
+names and its executable path, cgroup membership, capabilities, security label
+and audit information), connection information (description string, currently
+owned names) and the timestamp.
+
+Metadata is collected in the following circumstances:
+
+  * When a bus is created (KDBUS_CMD_MAKE), information about the calling task
+    is collected. This data is returned by the kernel via the
+    KDBUS_CMD_BUS_CREATOR_INFO call-
+
+  * When a connection is created (KDBUS_CMD_HELLO), information about the
+    calling task is collected. Alternatively, a privileged connection may
+    provide 'faked' information about credentials, PIDs and a security labels
+    which will be taken instead. This data is returned by the kernel as
+    information on a connection (KDBUS_CMD_CONN_INFO).
+
+  * When a message is sent (KDBUS_CMD_SEND), information about the sending task
+    and the sending connection are collected. This metadata will be attached
+    to the message when it arrives in the receiver's pool. If the connection
+    sending the message installed faked credentials (see above), the message
+    will not be augmented by any information about the currently sending task.
+
+Which metadata items are actually delivered depends on the following sets and
+masks:
+
+    (a) the system-wide kmod creds mask (module parameter 'attach_flags_mask')
+    (b) the per-connection send creds mask, set by the connecting client
+    (c) the per-connection receive creds mask, set by the connecting client
+    (d) the per-bus minimal creds mask, set by the bus creator
+    (e) the per-bus owner creds mask, set by the bus creator
+    (f) the mask specified when querying creds of a bus peer
+    (g) the mask specified when querying creds of a bus owner
+
+With the following rules:
+
+    [1] The creds attached to messages are determined as (a & b & c).
+    [2] When connecting to a bus (KDBUS_CMD_HELLO), and (~b & d) != 0, the call
+        will fail, the connection is refused.
+    [3] When querying creds of a bus peer, the creds returned are  (a & b & f)
+    [4] When querying creds of a bus owner, the creds returned are (a & e & g)
+    [5] When creating a new bus, and (d & ~a) != 0, then bus creation will fail
+
+Hence, userspace might not always get all requested metadata items that it
+requested. Code must be written so that it can cope with this fact.
+
+
+13.1 Known item types
+---------------------
+
+The following attach flags are currently supported.
+
+  KDBUS_ATTACH_TIMESTAMP
+    Attaches an item of type KDBUS_ITEM_TIMESTAMP which contains both the
+    monotonic and the realtime timestamp, taken when the message was
+    processed on the kernel side.
+
+  KDBUS_ATTACH_CREDS
+    Attaches an item of type KDBUS_ITEM_CREDS, containing credentials as
+    described in struct kdbus_creds: the user and group IDs in the usual four
+    flavors: real, effective, saved and file-system related.
+
+  KDBUS_ATTACH_PIDS
+    Attaches an item of type KDBUS_ITEM_PIDS, containing information on the
+    process. In particular, the PID (process ID), TID (thread ID), and PPID
+    (PID of the parent process).
+
+  KDBUS_ATTACH_AUXGROUPS
+    Attaches an item of type KDBUS_ITEM_AUXGROUPS, containing a dynamic
+    number of auxiliary groups the sending task was a member of.
+
+  KDBUS_ATTACH_NAMES
+    Attaches items of type KDBUS_ITEM_OWNED_NAME, one for each name the sending
+    connection currently owns. The name and flags are stored in kdbus_item.name
+    for each of them.
+
+  KDBUS_ATTACH_TID_COMM [*]
+    Attaches an items of type KDBUS_ITEM_TID_COMM, transporting the sending
+    task's 'comm', for the tid.  The string is stored in kdbus_item.str.
+
+  KDBUS_ATTACH_PID_COMM [*]
+    Attaches an items of type KDBUS_ITEM_PID_COMM, transporting the sending
+    task's 'comm', for the pid.  The string is stored in kdbus_item.str.
+
+  KDBUS_ATTACH_EXE [*]
+    Attaches an item of type KDBUS_ITEM_EXE, containing the path to the
+    executable of the sending task, stored in kdbus_item.str.
+
+  KDBUS_ATTACH_CMDLINE [*]
+    Attaches an item of type KDBUS_ITEM_CMDLINE, containing the command line
+    arguments of the sending task, as an array of strings, stored in
+    kdbus_item.str.
+
+  KDBUS_ATTACH_CGROUP
+    Attaches an item of type KDBUS_ITEM_CGROUP with the task's cgroup path.
+
+  KDBUS_ATTACH_CAPS
+    Attaches an item of type KDBUS_ITEM_CAPS, carrying sets of capabilities
+    that should be accessed via kdbus_item.caps.caps. Also, userspace should
+    be written in a way that it takes kdbus_item.caps.last_cap into account,
+    and derive the number of sets and rows from the item size and the reported
+    number of valid capability bits.
+
+  KDBUS_ATTACH_SECLABEL
+    Attaches an item of type KDBUS_ITEM_SECLABEL, which contains the SELinux
+    security label of the sending task. SELinux and other MACs might want to
+    do additional per-service security checks. For example, a service manager
+    might want to check the security label of a service file against the
+    security label of the client process checking the SELinux database before
+    allowing access.  The label can be accessed via kdbus_item->str.
+
+  KDBUS_ATTACH_AUDIT
+    Attaches an item of type KDBUS_ITEM_AUDIT, which contains the audit
+    sessionid and loginuid of the sending task. Access via kdbus_item->audit.
+
+  KDBUS_ATTACH_CONN_DESCRIPTION
+    Attaches an item of type KDBUS_ITEM_CONN_DESCRIPTION that contains a
+    descriptive string of the sending peer. That string can be supplied
+    during HELLO by attaching an item of type KDBUS_ITEM_CONN_DESCRIPTION.
+
+
+[*] Note that the content stored in these items can easily be tampered by
+    the sending tasks. Therefore, they should NOT be used for any sort of
+    security relevant assumptions. The only reason why they are transmitted is
+    to let receivers know about details that were set when metadata was
+    collected, even though the task they were collected from is not active any
+    longer when the items are received.
+
+
+13.2 Metadata and namespaces
+----------------------------
+
+Metadata such as PIDs, UIDs or GIDs are automatically translated to the
+namespaces of the task that receives them.
+
+
+14. Error codes
+===============================================================================
+
+Below is a list of error codes that might be returned by the individual
+ioctl commands. The list focuses on the return values from kdbus code itself,
+and might not cover those of all kernel internal functions.
+
+For all ioctls:
+
+  -ENOMEM	The kernel memory is exhausted
+  -ENOTTY	Illegal ioctl command issued for the file descriptor
+  -ENOSYS	The requested functionality is not available
+  -EINVAL	Unsupported item attached to command
+
+For all ioctls that carry a struct as payload:
+
+  -EFAULT	The supplied data pointer was not 64-bit aligned, or was
+		inaccessible from the kernel side.
+  -EINVAL	The size inside the supplied struct was smaller than expected
+  -EMSGSIZE	The size inside the supplied struct was bigger than expected
+  -ENAMETOOLONG	A supplied name is larger than the allowed maximum size
+
+For KDBUS_CMD_BUS_MAKE:
+
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid or
+		the supplied name does not start with the current uid and a '-'
+  -EEXIST	A bus of that name already exists
+  -ESHUTDOWN	The domain for the bus is already shut down
+  -EMFILE	The maximum number of buses for the current user is exhausted
+
+For KDBUS_CMD_ENDPOINT_MAKE:
+
+  -EPERM	The calling user is not privileged (see Terminology)
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid
+  -EEXIST	An endpoint of that name already exists
+
+For KDBUS_CMD_HELLO:
+
+  -EFAULT	The supplied pool size was 0 or not a multiple of the page size
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid, or
+		an illegal combination of KDBUS_HELLO_MONITOR,
+		KDBUS_HELLO_ACTIVATOR and KDBUS_HELLO_POLICY_HOLDER was passed
+		in the flags, or an invalid set of items was supplied
+  -ECONNREFUSED	The attach_flags_send field did not satisfy the requirements of
+		the bus
+  -EPERM	An KDBUS_ITEM_CREDS items was supplied, but the current user is
+		not privileged
+  -ESHUTDOWN	The bus has already been shut down
+  -EMFILE	The maximum number of connection on the bus has been reached
+  -EOPNOTSUPP	The endpoint does not support the connection flags
+		supplied in the kdbus_cmd_hello struct
+
+For KDBUS_CMD_BYEBYE:
+
+  -EALREADY	The connection has already been shut down
+  -EBUSY	There are still messages queued up in the connection's pool
+
+For KDBUS_CMD_SEND:
+
+  -EOPNOTSUPP	The connection is not an ordinary connection, or the passed
+		file descriptors are either kdbus handles or unix domain
+		sockets. Both are currently unsupported
+  -EINVAL	The submitted payload type is KDBUS_PAYLOAD_KERNEL,
+		KDBUS_MSG_EXPECT_REPLY was set without timeout or cookie
+		values, KDBUS_MSG_SYNC_REPLY was set without
+		KDBUS_MSG_EXPECT_REPLY, an invalid item was supplied,
+		src_id was != 0 and different from the current connection's ID,
+		a supplied memfd had a size of 0, a string was not properly
+		null-terminated
+  -ENOTUNIQ	The supplied destination is KDBUS_DST_ID_BROADCAST, a file
+		descriptor was passed, KDBUS_MSG_EXPECT_REPLY was set,
+		or a timeout was given for a broadcast message
+  -E2BIG	Too many items
+  -EMSGSIZE	The size of the message header and items or the payload vector
+		is too big.
+  -EEXIST	Multiple KDBUS_ITEM_FDS, KDBUS_ITEM_BLOOM_FILTER or
+		KDBUS_ITEM_DST_NAME items were supplied
+  -EBADF	The supplied KDBUS_ITEM_FDS or KDBUS_MSG_PAYLOAD_MEMFD items
+		contained an illegal file descriptor
+  -EMEDIUMTYPE	The supplied memfd is not a sealed kdbus memfd
+  -EMFILE	Too many file descriptors inside a KDBUS_ITEM_FDS
+  -EBADMSG	An item had illegal size, both a dst_id and a
+		KDBUS_ITEM_DST_NAME was given, or both a name and a bloom
+		filter was given
+  -ETXTBSY	The supplied kdbus memfd file cannot be sealed or the seal
+		was removed, because it is shared with other processes or
+		still mmap()ed
+  -ECOMM	A peer does not accept the file descriptors addressed to it
+  -EFAULT	The supplied bloom filter size was not 64-bit aligned
+  -EDOM		The supplied bloom filter size did not match the bloom filter
+		size of the bus
+  -EDESTADDRREQ	dst_id was set to KDBUS_DST_ID_NAME, but no KDBUS_ITEM_DST_NAME
+		was attached
+  -ESRCH	The name to look up was not found in the name registry
+  -EADDRNOTAVAIL KDBUS_MSG_NO_AUTO_START was given but the destination
+		 connection is an activator.
+  -ENXIO	The passed numeric destination connection ID couldn't be found,
+		or is not connected
+  -ECONNRESET	The destination connection is no longer active
+  -ETIMEDOUT	Timeout while synchronously waiting for a reply
+  -EINTR	System call interrupted while synchronously waiting for a reply
+  -EPIPE	When sending a message, a synchronous reply from the receiving
+		connection was expected but the connection died before
+		answering
+  -ENOBUFS	Too many pending messages on the receiver side
+  -EREMCHG	Both a well-known name and a unique name (ID) was given, but
+		the name is not currently owned by that connection.
+  -EXFULL	The memory pool of the receiver is full
+  -EREMOTEIO	While synchronously waiting for a reply, the remote peer
+		failed with an I/O error.
+
+For KDBUS_CMD_RECV:
+
+  -EINVAL	Invalid flags or offset
+  -EAGAIN	No message found in the queue
+  -ENOMSG	No message of the requested priority found
+  -EOVERFLOW	Broadcast messages have been lost
+
+For KDBUS_CMD_FREE:
+
+  -ENXIO	No pool slice found at given offset
+  -EINVAL	Invalid flags provided, the offset is valid, but the user is
+		not allowed to free the slice. This happens, for example, if
+		the offset was retrieved with KDBUS_RECV_PEEK.
+
+For KDBUS_CMD_NAME_ACQUIRE:
+
+  -EINVAL	Illegal command flags, illegal name provided, or an activator
+		tried to acquire a second name
+  -EPERM	Policy prohibited name ownership
+  -EALREADY	Connection already owns that name
+  -EEXIST	The name already exists and can not be taken over
+  -E2BIG	The maximum number of well-known names per connection
+		is exhausted
+  -ECONNRESET	The connection was reset during the call
+
+For KDBUS_CMD_NAME_RELEASE:
+
+  -EINVAL	Invalid command flags, or invalid name provided
+  -ESRCH	Name is not found found in the registry
+  -EADDRINUSE	Name is owned by a different connection and can't be released
+
+For KDBUS_CMD_NAME_LIST:
+
+  -EINVAL	Invalid flags
+  -ENOBUFS	No available memory in the connection's pool.
+
+For KDBUS_CMD_CONN_INFO:
+
+  -EINVAL	Invalid flags, or neither an ID nor a name was provided,
+		or the name is invalid.
+  -ESRCH	Connection lookup by name failed
+  -ENXIO	No connection with the provided connection ID found
+
+For KDBUS_CMD_CONN_UPDATE:
+
+  -EINVAL	Illegal flags or items
+  -EOPNOTSUPP	Operation not supported by connection.
+  -E2BIG	Too many policy items attached
+  -EINVAL	Wildcards submitted in policy entries, or illegal sequence
+		of policy items
+
+For KDBUS_CMD_ENDPOINT_UPDATE:
+
+  -E2BIG	Too many policy items attached
+  -EINVAL	Invalid flags, or wildcards submitted in policy entries,
+		or illegal sequence of policy items
+
+For KDBUS_CMD_MATCH_ADD:
+
+  -EINVAL	Illegal flags or items
+  -EDOM		Illegal bloom filter size
+  -EMFILE	Too many matches for this connection
+
+For KDBUS_CMD_MATCH_REMOVE:
+
+  -EINVAL	Illegal flags
+  -ENOENT	A match entry with the given cookie could not be found.
+
+
+15. Internal object relations
+===============================================================================
+
+This is a simplified outline of the internal kdbus object relations, for
+those interested in the inner life of the driver implementation.
+
+From the a mount point's (domain's) perspective:
+
+struct kdbus_domain
+  |» struct kdbus_domain_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_domain_user *user (pinned)
+              |   `» struct kdbus_queue_entry entries (many, embedded)
+              |        |» struct kdbus_pool_slice *slice (pinned)
+              |        |» struct kdbus_conn_reply *reply (owned)
+              |        '» struct kdbus_domain_user *user (pinned)
+              |
+              '» struct kdbus_domain_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)
Signature · 1 line
2.2.1
#2 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

I have some details feedback on the contents of this file, and some bigger questions. I'll split them out into separate mails.

So here, the bigger, general questions to start with. I've arrived late to this, so sorry if they've already been discussed, but the answers to some of the questions should actually be in this file, I would have expected.

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

An observation: The documentation below is substantial, but this API is enormous, so the documentation still feels rather thin. What would really help would be some example code in the doc.

And on the subject of code examples... Are there any (prototype) working user-space applications that exercise the current kdbus implementation? That is, can I install these kdbus patches, and then find a simple example application somewhere that does something to exercise kdbus?

And then: is there any substantial real-world application (e.g., a full D-Bus port) that is being developed in tandem with this kernel side patch? (I don't mean a user-space library; I mean a seriously large application.) This is an incredibly complex API whose failings are only going to become evident through real-world use. Solidifying an API in the kernel and then discovering the API problems later when writing real-world applications would make for a sad story. A story something like that of inotify, an API which is an order of magnitude less complex than kdbus. (I can't help but feel that many of inotify problems that I discuss at
https://lwn.net/Articles/605128/ might have been fixed or mitigated if a few real-world applications had been implemented before the API was set in stone.)

Documentation/kdbus.txt line 18

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+For a kdbus specific userspace library implementation please refer to:
+  http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-bus.h

Is this library intended just for systemd? More generally, is there an intention to provide a general purpose library API for kdbus? Or is the intention that each application will roll a library suitable to its needs? I think an answer to that question would be useful in this Documentation file.

Cheers,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#3 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael

Quoted 30 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

I have some details feedback on the contents of this file, and some bigger questions. I'll split them out into separate mails.

So here, the bigger, general questions to start with. I've arrived late to this, so sorry if they've already been discussed, but the answers to some of the questions should actually be in this file, I would have expected.

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

An observation: The documentation below is substantial, but this API is enormous, so the documentation still feels rather thin. What would really help would be some example code in the doc.

Quoted 5 lines

And on the subject of code examples... Are there any (prototype) working user-space applications that exercise the current kdbus implementation? That is, can I install these kdbus patches, and then find a simple example application somewhere that does something to exercise kdbus?

If you run a 3.18 kernel, you can install kdbus.ko from our repository and boot a full Fedora system running Gnome3 with kdbus, given that you compiled systemd with --enable-kdbus (which is still experimental). No legacy dbus1 daemon is running. Instead, we have a bus-proxy that converts classic dbus1 to kdbus, so all bus-communication runs on kdbus.

Quoted 5 lines

And then: is there any substantial real-world application (e.g., a full D-Bus port) that is being developed in tandem with this kernel side patch? (I don't mean a user-space library; I mean a seriously large application.) This is an incredibly complex API whose failings are only going to become evident through real-world use.

Quoted 8 lines

Solidifying an API in the kernel and then discovering the API problems later when writing real-world applications would make for a sad story. A story something like that of inotify, an API which is an order of magnitude less complex than kdbus. (I can't help but feel that many of inotify problems that I discuss at
https://lwn.net/Articles/605128/ might have been fixed or mitigated if a few real-world applications had been implemented before the API was set in stone.)

I think running a whole Gnome3 stack counts as "substantial real-world application", right? Sure, it's a dbus1-to-kdbus layer, but all the systemd tools use kdbus natively and it works just fine. In fact, we all run kdbus on our main-systems every day.

We've spent over a year fixing races and API misdesigns, we've talked to other toolkit developers (glib, qt, ..) and made sure we're backwards compatible to dbus1. I don't think the API is perfect, everyone makes mistakes. But with bus-proxy and systemd we have two huge users of kdbus that put a lot of pressure on API design.

Quoted 8 lines

Documentation/kdbus.txt line 18

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+For a kdbus specific userspace library implementation please refer to:
+  http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-bus.h

Is this library intended just for systemd? More generally, is there an intention to provide a general purpose library API for kdbus? Or is the intention that each application will roll a library suitable to its needs? I think an answer to that question would be useful in this Documentation file.

kdbus is in no way bound to systemd. There are ongoing efforts to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios.

Note that most of the toolkit work is on the marshaling level, which is independent of kdbus. kdbus just provides the transport level. DBus is just one, yet significant, application-layer on top of kdbus. Our test-cases use kdbus exclusively to transport raw byte streams.

Thanks
David

#4 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 40 lines · David Herrmann

Hi Michael

Quoted 30 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

I have some details feedback on the contents of this file, and some bigger questions. I'll split them out into separate mails.

So here, the bigger, general questions to start with. I've arrived late to this, so sorry if they've already been discussed, but the answers to some of the questions should actually be in this file, I would have expected.

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

An observation: The documentation below is substantial, but this API is enormous, so the documentation still feels rather thin. What would really help would be some example code in the doc.

Quoted 5 lines

And on the subject of code examples... Are there any (prototype) working user-space applications that exercise the current kdbus implementation? That is, can I install these kdbus patches, and then find a simple example application somewhere that does something to exercise kdbus?

Quoted 6 lines

If you run a 3.18 kernel, you can install kdbus.ko from our repository and boot a full Fedora system running Gnome3 with kdbus, given that you compiled systemd with --enable-kdbus (which is still experimental). No legacy dbus1 daemon is running. Instead, we have a bus-proxy that converts classic dbus1 to kdbus, so all bus-communication runs on kdbus.

FWIW, we've been building a "playground" repository for the kernel that contains this already for Fedora. If you have a stock Fedora 21 or rawhide install, you can use:

https://copr.fedoraproject.org/coprs/jwboyer/kernel-playground/

which has the kernel+kdbus and systemd built with --enable-kdbus already. Easy enough to throw in a VM for testing.

josh

#5 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi,

Quoted 52 lines · Josh Boyer
Quoted 40 lines · David Herrmann

Hi Michael

Quoted 30 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

I have some details feedback on the contents of this file, and some bigger questions. I'll split them out into separate mails.

So here, the bigger, general questions to start with. I've arrived late to this, so sorry if they've already been discussed, but the answers to some of the questions should actually be in this file, I would have expected.

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

An observation: The documentation below is substantial, but this API is enormous, so the documentation still feels rather thin. What would really help would be some example code in the doc.

Quoted 5 lines

And on the subject of code examples... Are there any (prototype) working user-space applications that exercise the current kdbus implementation? That is, can I install these kdbus patches, and then find a simple example application somewhere that does something to exercise kdbus?

Quoted 6 lines

If you run a 3.18 kernel, you can install kdbus.ko from our repository and boot a full Fedora system running Gnome3 with kdbus, given that you compiled systemd with --enable-kdbus (which is still experimental). No legacy dbus1 daemon is running. Instead, we have a bus-proxy that converts classic dbus1 to kdbus, so all bus-communication runs on kdbus.

FWIW, we've been building a "playground" repository for the kernel that contains this already for Fedora. If you have a stock Fedora 21 or rawhide install, you can use:

Quoted 6 lines

https://copr.fedoraproject.org/coprs/jwboyer/kernel-playground/

which has the kernel+kdbus and systemd built with --enable-kdbus already. Easy enough to throw in a VM for testing.

josh

Yes thanks josh!

Another addition, if kdbus is installed and loaded, you could also use systemd-nspawn to boot a full system (systemd compiled with --enable-kdbus) in a container [1], kdbusfs will be mounted in the container.

There is also the busctl tool to query kdbus...

http://www.freedesktop.org/wiki/Software/systemd/VirtualizedTesting/

Signature · 2 lines
Djalal Harouni
http://opendz.org
#6 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi all,

Quoted 19 lines · Djalal Harouni
Quoted 9 lines · Josh Boyer
Quoted 7 lines · David Herrmann

If you run a 3.18 kernel, you can install kdbus.ko from our repository and boot a full Fedora system running Gnome3 with kdbus, given that you compiled systemd with --enable-kdbus (which is still experimental). No legacy dbus1 daemon is running. Instead, we have a bus-proxy that converts classic dbus1 to kdbus, so all bus-communication runs on kdbus.

Quoted 8 lines

FWIW, we've been building a "playground" repository for the kernel that contains this already for Fedora. If you have a stock Fedora 21 or rawhide install, you can use:

https://copr.fedoraproject.org/coprs/jwboyer/kernel-playground/

which has the kernel+kdbus and systemd built with --enable-kdbus already. Easy enough to throw in a VM for testing.

Quoted 8 lines

Another addition, if kdbus is installed and loaded, you could also use systemd-nspawn to boot a full system (systemd compiled with --enable-kdbus) in a container [1], kdbusfs will be mounted in the container.

There is also the busctl tool to query kdbus...

http://www.freedesktop.org/wiki/Software/systemd/VirtualizedTesting/

It is reassuring that kdbus actually works :)

However, let me repeat and rephrase my previous questions:
Is there a noticable or measurable improvement from using kdbus? IOW, is the added complexity of kdbus worth the result?

I have stated my believe that current usage of D-Bus is not performance sensitive and the number of messages exchanged is low. I would love it if you would prove me wrong. Or if you could show that any D-Bus related bug in Gnome3 is fixed by kdbus.

I would sooo love it if someone would finally post some data that proves kdbus is useful beyond systemd.

Thanks,
Johannes

#7 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi

Quoted 9 lines · Johannes Stezenbach

However, let me repeat and rephrase my previous questions:
Is there a noticable or measurable improvement from using kdbus? IOW, is the added complexity of kdbus worth the result?

I have stated my believe that current usage of D-Bus is not performance sensitive and the number of messages exchanged is low. I would love it if you would prove me wrong. Or if you could show that any D-Bus related bug in Gnome3 is fixed by kdbus.

DBus is not used for performance sensitive applications because DBus is slow. We want to make it fast so we can finally use it for low-latency, high-throughput applications. A simple DBus method-call+reply takes 200us here, with kdbus it takes 8us (with UDS about 2us). If I increase the packet size from 8k to 128k, kdbus even tops UDS thanks to single-copy transfers.
The fact that there is no performance-critical application using DBus is, imho, an argument *pro* kdbus. People haven't been capable of making classic dbus1 fast enough for low-latency audio, thus, we present kdbus.

Starting up 'gdm' sends ~5k dbus messages on my machine. It takes >1s to transmit the messages alone. Each dbus1 message has to be copied 4 times for each direction. With kdbus, each message is copied only once for each transmission (or not at all, if you use memfds, though that doesn't mean it's necessarily faster). No intermediate context-switch is needed. This makes kdbus capable to transmit low-latency audio data *inline*.

DBus marshaling is the de-facto standard in all major(!) linux desktop systems. It is well established and accepted by many DEs. It also solves many other problems, including: policy, authentication/authorization, well-known name registry, efficient broadcasts/multicasts, peer discovery, bus discovery, metadata transmission, and more.
It is a shame that we cannot use this well-established protocol for low-latency applications. We, effectively, have to duplicate all this code on custom UDS and other transports just because DBus is too slow.

kdbus tries to unify those efforts, so that we don't need multiple policy implementations, name registries and peer discovery mechanisms. Furthermore, kdbus implements comprehensive, yet optional, metadata transmission that allows to identify and authenticate peers in a race-free manner (which is *not* possible with UDS).
Also, kdbus provides a single transport bus with sequential message numbering. If you use multiple channels, you cannot give any ordering guarantees across peers (for instance, regarding parallel name-registry changes).

Given these theoretical advantages, here're some examples:

*) The Tizen developers have been complaining about the high latency of DBus for polkit'ish policy queries. That's why their authentication framework uses custom UDS sockets (called 'Cynara'). If a UI-interaction needs multiple authentication-queries, you don't want it to take multiple milliseconds, given that you usually want to render the result in the same frame.

*) PulseAudio doesn't use DBus for data transmission. They had to implement their own marshaling code, transport layer and so on, just because DBus1-latency is horrible. With kdbus, we can basically drop this code-duplication and unify the IPC layer. Same is true for Wayland, btw.

*) By moving broadcast-transmission into the kernel, we can use the time-slices of the sender to perform heavy operations. This is also true for policy decisions, etc. With a userspace daemon, we cannot perform operations in a time-slice of the caller. This makes DoS attacks much harder.

*) With priority-inheritance, we can do synchronous calls into trusted peers and let them optionally use our time-slice to perform the action. This allows syscall-like/binder-like method-calls into other processes. Without priority-inheritance, this is not possible in a secure manner (see 'priority-inheritance').

*) Logging-daemons often want to attach metadata to log-messages so debugging/filtering gets easier. If short-lived programs send log-messages, the destination peer might not be able to read such metadata from /proc, as the process might no longer be available at that time. Same is true for policy-decisions like polkit does. You cannot send off method-calls and exit. You have to wait for a reply, even though you might not even care for it. If you don't wait, the other side might not be able to verify your identity and as such reject the request.

*) Even though the dbus traffic on idle-systems might be low, this doesn't mean it's not significant at boot-times or under high-load. If you run a dbus-monitor of your choice, you will see there is an significant number of messages exchanged during VT-switches, startup, shutdown, suspend, wakeup, hotplugging and similar situations where lots of control-messages are exchanged. We don't want to spend hundreds of ms just to transmit those messages.

*) dbus-daemon is not available during early-boot or shutdown.

These are just examples off the top of my head, but I think they're already pretty convincing.
David

#8 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi David,

On Tue, Jan 20, 2015 at 06:00:28PM +0100, David Herrmann wrote:
[big snip]

Quoted 2 lines

These are just examples off the top of my head, but I think they're already pretty convincing.

Thank you for writing this up. This is the information I was looking for which puts kdbus into context and explains the motivation for its development. Naturally I don't agree with all of it, but I'm content with what I learned so far.

Daniel informed me off-list that he (and probably others) does not understand what my questions were aiming at. I'm sorry about that, I thought it was clear I was just lacking the background information to understand what kdbus is and what it is not, and why it exists -- information I couldn't find in some hours of googling.

Thanks,
Johannes

#9 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to David Herrmann

Hi David,

Quoted 40 lines · David Herrmann

Hi Michael

Quoted 30 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

I have some details feedback on the contents of this file, and some bigger questions. I'll split them out into separate mails.

So here, the bigger, general questions to start with. I've arrived late to this, so sorry if they've already been discussed, but the answers to some of the questions should actually be in this file, I would have expected.

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

An observation: The documentation below is substantial, but this API is enormous, so the documentation still feels rather thin. What would really help would be some example code in the doc.

Quoted 5 lines

And on the subject of code examples... Are there any (prototype) working user-space applications that exercise the current kdbus implementation? That is, can I install these kdbus patches, and then find a simple example application somewhere that does something to exercise kdbus?

Quoted 6 lines

If you run a 3.18 kernel, you can install kdbus.ko from our repository and boot a full Fedora system running Gnome3 with kdbus, given that you compiled systemd with --enable-kdbus (which is still experimental). No legacy dbus1 daemon is running. Instead, we have a bus-proxy that converts classic dbus1 to kdbus, so all bus-communication runs on kdbus.

Good to hear. I think that some info like this should go out in the "00/" covering mails for future patch revisions, so that people can get some sense of the testing that has been done.

Quoted 14 lines
Quoted 5 lines

And then: is there any substantial real-world application (e.g., a full D-Bus port) that is being developed in tandem with this kernel side patch? (I don't mean a user-space library; I mean a seriously large application.) This is an incredibly complex API whose failings are only going to become evident through real-world use.

Quoted 8 lines

Solidifying an API in the kernel and then discovering the API problems later when writing real-world applications would make for a sad story. A story something like that of inotify, an API which is an order of magnitude less complex than kdbus. (I can't help but feel that many of inotify problems that I discuss at
https://lwn.net/Articles/605128/ might have been fixed or mitigated if a few real-world applications had been implemented before the API was set in stone.)

Quoted 2 lines

I think running a whole Gnome3 stack counts as "substantial real-world application", right?

Yes, I'll give you that ;-).

Quoted 9 lines

Sure, it's a dbus1-to-kdbus layer, but all the
systemd tools use kdbus natively and it works just fine. In fact, we all run kdbus on our main-systems every day.

We've spent over a year fixing races and API misdesigns, we've talked to other toolkit developers (glib, qt, ..) and made sure we're backwards compatible to dbus1. I don't think the API is perfect, everyone makes mistakes. But with bus-proxy and systemd we have two huge users of kdbus that put a lot of pressure on API design.

I'll say more about that in another mail in a moment. I'm not enthusiastic about the API.

Quoted 11 lines
Quoted 8 lines

Documentation/kdbus.txt line 18

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+For a kdbus specific userspace library implementation please refer to:
+  http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-bus.h

Is this library intended just for systemd? More generally, is there an intention to provide a general purpose library API for kdbus? Or is the intention that each application will roll a library suitable to its needs? I think an answer to that question would be useful in this Documentation file.

kdbus is in no way bound to systemd. There are ongoing efforts to port glib and qt to kdbus natively. The API is pretty simple

                                 ^^^^^^^^^^^^^^^^^^^^^^^^

I think you and I must have quite different definitions of "simple"... (For more on this point, see my reply to Daniel in a moment.)

Quoted 4 lines

and I don't
see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios.

Again, the above info would be useful in the Documentation file.

Quoted 4 lines

Note that most of the toolkit work is on the marshaling level, which is independent of kdbus. kdbus just provides the transport level. DBus is just one, yet significant, application-layer on top of kdbus. Our test-cases use kdbus exclusively to transport raw byte streams.

Okay. Thanks for the info.

Cheers,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#10 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Michael Kerrisk (man-pages)
Quoted 6 lines · Michael Kerrisk (man-pages)

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

I think the simplest reason is because we want to be able to build kdbus as a module. It's rather an optional driver than a core kernel feature. IMO, kernel primitives should be syscalls, but kdbus is not a primitive but an elaborate subsystem.

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system. Hence, we decided not to use a global kernel interface but specific ioctls on the nodes exposed by kdbusfs.

Thanks,
Daniel

#11 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hello Daniel,

Quoted 10 lines · Daniel Mack
Quoted 6 lines · Michael Kerrisk (man-pages)

This is an enormous and complex API. Why is the API ioctl() based, rather than system-call-based? Have we learned nothing from the hydra that the futex() multiplexing syscall became? (And kdbus is an order of magnitude more complex, by the look of things.) At the very least, a *good* justification of why the API is ioctl()-based should be part of this documentation file.

I think the simplest reason is because we want to be able to build kdbus as a module.

This isn't any _good_ justification...

Quoted 1 line

It's rather an optional driver than a core kernel feature.

Given the various things that I've seen said about kdbus, the preceding sentence makes little sense to me:

* kdbus will be the framework supporting user-space D-Bus in the future, and also used by systemd, and so on pretty much every desktop system.
* kdbus solves much of the bandwidth problem of D-Bus1. That, along with a host of other features mean that there will be a lot of user-space developers interested in using this API.
* Various parties in user space are already expressing strong interest in kdbus.

My guess from the above? This will NOT be an "optional driver". It *will be* a core kernel feature.

Quoted 2 lines

IMO, kernel primitives should be syscalls, but kdbus is not a primitive but an elaborate subsystem.

Agreed. It's an elaborate subsystem. But that fact doesn't in itself dictate any particular API design choice.

Quoted 2 lines

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system.

It's not clear to me how this point implies any particular API design choice.

Quoted 2 lines

Hence, we decided not to use a
global kernel interface but specific ioctls on the nodes exposed by kdbusfs.

I don't follow the reasoning here at all. Here's what we have, if I have grasped it roughly correctly:

* 16 ioctls exposed to user space.
* some 20 different structures exchanged between kernel and user space
* about 14k lines of kernel code implement the above
* some rather thin documentation of the whole lot

Sorry if that last point seems rather harsh. I know that you personally have done a lot of work on the kdbus.txt file. David Herrmann asserts that this is a simple API. It is not. He also suggests that there is no need for a libkdbus. I don't know whether that's right or not, but the point is then that there's an expectation that the raw kernel API is what user space will need to work with.

Notwithstanding the fact that there's a lot of (good) information in kdbus.txt, there's not nearly enough for someone to create useful, robust applications that use that API (and not enough that I as a reviewer feel comfortable about reviewing the API). As things stand, user-space developers will be forced to decipher large amounts of kernel code and existing applications in order to actually build things. And when they do, they'll be using one of the worst APIs known to man: ioctl(), an API that provides no type safety at all.

ioctl() is a get-out-of-jail free card when it comes to API design. Rather than thinking carefully and long about a set of coherent, stable APIs that provide some degree of type-safety to user-space, one just adds/changes/removes an ioctl. And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Concretely, I'd like to see the following in kdbus.txt:
* A lot more detail, adding the various pieces that are currently missing. I've mentioned already the absence of detail on the item blob structures, but there's probably several other pieces as well. My problem is that the API is so big and hard to grok that it's hard to even begin to work out what's missing from the documentation.
* Fleshing out the API summaries with code snippets that illustrate the use of the APIs.
* At least one simple working example application, complete with a walk through of how it's built and run.

Yes, all of this is a big demand. But this is a big API that is being added to the kernel, and one that may become widely used and for a long time. It's imperative that the API is well documented, and as well designed as possible. Furthermore, with such improved documentation I feel we'd be in a better position to evaluate the merits of an ioctl()-based API versus some other approach.

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#12 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 8 lines · Michael Kerrisk (man-pages)

It's rather an optional driver than a core kernel feature.

Given the various things that I've seen said about kdbus, the preceding sentence makes little sense to me:

* kdbus will be the framework supporting user-space D-Bus in the future, and also used by systemd, and so on pretty much every desktop system.

I have to agree with Michael here; it's really, **really** disengenuous to say that that if you don't want kdbus, you can just #ifconfig it out. The fact that it systemd will be using it means that it will very shortly become a core kernel feature which is absolutely mandatory. Sure, maybe it can be configured out for "tiny kernels", just as in theory we can configure out the VM system for really tiny embedded systems. But we should be treating this as something that is not optional, because the reality is that's the way it's going to be in very short order. So if that means to use proper system calls instead of ioctls, we should do that.

- Ted

#13 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Michael Kerrisk (man-pages)

Hi Michael,

Quoted 16 lines · Michael Kerrisk (man-pages)
Quoted 1 line · Daniel Mack

It's rather an optional driver than a core kernel feature.

Given the various things that I've seen said about kdbus, the preceding sentence makes little sense to me:

* kdbus will be the framework supporting user-space D-Bus in the future, and also used by systemd, and so on pretty much every desktop system.
* kdbus solves much of the bandwidth problem of D-Bus1. That, along with a host of other features mean that there will be a lot of user-space developers interested in using this API.
* Various parties in user space are already expressing strong interest in kdbus.

Quoted 2 lines

My guess from the above? This will NOT be an "optional driver". It *will be* a core kernel feature.

There will be userlands that will depend on kdbus, but that will still not turn the "driver" into a core Linux kernel feature. We really want it to be losely coupled from the rest of the kernel and optional after all. The kernel people are working toward making more and more things optional these days, and there will still be lots of systems that won't be using kdbus.

Quoted 5 lines
Quoted 2 lines

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system.

It's not clear to me how this point implies any particular API design choice.

It emphasizes the fact that our ioctl API can only be used with the nodes exposed by kdbusfs, and vice versa. I think operations on driver-specific files do not justify a new 'generic' syscall API.

Quoted 8 lines

Notwithstanding the fact that there's a lot of (good) information in kdbus.txt, there's not nearly enough for someone to create useful, robust applications that use that API (and not enough that I as a reviewer feel comfortable about reviewing the API). As things stand, user-space developers will be forced to decipher large amounts of kernel code and existing applications in order to actually build things. And when they do, they'll be using one of the worst APIs known to man: ioctl(), an API that provides no type safety at all.

I don't see how ioctls are any worse than syscalls with pointers to structures. One can screw up compatibility either way. How is an ioctl wrapper/prototype any less type-safe than a syscall wrapper?

Quoted 1 line

ioctl() is a get-out-of-jail free card when it comes to API design.

And how are syscalls different in that regard when they would both transport the same data structures? Also note that all kdbus ioctls necessarily operate on a file descriptor context, which an ioctl passes along by default.

Quoted 4 lines

Rather
than thinking carefully and long about a set of coherent, stable APIs that provide some degree of type-safety to user-space, one just adds/changes/removes an ioctl.

Adding another ioctl in the future for cases we didn't think about earlier would of course be considered a workaround; and even though such things happen all the time, it's certainly something we'd like to avoid.

However, we would also need to add another syscall in such cases, which is even worse IMO. So that's really not an argument against ioctls after all. What fundamental difference between a raw syscall and a ioctl, especially with regards to type safety, is there which would help us here?

Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

Quoted 11 lines

Concretely, I'd like to see the following in kdbus.txt:
* A lot more detail, adding the various pieces that are currently missing. I've mentioned already the absence of detail on the item blob structures, but there's probably several other pieces as well. My problem is that the API is so big and hard to grok that it's hard to even begin to work out what's missing from the documentation.
* Fleshing out the API summaries with code snippets that illustrate the use of the APIs.
* At least one simple working example application, complete with a walk through of how it's built and run.

Quoted 2 lines

Yes, all of this is a big demand. But this is a big API that is being added to the kernel, and one that may become widely used and for a long time.

Fair enough. Everything that helps people understand and use the API in a sane way is a good thing to have, and so is getting an assessment from people how are exposed to this API for the first time.

We'll be working on restructuring the documentation.

Thanks,
Daniel

#14 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Daniel,

Quoted 22 lines · Daniel Mack

Hi Michael,

Quoted 16 lines · Michael Kerrisk (man-pages)
Quoted 1 line · Daniel Mack

It's rather an optional driver than a core kernel feature.

Given the various things that I've seen said about kdbus, the preceding sentence makes little sense to me:

* kdbus will be the framework supporting user-space D-Bus in the future, and also used by systemd, and so on pretty much every desktop system.
* kdbus solves much of the bandwidth problem of D-Bus1. That, along with a host of other features mean that there will be a lot of user-space developers interested in using this API.
* Various parties in user space are already expressing strong interest in kdbus.

Quoted 2 lines

My guess from the above? This will NOT be an "optional driver". It *will be* a core kernel feature.

Quoted 6 lines

There will be userlands that will depend on kdbus, but that will still not turn the "driver" into a core Linux kernel feature. We really want it to be losely coupled from the rest of the kernel and optional after all. The kernel people are working toward making more and more things optional these days, and there will still be lots of systems that won't be using kdbus.

Make it optional and configurable if you want. But that misses my point. kdbus is very likely to become an essential, widely used piece of *general-purpose* piece of ABI infrastructure that will be configured into virtually every type of system. As such, the same standards should apply as for a "core kernel feature", whether or not you want to cal it that.

Quoted 9 lines
Quoted 5 lines
Quoted 2 lines

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system.

It's not clear to me how this point implies any particular API design choice.

It emphasizes the fact that our ioctl API can only be used with the nodes exposed by kdbusfs, and vice versa. I think operations on driver-specific files do not justify a new 'generic' syscall API.

I see your (repeated) use of words like "driver" as just a distraction, I'm sorry. "Driver-specific files" is an implementation detail. The point is that kdbus provides a complex, general-purpose feature for all of userland. It is core infrastructure that will be used by key pieces of the plumbing layer, and likely by many other applications as well. *Please* stop suggesting that it is not core infrastructure: kdbus has the potential to be a great IPC that will be very useful to many, many user-space developers.

(By the way, we have precedents for device/filesystem-specific system calls. Even a recent one, in memfd_create().)

Quoted 9 lines
Quoted 8 lines

Notwithstanding the fact that there's a lot of (good) information in kdbus.txt, there's not nearly enough for someone to create useful, robust applications that use that API (and not enough that I as a reviewer feel comfortable about reviewing the API). As things stand, user-space developers will be forced to decipher large amounts of kernel code and existing applications in order to actually build things. And when they do, they'll be using one of the worst APIs known to man: ioctl(), an API that provides no type safety at all.

Quoted 3 lines

I don't see how ioctls are any worse than syscalls with pointers to structures. One can screw up compatibility either way. How is an ioctl wrapper/prototype any less type-safe than a syscall wrapper?

Taking that argument to the extreme, we would have no system calls at all, just one gigantic ioctl() ;-).

Quoted 4 lines
Quoted 1 line

ioctl() is a get-out-of-jail free card when it comes to API design.

And how are syscalls different in that regard when they would both transport the same data structures?

My general impression is that when it comes to system calls, there's usually a lot more up front thought about API design.

Quoted 3 lines

Also note that all kdbus ioctls
necessarily operate on a file descriptor context, which an ioctl passes along by default.

I fail to see your point here. The same statement applies to multiple special-purpose system calls (epoll, inotify, various shared memory APIs, and so on).

Quoted 5 lines
Quoted 4 lines

Rather
than thinking carefully and long about a set of coherent, stable APIs that provide some degree of type-safety to user-space, one just adds/changes/removes an ioctl.

Quoted 8 lines

Adding another ioctl in the future for cases we didn't think about earlier would of course be considered a workaround; and even though such things happen all the time, it's certainly something we'd like to avoid.

However, we would also need to add another syscall in such cases, which is even worse IMO. So that's really not an argument against ioctls after all. What fundamental difference between a raw syscall and a ioctl, especially with regards to type safety, is there which would help us here?

Type safety helps user-space application developers. System calls have it, ioctl() does not.

Quoted 13 lines
Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

Quoted 3 lines

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

My suspicion is that not nearly enough thinking has yet been done about the design of the API. That's based on these observations:

* Documentation that is, considering the size of the API, *way* too thin.
* Some parts of the API not documented at all (various kdbus_item blobs)
* ABI changes happening even quite recently
* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

The above is just after a day of looking hard at kdbus.txt. I strongly suspect I'd find a lot of other issues if I spent more time on kdbus.

Quoted 11 lines
Quoted 11 lines

Concretely, I'd like to see the following in kdbus.txt:
* A lot more detail, adding the various pieces that are currently missing. I've mentioned already the absence of detail on the item blob structures, but there's probably several other pieces as well. My problem is that the API is so big and hard to grok that it's hard to even begin to work out what's missing from the documentation.
* Fleshing out the API summaries with code snippets that illustrate the use of the APIs.
* At least one simple working example application, complete with a walk through of how it's built and run.

Quoted 8 lines
Quoted 2 lines

Yes, all of this is a big demand. But this is a big API that is being added to the kernel, and one that may become widely used and for a long time.

Fair enough. Everything that helps people understand and use the API in a sane way is a good thing to have, and so is getting an assessment from people how are exposed to this API for the first time.

We'll be working on restructuring the documentation.

Thanks. I know it's a big effort, and I wish you success.

Cheers,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#15 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael

Quoted 11 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Daniel Mack
Quoted 5 lines
Quoted 2 lines

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system.

It's not clear to me how this point implies any particular API design choice.

It emphasizes the fact that our ioctl API can only be used with the nodes exposed by kdbusfs, and vice versa. I think operations on driver-specific files do not justify a new 'generic' syscall API.

Quoted 8 lines

I see your (repeated) use of words like "driver" as just a distraction, I'm sorry. "Driver-specific files" is an implementation detail. The point is that kdbus provides a complex, general-purpose feature for all of userland. It is core infrastructure that will be used by key pieces of the plumbing layer, and likely by many other applications as well. *Please* stop suggesting that it is not core infrastructure: kdbus has the potential to be a great IPC that will be very useful to many, many user-space developers.

We called it an 'ipc driver' so far. It is in no way meant as distraction. Feel free to call it 'core infrastructure'. I think we can agree that we want it to be generically useful, like other ipc mechanisms, including UDS and netlink.

Quoted 2 lines

(By the way, we have precedents for device/filesystem-specific system calls. Even a recent one, in memfd_create().)

memfd_create() is in no way file-system specific. Internally, it uses shmem, but that's an implementation detail. The API does not expose this in any way. If you were referring to sealing, it's implemented as fcntl(), not as a separate syscall. Furthermore, sealing is only limited to shmem as it's the only volatile storage. It's not an API restriction. Other volatile file-systems are free to implement sealing.

Quoted 7 lines
Quoted 4 lines
Quoted 1 line

ioctl() is a get-out-of-jail free card when it comes to API design.

And how are syscalls different in that regard when they would both transport the same data structures?

My general impression is that when it comes to system calls, there's usually a lot more up front thought about API design.

This is no technical reason why to use syscalls over ioctls. Imho, it's rather a reason to improve the kernel's ioctl-review process.

Quoted 7 lines
Quoted 3 lines

Also note that all kdbus ioctls
necessarily operate on a file descriptor context, which an ioctl passes along by default.

I fail to see your point here. The same statement applies to multiple special-purpose system calls (epoll, inotify, various shared memory APIs, and so on).

epoll and inotify don't have a 'parent' object living in the file-system. They *need* an entry-point. We can use open() for that.

You're right, from a technical viewpoint, there's no restriction. There're examples for both (eg., see Solaris /dev/poll, as ioctl()-based 'epoll').

Quoted 9 lines
Quoted 9 lines
Quoted 4 lines

Rather
than thinking carefully and long about a set of coherent, stable APIs that provide some degree of type-safety to user-space, one just adds/changes/removes an ioctl.

Adding another ioctl in the future for cases we didn't think about earlier would of course be considered a workaround; and even though such things happen all the time, it's certainly something we'd like to avoid.

Quoted 7 lines
Quoted 4 lines

However, we would also need to add another syscall in such cases, which is even worse IMO. So that's really not an argument against ioctls after all. What fundamental difference between a raw syscall and a ioctl, especially with regards to type safety, is there which would help us here?

Type safety helps user-space application developers. System calls have it, ioctl() does not.

This is simply not true. There is no type-safety in:
syscall(__NR_xyz, some, random, arguments)

The only way a syscall gets 'type-safe', is to provide a wrapper function. Same applies to ioctls. But people tend to not do that for ioctls, which is, again, not a technical argument against ioctls. It's a matter of psychology, though.

I still don't see a technical reason to use syscalls. API proposals welcome!

We're now working on a small kdbus helper library, which provides type-safe ioctl wrappers, item-iterators and documented examples. But, like syscalls, nobody is forced to use the wrappers. The API design is not affected by this.

Quoted 13 lines
Quoted 13 lines
Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

Quoted 8 lines
Quoted 3 lines

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

My suspicion is that not nearly enough thinking has yet been done about the design of the API. That's based on these observations:

* Documentation that is, considering the size of the API, *way* too thin.

Ok, working on that.

Quoted 1 line

* Some parts of the API not documented at all (various kdbus_item blobs)

All public structures have documentation in kdbus.h. It may need improvements, though.

Quoted 1 line

* ABI changes happening even quite recently

Please elaborate why 'recent ABI-changes' are a sign of a premature API.

I seriously doubt any API can be called 'perfect'. On the contrary, I believe that all APIs could be improved continuously. The fact that we, at one point, settle on an API is an admission of backwards-compatibility. I in no way think it's a sign of 'perfection'.
With kdbus our plan is to give API-guarantees starting with upstream inclusion. We know, that our API will not be perfect, none is. But we will try hard to fix anything that comes up, as long as we can. And this effort will manifest in ABI-breaks.

Quoted 2 lines

* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

If we only returned EINVAL on invalid arguments, user-space had to probe for each flag to see whether it's supported. By returning the set of supported flags, user-space can cache those and _reliably_ know which flags are supported.
We decided the overhead of a single u64 copy on each ioctl is preferred over a separate syscall/ioctl to query kernel flags. If you disagree, please elaborate (preferably with a suggestion how to do it better).

Quoted 2 lines

The above is just after a day of looking hard at kdbus.txt. I strongly suspect I'd find a lot of other issues if I spent more time on kdbus.

If you find the time, please do! Any hints how a specific part of the API could be done better, is highly appreciated. A lot of the more or less recent changes were done due to reviews from glib developers. More help is always welcome!

Thanks
David

#16 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 7 lines · David Herrmann

Hi Michael

Quoted 2 lines · Michael Kerrisk (man-pages)

* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

Quoted 9 lines

If we only returned EINVAL on invalid arguments, user-space had to probe for each flag to see whether it's supported. By returning the set of supported flags, user-space can cache those and _reliably_ know which flags are supported.
We decided the overhead of a single u64 copy on each ioctl is preferred over a separate syscall/ioctl to query kernel flags. If you disagree, please elaborate (preferably with a suggestion how to do it better).

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running.
While a u64 copy has relatively low overhead, it does have overhead,
and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

#17 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 10 lines · Austin S Hemmelgarn

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running. While a u64 copy has relatively low overhead, it does have overhead, and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

A single u64 in a structure is not going to be measurable at all, processors just copy memory too fast these days for 4 extra bytes to be noticable. So let's make this as easy as possible for userspace, making it simpler logic there, which is much more important than saving theoretical time in the kernel.

thanks,

greg k-h

#18 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hello Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 10 lines · Austin S Hemmelgarn

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running. While a u64 copy has relatively low overhead, it does have overhead, and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

Quoted 3 lines

A single u64 in a structure is not going to be measurable at all, processors just copy memory too fast these days for 4 extra bytes to be noticable.

It depends on the definition of measurable, I suppose, but this statement appears incorrect to me. In some cases (e.g., kdbus_msg_info) we're talking about *two* u64 fields (kernel_gs, kernel_msg_flags) being used to pass back sets of valid flags. That's 16 bytes, and it definitely makes a difference. Simply running a loop that does a naive memcpy() in a tight user-space loop (code below), I see the following for the execution of 1e9 loops:

Including the two extra u64 fields: 3.2 sec
Without the two extra u64 fields: 2.6 sec

On the same box, doing 1e9 calls to getppid() (i.e., pretty much the simplest syscall, giving us a rough measure of the context switch) takes 68 seconds. In other words, the cost of copying those 16 bytes is about 1% of the base context switch/syscall cost. I assume the costs of copying those 16 bytes across the kernel-user-space boundary would not be cheaper, but have not tested that. If my assumption is correct, then 1% seems a significant figure to me in an API whose raison d'être is speed.

Quoted 3 lines

So let's make this as easy as possible for userspace, making it simpler logic there, which is much more important than saving theoretical time in the kernel.

But this also missed the other part of the point. Copying these fields on every operation, when in fact they are only needed once, clutters the API, in my opinion. Good APIs are as simple as they can be to do their job. Redundancy is an enemy of simplicity. Simplest would have been a one time API that returns a structure containing all of the supported flags across the API. Alternatively, the traditional EINVAL approach is well understood, and suffices.

Thanks,

Michael

=========

#include <stdint.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct kdbus_msg_info {
    uint64_t offset;
    uint64_t msg_size;
    uint64_t return_flags;
};
struct kdbus_cmd_send {
        uint64_t size;
        uint64_t flags;
#if FIELDS >= 1
        uint64_t kernel_flags;
#endif
#if FIELDS >= 2
        uint64_t kernel_msg_flags;
#endif
        uint64_t return_flags;
        uint64_t msg_address;
        struct kdbus_msg_info reply;
        //struct kdbus_item items[0];
} __attribute__((aligned(8)));

int
main(int argc, char *argv[])

{
    long nloops, j;
    struct kdbus_cmd_send src, dst;
    memset(&dst, 0, sizeof(struct kdbus_cmd_send));

    printf("struct size: %zd\n", sizeof(struct kdbus_cmd_send));
    nloops = (argc > 1) ? atol(argv[1]) : 1000000000;

    for (j = 0; j < nloops; j++) {
        memcpy(&dst, &src, sizeof(struct kdbus_cmd_send));
    }

    exit(EXIT_SUCCESS);
}
Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#19 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi

Quoted 29 lines · Michael Kerrisk (man-pages)

Hello Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 10 lines · Austin S Hemmelgarn

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running. While a u64 copy has relatively low overhead, it does have overhead, and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

Quoted 3 lines

A single u64 in a structure is not going to be measurable at all, processors just copy memory too fast these days for 4 extra bytes to be noticable.

It depends on the definition of measurable, I suppose, but this statement appears incorrect to me. In some cases (e.g., kdbus_msg_info) we're talking about *two* u64 fields (kernel_gs, kernel_msg_flags) being used to pass back sets of valid flags. That's 16 bytes, and it definitely makes a difference. Simply running a loop that does a naive memcpy() in a tight user-space loop (code below), I see the following for the execution of 1e9 loops:

Including the two extra u64 fields: 3.2 sec
Without the two extra u64 fields: 2.6 sec

Quoted 7 lines

On the same box, doing 1e9 calls to getppid() (i.e., pretty much the simplest syscall, giving us a rough measure of the context switch) takes 68 seconds. In other words, the cost of copying those 16 bytes is about 1% of the base context switch/syscall cost. I assume the costs of copying those 16 bytes across the kernel-user-space boundary would not be cheaper, but have not tested that. If my assumption is correct, then 1% seems a significant figure to me in an API whose raison d'être is speed.

I have no idea how this is related to any kdbus ioctl?

A 16byte copy does not affect the performance of kdbus message transactions in any way that matters.

Quoted 11 lines
Quoted 3 lines

So let's make this as easy as possible for userspace, making it simpler logic there, which is much more important than saving theoretical time in the kernel.

But this also missed the other part of the point. Copying these fields on every operation, when in fact they are only needed once, clutters the API, in my opinion. Good APIs are as simple as they can be to do their job. Redundancy is an enemy of simplicity. Simplest would have been a one time API that returns a structure containing all of the supported flags across the API. Alternatively, the traditional EINVAL approach is well understood, and suffices.

We're going to drop "kernel_flags" in favor of a new KDBUS_FLAG_NEGOTIATE flag which asks the kernel to do feature negotiation for this ioctl and return the supported flags/items inline (overwriting the passed data). The ioctl will not be executed and will not affect the state of the FD.
I hope this keeps the API simple.

Thanks
David

#20 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 41 lines · David Herrmann

Hi

Quoted 29 lines · Michael Kerrisk (man-pages)

Hello Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 10 lines · Austin S Hemmelgarn

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running. While a u64 copy has relatively low overhead, it does have overhead, and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

Quoted 3 lines

A single u64 in a structure is not going to be measurable at all, processors just copy memory too fast these days for 4 extra bytes to be noticable.

It depends on the definition of measurable, I suppose, but this statement appears incorrect to me. In some cases (e.g., kdbus_msg_info) we're talking about *two* u64 fields (kernel_gs, kernel_msg_flags) being used to pass back sets of valid flags. That's 16 bytes, and it definitely makes a difference. Simply running a loop that does a naive memcpy() in a tight user-space loop (code below), I see the following for the execution of 1e9 loops:

Including the two extra u64 fields: 3.2 sec
Without the two extra u64 fields: 2.6 sec

Quoted 7 lines

On the same box, doing 1e9 calls to getppid() (i.e., pretty much the simplest syscall, giving us a rough measure of the context switch) takes 68 seconds. In other words, the cost of copying those 16 bytes is about 1% of the base context switch/syscall cost. I assume the costs of copying those 16 bytes across the kernel-user-space boundary would not be cheaper, but have not tested that. If my assumption is correct, then 1% seems a significant figure to me in an API whose raison d'être is speed.

Quoted 5 lines

I have no idea how this is related to any kdbus ioctl?

A 16byte copy does not affect the performance of kdbus message transactions in any way that matters.

Sorry for jumping in so late. Since this version of kdbus was sent, I've been on vacation for part of the time and I had the flu for the rest of the time.

What are the performance goals of kdbus? How fast is it ever intended to be? The reason I ask is that, in the current design, kdbus collects "metadata" (credentials and other identifying information, collected in kdbus_meta_proc_collect) from the sender of every message *at send time*. [1] This is slow, and it will always be slow. The slowness of this operation will, in my personal system performance crystal ball, overshadow the cost of a 16 byte copy by several orders of magnitude.

[1] After much discussion last time around, I'm at least convinced that the kdbus people have reasons to like the idea of capturing metadata for each message. I still think the design is wrong even from a security standpoint, but right now I'm talking about performance. If you want the data plane to be fast, it should be separated from the control plane as much as possible, and this design is the opposite.

--Andy

#21 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Andy,

Quoted 7 lines · Andy Lutomirski
Quoted 2 lines · David Herrmann

A 16byte copy does not affect the performance of kdbus message transactions in any way that matters.

What are the performance goals of kdbus? How fast is it ever intended to be?

One of the design goals of kdbus is to speed up a typical D-Bus message turnaround. That is, to minimize the number of context switches it currently takes to get a message across the bus, and to avoid unnecessary extra payload copies.

Even though I'm sure there's still room for future improvement, the benchmark test we provided in the kernel self-tests shows that basic data transmission performance is roughly comparable to that of UDS for smaller payloads. For payloads of bigger sizes (>128kb), kdbus is actually faster due to its zero-copy mechanism.

Quoted 7 lines

The reason I ask is that, in the current design, kdbus collects "metadata" (credentials and other identifying information, collected in kdbus_meta_proc_collect) from the sender of every message *at send time*. [1] This is slow, and it will always be slow. The slowness of this operation will, in my personal system performance crystal ball, overshadow the cost of a 16 byte copy by several orders of magnitude.

That's certainly true, but that's not a contradiction to the performance argument. Please keep in mind that if a receiving peer does not request any metadata, the kernel doesn't collect and attach any. We know that gathering of some of the metadata comes at a price, which is why we split up the information is such fine-grained pieces.

Also note that if a receiving peer opts in for a certain piece of metadata, it should do that that for a good reason, because it needs that data to process a request. Letting kdbus do the work of providing such information is still a lot faster than having the receiving peer gather it itself, as that would involve more syscalls and more context switches (let alone the fact that doing so is inherently racy, as explained in earlier threads).

So, yes, collecting metadata can slow down message exchange, but after all, that's an optional feature that has to be used with sense. I'll add some words on that to the man-pages.

HTH,
Daniel

#22 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 37 lines · Daniel Mack

Hi Andy,

Quoted 7 lines · Andy Lutomirski
Quoted 2 lines · David Herrmann

A 16byte copy does not affect the performance of kdbus message transactions in any way that matters.

What are the performance goals of kdbus? How fast is it ever intended to be?

One of the design goals of kdbus is to speed up a typical D-Bus message turnaround. That is, to minimize the number of context switches it currently takes to get a message across the bus, and to avoid unnecessary extra payload copies.

Even though I'm sure there's still room for future improvement, the benchmark test we provided in the kernel self-tests shows that basic data transmission performance is roughly comparable to that of UDS for smaller payloads. For payloads of bigger sizes (>128kb), kdbus is actually faster due to its zero-copy mechanism.

Quoted 7 lines

The reason I ask is that, in the current design, kdbus collects "metadata" (credentials and other identifying information, collected in kdbus_meta_proc_collect) from the sender of every message *at send time*. [1] This is slow, and it will always be slow. The slowness of this operation will, in my personal system performance crystal ball, overshadow the cost of a 16 byte copy by several orders of magnitude.

That's certainly true, but that's not a contradiction to the performance argument. Please keep in mind that if a receiving peer does not request any metadata, the kernel doesn't collect and attach any. We know that gathering of some of the metadata comes at a price, which is why we split up the information is such fine-grained pieces.

Quoted 7 lines

Also note that if a receiving peer opts in for a certain piece of metadata, it should do that that for a good reason, because it needs that data to process a request. Letting kdbus do the work of providing such information is still a lot faster than having the receiving peer gather it itself, as that would involve more syscalls and more context switches (let alone the fact that doing so is inherently racy, as explained in earlier threads).

All this is true, but if you used connect-time metadata, this would be a non-issue.

Given that I see almost no advantage to send-time metadata, and I see three disadvantages (slower, inconsistent with the basic POSIX model, and inconsistent with existing user-space dbus), I still don't see why you designed it this way.

There's an added disadvantage of the current design: if a kdbus user is communicating with a traditional d-bus user using the proxy, then IIUC the credentials at the time of connection get used.

In summary, the current design is (a) unlike almost everything else that uses file descriptors, (b) much slower, (c) different from traditional d-bus, and (d) gives inconsistent behavior to new clients depending on what server they're connecting to.

--Andy

Quoted 9 lines

So, yes, collecting metadata can slow down message exchange, but after all, that's an optional feature that has to be used with sense. I'll add some words on that to the man-pages.

HTH,
Daniel

#23 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 10 lines · Andy Lutomirski
Quoted 7 lines · Daniel Mack

Also note that if a receiving peer opts in for a certain piece of metadata, it should do that that for a good reason, because it needs that data to process a request. Letting kdbus do the work of providing such information is still a lot faster than having the receiving peer gather it itself, as that would involve more syscalls and more context switches (let alone the fact that doing so is inherently racy, as explained in earlier threads).

Quoted 4 lines

Given that I see almost no advantage to send-time metadata, and I see three disadvantages (slower, inconsistent with the basic POSIX model, and inconsistent with existing user-space dbus), I still don't see why you designed it this way.

Because effective information about tasks may change over time, and D-Bus is a connection-less protocol that has no notion of peer-to-peer connections.

As we explained before, currently, D-Bus peers do collect the same information already if they need to have them, but they have to do deal with the inherit races in such cases. kdbus is closing the gap by optionally providing the same information along with each message, if requested.

Quoted 3 lines

There's an added disadvantage of the current design: if a kdbus user is communicating with a traditional d-bus user using the proxy, then IIUC the credentials at the time of connection get used.

That's not quite true any more. After our discussion in v2, we agreed on dropping this detail. If you're using the proxy, no metadata is attached to messages any more. Userspace has to gather this information in the traditional, racy way in such cases. You are right - metadata about the proxy task is of no interest here, and hence dropping the information altogether is the most consistent thing we can do.

But again - that metadata thing just an optional feature. People developing with the bare kernel-level API are free to ignore all that and just just kdbus as low-level protocol for reliable multicast. Note that in such cases, you would still be able to retrieve the connect-time metadata if that's needed.

Thanks,
Daniel

#24 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 21 lines · Daniel Mack
Quoted 10 lines · Andy Lutomirski
Quoted 7 lines · Daniel Mack

Also note that if a receiving peer opts in for a certain piece of metadata, it should do that that for a good reason, because it needs that data to process a request. Letting kdbus do the work of providing such information is still a lot faster than having the receiving peer gather it itself, as that would involve more syscalls and more context switches (let alone the fact that doing so is inherently racy, as explained in earlier threads).

Quoted 4 lines

Given that I see almost no advantage to send-time metadata, and I see three disadvantages (slower, inconsistent with the basic POSIX model, and inconsistent with existing user-space dbus), I still don't see why you designed it this way.

Because effective information about tasks may change over time, and D-Bus is a connection-less protocol that has no notion of peer-to-peer connections.

Quoted 5 lines

As we explained before, currently, D-Bus peers do collect the same information already if they need to have them, but they have to do deal with the inherit races in such cases. kdbus is closing the gap by optionally providing the same information along with each message, if requested.

In all these discussions, no one ever gave a decent example use case. If a process drops some privilege, it must close all fds it has that captured its old privilege. This has nothing to do with kdbus. With kdbus, you still need to close and reopen your kdbus fd, unless you've disabled that bit of metadata, so using send-time metadata hasn't bought you benefit that I can see.

I agree that the design seems to have improved to a state of being at least decent, but that doesn't mean that using send-time metadata is a good idea for systemd or for anything else.

Quoted 12 lines
Quoted 4 lines

There's an added disadvantage of the current design: if a kdbus user is communicating with a traditional d-bus user using the proxy, then IIUC the credentials at the time of connection get used.

That's not quite true any more. After our discussion in v2, we agreed on dropping this detail. If you're using the proxy, no metadata is attached to messages any more. Userspace has to gather this information in the traditional, racy way in such cases. You are right - metadata about the proxy task is of no interest here, and hence dropping the information altogether is the most consistent thing we can do.

Quoted 6 lines

But again - that metadata thing just an optional feature. People developing with the bare kernel-level API are free to ignore all that and just just kdbus as low-level protocol for reliable multicast. Note that in such cases, you would still be able to retrieve the connect-time metadata if that's needed.

It's an optional feature that will get used, non-optionally, thousands of times on each boot, apparently. Keep in mind that it's also a scalability problem because it takes locks. If it ever gets used thousands of times per CPU on a big thousand-core machine, it's going to suck, and you'll have backed yourself into a corner.

--Andy

#25 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Andy,

Quoted 11 lines · Andy Lutomirski
Quoted 5 lines · Daniel Mack

As we explained before, currently, D-Bus peers do collect the same information already if they need to have them, but they have to do deal with the inherit races in such cases. kdbus is closing the gap by optionally providing the same information along with each message, if requested.

In all these discussions, no one ever gave a decent example use case. If a process drops some privilege, it must close all fds it has that captured its old privilege. This has nothing to do with kdbus.

kdbus does not implement any new concept here but sticks to what SCM_CREDENTIALS does on SOL_SEQPACKET. An application can get a file-descriptor from socket() or socketpair() and freely pass it around between different tasks or threads, but messages will always have the credentials attached that are valid at *send* time. SO_PEERCREDS, however, still reports the connect-time credentials, and kdbus provides exactly the same semantics and both ways of retrieving information.

Quoted 2 lines

I agree that the design seems to have improved to a state of being at least decent,

One reason for that is your feedback. Thanks for that again!

Quoted 5 lines

It's an optional feature that will get used, non-optionally, thousands of times on each boot, apparently. Keep in mind that it's also a scalability problem because it takes locks. If it ever gets used thousands of times per CPU on a big thousand-core machine, it's going to suck, and you'll have backed yourself into a corner.

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Also, when metadata is collected, the code mostly takes temporary references on objects like PIDs, namespaces etc. Which operation would you consider particularly expensive?

Thanks again,
Daniel

#26 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 35 lines · Daniel Mack

Hi Andy,

Quoted 11 lines · Andy Lutomirski
Quoted 5 lines · Daniel Mack

As we explained before, currently, D-Bus peers do collect the same information already if they need to have them, but they have to do deal with the inherit races in such cases. kdbus is closing the gap by optionally providing the same information along with each message, if requested.

In all these discussions, no one ever gave a decent example use case. If a process drops some privilege, it must close all fds it has that captured its old privilege. This has nothing to do with kdbus.

kdbus does not implement any new concept here but sticks to what SCM_CREDENTIALS does on SOL_SEQPACKET. An application can get a file-descriptor from socket() or socketpair() and freely pass it around between different tasks or threads, but messages will always have the credentials attached that are valid at *send* time. SO_PEERCREDS, however, still reports the connect-time credentials, and kdbus provides exactly the same semantics and both ways of retrieving information.

Quoted 2 lines

I agree that the design seems to have improved to a state of being at least decent,

One reason for that is your feedback. Thanks for that again!

Quoted 5 lines

It's an optional feature that will get used, non-optionally, thousands of times on each boot, apparently. Keep in mind that it's also a scalability problem because it takes locks. If it ever gets used thousands of times per CPU on a big thousand-core machine, it's going to suck, and you'll have backed yourself into a corner.

Quoted 10 lines

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

Quoted 4 lines

Also, when metadata is collected, the code mostly takes temporary references on objects like PIDs, namespaces etc. Which operation would you consider particularly expensive?

The refcounting, copies of some of the data, and counting bytes and allocating space. The refcounting is the part that will scale particularly badly on many CPUs.

Do you have some simple benchmark code you can share? I'd like to play with it a bit.

--Andy

Quoted 5 lines

Thanks again,
Daniel

#27 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

Quoted 2 lines

Do you have some simple benchmark code you can share? I'd like to play with it a bit.

Sure, it's part of the self-test suite. Call it with "-t benchmark" to run the benchmark as isolated test with verbose output. The code for that lives in test-benchmark.c.

Thanks,
Daniel

#28 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 28 lines · Daniel Mack

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

Quoted 4 lines

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

I should have said it differently. ABI is the wrong term -- it's more of a protocol issue.

It looks like, with the current code, the kernel will provide (optional) send-time metadata, and the sd-bus library will use it. The result will be that the communication protocol between clients and udev, systemd, systemd-logind, g-s-d, etc, will likely involve send-time metadata. This may end up being a bottleneck.

Once this happens, changing the protocol will be very hard without introducing security bugs. If people start switching to connection-time metadata to gain performance, then they'll break both the communication protocol and the expectations of client code. (In fact, it'll break twice, sort of, since I think that the current protocols are connect-time.)

To me, this seems like a down-side of using send-time metadata, albeit possibly not a huge downside at least in the near term. I don't see a corresponding benefit, though.

Quoted 8 lines
Quoted 3 lines

Do you have some simple benchmark code you can share? I'd like to play with it a bit.

Sure, it's part of the self-test suite. Call it with "-t benchmark" to run the benchmark as isolated test with verbose output. The code for that lives in test-benchmark.c.

I'll try to play with this soon. Thanks.

--Andy

Quoted 5 lines

Thanks,
Daniel

Signature · 2 lines
Andy Lutomirski
AMA Capital Management, LLC
#29 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 34 lines · Andy Lutomirski
Quoted 28 lines · Daniel Mack

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

Quoted 4 lines

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

Quoted 8 lines

I should have said it differently. ABI is the wrong term -- it's more of a protocol issue.

It looks like, with the current code, the kernel will provide (optional) send-time metadata, and the sd-bus library will use it. The result will be that the communication protocol between clients and udev, systemd, systemd-logind, g-s-d, etc, will likely involve send-time metadata. This may end up being a bottleneck.

A quick note on a couple of things I have seen in this conversation.

- The reason for kdbus is performance.

- pipes rather than unix domain sockets are likely the standard to meet. If you can't equal unix domain sockets for simple things you are likely leaving a lot of stops in. Last I looked pipes in general were notiably faster than unix domain sockets.

The performance numbers I saw posted up-thread were horrible. I have seen faster numbers across a network of machines. If your ping-pong latency isn't measured in nano-seconds you are probably doing something wrong.

- syscalls remove overhead. So since performance is kdbus's reason for existence let's remove some ridiculous stops, and get a fast path into the kernel.

- send-time metadata is a performance nightmare. SO_PASSCRED is hard to implement in a fast performant way, especially when namespaces get involved. Over the long term if you use send-time metadata you will grow the kind of compatibility hacks that the user namespace and the pid namespace have on SO_PASSCRED and things will slow down.

A similar effect that is more performant in general is to enforce that the sender has the expected attributes.

Quoted 10 lines

Once this happens, changing the protocol will be very hard without introducing security bugs. If people start switching to connection-time metadata to gain performance, then they'll break both the communication protocol and the expectations of client code. (In fact, it'll break twice, sort of, since I think that the current protocols are connect-time.)

To me, this seems like a down-side of using send-time metadata, albeit possibly not a huge downside at least in the near term. I don't see a corresponding benefit, though.

I think send-time metadata verification is less bad in this regard.

Eric

#30 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 45 lines · Eric W. Biederman
Quoted 34 lines · Andy Lutomirski
Quoted 28 lines · Daniel Mack

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

Quoted 4 lines

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

Quoted 8 lines

I should have said it differently. ABI is the wrong term -- it's more of a protocol issue.

It looks like, with the current code, the kernel will provide (optional) send-time metadata, and the sd-bus library will use it. The result will be that the communication protocol between clients and udev, systemd, systemd-logind, g-s-d, etc, will likely involve send-time metadata. This may end up being a bottleneck.

Quoted 3 lines

A quick note on a couple of things I have seen in this conversation.

- The reason for kdbus is performance.

No, that's not the only reason for kdbus, don't focus only on this. I set out a long list of things for why we created kdbus, speed was only one of the things. Security is also one, and the ability to gather these attributes in an atomic and secure way is very important as userspace wants this.

Quoted 9 lines

- pipes rather than unix domain sockets are likely the standard to meet. If you can't equal unix domain sockets for simple things you are likely leaving a lot of stops in. Last I looked pipes in general were notiably faster than unix domain sockets.

The performance numbers I saw posted up-thread were horrible. I have seen faster numbers across a network of machines. If your ping-pong latency isn't measured in nano-seconds you are probably doing something wrong.

It all depends on what you are passing on that "ping-pong", a real D-Bus connection has real data and meta data that has to be sent. Trying to make a fake benchmark number isn't going to show anything.

Quoted 2 lines

- syscalls remove overhead. So since performance is kdbus's reason for existence let's remove some ridiculous stops, and get a fast path into the kernel.

Again, not the only reason, see my first post in this thread for details.

thanks,

greg k-h

#31 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 48 lines · Greg Kroah-Hartman
Quoted 47 lines · Eric W. Biederman
Quoted 34 lines · Andy Lutomirski
Quoted 28 lines · Daniel Mack

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

Quoted 4 lines

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

Quoted 8 lines

I should have said it differently. ABI is the wrong term -- it's more of a protocol issue.

It looks like, with the current code, the kernel will provide (optional) send-time metadata, and the sd-bus library will use it. The result will be that the communication protocol between clients and udev, systemd, systemd-logind, g-s-d, etc, will likely involve send-time metadata. This may end up being a bottleneck.

A quick note on a couple of things I have seen in this conversation.

Quoted 7 lines
Quoted 1 line

- The reason for kdbus is performance.

No, that's not the only reason for kdbus, don't focus only on this. I set out a long list of things for why we created kdbus, speed was only one of the things. Security is also one, and the ability to gather these attributes in an atomic and secure way is very important as userspace wants this.

Perhaps I should have said the predominant reason. Certainly that seems to be most of what I have seen talked about.

Regardless looking at the performance in the design and removing any substantial obstacle to making things go fast.

Further. I had this conversation earlier in an earlier round of the review and I was told that in fact existing dbus applications do not
want or need these attributes. I think I heard journald wants them for
pretty printing things.

If security is your concern I really think per message attributes collected and sent when a message is sent is a bad idea. It has been a nasty anti-pattern in the kernel code. Lots and lots of meta-data copyed from a task and sent to someone else has significant performance, maintenance, and security impacts.

Code written in that pattern is complex and hard to analyze, and hard to think about. Consider debugging why a message does not get the expected treatment from your suid application because someone changed the euid over that particular call and had not thought about it's consequences. Frankly I have been there and done that and it is a mess.

So no I do not think breaking encapsulation and having weird side effects affecting your new primitive will have any security benefits
whatsover. It will just result in brittle complex code.

If you want to avoid the races causing sends through a file descriptor to fail that don't have the expected attributes (my constructive suggestion earlier) is a very different thing from a performance and mainteance standpoint. That does not increase the code complexity nearly as much in the implementation or in use, and unexpected failures happen right away.

Quoted 5 lines
Quoted 5 lines

- pipes rather than unix domain sockets are likely the standard to meet. If you can't equal unix domain sockets for simple things you are likely leaving a lot of stops in. Last I looked pipes in general were notiably faster than unix domain sockets.

Quoted 8 lines
Quoted 4 lines

The performance numbers I saw posted up-thread were horrible. I have seen faster numbers across a network of machines. If your ping-pong latency isn't measured in nano-seconds you are probably doing something wrong.

It all depends on what you are passing on that "ping-pong", a real D-Bus connection has real data and meta data that has to be sent. Trying to make a fake benchmark number isn't going to show anything.

All that I was intending to convey is that the numbers I have seen have been orders of magnitude slower than I would expect. And 10x to 100x slower than the code should be is a reason to ask why.

In my experience being efficient with small messages are important because (a) they are the hardest to make go fast (b) they are surprising common. Remote X application start-up times are very slow because of these.

People have a distressing habit of writing applications that send a small message and synchronously waits for it. Over time these small ipc calls build up and you are limited by how fast they will go.

Quoted 5 lines
Quoted 2 lines

- syscalls remove overhead. So since performance is kdbus's reason for existence let's remove some ridiculous stops, and get a fast path into the kernel.

Again, not the only reason, see my first post in this thread for details.

But performance is important, and performance is a good reason to use system calls.

Security is another reason to have real system calls, as there is less going on (compared to an ioctl multiplexer) so the code is easier to audit.

Eric

#32 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Daniel Mack
Quoted 33 lines · Daniel Mack

Hi Andy,

Quoted 13 lines · Andy Lutomirski
Quoted 10 lines · Daniel Mack

That's right, but again - if an application wants to gather this kind of information about tasks it interacts with, it can do so today by looking at /proc or similar sources. Desktop machines do exactly that already, and the kernel code executed in such cases very much resembles that in metadata.c, and is certainly not cheaper. kdbus just makes such information more accessible when requested. Which information is collected is defined by bit-masks on both the sender and the receiver connection, and most applications will effectively only use a very limited set by default if they go through one of the more high-level libraries.

Quoted 2 lines

I should rephrase a bit. Kdbus doesn't require use of send-time metadata. It does, however, strongly encourage it, and it sounds like

On the kernel level, kdbus just *offers* that, just like sockets offer SO_PASSCRED. On the userland level, kdbus helps applications get that information race-free, easier and faster than they would otherwise.

Quoted 4 lines

systemd and other major users will use send-time metadata. Once that happens, it's ABI (even if it's purely in userspace), and changing it is asking for security holes to pop up. So you'll be mostly stuck with it.

We know we can't break the ABI. At most, we could deprecate item types and introduce new ones, but we want to avoid that by all means of course. However, I fail to see how that is related to send time metadata, or even to kdbus in general, as all ABIs have to be kept stable.

Quoted 6 lines
Quoted 2 lines

Do you have some simple benchmark code you can share? I'd like to play with it a bit.

Sure, it's part of the self-test suite. Call it with "-t benchmark" to run the benchmark as isolated test with verbose output. The code for that lives in test-benchmark.c.

I see "latencies" of around 20 microseconds with lockdep and context tracking off. For example:

stats (UNIX): 226730 packets processed, latency (nsecs) min/max/avg
3845 // 34828 // 4069
stats (KDBUS): 37103 packets processed, latency (nsecs) min/max/avg
19123 // 99660 // 20696

This is IMO not very good. With memfds off:

stats (UNIX): 226061 packets processed, latency (nsecs) min/max/avg
3885 // 32019 // 4079
stats (KDBUS): 83284 packets processed, latency (nsecs) min/max/avg
10525 // 42578 // 10932

With memfds off and the payload set to 8 bytes:

stats (KDBUS): 77669 packets processed, latency (nsecs) min/max/avg
9963 // 64325 // 11645
stats (UNIX): 253695 packets processed, latency (nsecs) min/max/avg
2986 // 56094 // 3565

Am I missing something here? This is slow enough that a lightweight userspace dbus daemon should be able to outperform kdbus, or at least come very close.

It would be kind of nice to know how long just the send call takes, too.

--Andy

#33 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi

Quoted 2 lines · Andy Lutomirski

I see "latencies" of around 20 microseconds with lockdep and context tracking off. For example:

Without metadata nor memfd transmission, I get 2.5us for kdbus, 1.5us for UDS (8k payload). With 8-byte payloads, I get 2.2us and 1.2us. I suspect you enabled metadata transmission, which I think is not a fair comparison.

A few notes on that:

* kdbus is a bus layer. We don't intend to replace UDS, but improve dbus. Comparing roundtrip times with UDS is tempting, but in no way fair. To the very least, a bus layer has to perform peer-lookup, which UDS does not have to do. Imo, 2.5us vs. 1.5us is already pretty nice. Compare this to ~77us for dbus1 without marshaling.

* We have not optimized kdbus code-paths for speed, yet. Our main concerns are algorithmic challenges, and we believe they've been improved considerably with kdbus. I have constantly measured kdbus performance with 'perf' and flame-graphs, and there're a lot of possible optimizations (especially on locking). However, I think this can be done afterwards just fine. Neither API nor ioctl overhead has shown up in my measurements. If anyone has counter evidence, please let us know. But I'm a bit reluctant to change our API solely based on performance guesses.

* We're about 50% slower than UDS on 1-byte transmissions. With 32k we're on-par. How can a lightweight user-space daemon even get close to that?

* Broadcast performance is a completely different story. SEND gets around 30% faster compared to kdbus unicasts (as most of the control-paths are only taken once per message, instead of once per destination).

* test-benchmark.c does performance tests in a single process. If the bus-layer is implemented in user-space, you need to account for context-switches and task wakeups. My UDS and pipe round-trip latency tests got around 3x slower if done cross processes (3.7us instead of 1.2us). With a user-space daemon, those slow-downs are taken two times more often for each roundtrip.

* Process time is accounted on the sender, instead of a shared process (dbus-daemon). Broadcasts will thus no longer consume time-slices of dbus-daemon, but only the sender's.

With kdbus, we implement a bus-layer. This is our only target! If your target environment does not require a bus, then don't use kdbus. We don't intend to replace UDS. On a bus-layer, we need peer-discovery, policy-handling, destination-lookups, broadcast-management and more. Pipes/UDS do not provide any of this.
I cannot see how any other existing bus-implementation comes even close to kdbus, performance-wise. If someone does, please let us know!

Thanks
David

#34 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 11 lines · David Herrmann

Hi

Quoted 2 lines · Andy Lutomirski

I see "latencies" of around 20 microseconds with lockdep and context tracking off. For example:

Without metadata nor memfd transmission, I get 2.5us for kdbus, 1.5us for UDS (8k payload). With 8-byte payloads, I get 2.2us and 1.2us. I suspect you enabled metadata transmission, which I think is not a fair comparison.

I tried to disable metadata. I may have failed.

Regardless, if metadata is very slow, then that's more reason not to use it on send. And if you shouldn't use it, then maybe the kernel shouldn't provide it.

I assumed there was a context switch in there. I can try to test differently. If UDS is twice as fast *with* a contest switch, then a userspace solution should be faster.

Also, UDS can use memfds, too.

Quoted 8 lines

A few notes on that:

* kdbus is a bus layer. We don't intend to replace UDS, but improve dbus. Comparing roundtrip times with UDS is tempting, but in no way fair. To the very least, a bus layer has to perform peer-lookup, which UDS does not have to do. Imo, 2.5us vs. 1.5us is already pretty nice. Compare this to ~77us for dbus1 without marshaling.

This makes me wonder what dbus1 is doing wrong.

Quoted 10 lines

* We have not optimized kdbus code-paths for speed, yet. Our main concerns are algorithmic challenges, and we believe they've been improved considerably with kdbus. I have constantly measured kdbus performance with 'perf' and flame-graphs, and there're a lot of possible optimizations (especially on locking). However, I think this can be done afterwards just fine. Neither API nor ioctl overhead has shown up in my measurements. If anyone has counter evidence, please let us know. But I'm a bit reluctant to change our API solely based on performance guesses.

But removal of send-time metadata can't be done after the fact.

--Andy

#35 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to David Herrmann

Hi David,

Quoted 41 lines · David Herrmann

Hi

Quoted 29 lines · Michael Kerrisk (man-pages)

Hello Greg,

Quoted 12 lines · Greg Kroah-Hartman
Quoted 10 lines · Austin S Hemmelgarn

While I agree that there should be a way for userspace to get the list of supported operations, userspace apps will only actually care about that once, when they begin talking to kdbus, because (ignoring the live kernel patching that people have been working on recently) the list of supported operations isn't going to change while the system is running. While a u64 copy has relatively low overhead, it does have overhead, and that is very significant when you consider part of the reason some people want kdbus is for the performance gain. Especially for those automotive applications that have been mentioned which fire off thousands of messages during start-up, every little bit of performance is significant.

Quoted 3 lines

A single u64 in a structure is not going to be measurable at all, processors just copy memory too fast these days for 4 extra bytes to be noticable.

It depends on the definition of measurable, I suppose, but this statement appears incorrect to me. In some cases (e.g., kdbus_msg_info) we're talking about *two* u64 fields (kernel_gs, kernel_msg_flags) being used to pass back sets of valid flags. That's 16 bytes, and it definitely makes a difference. Simply running a loop that does a naive memcpy() in a tight user-space loop (code below), I see the following for the execution of 1e9 loops:

Including the two extra u64 fields: 3.2 sec
Without the two extra u64 fields: 2.6 sec

Quoted 7 lines

On the same box, doing 1e9 calls to getppid() (i.e., pretty much the simplest syscall, giving us a rough measure of the context switch) takes 68 seconds. In other words, the cost of copying those 16 bytes is about 1% of the base context switch/syscall cost. I assume the costs of copying those 16 bytes across the kernel-user-space boundary would not be cheaper, but have not tested that. If my assumption is correct, then 1% seems a significant figure to me in an API whose raison d'être is speed.

Quoted 4 lines

I have no idea how this is related to any kdbus ioctl?

A 16byte copy does not affect the performance of kdbus message transactions in any way that matters.

I'm not sure if it's related/significant or not, since I'm ignorant of the performance figures for kdbus. I just got curious when Greg stated that the cost of copying would not be noticeable. (I got curious also about my assumption, and did an experiment with a dummy system call that throws bytes across the fence into user space. The cost of an extra 16 bytes (56 to 72 bytes) is about 3% of the base syscall/context switch cost.)

Quoted 12 lines
Quoted 11 lines
Quoted 3 lines

So let's make this as easy as possible for userspace, making it simpler logic there, which is much more important than saving theoretical time in the kernel.

But this also missed the other part of the point. Copying these fields on every operation, when in fact they are only needed once, clutters the API, in my opinion. Good APIs are as simple as they can be to do their job. Redundancy is an enemy of simplicity. Simplest would have been a one time API that returns a structure containing all of the supported flags across the API. Alternatively, the traditional EINVAL approach is well understood, and suffices.

Quoted 6 lines

We're going to drop "kernel_flags" in favor of a new KDBUS_FLAG_NEGOTIATE flag which asks the kernel to do feature negotiation for this ioctl and return the supported flags/items inline (overwriting the passed data). The ioctl will not be executed and will not affect the state of the FD.
I hope this keeps the API simple.

Not sure I quite understand the details from your description, but I assume the it'll end up in the doc, and I'll try to take a look later.

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#36 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to David Herrmann

Hi David,

Quoted 24 lines · David Herrmann

Hi Michael

Quoted 11 lines · Michael Kerrisk (man-pages)
Quoted 9 lines · Daniel Mack
Quoted 5 lines
Quoted 2 lines

Also, the context the kdbus commands operate on originate from a mountable special-purpose file system.

It's not clear to me how this point implies any particular API design choice.

It emphasizes the fact that our ioctl API can only be used with the nodes exposed by kdbusfs, and vice versa. I think operations on driver-specific files do not justify a new 'generic' syscall API.

Quoted 8 lines

I see your (repeated) use of words like "driver" as just a distraction, I'm sorry. "Driver-specific files" is an implementation detail. The point is that kdbus provides a complex, general-purpose feature for all of userland. It is core infrastructure that will be used by key pieces of the plumbing layer, and likely by many other applications as well. *Please* stop suggesting that it is not core infrastructure: kdbus has the potential to be a great IPC that will be very useful to many, many user-space developers.

Quoted 4 lines

We called it an 'ipc driver' so far. It is in no way meant as distraction. Feel free to call it 'core infrastructure'. I think we can agree that we want it to be generically useful, like other ipc mechanisms, including UDS and netlink.

Yes.

Quoted 10 lines
Quoted 2 lines

(By the way, we have precedents for device/filesystem-specific system calls. Even a recent one, in memfd_create().)

memfd_create() is in no way file-system specific. Internally, it uses shmem, but that's an implementation detail. The API does not expose this in any way. If you were referring to sealing, it's implemented as fcntl(), not as a separate syscall. Furthermore, sealing is only limited to shmem as it's the only volatile storage. It's not an API restriction. Other volatile file-systems are free to implement sealing.

My bad. I mispoke there.

Quoted 10 lines
Quoted 7 lines
Quoted 4 lines
Quoted 1 line

ioctl() is a get-out-of-jail free card when it comes to API design.

And how are syscalls different in that regard when they would both transport the same data structures?

My general impression is that when it comes to system calls, there's usually a lot more up front thought about API design.

This is no technical reason why to use syscalls over ioctls. Imho, it's rather a reason to improve the kernel's ioctl-review process.

Agreed it's not a technical reason. But the distinction I make does capture how things usually work.

[...]

Quoted 17 lines
Quoted 9 lines
Quoted 9 lines
Quoted 4 lines

Rather
than thinking carefully and long about a set of coherent, stable APIs that provide some degree of type-safety to user-space, one just adds/changes/removes an ioctl.

Adding another ioctl in the future for cases we didn't think about earlier would of course be considered a workaround; and even though such things happen all the time, it's certainly something we'd like to avoid.

Quoted 7 lines
Quoted 4 lines

However, we would also need to add another syscall in such cases, which is even worse IMO. So that's really not an argument against ioctls after all. What fundamental difference between a raw syscall and a ioctl, especially with regards to type safety, is there which would help us here?

Type safety helps user-space application developers. System calls have it, ioctl() does not.

Quoted 7 lines

This is simply not true. There is no type-safety in:
syscall(__NR_xyz, some, random, arguments)

The only way a syscall gets 'type-safe', is to provide a wrapper function. Same applies to ioctls. But people tend to not do that for ioctls, which is, again, not a technical argument against ioctls. It's a matter of psychology, though.

Yes, I see I wasn't quite clear enough. I should have said:

Type safety helps user-space application developers. *As typically provided to user-space via libc wrappers*, system calls have it, ioctl() does not.

And system call wrappers are generally provided pretty much automatically by libcs (at least, mostly, there's some to-ing and fro-ing about this in glibc-land these days as you are aware from the memfd_create() story;
http://thread.gmane.org/gmane.comp.lib.glibc.alpha/45884/focus=46937).

So, in practice user-space programmers typically automatically get type safety with system calls, but not with ioctl().

Quoted 26 lines

I still don't see a technical reason to use syscalls. API proposals welcome! We're now working on a small kdbus helper library, which provides type-safe ioctl wrappers, item-iterators and documented examples. But, like syscalls, nobody is forced to use the wrappers. The API design is not affected by this.

Quoted 20 lines
Quoted 13 lines
Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

Quoted 3 lines

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

My suspicion is that not nearly enough thinking has yet been done about the design of the API. That's based on these observations:

Quoted 8 lines
Quoted 1 line

* Documentation that is, considering the size of the API, *way* too thin.

Ok, working on that.

Quoted 1 line

* Some parts of the API not documented at all (various kdbus_item blobs)

All public structures have documentation in kdbus.h. It may need improvements, though.

Again -- that's very thin--one liners aand sentence fragments for the most part. (Not that I think that needs to be fixed, just that that doesn't fit with my definition of "documented", which should be something like what I've requested for kdbus.txt.)

Quoted 9 lines
Quoted 1 line

* ABI changes happening even quite recently

Please elaborate why 'recent ABI-changes' are a sign of a premature API.

I seriously doubt any API can be called 'perfect'. On the contrary, I believe that all APIs could be improved continuously. The fact that we, at one point, settle on an API is an admission of backwards-compatibility. I in no way think it's a sign of 'perfection'.

I agree that no API is perfect. But some emerge from the starting gate in much better state than others. kdbus will likely be an important API, and it's important that it's well designed one at the outset.

Quoted 4 lines

With kdbus our plan is to give API-guarantees starting with upstream inclusion. We know, that our API will not be perfect, none is. But we will try hard to fix anything that comes up, as long as we can. And this effort will manifest in ABI-breaks.

Fair enough. My concern is that upstream inclusion is being rushed before the API design can be well assessed.

Quoted 6 lines
Quoted 2 lines

* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

If we only returned EINVAL on invalid arguments, user-space had to probe for each flag to see whether it's supported. By returning the set of supported flags, user-space can cache those and _reliably_ know

(Not sure why you emphasize "reliably" here...)

Quoted 5 lines

which flags are supported.
We decided the overhead of a single u64 copy on each ioctl is preferred over a separate syscall/ioctl to query kernel flags. If you disagree, please elaborate (preferably with a suggestion how to do it better).

Well that's a quite unconventional design choice. Determining the set of supported flags in an API is a one-time operation. The natural--and I would say, *obviously* better--approach to this would be either the traditional EINVAL approach or an API that is called once to retrieve the set of supported flags. Instead, kdbus clutters the APIs with a mostly unneeded extra piece of information on *every* call, and fractionally increases the run time, for no good reason.

Now, you might say that my suggested alternatives are not obviously better. My response is that, at the very least, in the documentation I'd expect to see this unconventional approach clearly highlighted and accompanied with a sound reason for choosing it. (Note: so far I still haven't actually seen a sound reason...)

Quoted 6 lines
Quoted 2 lines

The above is just after a day of looking hard at kdbus.txt. I strongly suspect I'd find a lot of other issues if I spent more time on kdbus.

If you find the time, please do! Any hints how a specific part of the API could be done better, is highly appreciated. A lot of the more or less recent changes were done due to reviews from glib developers.

Could you point me at those reviews (mailing list archives?)?

So, I'm thinking about things such as the following:

* The odd choice of ioctl() as the API mechanism for what should become a key user-space API. (BTW, which other widely used IPC API ever took the approach of ioctl() as the mechanism?)

* Weak justifications for unconventional API design choices such as the 'kernel_flags' above.

* Thin documentation that doesn't provide nearly enough detail, has no worked examples of the use of the APIs (when it should contain a multitude of such examples), and has no rationale for the API design choices [1].

* An API design that consists of 16 ioctl() requests and 20+ structures exchanged between user and kernel space being called "simple". (Clearly it is not.)

Given a list of points like that, I worry that not nearly enough thought has been put into design of the API, and certainly would be very concerned to think that it might be merged into mainline in the near future.

At this point, I think the onus is on the kdbus developers to provide strong evidence that they have a good API design, one that will well serve the needs of thousands of user-space programmers for the next few decades. Such evidence would include at least:

* Detailed documentation that fully described all facets of the API
* A number of working, well documented example programs that start (very) simple, and ramp up to demonstrate more complex pieces of the API.
* Documented rationale for API design choices.

To date, much of that sort of evidence is lacking, and I worry that the job of proper API design will be left to someone else, someone who devises a user-space library that provides a suitable abstraction on top of the current ioctl() API (but may be forced to make design compromises because of design failings in the underlying kernel API).

Quoted 1 line

More help is always welcome!

That's what I'm trying to do at the moment...

Cheers,

Michael

[1] Elsewhere in this thread, you've said that "with bus-proxy and systemd we have two huge users of kdbus that put a lot of pressure on API design." I would have expected that the results of that pressure should be captured in documentation of the rationale for the API design. I haven't found any of that, so far.

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#37 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Michael Kerrisk (man-pages)
Quoted 20 lines · Michael Kerrisk (man-pages)
Quoted 13 lines
Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

Quoted 3 lines

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

My suspicion is that not nearly enough thinking has yet been done about the design of the API. That's based on these observations:

Quoted 8 lines

* Documentation that is, considering the size of the API, *way* too thin.
* Some parts of the API not documented at all (various kdbus_item blobs)
* ABI changes happening even quite recently
* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

The above is just after a day of looking hard at kdbus.txt. I strongly suspect I'd find a lot of other issues if I spent more time on kdbus.

"not enough thinking"?

We started working on kdbus 2 years ago this FOSDEM (in a few weeks.) Before that we have been thinking about this for many years, learning from the previous attempts to get this type of feature merged into the kernel, talking with users about what they need for this, and soliciting kernel developer's opinions on what type of API would be best for this type of feature.

Since then we have done nothing but constantly revise the API. My first mock ups were way too simple, and in discussing things with people much more knowledgeable about D-Bus, they pointed out the problems, and we iterated. And iterated. And iterated some more. We have worked with just about every userspace libdbus developer group, including QtDbus developers as well as glib developers. Now not all of them agreed with some of our decisions in the implementation, which is fair enough, you can't please everyone, but they _all_ agree that what we have now is the proper way to implement this type of functionality and have reviewed the features as being correct and compatible with their needs and users.

Those discussions have happened in emails, presentations, meetings, and hackfests pretty much continuously for the past 2 years all around the world.

We have stress-tested the api with both unit tests (which are included here in the patch set) as well as a real-world implementation (sd-bus in the systemd source repo.) That real-world implementation successfully has been booting many of our daily machines for many months now.

Yes, the documentation can always be better, but please don't confuse the lack of understanding how D-Bus works and its model with the lack of understanding this kdbus implementation, the two are not comparable. For some good primers on what D-Bus is, and the terminology it expects see:
http://dbus.freedesktop.org/doc/dbus-tutorial.html
and also:
http://dbus.freedesktop.org/doc/dbus-faq.html#other-ipc

We are not going to put a basic "here is what D-Bus is and how to use it" into the kernel tree, that is totally outside the scope here.

I suggest reading the tutorial above, and then going back and reading the kdbus documentation provided. If you think we are lacking stuff on the kdbus side, we will be glad to flush out any needed areas.

Also, Daniel has said he will work on a basic userspace "example" library to show how to use this api, which might make the api a bit easier to understand.

However, I personally don't think this "example code" is necessary at all. We don't ask for this type of "simple examples" from other new kernel apis we create and add to the kernel all the time. We require there to be a user of the api, but not one that is so well documented that others can write a from-scratch raw userspace replacement. Specific examples of this are my previously mentioned ioctl users (btrfs, mei, mic, openvlan, etc.), and the grand-daddy of all horrid apis, DRM.

Users aren't going to be writing their own "raw kdbus" libraries. Or if they are, they are going to start with one of the existing implementations we have (the test examples and sd-bus, and I think there is a native Go implementation somewhere as well.) Users are going to be using those libraries to write their code, and to be honest, the user api for sd-bus is a delight to use compared to the "old style" libdbus interface as we have the benefit of 10 years of experience working with D-Bus apis in the wild now to learn from past mistakes.

Back to the API. We have taken review comments on the previous postings of the code and reworked the API, moving it from a character device to be a filesystem, which ended up making things a lot easier in the end, a good example of a review process that is working. Those changes are a sign that our development review process works. People pointed out problems in our character api that we hadn't thought about from the kernel implementation side. And so we changed them and the code is better and more robust because of it, a success story for our review process.

Personally, I was the one that started down the character device node path, so blame that design decision on me, not the other developers here. And I was wrong with that, but moving from character to a filesystem wasn't a huge change, the structures and interactions all remained almost identical, as the logic behind the API is, in my opinion, correct for the problem it is addressing.

The 37 different developers who have contributed to this code base are quite talented and skilled and experienced in user and kernel apis, having implemented many apis of their own that users rely on every day.

Yes, we all make design mistakes, and you might not agree with some of them, that's fine. But it is flat out rude to say that we have not been thinking about this, when I would guess that this is one of the largest (in time and contributions) kernel development feature to be worked on in the past few years.

And yes, I'm being very defensive, as I take this very seriously, so please, don't so lightly dismiss us as not knowing what we are doing, as frankly, we do.

Thanks for making it this far, I'll go back to technical discussions of the API now, as that's what we should be doing, not casting aspirations as to the aptitude of the people involved.

thanks,

greg k-h

#38 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Greg,

First of all, I seem to have offended you. That was not my intention. It's certainly not my intent to disparage you or your work (or for that matter, the other kdbus developers). Insofar as any of the wordings I've used suggested otherwise, I do apologize.

I'll comment on various points below, keeping it as technical as I can. Then I have a couple of general questions at the end with the goal of ensuring that my comments are not coming from a broken world view.

Quoted 50 lines · Greg Kroah-Hartman
Quoted 20 lines · Michael Kerrisk (man-pages)
Quoted 13 lines
Quoted 6 lines

And that process seems to be frequent and ongoing even now. (And it's to your great credit that the API/ABI breaks are clearly and honestly marked in the kdbus.h changelog.) All of this lightens the burden of API design for kernel developers, but I'm concerned that the long-term pain for user-space developers who use an API which (in my estimation) may come to be widely used will be enormous.

Yes, we've jointly reviewed the API details again until just recently to unify structs and enums etc, and added fields to make the ioctls structs more versatile for possible future additions. By that, we effectively broke the ABI, but we did that because we know we can't do such things again in the future.

Quoted 3 lines

But again - I don't see how this would be different when using syscalls rather than ioctls to transport information between the driver and userspace. Could you elaborate?

My suspicion is that not nearly enough thinking has yet been done about the design of the API. That's based on these observations:

Quoted 8 lines

* Documentation that is, considering the size of the API, *way* too thin.
* Some parts of the API not documented at all (various kdbus_item blobs)
* ABI changes happening even quite recently
* API oddities such as the 'kernel_flags' fields. Why do I need to be told what flags the kernel supports on *every* operation?

The above is just after a day of looking hard at kdbus.txt. I strongly suspect I'd find a lot of other issues if I spent more time on kdbus.

"not enough thinking"?

We started working on kdbus 2 years ago this FOSDEM (in a few weeks.) Before that we have been thinking about this for many years, learning from the previous attempts to get this type of feature merged into the kernel, talking with users about what they need for this, and soliciting kernel developer's opinions on what type of API would be best for this type of feature.

Since then we have done nothing but constantly revise the API. My first mock ups were way too simple, and in discussing things with people much more knowledgeable about D-Bus, they pointed out the problems, and we iterated. And iterated. And iterated some more. We have worked with just about every userspace libdbus developer group, including QtDbus developers as well as glib developers. Now not all of them agreed with some of our decisions in the implementation, which is fair enough, you can't please everyone, but they _all_ agree that what we have now is the proper way to implement this type of functionality and have reviewed the features as being correct and compatible with their needs and users.

Quoted 8 lines

Those discussions have happened in emails, presentations, meetings, and hackfests pretty much continuously for the past 2 years all around the world.

We have stress-tested the api with both unit tests (which are included here in the patch set) as well as a real-world implementation (sd-bus in the systemd source repo.) That real-world implementation successfully has been booting many of our daily machines for many months now.

Notwithstanding that I don't see how a unit test stress tests an API *design*, I've no reason to doubt that kdbus works. But that's not the point of my concern. I worry how usable this API is going to be for the world at large.

Quoted 11 lines

Yes, the documentation can always be better, but please don't confuse the lack of understanding how D-Bus works and its model with the lack of understanding this kdbus implementation, the two are not comparable. For some good primers on what D-Bus is, and the terminology it expects see:
http://dbus.freedesktop.org/doc/dbus-tutorial.html
and also:
http://dbus.freedesktop.org/doc/dbus-faq.html#other-ipc

We are not going to put a basic "here is what D-Bus is and how to use it" into the kernel tree, that is totally outside the scope here.

I didn't expect that you should do that. But it does touch on a general question that I'll leave to the end of this mail.

Quoted 8 lines

I suggest reading the tutorial above, and then going back and reading the kdbus documentation provided. If you think we are lacking stuff on the kdbus side, we will be glad to flush out any needed areas.

Also, Daniel has said he will work on a basic userspace "example" library to show how to use this api, which might make the api a bit easier to understand.

Quoted 5 lines

However, I personally don't think this "example code" is necessary at all. We don't ask for this type of "simple examples" from other new
kernel apis we create and add to the kernel all the time. We require
there to be a user of the api, but not one that is so well documented that others can write a from-scratch raw userspace replacement.

What you've just summarized there is how low a bar we've historically set in API design. Thus, the API is littered with (for example) dozens of system calls that were insufficiently well thought out in their design, and have subsequently been superseded by replacements that fixed the design mistakes. One of the cause of that problems is the targeting of "*a* user of the API"--general purpose APIs need to be considered from the point of view of multiple potentially different use cases. And I'm certainly not talking about being able to reimplement the API, But, the API is a contract, and it needs to be well understood by its creators and consumers in order that they can assess and use that API. Extensive Documentation generally is the best way to do that.

And, anyway, I had understood that there was a rough consensus that we do want to see more tests/examples and documentation happening in the future. Certainly, the number kernel developers who are taking a shot at writing man pages these days is refreshing. (We are 7/7 for man-page documented system calls in the 3.17-3.19 frame. That's a trend I've done my best to encourage, and hope to see continue in the future.) And now we have kselftest, in part thanks to your good efforts.

Quoted 3 lines

Specific examples of this are my previously mentioned ioctl users (btrfs, mei, mic, openvlan, etc.), and the grand-daddy of all horrid apis, DRM.

You've made this comparison a number of times, but I think it misses a crucial point. Those examples are all(?) domain-specific APIs with relatively few users in terms of user-space applications, whereas, IIUC, kdbus is intended to be an IPC mechanism that can be employed by user-space applications in a general-purpose fashion, and upon which potentially a multitude of different applications might be built. That's why I think the decision to use an ioctl()-based interface needs to be considered from a (very) skeptical point of view: no other general-purpose IPC mechanism employs such an approach. (Again, see one of my general questions at the end of this mail.)

Quoted 26 lines

Users aren't going to be writing their own "raw kdbus" libraries. Or if they are, they are going to start with one of the existing implementations we have (the test examples and sd-bus, and I think there is a native Go implementation somewhere as well.) Users are going to be using those libraries to write their code, and to be honest, the user api for sd-bus is a delight to use compared to the "old style" libdbus interface as we have the benefit of 10 years of experience working with D-Bus apis in the wild now to learn from past mistakes.

Back to the API. We have taken review comments on the previous postings of the code and reworked the API, moving it from a character device to be a filesystem, which ended up making things a lot easier in the end, a good example of a review process that is working. Those changes are a sign that our development review process works. People pointed out problems in our character api that we hadn't thought about from the kernel implementation side. And so we changed them and the code is better and more robust because of it, a success story for our review process.

Personally, I was the one that started down the character device node path, so blame that design decision on me, not the other developers here. And I was wrong with that, but moving from character to a filesystem wasn't a huge change, the structures and interactions all remained almost identical, as the logic behind the API is, in my opinion, correct for the problem it is addressing.

Quoted 3 lines

The 37 different developers who have contributed to this code base are quite talented and skilled and experienced in user and kernel apis, having implemented many apis of their own that users rely on every day.

Yes, but I am not sure that the 15 developers who made each made 1 commit (out of 2816 to date) would have done much work on the API. And probably the same is true for the 9 more who made just 2 or 3 commits. As one would expect, the great deal of the good work has been done by a small
core: just shy of 95% commits by the top 5 committers.

Quoted 9 lines

Yes, we all make design mistakes, and you might not agree with some of them, that's fine. But it is flat out rude to say that we have not been thinking about this, when I would guess that this is one of the largest (in time and contributions) kernel development feature to be worked on in the past few years.

And yes, I'm being very defensive, as I take this very seriously, so please, don't so lightly dismiss us as not knowing what we are doing, as frankly, we do.

Greg, I did not say you hadn't been thinking about this [API design]. (But I acknowledge my words could have been better chosen.) However, API design is hard to get right, and causes endless pain when it's wrong. And by now I've been watching long enough to know that the mistakes are frequent. Even Davide Libenzi, who once upon a time was one of our more prolific and talented creators of APIs made mistakes. Thus, for example, as we speak, the third iteration of epoll_wait() is in development (epoll_wait() ==> epoll_pwait() ==> epoll_pwait1()). And epoll is an API that is significantly simpler than kdbus.

In my observation, a good API design is a well documented API design. Otherwise, it's virtually impossible to think thoroughly about the API, and that is especially true as the API gets larger. (And AFAICS, the kdbus API is bigger than, for example, the epoll API by an order of magnitude, or so.) Part of that documentation also should include some concrete examples of the use of the API. Again because it helps people to think about and assess the API. (This is especially the case for the fresh minds that explore the new API for the first time without having the preconceptions that are almost inevitable for the creators of the API.)

(BTW, I'm not ignoring your contents about the D-Bus spec above. But kdbus is a free-standing API, IIUC, and as such, it should be assessed on its own.)

I would summarize your statement above, as "trust us, we know what we're doing". With respect, my default position is not to trust. It's nothing personal: API design is hard, and mistakes are too often made. What I want to say in return is "trust us", where "us" is used very inclusively to mean: the kernel maintainers, and for that matter user-space programmers, who need enough information that we can make a well-informed assessment of the merits of an API that will need to be supported forever and may have a multitude of different users. In my assessment, the current information is far from sufficient, and it's a considerable risk to merge the API lacking such information.

Quoted 3 lines

Thanks for making it this far, I'll go back to technical discussions of the API now, as that's what we should be doing, not casting aspirations as to the aptitude of the people involved.

Greg, that comment, with its implication that I am not concerned about technical matters, but rather with something more malicious was quite uncalled for.

But, I am happy to return to technical matters. And I think it best to start with a couple of fundamental questions, since some of the comments I've seen to date from different kdbus developers seem to conflict:

1. Is this intended to be a general purpose API that might see a multitude of different users, or is it thought of as an API designed to support a few specific users such as D-Bus and maybe a handful of others? I had thought the former, but when you point me in the direction of the D-Bus spec, I start to have doubts.

2. Is the API to be invoked directly by applications or is intended to be used only behind specific libraries? You seem to be saying that the latter is the case (here, I'm referring to your comment above about sd-bus). However, when I asked David Herrmann a similar question I got this responser:

"kdbus is in no way bound to systemd. There are ongoing efforts
to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios."

To me, that implies that users will employ the raw kernel API.

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#39 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael,

Quoted 6 lines · Michael Kerrisk (man-pages)

2. Is the API to be invoked directly by applications or is intended to be used only behind specific libraries? You seem to be saying that the latter is the case (here, I'm referring to your comment above about sd-bus). However, when I asked David Herrmann a similar question I got this responser:

Quoted 7 lines

"kdbus is in no way bound to systemd. There are ongoing efforts
to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios."

To me, that implies that users will employ the raw kernel API.

The way I read this is that there will (probably) be a handful of users, namely the existing dbus libraries: libdus, sd-bus, glib, Qt, ell, and maybe a few others. However, third-party developers will not know/care about the details of kdbus, they'll just be coding against the dbus libraries as before (might be minor changes, but they certainly won't need to know anything about the kernel API). Similarly to how userspace developers now code against their libc of choice, rather than use kernel syscalls directly.

HTH,

Tom

#40 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 8 lines · Tom Gundersen

The way I read this is that there will (probably) be a handful of users, namely the existing dbus libraries: libdus, sd-bus, glib, Qt, ell, and maybe a few others. However, third-party developers will not know/care about the details of kdbus, they'll just be coding against the dbus libraries as before (might be minor changes, but they certainly won't need to know anything about the kernel API). Similarly to how userspace developers now code against their libc of choice, rather than use kernel syscalls directly.

Which means we do need proper man pages and detailed documentation for it, just like syscalls for syscalls which just happened to be used by a few libcs. I suspect it really should be implemented as syscalls anyway, but we can leave that argument aside from now. Good documentation certainly helps with making that decision in an educated way.

#41 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Tom Gundersen
Quoted 18 lines · Tom Gundersen

Hi Michael,

Quoted 6 lines · Michael Kerrisk (man-pages)

2. Is the API to be invoked directly by applications or is intended to be used only behind specific libraries? You seem to be saying that the latter is the case (here, I'm referring to your comment above about sd-bus). However, when I asked David Herrmann a similar question I got this responser:

Quoted 7 lines

"kdbus is in no way bound to systemd. There are ongoing efforts
to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios."

To me, that implies that users will employ the raw kernel API.

Quoted 8 lines

The way I read this is that there will (probably) be a handful of users, namely the existing dbus libraries: libdus, sd-bus, glib, Qt, ell, and maybe a few others. However, third-party developers will not know/care about the details of kdbus, they'll just be coding against the dbus libraries as before (might be minor changes, but they certainly won't need to know anything about the kernel API). Similarly to how userspace developers now code against their libc of choice, rather than use kernel syscalls directly.

Thanks, Tom, for the input. I'm still confused though, since elsewhere in this thread David Herrmann said in response to a question of mine:

I think we can agree that we want it to be generically useful, like other ipc mechanisms, including UDS and netlink.

Again, that sounds to me like the vision is not "a handful of users". Hopefully Greg and David can clarify.

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#42 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi

Quoted 26 lines · Michael Kerrisk (man-pages)
Quoted 16 lines · Tom Gundersen
Quoted 6 lines · Michael Kerrisk (man-pages)

2. Is the API to be invoked directly by applications or is intended to be used only behind specific libraries? You seem to be saying that the latter is the case (here, I'm referring to your comment above about sd-bus). However, when I asked David Herrmann a similar question I got this responser:

Quoted 7 lines

"kdbus is in no way bound to systemd. There are ongoing efforts
to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios."

To me, that implies that users will employ the raw kernel API.

Quoted 8 lines

The way I read this is that there will (probably) be a handful of users, namely the existing dbus libraries: libdus, sd-bus, glib, Qt, ell, and maybe a few others. However, third-party developers will not know/care about the details of kdbus, they'll just be coding against the dbus libraries as before (might be minor changes, but they certainly won't need to know anything about the kernel API). Similarly to how userspace developers now code against their libc of choice, rather than use kernel syscalls directly.

Quoted 8 lines

Thanks, Tom, for the input. I'm still confused though, since elsewhere in this thread David Herrmann said in response to a question of mine:

I think we can agree that we want it to be generically useful, like other ipc mechanisms, including UDS and netlink.

Again, that sounds to me like the vision is not "a handful of users". Hopefully Greg and David can clarify.

I only expect a handful of users to call the ioctls directly. The libraries that implement the payload-marshaling, in particular. It's a similar situation with netlink.

Thanks
David

#43 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 36 lines · David Herrmann

Hi

Quoted 32 lines · Michael Kerrisk (man-pages)
Quoted 16 lines · Tom Gundersen
Quoted 6 lines · Michael Kerrisk (man-pages)

2. Is the API to be invoked directly by applications or is intended to be used only behind specific libraries? You seem to be saying that the latter is the case (here, I'm referring to your comment above about sd-bus). However, when I asked David Herrmann a similar question I got this responser:

Quoted 7 lines

"kdbus is in no way bound to systemd. There are ongoing efforts
to port glib and qt to kdbus natively. The API is pretty simple and I don't see how a libkdbus would simplify things. In fact, even our tests only have slim wrappers around the ioctls to simplify error-handling in test-scenarios."

To me, that implies that users will employ the raw kernel API.

Quoted 8 lines

The way I read this is that there will (probably) be a handful of users, namely the existing dbus libraries: libdus, sd-bus, glib, Qt, ell, and maybe a few others. However, third-party developers will not know/care about the details of kdbus, they'll just be coding against the dbus libraries as before (might be minor changes, but they certainly won't need to know anything about the kernel API). Similarly to how userspace developers now code against their libc of choice, rather than use kernel syscalls directly.

Thanks, Tom, for the input. I'm still confused though, since elsewhere in this thread David Herrmann said in response to a question of mine:

I think we can agree that we want it to be generically useful, like other ipc mechanisms, including UDS and netlink.

Quoted 6 lines
Quoted 2 lines

Again, that sounds to me like the vision is not "a handful of users". Hopefully Greg and David can clarify.

I only expect a handful of users to call the ioctls directly. The libraries that implement the payload-marshaling, in particular. It's a similar situation with netlink.

Thanks, David, for the clarification. I think it would have been helpful to have that more clearly stated up front, especially as some comments in this thread, such as the above, could be interpreted to mean quite the opposite. Can I suggest that some text on this point be added to kdbus.txt?

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#44 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael,

Quoted 11 lines · Michael Kerrisk (man-pages)
Quoted 3 lines · David Herrmann

I only expect a handful of users to call the ioctls directly. The libraries that implement the payload-marshaling, in particular. It's a similar situation with netlink.

Thanks, David, for the clarification. I think it would have been helpful to have that more clearly stated up front, especially as some comments in this thread, such as the above, could be interpreted to mean quite the opposite. Can I suggest that some text on this point be added to kdbus.txt?

We're currently working on an a set of comprehensive man pages to document all the commands in the API, along with every struct, enum etc. We do that so that developers are able to actually understand every detail of the API, even though most people - as David explained - will not use that interface directly in the first place but let one of the high-level libraries help them integrate D-Bus functionality into their applications.

If you want, have a look at the upstream repository for a preliminary
version of the new docs.

Thanks,
Daniel

#45 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hello Daniel,

Quoted 15 lines · Daniel Mack

Hi Michael,

Quoted 11 lines · Michael Kerrisk (man-pages)
Quoted 3 lines · David Herrmann

I only expect a handful of users to call the ioctls directly. The libraries that implement the payload-marshaling, in particular. It's a similar situation with netlink.

Thanks, David, for the clarification. I think it would have been helpful to have that more clearly stated up front, especially as some comments in this thread, such as the above, could be interpreted to mean quite the opposite. Can I suggest that some text on this point be added to kdbus.txt?

Quoted 7 lines

We're currently working on an a set of comprehensive man pages to document all the commands in the API, along with every struct, enum etc. We do that so that developers are able to actually understand every detail of the API, even though most people - as David explained - will not use that interface directly in the first place but let one of the high-level libraries help them integrate D-Bus functionality into their applications.

(I suggest that some text about this text go into the kdbus(7) page.)

Quoted 2 lines

If you want, have a look at the upstream repository for a preliminary
version of the new docs.

That's at https://code.google.com/p/d-bus/ , right? This looks like a good direction to go in. Thanks for tackling that.

I hope to take a longer look sometime soon, but a few general conventions for man-pages that you might want to consider following:

* When listing errors, I think you should change your language/formatting somewhat. Examples here from kdbus.endpoint.7:

(1) The man page says

RETURN VALUE
On success, all mentioned ioctl commands return 0.

Better to write this from a user-space point of view:

RETURN VALUE
On success, all mentioned ioctl commands return 0; on error, -1 is returned, and errno is set to indicate the error.

(2) I would change the wording in the ERRORS sections from "may return the following errors"
to
"may fail with the following errors"

(3) When listing the errors, drop the minus signs; that's not what user-space sees. They see a positive value in errno.

(4) The usual formatting convention for constants, including error constants in man pages is boldface, rather than underline/emphasis.

(5) Insofar as it's possible, it would be good to make all pages format nicely within 80 columns. Some of the literal text and ASCII art could, I think, be narrowed.

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#46 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Greg Kroah-Hartman
Quoted 9 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus. This patch adds detailed documentation about the kernel level API design.

And now the details feedback.

Please note that for the various points I raise below, even in cases where I don't suggest/request a fix, the fact that I've needed to answer a question probably suggests a deficiency in the documentation that probably needs to be remedied.

Many of my comments below are wording and typo fixes. While these may sem trivial, the existence of various wording problems and typos is a significant distraction, especially while trying to grok a document of this size.

I've marked one or two notable questions about the API with "###".

Quoted 34 lines
---
 Documentation/kdbus.txt | 2107 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 2107 insertions(+)
 create mode 100644 Documentation/kdbus.txt
Documentation/kdbus.txt new file +19 -0
new file mode 100644
index 000000000000..2592a7e37079
@@ -0,0 +1,2107 @@
+D-Bus is a system for powerful, easy to use interprocess communication (IPC).
+
+The focus of this document is an overview of the low-level, native kernel D-Bus
+transport called kdbus. Kdbus exposes its functionality via files in a
+filesystem called 'kdbusfs'. All communication between processes takes place
+via ioctls on files exposed through the mount point of a kdbusfs. The default
+mount point of kdbusfs is /sys/fs/kdbus.
+
+Please note that kdbus was designed as transport layer for D-Bus, but is in no
+way limited, nor controlled by the D-Bus protocol specification. The D-Bus
+protocol is one possible application layer on top of kdbus.
+
+For the general D-Bus protocol specification, the payload format, the
+marshaling, and the communication semantics, please refer to:
+  http://dbus.freedesktop.org/doc/dbus-specification.html
+
+For a kdbus specific userspace library implementation please refer to:
+  http://cgit.freedesktop.org/systemd/systemd/tree/src/systemd/sd-bus.h
+

Documentation/kdbus.txt line 29

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+Articles about D-Bus and kdbus:
+  http://lwn.net/Articles/580194/
+
+
+1. Terminology
+===============================================================================
+
+  Domain:
+    A domain is created each time a kdbusfs is mounted. Each process that is
+    capable to mount a new instance of a kdbusfs will have its own kdbus

s/is capable to mount/mounts/

Documentation/kdbus.txt line 32

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+    hierarchy. Each domain (ie, each mount point) offers its own "control"
+    file to create new buses. Domains have no connection to each other and
+    cannot see nor talk to each other. See section 5 for more details.

Smoother would be:

s/cannot see nor talk/can neither see nor talk/

Documentation/kdbus.txt line 38

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+
+  Bus:
+    A bus is a named object inside a domain. Clients exchange messages
+    over a bus. Multiple buses themselves have no connection to each other;
+    messages can only be exchanged on the same bus. The default endpoint of
+    a bus, where clients establish the connection to, is the "bus" file

Maybe:

where clients establish the connection to
==>
to which clients establish connections
?

Documentation/kdbus.txt line 41

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+    /sys/fs/kdbus/<bus name>/bus.
+    Common operating system setups create one "system bus" per system, and one
+    "user bus" for every logged-in user. Applications or services may create

At the kdbus level is there any difference between such system and user buses? If not, it would perhaps be good to insert a parenthetical aside to say that.

Quoted 15 lines
Documentation/kdbus.txt new file +15 -0
+    their own private buses.  See section 5 for more details.
+
+  Endpoint:
+    An endpoint provides a file to talk to a bus. Opening an endpoint
+    creates a new connection to the bus to which the endpoint belongs. All
+    endpoints have unique names and are accessible as files underneath the
+    directory of a bus, e.g., /sys/fs/kdbus/<bus>/<endpoint>
+    Every bus has a default endpoint called "bus". A bus can optionally offer
+    additional endpoints with custom names to provide restricted access to the
+    bus. Custom endpoints carry additional policy which can be used to create
+    sandboxes with locked-down, limited, filtered access to a bus.  See
+    section 5 for more details.
+
+  Connection:
+    A connection to a bus is created by opening an endpoint file of a bus and

Documentation/kdbus.txt line 66

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+    becoming an active client with the HELLO exchange. Every ordinary client
+    connection has a unique identifier on the bus and can address messages to
+    every other connection on the same bus by using the peer's connection id
+    as the destination.  See section 6 for more details.
+
+  Pool:
+    Each connection allocates a piece of shmem-backed memory that is used
+    to receive messages and answers to ioctl commands from the kernel. It is
+    never used to send anything to the kernel. In order to access that memory,
+    userspace must mmap() it into its address space.

s/userspace/a userspace application/

Documentation/kdbus.txt line 73

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+    See section 12 for more details.
+
+  Well-known Name:
+    A connection can, in addition to its implicit unique connection id, request
+    the ownership of a textual well-known name. Well-known names are noted in
+    reverse-domain notation, such as com.example.service1. Connections offering
+    a service on a bus are usually reached by its well-known name. The analogy

Noun/pronoun number disagreement at "Connections... its".
==>
A connection that offers a service on a bus is usually reached by its well-known name.

Documentation/kdbus.txt line 74

Quoted 1 line
Documentation/kdbus.txt new file +1 -0
+    of connection id and well-known name is an IP address and a DNS name

Doing s/id/ID/ throughout the doc would help readability. (The doc already uses "ID" in some places, so consistency is a further argument for this change.)

Documentation/kdbus.txt line 80

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+    associated with that address.
+
+  Message:
+    Connections can exchange messages with other connections by addressing
+    the peers with their connection id or well-known name. A message consists
+    of a message header with kernel-specific information on how to route the

What does "kernel-specific" mean here? Something needs explaining (or removing).

Documentation/kdbus.txt line 82

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+    message, and the message payload, which is a logical byte stream of
+    arbitrary size. Messages can carry additional file descriptors to be passed

So, this is FD passing like UNIX domain sockets? If yes, it would be helpful here to mention that analogy.

Documentation/kdbus.txt line 86

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+    from one connection to another. Every connection can specify which set of
+    metadata the kernel should attach to the message when it is delivered
+    to the receiving connection. Metadata contains information like: system
+    timestamps, uid, gid, tid, proc-starttime, well-known-names, process comm,

s/well-known-names/well-known names/

See the note on "ID" above. I think UID, GID, TID throughout would help readability.

Documentation/kdbus.txt line 92

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+    process exe, process argv, cgroup, capabilities, seclabel, audit session,
+    loginuid and the connection's human-readable name.
+    See section 7 and 13 for more details.
+
+  Item:
+    The API of kdbus implements a notion of items, submitted through and

s/a notion/the notion/

Documentation/kdbus.txt line 100

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+    returned by most ioctls, and stored inside data structures in the
+    connection's pool. See section 4 for more details.
+
+  Broadcast and Match:
+    Broadcast messages are potentially sent to all connections of a bus. By
+    default, the connections will not actually receive any of the sent
+    broadcast messages; only after installing a match for specific message
+    properties, a broadcast message passes this filter.

"Filter" suddenly gets mentioned here without previously being defined. I suspect the last piece should read more like:

a connection will receive a broadcast message only after it installs a filter that matches the specific message properties of the broadcast message.

Documentation/kdbus.txt line 105

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+    See section 10 for more details.
+
+  Policy:
+    A policy is a set of rules that define which connections can see, talk to,
+    or register a well-know name on the bus. A policy is attached to buses and

s/know/know/

Documentation/kdbus.txt line 108

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+    custom endpoints, and modified by policy holder connections or owners of
+    custom endpoints. See section 11 for more details.
+    See section 11 for more details.

Repeated last sentence.

Quoted 53 lines
Documentation/kdbus.txt new file +53 -0
+  Privileged bus users:
+    A user connecting to the bus is considered privileged if it is either the
+    creator of the bus, or if it has the CAP_IPC_OWNER capability flag set.
+
+
+2. Control Files Layout
+===============================================================================
+
+The kdbus interface is exposed through files in its kdbusfs mount point
+(defaults to /sys/fs/kdbus):
+
+  /sys/fs/kdbus                 (mount point of kdbusfs)
+  |-- control                   (domain control-file)
+  |-- 0-system                  (bus of user uid=0)
+  |   |-- bus                   (default endpoint of bus '0-system')
+  |   `-- ep.apache             (custom endpoint of bus '0-system')
+  |-- 1000-user                 (bus of user uid=1000)
+  |   `-- bus                   (default endpoint of bus '1000-user')
+  `-- 2702-user                 (bus of user uid=2702)
+      |-- bus                   (default endpoint of bus '2702-user')
+      `-- ep.app                (custom endpoint of bus '2702-user')
+
+
+3. Data Structures and flags
+===============================================================================
+
+3.1 Data structures and interconnections
+----------------------------------------
+
+  +--------------------------------------------------------------------------+
+  | Domain (Mount Point)                                                     |
+  | /sys/fs/kdbus/control                                                    |
+  | +----------------------------------------------------------------------+ |
+  | | Bus (System Bus)                                                     | |
+  | | /sys/fs/kdbus/0-system/                                              | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | | Endpoint                      | | Endpoint                       | | |
+  | | | /sys/fs/kdbus/0-system/bus    | | /sys/fs/kdbus/0-system/ep.app  | | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |
+  | | | Connection   | | Connection   | | Connection   | | Connection    | | |
+  | | | :1.22        | | :1.25        | | :1.55        | | :1.81         | | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |
+  | +----------------------------------------------------------------------+ |
+  |                                                                          |
+  | +----------------------------------------------------------------------+ |
+  | | Bus (User Bus for UID 2702)                                          | |
+  | | /sys/fs/kdbus/2702-user/                                             | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | | Endpoint                      | | Endpoint                       | | |
+  | | | /sys/fs/kdbus/2702-user/bus   | | /sys/fs/kdbus/2702-user/ep.app | | |
+  | | +-------------------------------+ +--------------------------------+ | |
+  | | +--------------+ +--------------+ +--------------+ +---------------+ | |

Documentation/kdbus.txt line 172

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  | | | Connection   | | Connection   | | Connection   | | Connection    | | |
+  | | | :1.22        | | :1.25        | | :1.55        | | :1.81         | | |
+  | | +--------------+ +--------------+ +--------------------------------+ | |
+  | +----------------------------------------------------------------------+ |
+  +--------------------------------------------------------------------------+
+
+The above description uses the D-Bus notation of unique connection names that
+adds a ":1." prefix to the connection's unique ID. kdbus itself doesn't
+use that notation, neither internally nor externally. However, libraries and
+other userspace code that aims for compatibility to D-Bus might.

s/compatibility to/compatibility with/

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+
+3.2 Flags
+---------
+
+All ioctls used in the communication with the driver contain three 64-bit
+fields: 'flags', 'kernel_flags' and 'return_flags'. All of them are specific

Documentation/kdbus.txt line 188

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+to the ioctl used.
+
+In 'flags', the behavior of the command can be tweaked. All bits that are not
+recognized by the kernel in this field are rejected, and the ioctl fails with
+-EINVAL.
+
+In 'kernel_flags', the kernel driver writes back the mask of supported bits
+upon each call, and sets the KDBUS_FLAGS_KERNEL bit. This is a way to probe
+possible kernel features and make userspace code forward and backward
+compatible.

So, is "kernel_flags' a bounding superset of what the caller may specify in 'flags'? If yes, please make that clearer.

Quoted 12 lines
Documentation/kdbus.txt new file +12 -0
+
+In 'return_flags', the kernel can return results of the command, in addition
+to the actual return value. This is mostly to inform userspace about non-fatal
+conditions that occurred during the execution of the command.
+
+
+4. Items
+===============================================================================
+
+To flexibly augment transport structures, data blobs of type struct kdbus_item
+can be attached to the structs passed into the ioctls. Some ioctls make items
+of certain types mandatory, others are optional. Unsupported items will cause

Documentation/kdbus.txt line 210

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+the ioctl to fail -EINVAL.
+
+The total size of an item is variable and is in some cases defined by the item
+type. In other cases, they can be of arbitrary length (for instance, a string).
+
+Items are also used for information stored in a connection's pool, such as
+received messages, name lists or requested connection or bus owner information.
+
+Whenever items are used as part of the kdbus kernel API, they are embedded in
+structs that have an overall size of their own, so there can be multiple items

"have an overall size of their own" as hard to grok. I think you mean

... are embedded insides structs that themselves include a size field containing the overall size of the structure. This allows multiple items per ioctl.

Documentation/kdbus.txt line 214

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+per ioctl.
+
+The kernel expects all items to be aligned to 8-byte boundaries. Unaligned
+items or such that are unsupported by the ioctl are rejected.

s/such/items/?
(Or otherwise replace "such" with whatever it actually means.)

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+A simple iterator in userspace would iterate over the items until the items
+have reached the embedding structure's overall size. An example implementation
+of such an iterator can be found in tools/testing/selftests/kdbus/kdbus-util.h.
+
+
+5. Creation of new domains, buses and endpoints
+===============================================================================
+

Documentation/kdbus.txt

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+5.1 Domains
+-----------
+
+A domain is a container of buses. Domains themselves do not provide any IPC
+functionality. Their sole purpose is to manage buses allocated in their
+domain. Each time kdbusfs is mounted, a new kdbus domain is created, with its
+own 'control' file. The lifetime of the domain ends once the user has unmounted
+the kdbusfs. If you mount kdbusfs multiple times, each will have its own kdbus
+domain internally. 

What does that last sentence mean? Somehow it needs to be reworded to better convey whatever sense it is trying to convey.

Documentation/kdbus.txt line 242

Quoted 10 lines

Operations performed on one domain do not affect any

Documentation/kdbus.txt new file +9 -0
+other domain.
+
+The full kdbusfs hierarchy, any sub-directory, or file can be bind-mounted to
+an external mount point and will remain fully functional. The kdbus domain and
+any linked resources stay available until the original mount and all subsequent
+bind-mounts have been unmounted.
+
+During creation, domains pin the user-namespace of the creator and use
+it as controlling user-namespace for this domain. Any user accounting is done

s/as/as the/

Documentation/kdbus.txt line 247

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+relative to that user-namespace.
+
+Newly created kdbus domains do not have any bus pre-created. The only resource
+available is a 'control' file, which is used to manage kdbus domains.
+Currently, 'control' files are exclusively used to create buses via

s/exclusively used/used exclusively/

Documentation/kdbus.txt line 254

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+KDBUS_CMD_BUS_MAKE, but further ioctls might be added in the future.
+
+
+5.2 Buses
+---------
+
+A bus is a shared resource between connections to transmit messages. Each bus

==> A bus is a resource that is shared between connections in order to
transmit messages

Documentation/kdbus.txt line 256

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+is independent and operations on the bus will not have any effect on other
+buses. A bus is a management entity, that controls the addresses of its

s/,//

Documentation/kdbus.txt line 261

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+connections, their policies and message transactions performed via this bus.
+
+Each bus is bound to the domain it was created on. It has a custom name that is
+unique across all buses of a domain. In kdbusfs, a bus is presented as a
+directory. No operations can be performed on the bus itself, instead you need

s/,/;/

Quoted 1 line

+to perform those on an endpoint associated with the bus. Endpoints are

s/those/operations/

Documentation/kdbus.txt line 267

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+accessible as files underneath the bus directory. A default endpoint called
+"bus" is provided on each bus.
+
+Bus names may be chosen freely except for one restriction: the name
+must be prefixed with the numeric UID of the creator and a dash. This

s/UID/effective UID/
(I assume it's the effective UID...)

Documentation/kdbus.txt line 269

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+is required to avoid namespace clashes between different users. When
+creating a bus the name must be passed in properly formatted, or the

the name must be passed in properly formatted ==>
that name that is passed in must be properly formatted

Documentation/kdbus.txt line 271

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+kernel will refuse creation of the bus. Example: "1047-foobar" is an
+OK name for a bus registered by a user with UID 1047. However,

s/OK/acceptable/

Documentation/kdbus.txt line 275

Quoted 4 lines

+"1024-foobar" is not, and neither is "foobar".

Documentation/kdbus.txt new file +3 -0
+The UID must be provided in the user-namespace of the parent domain.
+
+To create a new bus, you need to open the control file of a domain and run the

s/run/employ/ (One doesn't "run" a system call.)

Documentation/kdbus.txt line 277

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+KDBUS_CMD_BUS_MAKE ioctl. The control file descriptor that was used to issue
+KDBUS_CMD_BUS_MAKE must not have been used for any other control-ioctl before

Maybe better:

have been used for any other control-ioctl before ==>
previously have been used for any other control-ioctl

Quoted 1 line

+and needs to be kept open for the entire life-time of the created bus. Closing

s/needs/must/ (just reads smoother)

Documentation/kdbus.txt line 284

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+it will immediately cleanup the entire bus and all its associated resources and
+endpoints. Every control file descriptor can only be used to create a single
+new bus; from that point on, it is not used for any further communication until
+the final close().
+
+Each bus will generate a random, 128-bit UUID upon creation. It will be

/It/This UUID/

Documentation/kdbus.txt line 288

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+returned to creators of connections through kdbus_cmd_hello.id128 and can
+be used by userspace to uniquely identify buses, even across different machines
+or containers. The UUID will have its variant bits set to 'DCE', and denote
+version 4 (random).

I find that last sentence rather difficult to grasp. I think more detail needs to be added.

Documentation/kdbus.txt line 291

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+When creating buses, a variable list of items that must be passed in
+the items array is expected otherwise bus creation will fail.

What does "a variable list of items that must be passed in the items array" mean? Something needs fixing, I think.

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+
+5.3 Endpoints
+-------------
+
+Endpoints are entry points to a bus. By default, each bus has a default
+endpoint called 'bus'. The bus owner has the ability to create custom
+endpoints with specific names, permissions, and policy databases (see below).
+An endpoint is presented as file underneath the directory of the parent bus.

Documentation/kdbus.txt line 310

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+To create a custom endpoint, open the default endpoint ('bus') and use the
+KDBUS_CMD_ENDPOINT_MAKE ioctl with "struct kdbus_cmd_make". Custom endpoints
+always have a policy database that, by default, forbids any operation. You have
+to explicitly install policy entries to allow any operation on this endpoint.
+Once KDBUS_CMD_ENDPOINT_MAKE succeeded, this file descriptor will manage the
+newly created endpoint resource. It cannot be used to manage further resources.
+
+Endpoint names may be chosen freely except for one restriction: the name
+must be prefixed with the numeric UID of the creator and a dash. This

s/UID/effective UID/

Documentation/kdbus.txt

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+is required to avoid namespace clashes between different users. When
+creating an endpoint the name must be passed in properly formatted, or the

creating an endpoint the name must be passed in properly formatted ==>
creating an endpoint, the name that is passed in must be properly formatted

Documentation/kdbus.txt line 314

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+kernel will refuse creation of the endpoint. Example: "1047-foobar" is an
+OK name for an endpoint registered by a user with UID 1047. However,

s/OK/acceptable/

Quoted 1 line

+"1024-foobar" is not, and neither is "foobar".

Because this text reads almost exactly as the bus text in 5.2, I did a double take here. I suggest making the text more distinct in each case.

So, for example:

Example: "1047-my-endpoint" is an OK name for an endpoint registered by a user with UID 1047. However, "1024-my-endpoint" is not, and neither is "my-endpoint".

(And you could do similar in the bus text in section 5.2.)

Documentation/kdbus.txt line 319

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+The UID must be provided in the user-namespace of the parent domain.
+
+To create connections to a bus, you use KDBUS_CMD_HELLO. See section 6 for
+details. Note that once KDBUS_CMD_HELLO succeeded, this file descriptor manages

Note that once KDBUS_CMD_HELLO succeeded,
==>
Note that after a successful KDBUS_CMD_HELLO,

Documentation/kdbus.txt line 327

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+the newly created connection resource. It cannot be used to manage further
+resources.
+
+
+5.4 Creating buses and endpoints
+--------------------------------
+
+KDBUS_CMD_BUS_MAKE, and KDBUS_CMD_ENDPOINT_MAKE take a

s/,//

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+struct kdbus_cmd_make argument.
+
+struct kdbus_cmd_make {
+  __u64 size;
+    The overall size of the struct, including its items.
+
+  __u64 flags;
+    The flags for creation.
+
+    KDBUS_MAKE_ACCESS_GROUP

Documentation/kdbus.txt line 347

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+      Make the bus or endpoint file group-accessible
+
+    KDBUS_MAKE_ACCESS_WORLD
+      Make the bus or endpoint file world-accessible
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 350

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+
+  struct kdbus_item items[0];
+    A list of items that has specific meanings for KDBUS_CMD_BUS_MAKE

s/has/have/

Documentation/kdbus.txt line 355

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+    and KDBUS_CMD_ENDPOINT_MAKE (see above).
+
+    Following items are expected for KDBUS_CMD_BUS_MAKE:
+    KDBUS_ITEM_MAKE_NAME
+      Contains a string to identify the bus name.

So, up to here, I've seen no definition of 'kdbus_item', which leaves me asking questions like: what subfield is KDBUS_ITEM_MAKE_NAME stored in? which subfield holds the pointer to the string?

Somewhere earlier, kdbus_item needs to be exaplained in more detail, I think.

Documentation/kdbus.txt line 365

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+    KDBUS_ITEM_BLOOM_PARAMETER
+      Bus-wide bloom parameters passed in a dbus_bloom_parameter struct
+
+    KDBUS_ITEM_ATTACH_FLAGS_RECV
+      An optional item that contains a set of required attach flags
+      that connections must allow. This item is used as a negotiation
+      measure during connection creation. If connections do not satisfy
+      the bus requirements, they are not allowed on the bus.
+      If not set, the bus does not require any metadata to be attached,

s/,/;/

Quoted 11 lines
Documentation/kdbus.txt new file +11 -0
+      in this case connections are free to set their own attach flags.
+
+    KDBUS_ITEM_ATTACH_FLAGS_SEND
+      An optional item that contains a set of attach flags that are
+      returned to connections when they query the bus creator metadata.
+      If not set, no metadata is returned.
+
+    Unrecognized items are rejected, and the ioctl will fail with -EINVAL.
+};
+
+

Documentation/kdbus.txt line 386

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+6. Connections
+===============================================================================
+
+
+6.1 Connection IDs and well-known connection names
+--------------------------------------------------
+
+Connections are identified by their connection id, internally implemented as a
+uint64_t counter. The IDs of every newly created bus start at 1, and every new
+connection will increment the counter by 1. The ids are not reused.

Again, please change "ids" to IDs" throughout.

Documentation/kdbus.txt line 396

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+In higher level tools, the user visible representation of a connection is
+defined by the D-Bus protocol specification as ":1.<id>".
+
+Messages with a specific uint64_t destination id are directly delivered to
+the connection with the corresponding id. Messages with the special destination
+id KDBUS_DST_ID_BROADCAST are broadcast messages and are potentially delivered
+to all known connections on the bus; clients interested in broadcast messages
+need to subscribe to the specific messages they are interested, though before
+any broadcast message reaches them.

The piece following the semicolon would be better as this separate sentence, I think:

However, in order to receive any broadcast messages, clients must to subscribe to the specific messages in which they are interested.

Quoted 72 lines
Documentation/kdbus.txt new file +72 -0
+
+Messages synthesized and sent directly by the kernel will carry the special
+source id KDBUS_SRC_ID_KERNEL (0).
+
+In addition to the unique uint64_t connection id, established connections can
+request the ownership of well-known names, under which they can be found and
+addressed by other bus clients. A well-known name is associated with one and
+only one connection at a time. See section 8 on name acquisition and the
+name registry, and the validity of names.
+
+Messages can specify the special destination id 0 and carry a well-known name
+in the message data. Such a message is delivered to the destination connection
+which owns that well-known name.
+
+  +-------------------------------------------------------------------------+
+  | +---------------+     +---------------------------+                     |
+  | | Connection    |     | Message                   | -----------------+  |
+  | | :1.22         | --> | src: 22                   |                  |  |
+  | |               |     | dst: 25                   |                  |  |
+  | |               |     |                           |                  |  |
+  | |               |     |                           |                  |  |
+  | |               |     +---------------------------+                  |  |
+  | |               |                                                    |  |
+  | |               | <--------------------------------------+           |  |
+  | +---------------+                                        |           |  |
+  |                                                          |           |  |
+  | +---------------+     +---------------------------+      |           |  |
+  | | Connection    |     | Message                   | -----+           |  |
+  | | :1.25         | --> | src: 25                   |                  |  |
+  | |               |     | dst: 0xffffffffffffffff   | -------------+   |  |
+  | |               |     |  (KDBUS_DST_ID_BROADCAST) |              |   |  |
+  | |               |     |                           | ---------+   |   |  |
+  | |               |     +---------------------------+          |   |   |  |
+  | |               |                                            |   |   |  |
+  | |               | <--------------------------------------------------+  |
+  | +---------------+                                            |   |      |
+  |                                                              |   |      |
+  | +---------------+     +---------------------------+          |   |      |
+  | | Connection    |     | Message                   | --+      |   |      |
+  | | :1.55         | --> | src: 55                   |   |      |   |      |
+  | |               |     | dst: 0 / org.foo.bar      |   |      |   |      |
+  | |               |     |                           |   |      |   |      |
+  | |               |     |                           |   |      |   |      |
+  | |               |     +---------------------------+   |      |   |      |
+  | |               |                                     |      |   |      |
+  | |               | <------------------------------------------+   |      |
+  | +---------------+                                     |          |      |
+  |                                                       |          |      |
+  | +---------------+                                     |          |      |
+  | | Connection    |                                     |          |      |
+  | | :1.81         |                                     |          |      |
+  | | org.foo.bar   |                                     |          |      |
+  | |               |                                     |          |      |
+  | |               |                                     |          |      |
+  | |               | <-----------------------------------+          |      |
+  | |               |                                                |      |
+  | |               | <----------------------------------------------+      |
+  | +---------------+                                                       |
+  +-------------------------------------------------------------------------+
+
+
+6.2 Creating connections
+------------------------
+
+A connection to a bus is created by opening an endpoint file of a bus and
+becoming an active client with the KDBUS_CMD_HELLO ioctl. Every connected client
+connection has a unique identifier on the bus and can address messages to every
+other connection on the same bus by using the peer's connection id as the
+destination.
+
+The KDBUS_CMD_HELLO ioctl takes the following struct as argument.
+

Documentation/kdbus.txt line 478

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+struct kdbus_cmd_hello {
+  __u64 size;
+    The overall size of the struct, including all attached items.
+
+  __u64 flags;
+    Flags to apply to this connection:
+
+    KDBUS_HELLO_ACCEPT_FD
+      When this flag is set, the connection can be sent file descriptors
+      as message payload. If it's not set, any attempt of doing so will

s/any attempt of doing so/an attempt to send file descriptors/

Documentation/kdbus.txt line 483

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+      result in -ECOMM on the sender's side.
+
+    KDBUS_HELLO_ACTIVATOR
+      Make this connection an activator (see below). With this bit set,
+      an item of type KDBUS_ITEM_NAME has to be attached which describes

s/attached which describes/attached. This item describes/

Documentation/kdbus.txt line 488

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+      the well-known name this connection should be an activator for.
+
+    KDBUS_HELLO_POLICY_HOLDER
+      Make this connection a policy holder (see below). With this bit set,
+      an item of type KDBUS_ITEM_NAME has to be attached which describes

s/attached which describes/attached. This item describes/

Documentation/kdbus.txt line 492

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+      the well-known name this connection should hold a policy for.
+
+    KDBUS_HELLO_MONITOR
+      Make this connection an eaves-dropping connection. See section 6.8 for

s/eaves-dropping/eavesdropping/

Documentation/kdbus.txt line 495

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+      more information.
+
+To also receive broadcast messages,

^
Indentation error.

Documentation/kdbus.txt line 503

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+      the connection has to upload appropriate matches as well.
+      This flag is only valid for privileged bus connections.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 509

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+
+  __u64 attach_flags_send;
+      Set the bits for metadata this connection permits to be sent to the
+      receiving peer. Only metadata items that are both allowed to be sent by
+      the sender and that are requested by the receiver will effectively be
+      attached to the message eventually. Note, however, that the bus may

What does "eventually" mean here?

Quoted 1 line

+ optionally enforce some of those bits to be set. If the match fails,

s/enforce/require/ ?

Documentation/kdbus.txt line 517

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+      -ECONNREFUSED will be returned. In either case, this field will be set
+      to the mask of metadata items that are enforced by the bus. The
+      KDBUS_FLAGS_KERNEL bit will as well be set.
+
+  __u64 attach_flags_recv;
+      Request the attachment of metadata for each message received by this
+      connection. The metadata actually attached may actually augment the list

Seems like two "actually" in the previous line is one too many.

Quoted 12 lines
Documentation/kdbus.txt new file +12 -0
+      of requested items. See section 13 for more details.
+
+  __u64 bus_flags;
+      Upon successful completion of the ioctl, this member will contain the
+      flags of the bus it connected to.
+
+  __u64 id;
+      Upon successful completion of the ioctl, this member will contain the
+      id of the new connection.
+
+  __u64 pool_size;
+      The size of the communication pool, in bytes. The pool can be accessed

Documentation/kdbus.txt line 539

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+      by calling mmap() on the file descriptor that was used to issue the
+      KDBUS_CMD_HELLO ioctl.
+
+  __u64 offset;
+      The kernel will return the offset in the pool where returned details
+      will be stored.
+
+  __u8 id128[16];
+      Upon successful completion of the ioctl, this member will contain the
+      128 bit wide UUID of the connected bus.

s/128 bit wide/128-bit/

Documentation/kdbus.txt line 542

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+
+  struct kdbus_item items[0];
+      Variable list of items to add optional additional information. The

s/to add optional additional/containing optional additional/

Documentation/kdbus.txt line 546

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+      following items are currently expected/valid:
+
+      KDBUS_ITEM_CONN_DESCRIPTION
+        Contains a string to describes this connection's name, so it can be

s/to/that/

Quoted 15 lines
Documentation/kdbus.txt new file +15 -0
+        identified later.
+
+      KDBUS_ITEM_NAME
+      KDBUS_ITEM_POLICY_ACCESS
+        For activators and policy holders only, combinations of these two
+        items describe policy access entries (see section about policy).
+
+      KDBUS_ITEM_CREDS
+      KDBUS_ITEM_PIDS
+      KDBUS_ITEM_SECLABEL
+        Privileged bus users may submit these types in order to create
+        connections with faked credentials. This information will be returned
+        when peer information is queried by KDBUS_CMD_CONN_INFO. See section
+        13 for more information.
+

Documentation/kdbus.txt line 571

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+      Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+At the offset returned in the 'offset' field of struct kdbus_cmd_hello, the
+kernel will store items of the following types:
+
+  KDBUS_ITEM_BLOOM_PARAMETER
+      Bloom filter parameter as defined by the bus creator (see below).
+
+The offset in the pool has to be freed with the KDBUS_CMD_FREE ioctl.

As far as I can tell, KDBUS_CMD_FREE detailed anywhere in this file. It needs a detailed description soemwhere.

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+
+6.3 Activator and policy holder connection
+------------------------------------------
+
+An activator connection is a placeholder for a well-known name. Messages sent
+to such a connection can be used by userspace to start an implementer

Documentation/kdbus.txt line 587

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+connection, which will then get all the messages from the activator copied
+over. An activator connection cannot be used to send any message.
+
+A policy holder connection only installs a policy for one or more names.
+These policy entries are kept active as long as the connection is alive, and
+are removed once it terminates. Such a policy connection type can be used to
+deploy restrictions for names that are not yet active on the bus. A policy
+holder connection cannot be used to send any message.
+
+The creation of activator, policy holder or monitor connections is an operation

What is a "monitor connection"? That term springs up unannounced. Is it an "eavesdropping connection" as described above? Either define the term "monitor connection" or use consistent terminology. (Actually, further down in the document, it is clarified that "monitor connection" == "eavesdropper". But that is not clear at THIS point in the document. It needs to be clearer.)

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+restricted to privileged users on the bus (see section "Terminology").
+
+
+6.4 Retrieving information on a connection

Documentation/kdbus.txt line 601

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+------------------------------------------
+
+The KDBUS_CMD_CONN_INFO ioctl can be used to retrieve credentials and
+properties of the initial creator of a connection. This ioctl uses the
+following struct:
+
+struct kdbus_cmd_info {
+  __u64 size;
+    The overall size of the struct, including the name with its 0-byte string
+    terminator.

"0-byte string terminator" reads strangely. I assume you mean "terminating null byte" / "null-terminated string" Best to use those more standard terms.

So, maybe:

including the name with its terminating null byte

or:

including the null-terminated 'name' string

There are multiple other instances of 0-byte in the doc, and I think they should also be fixed in a similar fashion.

Documentation/kdbus.txt line 604

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+
+  __u64 flags;
+    Specify which metadata items should be attached to the answer.

s/Specify/Specifies/

Documentation/kdbus.txt line 611

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+    See section 13 for more details.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 614

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+
+  __u64 id;
+    The connection's numerical ID to retrieve information for. If set to

Hard to parse sentence.

==> The numerical ID of the connection for which information is to
be retrieved.

Quoted 1 line

+ non-zero value, the 'name' field is ignored.

s/non-zero value/a non-zero value/

Documentation/kdbus.txt line 618

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+
+  __u64 offset;
+    When the ioctl returns, this value will yield the offset of the connection

s/value will yield/field will contain/

Quoted 18 lines
Documentation/kdbus.txt new file +18 -0
+    information inside the caller's pool.
+
+  __u64 info_size;
+    The kernel will return the size of the returned information, so applications
+    can optionally mmap specific parts of the pool.
+
+  struct kdbus_item items[0];
+    The optional item list, containing the well-known name to look up as
+    a KDBUS_ITEM_OWNED_NAME. Only required if the 'id' field is set to 0.
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+After the ioctl returns, the following struct will be stored in the caller's
+pool at 'offset'.
+
+struct kdbus_info {
+  __u64 size;
+    The overall size of the struct, including all its items.

Documentation/kdbus.txt line 646

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+  __u64 id;
+    The connection's unique ID.
+
+  __u64 flags;
+    The connection's flags as specified when it was created.
+
+  struct kdbus_item items[0];
+    Depending on the 'flags' field in struct kdbus_cmd_info, items of
+    types KDBUS_ITEM_OWNED_NAME and KDBUS_ITEM_CONN_DESCRIPTION are followed

s/are followed/follow/

Quoted 20 lines
Documentation/kdbus.txt new file +20 -0
+    here.
+};
+
+Once the caller is finished with parsing the return buffer, it needs to call
+KDBUS_CMD_FREE for the offset.
+
+
+6.5 Getting information about a connection's bus creator
+--------------------------------------------------------
+
+The KDBUS_CMD_BUS_CREATOR_INFO ioctl takes the same struct as
+KDBUS_CMD_CONN_INFO but is used to retrieve information about the creator of
+the bus the connection is attached to. The metadata returned by this call is
+collected during the creation of the bus and is never altered afterwards, so
+it provides pristine information on the task that created the bus, at the
+moment when it did so.
+
+In response to this call, a slice in the connection's pool is allocated and
+filled with an object of type struct kdbus_info, pointed to by the ioctl's
+'offset' field.

Documentation/kdbus.txt line 676

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+struct kdbus_info {
+  __u64 size;
+    The overall size of the struct, including all its items.
+
+  __u64 id;
+    The bus ID
+
+  __u64 flags;
+    The bus flags as specified when it was created.

s/it/the bus/

Quoted 23 lines
Documentation/kdbus.txt new file +23 -0
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  struct kdbus_item items[0];
+    Metadata information is stored in items here. The item list contains
+    a KDBUS_ITEM_MAKE_NAME item that indicates the bus name of the
+    calling connection.
+};
+
+Once the caller is finished with parsing the return buffer, it needs to call
+KDBUS_CMD_FREE for the offset.
+
+
+6.6 Updating connection details
+-------------------------------
+
+Some of a connection's details can be updated with the KDBUS_CMD_CONN_UPDATE
+ioctl, using the file descriptor that was used to create the connection.
+The update command uses the following struct.
+
+struct kdbus_cmd_update {
+  __u64 size;

Documentation/kdbus.txt line 709

Quoted 10 lines
Documentation/kdbus.txt new file +9 -0
+    The overall size of the struct, including all its items.
+
+  __u64 flags;
+    Currently no flags are supported. Reserved for future use.
 
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Quoted 21 lines
Documentation/kdbus.txt new file +21 -0
+
+  struct kdbus_item items[0];
+    Items to describe the connection details to be updated. The following item
+    types are supported:
+
+    KDBUS_ITEM_ATTACH_FLAGS_SEND
+      Supply a new set of items that this connection permits to be sent along
+      with messages.
+
+    KDBUS_ITEM_ATTACH_FLAGS_RECV
+      Supply a new set of items to be attached to each message.
+
+    KDBUS_ITEM_NAME
+    KDBUS_ITEM_POLICY_ACCESS
+      Policy holder connections may supply a new set of policy information
+      with these items. For other connection types, -EOPNOTSUPP is returned.
+
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+

Documentation/kdbus.txt line 740

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+6.7 Termination
+---------------
+
+A connection can be terminated by simply closing its file descriptor. All
+pending incoming messages will be discarded, and the memory in the pool will
+be freed.
+
+An alternative way of closing down a connection is calling the KDBUS_CMD_BYEBYE
+ioctl on it, which will only succeed if the message queue of the connection is
+empty at the time of closing, otherwise, -EBUSY is returned.

The preceding is a little hard to parse. I suggest:

An alternative way of closing down a connection is via the KDBUS_CMD_BYEBYE ioctl. This ioctly will succeed only if the message queue of the connection is empty at the time of closing; otherwise, -EBUSY is returned.

Quoted 68 lines
Documentation/kdbus.txt new file +68 -0
+
+When this ioctl returns successfully, the connection has been terminated and
+won't accept any new messages from remote peers. This way, a connection can
+be terminated race-free, without losing any messages.
+
+
+6.8 Monitor connections ('eavesdropper')
+----------------------------------------
+
+Eavesdropping connections are created by setting the KDBUS_HELLO_MONITOR flag
+in struct kdbus_hello.flags. Such connections have all properties of any other,
+regular connection, except for the following details:
+
+  * They will get every message sent over the bus, both unicasts and broadcasts
+
+  * Installing matches for broadcast messages is neither necessary nor allowed
+
+  * They cannot send messages or be directly addressed as receiver
+
+  * Their creation and destruction will not cause KDBUS_ITEM_ID_{ADD,REMOVE}
+    notifications to be generated, so other connections cannot detect the
+    presence of an eavesdropper.
+
+
+7. Messages
+===============================================================================
+
+Messages consist of a fixed-size header followed directly by a list of
+variable-sized data 'items'. The overall message size is specified in the
+header of the message. The chain of data items can contain well-defined
+message metadata fields, raw data, references to data, or file descriptors.
+
+
+7.1 Sending messages
+--------------------
+
+Messages are passed to the kernel with the KDBUS_CMD_SEND ioctl. Depending
+on the destination address of the message, the kernel delivers the message to
+the specific destination connection or to all connections on the same bus.
+Sending messages across buses is not possible. Messages are always queued in
+the memory pool of the destination connection (see below).
+
+The KDBUS_CMD_SEND ioctl uses struct kdbus_cmd_send to describe the message
+transfer.
+
+struct kdbus_cmd_send {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    Flags for message delivery:
+
+    KDBUS_SEND_SYNC_REPLY
+      By default, all calls to kdbus are considered asynchronous,
+      non-blocking. However, as there are many use cases that need to wait
+      for a remote peer to answer a method call, there's a way to send a
+      message and wait for a reply in a synchronous fashion. This is what
+      the KDBUS_MSG_SYNC_REPLY controls. The KDBUS_CMD_SEND ioctl will block
+      until the reply has arrived, the timeout limit is reached, in case the
+      remote connection was shut down, or if interrupted by a signal before
+      any reply; see signal(7).
+
+      The offset of the reply message in the sender's pool is stored in in
+      'offset_reply' when the ioctl has returned without error. Hence, there
+      is no need for another KDBUS_CMD_RECV ioctl or anything else to receive
+      the reply.
+
+  __u64 kernel_flags;

Documentation/kdbus.txt line 818

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+    Valid flags for this command, returned by the kernel upon each call of
+    KDBUS_CMD_SEND.
+
+  __u64 kernel_msg_flags;
+    Valid bits for message flags, returned by the kernel upon each call of
+    KDBUS_CMD_SEND.
+
+  __u64 return_flags;
+    Kernel-provided flags, returning non-fatal errors that occurred during
+    send. Currently unused.

And, so presumably always returned as 0? Best to note that.

Quoted 22 lines
Documentation/kdbus.txt new file +22 -0
+
+  __u64 msg_address;
+    Userspace has to provide a pointer to a message (struct kdbus_msg) to send.
+
+  struct kdbus_msg_info reply;
+    Only used for synchronous replies. See description of struct kdbus_cmd_recv
+    for more details.
+
+  struct kdbus_item items[0];
+    The following items are currently recognized:
+
+    KDBUS_ITEM_CANCEL_FD
+      When this optional item is passed in, and the call is executed as SYNC
+      call, the passed in file descriptor can be used as alternative
+      cancellation point. The kernel will call poll() on this file descriptor,
+      and if it reports any incoming bytes, the blocking send operation will
+      be canceled, and the call will return -ECANCELED. Any type of file
+      descriptor that implements poll() can be used as payload to this item.
+      For asynchronous message sending, this item is accepted but ignored.
+
+    All other items are rejected, and the ioctl will fail with -EINVAL.
+};

Documentation/kdbus.txt line 850

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+The message referenced by 'msg_address' above has the following layout.
+
+struct kdbus_msg {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    KDBUS_MSG_EXPECT_REPLY
+      Expect a reply from the remote peer to this message. With this bit set,

s/from the remote peer to this message/to this message from the remote peer/

Documentation/kdbus.txt line 855

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+      the timeout_ns field must be set to a non-zero number of nanoseconds in
+      which the receiving peer is expected to reply. If such a reply is not
+      received in time, the sender will be notified with a timeout message
+      (see below). The value must be an absolute value, in nanoseconds and
+      based on CLOCK_MONOTONIC.

Why is the option of a relative timeout not available?

Quoted 26 lines
Documentation/kdbus.txt new file +26 -0
+      For a message to be accepted as reply, it must be a direct message to
+      the original sender (not a broadcast), and its kdbus_msg.reply_cookie
+      must match the previous message's kdbus_msg.cookie.
+
+      Expected replies also temporarily open the policy of the sending
+      connection, so the other peer is allowed to respond within the given
+      time window.
+
+    KDBUS_MSG_NO_AUTO_START
+      By default, when a message is sent to an activator connection, the
+      activator notified and will start an implementer. This flag inhibits
+      that behavior. With this bit set, and the remote being an activator,
+      -EADDRNOTAVAIL is returned from the ioctl.
+
+  __s64 priority;
+    The priority of this message. Receiving messages (see below) may
+    optionally be constrained to messages of a minimal priority. This
+    allows for use cases where timing critical data is interleaved with
+    control data on the same connection. If unused, the priority should be
+    set to zero.
+
+  __u64 dst_id;
+    The numeric ID of the destination connection, or KDBUS_DST_ID_BROADCAST
+    (~0ULL) to address every peer on the bus, or KDBUS_DST_ID_NAME (0) to look
+    it up dynamically from the bus' name registry. In the latter case, an item
+    of type KDBUS_ITEM_DST_NAME is mandatory.

Documentation/kdbus.txt line 892

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+  __u64 src_id;
+    Upon return of the ioctl, this member will contain the sending
+    connection's numerical ID. Should be 0 at send time.
+
+  __u64 payload_type;
+    Type of the payload in the actual data records. Currently, only
+    KDBUS_PAYLOAD_DBUS is accepted as input value of this field. When
+    receiving messages that are generated by the kernel (notifications),
+    this field will yield KDBUS_PAYLOAD_KERNEL.

s/yield/cointain/ ?

Quoted 81 lines
Documentation/kdbus.txt new file +81 -0
+
+  __u64 cookie;
+    Cookie of this message, for later recognition. Also, when replying
+    to a message (see above), the cookie_reply field must match this value.
+
+  __u64 timeout_ns;
+    If the message sent requires a reply from the remote peer (see above),
+    this field contains the timeout in absolute nanoseconds based on
+    CLOCK_MONOTONIC.
+
+  __u64 cookie_reply;
+    If the message sent is a reply to another message, this field must
+    match the cookie of the formerly received message.
+
+  struct kdbus_item items[0];
+    A dynamically sized list of items to contain additional information.
+    The following items are expected/valid:
+
+    KDBUS_ITEM_PAYLOAD_VEC
+    KDBUS_ITEM_PAYLOAD_MEMFD
+    KDBUS_ITEM_FDS
+      Actual data records containing the payload. See section "Passing of
+      Payload Data".
+
+    KDBUS_ITEM_BLOOM_FILTER
+      Bloom filter for matches (see below).
+
+    KDBUS_ITEM_DST_NAME
+      Well-known name to send this message to. Required if dst_id is set
+      to KDBUS_DST_ID_NAME. If a connection holding the given name can't
+      be found, -ESRCH is returned.
+      For messages to a unique name (ID), this item is optional. If present,
+      the kernel will make sure the name owner matches the given unique name.
+      This allows userspace tie the message sending to the condition that a
+      name is currently owned by a certain unique name.
+};
+
+The message will be augmented by the requested metadata items when queued into
+the receiver's pool. See also section 13.2 ("Metadata and namespaces").
+
+
+7.2 Message layout
+------------------
+
+The layout of a message is shown below.
+
+  +-------------------------------------------------------------------------+
+  | Message                                                                 |
+  | +---------------------------------------------------------------------+ |
+  | | Header                                                              | |
+  | | size:          overall message size, including the data records     | |
+  | | destination:   connection id of the receiver                        | |
+  | | source:        connection id of the sender (set by kernel)          | |
+  | | payload_type:  "DBusDBus" textual identifier stored as uint64_t     | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size (without padding)                        | |
+  | | type:  type of data                                                 | |
+  | | data:  reference to data (address or file descriptor)               | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | padding bytes to the next 8 byte alignment                          | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size (without padding)                        | |
+  | | ...                                                                 | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | padding bytes to the next 8 byte alignment                          | |
+  | +---------------------------------------------------------------------+ |
+  | +---------------------------------------------------------------------+ |
+  | | Data Record                                                         | |
+  | | size:  overall record size                                          | |
+  | | ...                                                                 | |
+  | +---------------------------------------------------------------------+ |
+  |   ... further data records ...                                          |
+  +-------------------------------------------------------------------------+
+
+

Documentation/kdbus.txt line 983

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+7.3 Passing of Payload Data
+---------------------------
+
+When connecting to the bus, receivers request a memory pool of a given size,
+large enough to carry all backlog of data enqueued for the connection. The
+pool is internally backed by a shared memory file which can be mmap()ed by
+the receiver.
+
+KDBUS_MSG_PAYLOAD_VEC:
+  Messages are directly copied by the sending process into the receiver's pool,

s/,/./ and then start a new sentence.

Documentation/kdbus.txt line 985

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+  that way two peers can exchange data by effectively doing a single-copy from
+  one process to another, the kernel will not buffer the data anywhere else.

s/,/;/

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+
+KDBUS_MSG_PAYLOAD_MEMFD:
+  Messages can reference memfd files which contain the data.
+  memfd files are tmpfs-backed files that allow sealing of the content of the

Documentation/kdbus.txt line 999

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  file, which prevents all writable access to the file content.
+  Only memfds that have (F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL) set
+  are accepted as payload data, which enforces reliable passing of data.
+  The receiver can assume that neither the sender nor anyone else can alter the
+  content after the message is sent.
+  Apart from the sender filling-in the content into memfd files, the data will
+  be passed as zero-copy from one process to another, read-only, shared between
+  the peers.
+
+The sender must not make any assumptions on the type how data is received by the

Wording error at "the type how". Some fix is needed.

Documentation/kdbus.txt line 1003

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+remote peer. The kernel is free to re-pack multiple VEC and MEMFD payloads. For
+instance, the kernel may decide to merge multiple VECs into a single VEC, inline
+MEMFD payloads into memory or merge all passed VECs into a single MEMFD.
+However, the kernel preserves the order of passed data. This means, the order of

s/,//

Quoted 1 line

+all VEC and MEMFD items is not changed in respect to each other.

s/in/with/

Documentation/kdbus.txt line 1015

Quoted 11 lines
Documentation/kdbus.txt new file +11 -0
+
+In other words: All passed VEC and MEMFD data payloads are treated as a single
+stream of data that may be received by the remote peer in a different set of
+hunks than it was sent as.
+
+
+7.4 Receiving messages
+----------------------
+
+Messages are received by the client with the KDBUS_CMD_RECV ioctl. The endpoint
+file of the bus supports poll() to wake up the receiving process when new

s%poll()%poll/select()/epoll% ?

Quoted 19 lines
Documentation/kdbus.txt new file +19 -0
+messages are queued up to be received.
+
+With the KDBUS_CMD_RECV ioctl, a struct kdbus_cmd_recv is used.
+
+struct kdbus_cmd_recv {
+  __u64 size;
+    The overall size of the struct, including the attached items.
+
+  __u64 flags;
+    Flags to control the receive command.
+
+    KDBUS_RECV_PEEK
+      Just return the location of the next message. Do not install file
+      descriptors or anything else. This is usually used to determine the
+      sender of the next queued message.
+
+    KDBUS_RECV_DROP
+      Drop the next message without doing anything else with it, and free the
+      pool slice. This a short-cut for KDBUS_RECV_PEEK and KDBUS_CMD_FREE.

Documentation/kdbus.txt line 1044

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+    KDBUS_RECV_USE_PRIORITY
+      Use the priority field (see below).
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Kernel-provided flags, returning non-fatal errors that occurred during
+    send. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 1049

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+
+  __s64 priority;
+    With KDBUS_RECV_USE_PRIORITY set in flags, receive the next message in
+    the queue with at least the given priority. If no such message is waiting
+    in the queue, -ENOMSG is returned.

###
How do I simply select the highest priority message, without knowing what its priority is?

Quoted 32 lines
Documentation/kdbus.txt new file +32 -0
+
+  __u64 dropped_msgs;
+    If the CMD_RECV ioctl fails with EOVERFLOW, this field is filled by
+    the kernel with the number of messages that couldn't be transmitted to
+    this connection. In that case, the @offset member must not be accessed.
+
+  struct kdbus_msg_info msg;
+   Embedded struct to be filled when the command succeeded (see below).
+
+  struct kdbus_item items[0];
+    Items to specify further details for the receive command. Currently unused.
+};
+
+Both 'struct kdbus_cmd_recv' and 'struct kdbus_cmd_send' embed 'struct
+kdbus_msg_info'. For the SEND ioctl, it is used to catch synchronous replies,
+if one was requested, and is unused otherwise.
+
+struct kdbus_msg_info {
+  __u64 offset;
+    Upon return of the ioctl, this field contains the offset in the receiver's
+    memory pool. The memory must be freed with KDBUS_CMD_FREE.
+
+  __u64 msg_size;
+    Upon successful return of the ioctl, this field contains the size of the
+    allocated slice at offset @offset. It is the combination of the size of
+    the stored kdbus_msg object plus all appended VECs. You can use it in
+    combination with @offset to map a single message, instead of mapping the
+    whole pool.
+
+  __u64 return_flags;
+    Kernel-provided return flags. Currently, the following flags are defined.
+

Documentation/kdbus.txt line 1091

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+      KDBUS_RECV_RETURN_INCOMPLETE_FDS
+        The message contained file descriptors which couldn't be installed
+        into the receiver's task. Most probably that happened because the
+        maximum number of file descriptors for that task were exceeded.
+        The message is still delivered, so this is not a fatal condition.
+        File descriptors inside the KDBUS_ITEM_FDS item that could not be
+        installed will be set to -1.
+};
+
+Unless KDBUS_RECV_DROP was passed, and given that the ioctl succeeded, the

s/and given that the ioctl succeeded/after a successful KDBUS_CMD_RECV ioctl/

Documentation/kdbus.txt line 1098

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+offset field contains the location of the new message inside the receiver's
+pool. The message is stored as struct kdbus_msg at this offset, and can be
+interpreted with the semantics described above.
+
+Also, if the connection allowed for file descriptor to be passed
+(KDBUS_HELLO_ACCEPT_FD), and if the message contained any, they will be
+installed into the receiving process after the KDBUS_CMD_RECV ioctl returns.

###
"after"??? When exactly?

Quoted 14 lines
Documentation/kdbus.txt new file +14 -0
+The receiving task is obliged to close all of them appropriately. If
+KDBUS_RECV_PEEK is set, no file descriptors are installed. This allows for
+peeking at a message and dropping it via KDBUS_RECV_DROP, without installing
+the passed file descriptors into the receiving process.
+
+The caller is obliged to call KDBUS_CMD_FREE with the returned offset when
+the memory is no longer needed.
+
+
+8. Name registry
+===============================================================================
+
+Each bus instantiates a name registry to resolve well-known names into unique
+connection IDs for message delivery. The registry will be queried when a

Documentation/kdbus.txt line 1122

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+message is sent with kdbus_msg.dst_id set to KDBUS_DST_ID_NAME, or when a
+registry dump is requested.
+
+All of the below is subject to policy rules for SEE and OWN permissions.
+
+
+8.1 Name validity
+-----------------
+
+A name has to comply to the following rules to be considered valid:

s/comply to/comply with/

Quoted 38 lines
Documentation/kdbus.txt new file +38 -0
+
+ - 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 contain at least one '.' (period) character
+   (and thus at least two elements)
+ - The name must not begin with a '.' (period) character
+ - The name must not exceed KDBUS_NAME_MAX_LEN (255)
+
+
+8.2 Acquiring a name
+--------------------
+
+To acquire a name, a client uses the KDBUS_CMD_NAME_ACQUIRE ioctl with the
+following data structure.
+
+struct kdbus_cmd_name {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 flags;
+    Flags to control details in the name acquisition.
+
+    KDBUS_NAME_REPLACE_EXISTING
+      Acquiring a name that is already present usually fails, unless this flag
+      is set in the call, and KDBUS_NAME_ALLOW_REPLACEMENT or (see below) was
+      set when the current owner of the name acquired it, or if the current
+      owner is an activator connection (see below).
+
+    KDBUS_NAME_ALLOW_REPLACEMENT
+      Allow other connections to take over this name. When this happens, the
+      former owner of the connection will be notified of the name loss.
+
+    KDBUS_NAME_QUEUE (acquire)
+      A name that is already acquired by a connection, and which wasn't
+      requested with the KDBUS_NAME_ALLOW_REPLACEMENT flag set can not be

Documentation/kdbus.txt line 1170

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+      acquired again. However, a connection can put itself in a queue of
+      connections waiting for the name to be released. Once that happens, the
+      first connection in that queue becomes the new owner and is notified
+      accordingly.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Quoted 17 lines
Documentation/kdbus.txt new file +17 -0
+
+  struct kdbus_item items[0];
+    Items to submit the name. Currently, one item of type KDBUS_ITEM_NAME is
+    expected and allowed, and the contained string must be a valid bus name.
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+8.3 Releasing a name
+--------------------
+
+A connection may release a name explicitly with the KDBUS_CMD_NAME_RELEASE
+ioctl. If the connection was an implementer of an activatable name, its
+pending messages are moved back to the activator. If there are any connections
+queued up as waiters for the name, the oldest one of them will become the new
+owner. The same happens implicitly for all names once a connection terminates.
+

Documentation/kdbus.txt line 1197

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+The KDBUS_CMD_NAME_RELEASE ioctl uses the same data structure as the
+acquisition call, but with slightly different field usage.
+
+struct kdbus_cmd_name {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 flags;
+    Flags to the command. Currently unused.

And, so presumably must be 0? Best to note that.

Documentation/kdbus.txt line 347

Quoted 6 lines
Documentation/kdbus.txt new file +6 -0
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Quoted 27 lines
Documentation/kdbus.txt new file +27 -0
+  struct kdbus_item items[0];
+    Items to submit the name. Currently, one item of type KDBUS_ITEM_NAME is
+    expected and allowed, and the contained string must be a valid bus name.
+};
+
+
+8.4 Dumping the name registry
+-----------------------------
+
+A connection may request a complete or filtered dump of currently active bus
+names with the KDBUS_CMD_NAME_LIST ioctl, which takes a struct
+kdbus_cmd_name_list as argument.
+
+struct kdbus_cmd_name_list {
+  __u64 flags;
+    Any combination of flags to specify which names should be dumped.
+
+    KDBUS_NAME_LIST_UNIQUE
+      List the unique (numeric) IDs of the connection, whether it owns a name
+      or not.
+
+    KDBUS_NAME_LIST_NAMES
+      List well-known names stored in the database which are actively owned by
+      a real connection (not an activator).
+
+    KDBUS_NAME_LIST_ACTIVATORS
+      List names that are owned by an activator.

Documentation/kdbus.txt line 1241

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+    KDBUS_NAME_LIST_QUEUED
+      List connections that are not yet owning a name but are waiting for it
+      to become available.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Quoted 131 lines
Documentation/kdbus.txt new file +131 -0
+
+  __u64 offset;
+    When the ioctl returns successfully, the offset to the name registry dump
+    inside the connection's pool will be stored in this field.
+};
+
+The returned list of names is stored in a struct kdbus_name_list that in turn
+contains a dynamic number of struct kdbus_cmd_name that carry the actual
+information. The fields inside that struct kdbus_cmd_name is described next.
+
+struct kdbus_name_info {
+  __u64 size;
+    The overall size of this struct, including the name with its 0-byte string
+    terminator.
+
+  __u64 owner_id;
+    The owning connection's unique ID.
+
+  __u64 conn_flags;
+    The flags of the owning connection.
+
+  struct kdbus_item items[0];
+    Items containing the actual name. Currently, one item of type
+    KDBUS_ITEM_OWNED_NAME will be attached, including the name's flags. In that
+    item, the flags field of the name may carry the following bits:
+
+    KDBUS_NAME_ALLOW_REPLACEMENT
+      Other connections are allowed to take over this name from the
+      connection that owns it.
+
+    KDBUS_NAME_IN_QUEUE (list)
+      When retrieving a list of currently acquired name in the registry, this
+      flag indicates whether the connection actually owns the name or is
+      currently waiting for it to become available.
+
+    KDBUS_NAME_ACTIVATOR (list)
+      An activator connection owns a name as a placeholder for an implementer,
+      which is started on demand as soon as the first message arrives. There's
+      some more information on this topic below. In contrast to
+      KDBUS_NAME_REPLACE_EXISTING, when a name is taken over from an activator
+      connection, all the messages that have been queued in the activator
+      connection will be moved over to the new owner. The activator connection
+      will still be tracked for the name and will take control again if the
+      implementer connection terminates.
+      This flag can not be used when acquiring a name, but is implicitly set
+      through KDBUS_CMD_HELLO with KDBUS_HELLO_ACTIVATOR set in
+      kdbus_cmd_hello.conn_flags.
+};
+
+The returned buffer must be freed with the KDBUS_CMD_FREE ioctl when the user
+is finished with it.
+
+
+9. Notifications
+===============================================================================
+
+The kernel will notify its users of the following events.
+
+  * When connection A is terminated while connection B is waiting for a reply
+    from it, connection B is notified with a message with an item of type
+    KDBUS_ITEM_REPLY_DEAD.
+
+  * When connection A does not receive a reply from connection B within the
+    specified timeout window, connection A will receive a message with an item
+    of type KDBUS_ITEM_REPLY_TIMEOUT.
+
+  * When an ordinary connection (not a monitor) is created on or removed from
+    a bus, messages with an item of type KDBUS_ITEM_ID_ADD or
+    KDBUS_ITEM_ID_REMOVE, respectively, are sent to all bus members that match
+    these messages through their match database. Eavesdroppers (monitor
+    connections) do not cause such notifications to be sent. They are invisible
+    on the bus.
+
+  * When a connection gains or loses ownership of a name, messages with an item
+    of type KDBUS_ITEM_NAME_ADD, KDBUS_ITEM_NAME_REMOVE or
+    KDBUS_ITEM_NAME_CHANGE are sent to all bus members that match these
+    messages through their match database.
+
+A kernel notification is a regular kdbus message with the following details.
+
+  * kdbus_msg.src_id == KDBUS_SRC_ID_KERNEL
+  * kdbus_msg.dst_id == KDBUS_DST_ID_BROADCAST
+  * kdbus_msg.payload_type == KDBUS_PAYLOAD_KERNEL
+  * Has exactly one of the aforementioned items attached
+
+Kernel notifications have an item of type KDBUS_ITEM_TIMESTAMP attached.
+
+
+10. Message Matching, Bloom filters
+===============================================================================
+
+10.1 Matches for broadcast messages from other connections
+----------------------------------------------------------
+
+A message addressed at the connection ID KDBUS_DST_ID_BROADCAST (~0ULL) is a
+broadcast message, delivered to all connected peers which installed a rule to
+match certain properties of the message. Without any rules installed in the
+connection, no broadcast message or kernel-side notifications will be delivered
+to the connection. Broadcast messages are subject to policy rules and TALK
+access checks.
+
+See section 11 for details on policies, and section 11.5 for more
+details on implicit policies.
+
+Matches for messages from other connections (not kernel notifications) are
+implemented as bloom filters. The sender adds certain properties of the message
+as elements to a bloom filter bit field, and sends that along with the
+broadcast message.
+
+The connection adds the message properties it is interested as elements to a
+bloom mask bit field, and uploads the mask to the match rules of the
+connection.
+
+The kernel will match the broadcast message's bloom filter against the
+connections bloom mask (simply by &-ing it), and decide whether the message
+should be delivered to the connection.
+
+The kernel has no notion of any specific properties of the message, all it
+sees are the bit fields of the bloom filter and mask to match against. The
+use of bloom filters allows simple and efficient matching, without exposing
+any message properties or internals to the kernel side. Clients need to deal
+with the fact that they might receive broadcasts which they did not subscribe
+to, as the bloom filter might allow false-positives to pass the filter.
+
+To allow the future extension of the set of elements in the bloom filter, the
+filter specifies a "generation" number. A later generation must always contain
+all elements of the set of the previous generation, but can add new elements
+to the set. The match rules mask can carry an array with all previous
+generations of masks individually stored. When the filter and mask are matched
+by the kernel, the mask with the closest matching "generation" is selected
+as the index into the mask array.

Documentation/kdbus.txt line 1382

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+
+10.2 Matches for kernel notifications
+------------------------------------
+
+To receive kernel generated notifications (see section 9), a connection must
+install special match rules that are different from the bloom filter matches
+described in the section above. They can be filtered by a sender connection's
+ID, by one of the name the sender connection owns at the time of sending the
+message, or by type of the notification (id/name add/remove/change).

s/type/the type/

Documentation/kdbus.txt line 1392

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+10.3 Adding a match
+-------------------
+
+To add a match, the KDBUS_CMD_MATCH_ADD ioctl is used, which takes a struct
+of the struct described below.
+
+Note that each of the items attached to this command will internally create
+one match 'rule', and the collection of them, which is submitted as one block
+via the ioctl is called a 'match'. To allow a message to pass, all rules of a

s/ioctl/ioctl,/

Documentation/kdbus.txt line 1395

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+match have to be satisfied. Hence, adding more items to the command will only
+narrow the possibility of a match to effectively let the message pass, and will
+cause the connection's user space process to wake up less likely.

Make that last line

decrease the chance that the connection's userspace process wil be woken up

Documentation/kdbus.txt line 1397

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+
+Multiple matches can be installed per connection. As long as one of it has a

s/it/them/ ?
(If that change is not correct, then the sentence is quite confused.)

Quoted 12 lines
Documentation/kdbus.txt new file +12 -0
+set of rules which allows the message to pass, this one will be decisive.
+
+struct kdbus_cmd_match {
+  __u64 size;
+    The overall size of the struct, including its items.
+
+  __u64 cookie;
+    A cookie which identifies the match, so it can be referred to at removal
+    time.
+
+  __u64 flags;
+    Flags to control the behavior of the ioctl.

Documentation/kdbus.txt line 1419

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+    KDBUS_MATCH_REPLACE:
+      Remove all entries with the given cookie before installing the new one.
+      This allows for race-free replacement of matches.
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 1432

Quoted 13 lines
Documentation/kdbus.txt new file +13 -0
+
+  struct kdbus_item items[0];
+    Items to define the actual rules of the matches. The following item types
+    are expected. Each item will cause one new match rule to be created.
+
+    KDBUS_ITEM_BLOOM_MASK
+      An item that carries the bloom filter mask to match against in its
+      data field. The payload size must match the bloom filter size that
+      was specified when the bus was created.
+      See section 10.4 for more information.
+
+    KDBUS_ITEM_NAME
+      Specify a name that a sending connection must own at a time of sending

s/a time/the time/

Quoted 35 lines
Documentation/kdbus.txt new file +35 -0
+      a broadcast message in order to match this rule.
+
+    KDBUS_ITEM_ID
+      Specify a sender connection's ID that will match this rule.
+
+    KDBUS_ITEM_NAME_ADD
+    KDBUS_ITEM_NAME_REMOVE
+    KDBUS_ITEM_NAME_CHANGE
+      These items request delivery of broadcast messages that describe a name
+      acquisition, loss, or change. The details are stored in the item's
+      kdbus_notify_name_change member. All information specified must be
+      matched in order to make the message pass. Use KDBUS_MATCH_ID_ANY to
+      match against any unique connection ID.
+
+    KDBUS_ITEM_ID_ADD
+    KDBUS_ITEM_ID_REMOVE
+      These items request delivery of broadcast messages that are generated
+      when a connection is created or terminated. struct kdbus_notify_id_change
+      is used to store the actual match information. This item can be used to
+      monitor one particular connection ID, or, when the id field is set to
+      KDBUS_MATCH_ID_ANY, all of them.
+
+    Items of other types are rejected, and the ioctl will fail with -EINVAL.
+};
+
+
+10.4 Bloom filters
+------------------
+
+Bloom filters allow checking whether a given word is present in a dictionary.
+This allows connections to set up a mask for information it is interested in,
+and will be delivered signal messages that have a matching filter.
+
+For general information on bloom filters, see
+

Documentation/kdbus.txt line 1477

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  https://en.wikipedia.org/wiki/Bloom_filter
+
+The size of the bloom filter is defined per bus when it is created, in
+kdbus_bloom_parameter.size. All bloom filters attached to signals on the bus
+must match this size, and all bloom filter matches uploaded by connections must
+also match the size, or a multiple thereof (see below).
+
+The calculation of the mask has to be done on the userspace side. The kernel
+just checks the bitmasks to decide whether or not to let the message pass. All
+bits in the mask must match the filter in and bit-wise AND logic, but the

Parse error at "in and bit-wise AND logic". I am not sure what you are meaning there, buth something needs fixing.

Documentation/kdbus.txt line 1486

Quoted 9 lines
Documentation/kdbus.txt new file +9 -0
+mask may have more bits set than the filter. Consequently, false positive
+matches are expected to happen, and userspace must deal with that fact.
+
+Masks are entities that are always passed to the kernel as part of a match
+(with an item of type KDBUS_ITEM_BLOOM_MASK), and filters can be attached to
+signals, with an item of type KDBUS_ITEM_BLOOM_FILTER.
+
+For a filter to match, all its bits have to be set in the match mask as well.
+For example, consider a bus has a bloom size of 8 bytes, and the following

s/has/that has/

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+mask/filter combinations:
+
+    filter  0x0101010101010101
+    mask    0x0101010101010101
+            -> matches
+
+    filter  0x0303030303030303
+    mask    0x0101010101010101

Documentation/kdbus.txt line 1504

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+            -> doesn't match
+
+    filter  0x0101010101010101
+    mask    0x0303030303030303
+            -> matches
+
+Hence, in order to catch all messages, a mask filled with 0xff bytes can be
+installed as a wildcard match rule.
+
+Uploaded matches may contain multiple masks, each of which in the size of the

Parse error at "each of which in the size of"
s/in/is/?

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+bloom size defined by the bus. Each block of a mask is called a 'generation',
+starting at index 0.
+
+At match time, when a signal is about to be delivered, a bloom mask generation
+is passed, which denotes which of the bloom masks the filter should be matched
+against. This allows userspace to provide backward compatible masks at upload
+time, while older clients can still match against older versions of filters.
+
+
+10.5 Removing a match

Documentation/kdbus.txt line 1524

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+--------------------
+
+Matches can be removed through the KDBUS_CMD_MATCH_REMOVE ioctl, which again
+takes struct kdbus_cmd_match as argument, but its fields are used slightly
+differently.
+
+struct kdbus_cmd_match {
+  __u64 size;
+    The overall size of the struct. As it has no items in this use case, the
+    value should yield 16.

s/yield/contain/ ?

Documentation/kdbus.txt line 1537

Quoted 13 lines
Documentation/kdbus.txt new file +13 -0
+
+  __u64 cookie;
+    The cookie of the match, as it was passed when the match was added.
+    All matches that have this cookie will be removed.
+
+  __u64 flags;
+    Unused for this use case,
+
+  __u64 kernel_flags;
+    Valid flags for this command, returned by the kernel upon each call.
+
+  __u64 return_flags;
+    Flags returned by the kernel. Currently unused.

And, so presumably always returned as 0? Best to note that.

Documentation/kdbus.txt line 1548

Quoted 11 lines
Documentation/kdbus.txt new file +11 -0
+
+  struct kdbus_item items[0];
+    Unused und not allowed for this use case.
+};
+
+
+11. Policy
+===============================================================================
+
+A policy databases restrict the possibilities of connections to own, see and
+talk to well-known names. It can be associated with a bus (through a policy

s/It/A policy/

Documentation/kdbus.txt line 1556

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+holder connection) or a custom endpoint.
+
+See section 8.1 for more details on the validity of well-known names.
+
+Default endpoints of buses always have a policy database. The default
+policy is to deny all operations except for operations that are covered by
+implicit policies. Custom endpoints always have a policy, and by default,
+a policy database is empty. Therefore, unless policy rules are added, all

s/a policy database/the policy database/

Quoted 48 lines
Documentation/kdbus.txt new file +48 -0
+operations will also be denied by default.
+
+See section 11.5 for more details on implicit policies.
+
+A set of policy rules is described by a name and multiple access rules, defined
+by the following struct.
+
+struct kdbus_policy_access {
+  __u64 type;	/* USER, GROUP, WORLD */
+    One of the following.
+
+    KDBUS_POLICY_ACCESS_USER
+      Grant access to a user with the uid stored in the 'id' field.
+
+    KDBUS_POLICY_ACCESS_GROUP
+      Grant access to a user with the gid stored in the 'id' field.
+
+    KDBUS_POLICY_ACCESS_WORLD
+      Grant access to everyone. The 'id' field is ignored.
+
+  __u64 access;	/* OWN, TALK, SEE */
+    The access to grant.
+
+    KDBUS_POLICY_SEE
+      Allow the name to be seen.
+
+    KDBUS_POLICY_TALK
+      Allow the name to be talked to.
+
+    KDBUS_POLICY_OWN
+      Allow the name to be owned.
+
+  __u64 id;
+    For KDBUS_POLICY_ACCESS_USER, stores the uid.
+    For KDBUS_POLICY_ACCESS_GROUP, stores the gid.
+};
+
+Policies are set through KDBUS_CMD_HELLO (when creating a policy holder
+connection), KDBUS_CMD_CONN_UPDATE (when updating a policy holder connection),
+KDBUS_CMD_ENDPOINT_MAKE (creating a custom endpoint) or
+KDBUS_CMD_ENDPOINT_UPDATE (updating a custom endpoint). In all cases, the name
+and policy access information is stored in items of type KDBUS_ITEM_NAME and
+KDBUS_ITEM_POLICY_ACCESS. For this transport, the following rules apply.
+
+  * An item of type KDBUS_ITEM_NAME must be followed by at least one
+    KDBUS_ITEM_POLICY_ACCESS item
+  * An item of type KDBUS_ITEM_NAME can be followed by an arbitrary number of
+    KDBUS_ITEM_POLICY_ACCESS items

Documentation/kdbus.txt line 1614

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  * An arbitrary number of groups of names and access levels can be passed
+
+uids and gids are internally always stored in the kernel's view of global ids,
+and are translated back and forth on the ioctl level accordingly.
+
+
+11.2 Wildcard names
+-------------------
+
+Policy holder connections may upload names that contain the wild card suffix

s/wild card/wildcard/

Documentation/kdbus.txt line 1618

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+(".*"). That way, a policy can be uploaded that is effective for every
+well-known name that extends the provided name by exactly one more level.
+
+For example, if an item of a set up uploaded policy rules contains the name

I find that last line very difficult to parse. Someehting is broken. What are you trying to say?

Quoted 1 line

+"foo.bar.*", both "foo.bar.baz" and "foo.bar.bazbaz" are valid, but

s/both/then both/ to help parsing.

Quoted 36 lines

+"foo.bar.baz.baz" is not.

Documentation/kdbus.txt new file +35 -0
+
+This allows connections to take control over multiple names that the policy
+holder doesn't need to know about when uploading the policy.
+
+Such wildcard entries are not allowed for custom endpoints.
+
+
+11.3 Policy example
+-------------------
+
+For example, a set of policy rules may look like this:
+
+  KDBUS_ITEM_NAME: str='org.foo.bar'
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, id=1000
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, id=1001
+  KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE
+  KDBUS_ITEM_NAME: str='org.blah.baz'
+  KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, id=0
+  KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK
+
+That means that 'org.foo.bar' may only be owned by uid 1000, but every user on
+the bus is allowed to see the name. However, only uid 1001 may actually send
+a message to the connection and receive a reply from it.
+
+The second rule allows 'org.blah.baz' to be owned by uid 0 only, but every user
+may talk to it.
+
+
+11.4 TALK access and multiple well-known names per connection
+-------------------------------------------------------------
+
+Note that TALK access is checked against all names of a connection.
+For example, if a connection owns both 'org.foo.bar' and 'org.blah.baz', and
+the policy database allows 'org.blah.baz' to be talked to by WORLD, then this
+permission is also granted to 'org.foo.bar'. That might sound illogical, but

Documentation/kdbus.txt line 1665

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+after all, we allow messages to be directed to either the ID or a well-known
+name, and policy is applied to the connection, not the name. In other words,
+the effective TALK policy for a connection is the most permissive of all names
+the connection owns.
+
+For broadcast messages, the receiver needs TALK permissions to the sender to
+receive the broadcast.
+
+If a policy database exists for a bus (because a policy holder created one on
+demand) or for a custom endpoint (which always has one), each one is consulted

By "created one on demand" do you mean "explicitly created one"? If so please use the latter wording, since its clearer.

Quoted 1 line

+during name registry listing, name owning or message delivery. If either one

What is "name owning". I think this could be worded better.

Quoted 42 lines
Documentation/kdbus.txt new file +42 -0
+fails, the operation is failed with -EPERM.
+
+For best practices, connections that own names with a restricted TALK
+access should not install matches. This avoids cases where the sent
+message may pass the bloom filter due to false-positives and may also
+satisfy the policy rules.
+
+
+11.5 Implicit policies
+----------------------
+
+Depending on the type of the endpoint, a set of implicit rules that
+override installed policies might be enforced.
+
+On default endpoints, the following set is enforced and checked before
+any user-supplied policy is checked.
+
+  * Privileged connections always override any installed policy. Those
+    connections could easily install their own policies, so there is no
+    reason to enforce installed policies.
+  * Connections can always talk to connections of the same user. This
+    includes broadcast messages.
+
+Custom endpoints have stricter policies. The following rules apply:
+
+  * Policy rules are always enforced, even if the connection is a privileged
+    connection.
+  * Policy rules are always enforced for TALK access, even if both ends are
+    running under the same user. This includes broadcast messages.
+  * To restrict the set of names that can be seen, endpoint policies can
+    install "SEE" policies.
+
+
+12. Pool
+===============================================================================
+
+A pool for data received from the kernel is installed for every connection of
+the bus, and is sized according to the information stored in the
+KDBUS_ITEM_BLOOM_PARAMETER item that is returned by KDBUS_CMD_HELLO.
+
+The pool is written to by the kernel when one of the following ioctls is issued:
+

Documentation/kdbus.txt line 1718

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  * KDBUS_CMD_HELLO, to receive details about the bus the connection was made to
+  * KDBUS_CMD_RECV, to receive a message
+  * KDBUS_CMD_NAME_LIST, to dump the name registry
+  * KDBUS_CMD_CONN_INFO, to retrieve information on a connection
+
+The offsets returned by either one of the aforementioned ioctls describe offsets
+inside the pool. In order to make the slice available for subsequent calls,
+KDBUS_CMD_FREE has to be called on the offset.
+
+To access the memory, the caller is expected to mmap() it to its task, like

s/to its task//

Quoted 19 lines
Documentation/kdbus.txt new file +19 -0
+this:
+
+  /*
+   * POOL_SIZE has to be a multiple of PAGE_SIZE, and it must match the
+   * value that was previously returned through the KDBUS_ITEM_BLOOM_PARAMETER
+   * item field when the KDBUS_CMD_HELLO ioctl returned.
+   */
+
+  buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, conn_fd, 0);
+
+Alternatively, instead of mapping the entire pool buffer, only parts of it can
+be mapped. The length of the response is returned by the kernel along with the
+offset for each of the ioctls listed above.
+
+
+13. Metadata
+===============================================================================
+
+kdbus records data about the system in certain situations. Such metadata can

Documentation/kdbus.txt line 1747

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+refer to the currently active process (creds, PIDs, current user groups, process
+names and its executable path, cgroup membership, capabilities, security label
+and audit information), connection information (description string, currently
+owned names) and the timestamp.
+
+Metadata is collected in the following circumstances:
+
+  * When a bus is created (KDBUS_CMD_MAKE), information about the calling task
+    is collected. This data is returned by the kernel via the
+    KDBUS_CMD_BUS_CREATOR_INFO call-

s/-/./

Documentation/kdbus.txt line 1751

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+
+  * When a connection is created (KDBUS_CMD_HELLO), information about the
+    calling task is collected. Alternatively, a privileged connection may
+    provide 'faked' information about credentials, PIDs and a security labels

s/a security/security/

Quoted 123 lines
Documentation/kdbus.txt new file +123 -0
+    which will be taken instead. This data is returned by the kernel as
+    information on a connection (KDBUS_CMD_CONN_INFO).
+
+  * When a message is sent (KDBUS_CMD_SEND), information about the sending task
+    and the sending connection are collected. This metadata will be attached
+    to the message when it arrives in the receiver's pool. If the connection
+    sending the message installed faked credentials (see above), the message
+    will not be augmented by any information about the currently sending task.
+
+Which metadata items are actually delivered depends on the following sets and
+masks:
+
+    (a) the system-wide kmod creds mask (module parameter 'attach_flags_mask')
+    (b) the per-connection send creds mask, set by the connecting client
+    (c) the per-connection receive creds mask, set by the connecting client
+    (d) the per-bus minimal creds mask, set by the bus creator
+    (e) the per-bus owner creds mask, set by the bus creator
+    (f) the mask specified when querying creds of a bus peer
+    (g) the mask specified when querying creds of a bus owner
+
+With the following rules:
+
+    [1] The creds attached to messages are determined as (a & b & c).
+    [2] When connecting to a bus (KDBUS_CMD_HELLO), and (~b & d) != 0, the call
+        will fail, the connection is refused.
+    [3] When querying creds of a bus peer, the creds returned are  (a & b & f)
+    [4] When querying creds of a bus owner, the creds returned are (a & e & g)
+    [5] When creating a new bus, and (d & ~a) != 0, then bus creation will fail
+
+Hence, userspace might not always get all requested metadata items that it
+requested. Code must be written so that it can cope with this fact.
+
+
+13.1 Known item types
+---------------------
+
+The following attach flags are currently supported.
+
+  KDBUS_ATTACH_TIMESTAMP
+    Attaches an item of type KDBUS_ITEM_TIMESTAMP which contains both the
+    monotonic and the realtime timestamp, taken when the message was
+    processed on the kernel side.
+
+  KDBUS_ATTACH_CREDS
+    Attaches an item of type KDBUS_ITEM_CREDS, containing credentials as
+    described in struct kdbus_creds: the user and group IDs in the usual four
+    flavors: real, effective, saved and file-system related.
+
+  KDBUS_ATTACH_PIDS
+    Attaches an item of type KDBUS_ITEM_PIDS, containing information on the
+    process. In particular, the PID (process ID), TID (thread ID), and PPID
+    (PID of the parent process).
+
+  KDBUS_ATTACH_AUXGROUPS
+    Attaches an item of type KDBUS_ITEM_AUXGROUPS, containing a dynamic
+    number of auxiliary groups the sending task was a member of.
+
+  KDBUS_ATTACH_NAMES
+    Attaches items of type KDBUS_ITEM_OWNED_NAME, one for each name the sending
+    connection currently owns. The name and flags are stored in kdbus_item.name
+    for each of them.
+
+  KDBUS_ATTACH_TID_COMM [*]
+    Attaches an items of type KDBUS_ITEM_TID_COMM, transporting the sending
+    task's 'comm', for the tid.  The string is stored in kdbus_item.str.
+
+  KDBUS_ATTACH_PID_COMM [*]
+    Attaches an items of type KDBUS_ITEM_PID_COMM, transporting the sending
+    task's 'comm', for the pid.  The string is stored in kdbus_item.str.
+
+  KDBUS_ATTACH_EXE [*]
+    Attaches an item of type KDBUS_ITEM_EXE, containing the path to the
+    executable of the sending task, stored in kdbus_item.str.
+
+  KDBUS_ATTACH_CMDLINE [*]
+    Attaches an item of type KDBUS_ITEM_CMDLINE, containing the command line
+    arguments of the sending task, as an array of strings, stored in
+    kdbus_item.str.
+
+  KDBUS_ATTACH_CGROUP
+    Attaches an item of type KDBUS_ITEM_CGROUP with the task's cgroup path.
+
+  KDBUS_ATTACH_CAPS
+    Attaches an item of type KDBUS_ITEM_CAPS, carrying sets of capabilities
+    that should be accessed via kdbus_item.caps.caps. Also, userspace should
+    be written in a way that it takes kdbus_item.caps.last_cap into account,
+    and derive the number of sets and rows from the item size and the reported
+    number of valid capability bits.
+
+  KDBUS_ATTACH_SECLABEL
+    Attaches an item of type KDBUS_ITEM_SECLABEL, which contains the SELinux
+    security label of the sending task. SELinux and other MACs might want to
+    do additional per-service security checks. For example, a service manager
+    might want to check the security label of a service file against the
+    security label of the client process checking the SELinux database before
+    allowing access.  The label can be accessed via kdbus_item->str.
+
+  KDBUS_ATTACH_AUDIT
+    Attaches an item of type KDBUS_ITEM_AUDIT, which contains the audit
+    sessionid and loginuid of the sending task. Access via kdbus_item->audit.
+
+  KDBUS_ATTACH_CONN_DESCRIPTION
+    Attaches an item of type KDBUS_ITEM_CONN_DESCRIPTION that contains a
+    descriptive string of the sending peer. That string can be supplied
+    during HELLO by attaching an item of type KDBUS_ITEM_CONN_DESCRIPTION.
+
+
+[*] Note that the content stored in these items can easily be tampered by
+    the sending tasks. Therefore, they should NOT be used for any sort of
+    security relevant assumptions. The only reason why they are transmitted is
+    to let receivers know about details that were set when metadata was
+    collected, even though the task they were collected from is not active any
+    longer when the items are received.
+
+
+13.2 Metadata and namespaces
+----------------------------
+
+Metadata such as PIDs, UIDs or GIDs are automatically translated to the
+namespaces of the task that receives them.
+
+
+14. Error codes

Documentation/kdbus.txt line 1884

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+===============================================================================
+
+Below is a list of error codes that might be returned by the individual
+ioctl commands. The list focuses on the return values from kdbus code itself,
+and might not cover those of all kernel internal functions.
+
+For all ioctls:
+
+  -ENOMEM	The kernel memory is exhausted
+  -ENOTTY	Illegal ioctl command issued for the file descriptor

Why ENOTTY here, rather than EINVAL? The latter is, I beleive, the usual ioctl() error for invalid commands, I believe (If you keep ENOTTY, add an explanation in this document.)

Quoted 1 line

+ -ENOSYS The requested functionality is not available

Maybe add here an explanation or examples of why the functionality is not available?

Documentation/kdbus.txt line 1893

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+  -EINVAL	Unsupported item attached to command
+
+For all ioctls that carry a struct as payload:
+
+  -EFAULT	The supplied data pointer was not 64-bit aligned, or was
+		inaccessible from the kernel side.
+  -EINVAL	The size inside the supplied struct was smaller than expected
+  -EMSGSIZE	The size inside the supplied struct was bigger than expected

Why two different errors for smaller and larger than expected? (If you keep things this way, pelase explain the reason in this document.)

Quoted 19 lines
Documentation/kdbus.txt new file +19 -0
+  -ENAMETOOLONG	A supplied name is larger than the allowed maximum size
+
+For KDBUS_CMD_BUS_MAKE:
+
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid or
+		the supplied name does not start with the current uid and a '-'
+  -EEXIST	A bus of that name already exists
+  -ESHUTDOWN	The domain for the bus is already shut down
+  -EMFILE	The maximum number of buses for the current user is exhausted
+
+For KDBUS_CMD_ENDPOINT_MAKE:
+
+  -EPERM	The calling user is not privileged (see Terminology)
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid
+  -EEXIST	An endpoint of that name already exists
+
+For KDBUS_CMD_HELLO:
+
+  -EFAULT	The supplied pool size was 0 or not a multiple of the page size

Documentation/kdbus.txt line 1922

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  -EINVAL	The flags supplied in the kdbus_cmd_make struct are invalid, or
+		an illegal combination of KDBUS_HELLO_MONITOR,
+		KDBUS_HELLO_ACTIVATOR and KDBUS_HELLO_POLICY_HOLDER was passed
+		in the flags, or an invalid set of items was supplied
+  -ECONNREFUSED	The attach_flags_send field did not satisfy the requirements of
+		the bus
+  -EPERM	An KDBUS_ITEM_CREDS items was supplied, but the current user is
+		not privileged
+  -ESHUTDOWN	The bus has already been shut down
+  -EMFILE	The maximum number of connection on the bus has been reached

s/connection/connections/

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+  -EOPNOTSUPP	The endpoint does not support the connection flags
+		supplied in the kdbus_cmd_hello struct
+
+For KDBUS_CMD_BYEBYE:
+
+  -EALREADY	The connection has already been shut down
+  -EBUSY	There are still messages queued up in the connection's pool
+

Documentation/kdbus.txt line 1940

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+For KDBUS_CMD_SEND:
+
+  -EOPNOTSUPP	The connection is not an ordinary connection, or the passed
+		file descriptors are either kdbus handles or unix domain
+		sockets. Both are currently unsupported
+  -EINVAL	The submitted payload type is KDBUS_PAYLOAD_KERNEL,
+		KDBUS_MSG_EXPECT_REPLY was set without timeout or cookie
+		values, KDBUS_MSG_SYNC_REPLY was set without
+		KDBUS_MSG_EXPECT_REPLY, an invalid item was supplied,
+		src_id was != 0 and different from the current connection's ID,

s/src_id was != 0 and different/src_id was nonzero and was different/

Quoted 47 lines
Documentation/kdbus.txt new file +47 -0
+		a supplied memfd had a size of 0, a string was not properly
+		null-terminated
+  -ENOTUNIQ	The supplied destination is KDBUS_DST_ID_BROADCAST, a file
+		descriptor was passed, KDBUS_MSG_EXPECT_REPLY was set,
+		or a timeout was given for a broadcast message
+  -E2BIG	Too many items
+  -EMSGSIZE	The size of the message header and items or the payload vector
+		is too big.
+  -EEXIST	Multiple KDBUS_ITEM_FDS, KDBUS_ITEM_BLOOM_FILTER or
+		KDBUS_ITEM_DST_NAME items were supplied
+  -EBADF	The supplied KDBUS_ITEM_FDS or KDBUS_MSG_PAYLOAD_MEMFD items
+		contained an illegal file descriptor
+  -EMEDIUMTYPE	The supplied memfd is not a sealed kdbus memfd
+  -EMFILE	Too many file descriptors inside a KDBUS_ITEM_FDS
+  -EBADMSG	An item had illegal size, both a dst_id and a
+		KDBUS_ITEM_DST_NAME was given, or both a name and a bloom
+		filter was given
+  -ETXTBSY	The supplied kdbus memfd file cannot be sealed or the seal
+		was removed, because it is shared with other processes or
+		still mmap()ed
+  -ECOMM	A peer does not accept the file descriptors addressed to it
+  -EFAULT	The supplied bloom filter size was not 64-bit aligned
+  -EDOM		The supplied bloom filter size did not match the bloom filter
+		size of the bus
+  -EDESTADDRREQ	dst_id was set to KDBUS_DST_ID_NAME, but no KDBUS_ITEM_DST_NAME
+		was attached
+  -ESRCH	The name to look up was not found in the name registry
+  -EADDRNOTAVAIL KDBUS_MSG_NO_AUTO_START was given but the destination
+		 connection is an activator.
+  -ENXIO	The passed numeric destination connection ID couldn't be found,
+		or is not connected
+  -ECONNRESET	The destination connection is no longer active
+  -ETIMEDOUT	Timeout while synchronously waiting for a reply
+  -EINTR	System call interrupted while synchronously waiting for a reply
+  -EPIPE	When sending a message, a synchronous reply from the receiving
+		connection was expected but the connection died before
+		answering
+  -ENOBUFS	Too many pending messages on the receiver side
+  -EREMCHG	Both a well-known name and a unique name (ID) was given, but
+		the name is not currently owned by that connection.
+  -EXFULL	The memory pool of the receiver is full
+  -EREMOTEIO	While synchronously waiting for a reply, the remote peer
+		failed with an I/O error.
+
+For KDBUS_CMD_RECV:
+
+  -EINVAL	Invalid flags or offset

Documentation/kdbus.txt line 1997

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+  -EAGAIN	No message found in the queue
+  -ENOMSG	No message of the requested priority found
+  -EOVERFLOW	Broadcast messages have been lost
+
+For KDBUS_CMD_FREE:
+
+  -ENXIO	No pool slice found at given offset
+  -EINVAL	Invalid flags provided, the offset is valid, but the user is
+		not allowed to free the slice. This happens, for example, if
+		the offset was retrieved with KDBUS_RECV_PEEK.

It would be easier to read if this was written to clarify that there are two distinct error cases:

-EINVAL Invalid flags provided.
-EINVAL The offset is valid, but the user is
not allowed to free the slice. This happens, for example, if the offset was retrieved with KDBUS_RECV_PEEK.

Quoted 99 lines
Documentation/kdbus.txt new file +99 -0
+For KDBUS_CMD_NAME_ACQUIRE:
+
+  -EINVAL	Illegal command flags, illegal name provided, or an activator
+		tried to acquire a second name
+  -EPERM	Policy prohibited name ownership
+  -EALREADY	Connection already owns that name
+  -EEXIST	The name already exists and can not be taken over
+  -E2BIG	The maximum number of well-known names per connection
+		is exhausted
+  -ECONNRESET	The connection was reset during the call
+
+For KDBUS_CMD_NAME_RELEASE:
+
+  -EINVAL	Invalid command flags, or invalid name provided
+  -ESRCH	Name is not found found in the registry
+  -EADDRINUSE	Name is owned by a different connection and can't be released
+
+For KDBUS_CMD_NAME_LIST:
+
+  -EINVAL	Invalid flags
+  -ENOBUFS	No available memory in the connection's pool.
+
+For KDBUS_CMD_CONN_INFO:
+
+  -EINVAL	Invalid flags, or neither an ID nor a name was provided,
+		or the name is invalid.
+  -ESRCH	Connection lookup by name failed
+  -ENXIO	No connection with the provided connection ID found
+
+For KDBUS_CMD_CONN_UPDATE:
+
+  -EINVAL	Illegal flags or items
+  -EOPNOTSUPP	Operation not supported by connection.
+  -E2BIG	Too many policy items attached
+  -EINVAL	Wildcards submitted in policy entries, or illegal sequence
+		of policy items
+
+For KDBUS_CMD_ENDPOINT_UPDATE:
+
+  -E2BIG	Too many policy items attached
+  -EINVAL	Invalid flags, or wildcards submitted in policy entries,
+		or illegal sequence of policy items
+
+For KDBUS_CMD_MATCH_ADD:
+
+  -EINVAL	Illegal flags or items
+  -EDOM		Illegal bloom filter size
+  -EMFILE	Too many matches for this connection
+
+For KDBUS_CMD_MATCH_REMOVE:
+
+  -EINVAL	Illegal flags
+  -ENOENT	A match entry with the given cookie could not be found.
+
+
+15. Internal object relations
+===============================================================================
+
+This is a simplified outline of the internal kdbus object relations, for
+those interested in the inner life of the driver implementation.
+
+From the a mount point's (domain's) perspective:
+
+struct kdbus_domain
+  |» struct kdbus_domain_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_domain_user *user (pinned)
+              |   `» struct kdbus_queue_entry entries (many, embedded)
+              |        |» struct kdbus_pool_slice *slice (pinned)
+              |        |» struct kdbus_conn_reply *reply (owned)
+              |        '» struct kdbus_domain_user *user (pinned)
+              |
+              '» struct kdbus_domain_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)

Documentation/kdbus.txt line 2107

Quoted 10 lines
Documentation/kdbus.txt new file +10 -0
+
+
+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)

Thanks,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#47 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael,

Thanks a lot for for intense review of the documentation. Much appreciated.

I've addressed all but the below issues, following your suggestions.

Quoted 6 lines · Michael Kerrisk (man-pages)

Documentation/kdbus.txt line 355

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+    and KDBUS_CMD_ENDPOINT_MAKE (see above).
+
+    Following items are expected for KDBUS_CMD_BUS_MAKE:
+    KDBUS_ITEM_MAKE_NAME
+      Contains a string to identify the bus name.
Quoted 6 lines

So, up to here, I've seen no definition of 'kdbus_item', which leaves me asking questions like: what subfield is KDBUS_ITEM_MAKE_NAME stored in? which subfield holds the pointer to the string?

Somewhere earlier, kdbus_item needs to be exaplained in more detail, I think.

Hmm, you're quoting text from section 5, and section 4 actually describes the concept of items quite well I believe?

Quoted 8 lines

Documentation/kdbus.txt line 1049

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+  __s64 priority;
+    With KDBUS_RECV_USE_PRIORITY set in flags, receive the next message in
+    the queue with at least the given priority. If no such message is waiting
+    in the queue, -ENOMSG is returned.

###
How do I simply select the highest priority message, without knowing what its priority is?

The wording is indeed unclear here. KDBUS_RECV_USE_PRIORITY causes the messages to be dequeued by their priority. The 'priority' field is simply a filter that request a minimum priority. By setting this field to the highest possible value, you effectively bypass the filter. I've added a better description now.

Quoted 6 lines

Documentation/kdbus.txt line 1884

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+  -ENOMEM	The kernel memory is exhausted
+  -ENOTTY	Illegal ioctl command issued for the file descriptor

Why ENOTTY here, rather than EINVAL? The latter is, I beleive, the usual ioctl() error for invalid commands, I believe (If you keep ENOTTY, add an explanation in this document.)

Hmm, no. -ENOTTY is commonly used as return code when calling ioctls that can't be handled by the FDs they're called on. 'man errno(3)' even
states: "ENOTTY Inappropriate I/O control operation (POSIX.1)".

Quoted 11 lines

Documentation/kdbus.txt line 1893

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+  -EINVAL	Unsupported item attached to command
+
+For all ioctls that carry a struct as payload:
+
+  -EFAULT	The supplied data pointer was not 64-bit aligned, or was
+		inaccessible from the kernel side.
+  -EINVAL	The size inside the supplied struct was smaller than expected
+  -EMSGSIZE	The size inside the supplied struct was bigger than expected

Why two different errors for smaller and larger than expected? (If you keep things this way, pelase explain the reason in this document.)

Providing a struct that is smaller than the minimum doesn't give the ioctl a valid set of information to process the request. Hence, I think -EINVAL is appropriate. However, -EMSGSIZE is something that users might hit when they make message payloads too big, and I think it's good to have a change to distinguish the two cases in error handling. I added something in the document now.

Again, thanks a lot for reading the documentation so accurately!

Daniel

#48 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Daniel,

Quoted 5 lines · Daniel Mack

Hi Michael,

Thanks a lot for for intense review of the documentation. Much appreciated.

I've addressed all but the below issues, following your suggestions.

Are your changes already visible somewhere?

Quoted 11 lines · Michael Kerrisk (man-pages)
Quoted 10 lines

Documentation/kdbus.txt line 355

Quoted 5 lines
Documentation/kdbus.txt new file +5 -0
+    and KDBUS_CMD_ENDPOINT_MAKE (see above).
+
+    Following items are expected for KDBUS_CMD_BUS_MAKE:
+    KDBUS_ITEM_MAKE_NAME
+      Contains a string to identify the bus name.

So, up to here, I've seen no definition of 'kdbus_item', which leaves me asking questions like: what subfield is KDBUS_ITEM_MAKE_NAME stored in? which subfield holds the pointer to the string?

Quoted 5 lines
Quoted 2 lines

Somewhere earlier, kdbus_item needs to be exaplained in more detail, I think.

Hmm, you're quoting text from section 5, and section 4 actually describes the concept of items quite well I believe?

Well, Section 4 is pretty short. My point is that most of the various blob formats (e.g., kdbus_pids, kdbus_caps, kdbus_memfd) are not documented in kdbus.txt. They all should be, IMO.

Quoted 9 lines
Quoted 8 lines

Documentation/kdbus.txt line 1049

Quoted 4 lines
Documentation/kdbus.txt new file +4 -0
+  __s64 priority;
+    With KDBUS_RECV_USE_PRIORITY set in flags, receive the next message in
+    the queue with at least the given priority. If no such message is waiting
+    in the queue, -ENOMSG is returned.

###
How do I simply select the highest priority message, without knowing what its priority is?

Quoted 5 lines

The wording is indeed unclear here. KDBUS_RECV_USE_PRIORITY causes the messages to be dequeued by their priority. The 'priority' field is simply a filter that request a minimum priority. By setting this field to the highest possible value, you effectively bypass the filter. I've added a better description now.

Thanks for the clarification.

Quoted 10 lines
Quoted 6 lines

Documentation/kdbus.txt line 1884

Quoted 2 lines
Documentation/kdbus.txt new file +2 -0
+  -ENOMEM	The kernel memory is exhausted
+  -ENOTTY	Illegal ioctl command issued for the file descriptor

Why ENOTTY here, rather than EINVAL? The latter is, I beleive, the usual ioctl() error for invalid commands, I believe (If you keep ENOTTY, add an explanation in this document.)

Hmm, no. -ENOTTY is commonly used as return code when calling ioctls that can't be handled by the FDs they're called on. 'man errno(3)' even
states: "ENOTTY Inappropriate I/O control operation (POSIX.1)".

Okay.

Quoted 12 lines
Quoted 11 lines

Documentation/kdbus.txt line 1893

Quoted 8 lines
Documentation/kdbus.txt new file +8 -0
+  -EINVAL	Unsupported item attached to command
+
+For all ioctls that carry a struct as payload:
+
+  -EFAULT	The supplied data pointer was not 64-bit aligned, or was
+		inaccessible from the kernel side.
+  -EINVAL	The size inside the supplied struct was smaller than expected
+  -EMSGSIZE	The size inside the supplied struct was bigger than expected

Why two different errors for smaller and larger than expected? (If you keep things this way, pelase explain the reason in this document.)

Quoted 6 lines

Providing a struct that is smaller than the minimum doesn't give the ioctl a valid set of information to process the request. Hence, I think -EINVAL is appropriate. However, -EMSGSIZE is something that users might hit when they make message payloads too big, and I think it's good to have a change to distinguish the two cases in error handling. I added something in the document now.

Thanks.

Quoted 1 line

Again, thanks a lot for reading the documentation so accurately!

You're welcome.

Cheers,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#49 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Hi Michael,

Quoted 5 lines · Michael Kerrisk (man-pages)
Quoted 1 line · Daniel Mack

I've addressed all but the below issues, following your suggestions.

Are your changes already visible somewhere?

Yes, in the upstream repo for the standalone module, which we also use to build the patch set from:

https://code.google.com/p/d-bus/source/browse/kdbus.txt

Quoted 6 lines
Quoted 2 lines

Hmm, you're quoting text from section 5, and section 4 actually describes the concept of items quite well I believe?

Well, Section 4 is pretty short. My point is that most of the various blob formats (e.g., kdbus_pids, kdbus_caps, kdbus_memfd) are not documented in kdbus.txt. They all should be, IMO.

Okay, I'll add some text about them.

Best regards,
Daniel

#50 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Michael Kerrisk (man-pages)

Daniel,

Quoted 3 lines · Michael Kerrisk (man-pages)
Quoted 2 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

[...]

Quoted 10 lines

Documentation/kdbus.txt line 1098

Quoted 7 lines
Documentation/kdbus.txt new file +7 -0
+offset field contains the location of the new message inside the receiver's
+pool. The message is stored as struct kdbus_msg at this offset, and can be
+interpreted with the semantics described above.
+
+Also, if the connection allowed for file descriptor to be passed
+(KDBUS_HELLO_ACCEPT_FD), and if the message contained any, they will be
+installed into the receiving process after the KDBUS_CMD_RECV ioctl returns.

###
"after"??? When exactly?

By the way, what was the answer to this question?

Cheers,

Michael

Signature · 3 lines
Michael Kerrisk
Linux man-pages maintainer; http://www.kernel.org/doc/man-pages/
Linux/UNIX System Programming Training: http://man7.org/training/
#51 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 10 lines · Michael Kerrisk (man-pages)
Quoted 6 lines · Michael Kerrisk (man-pages)

Documentation/kdbus.txt line 1098

Quoted 3 lines
Documentation/kdbus.txt new file +3 -0
+Also, if the connection allowed for file descriptor to be passed
+(KDBUS_HELLO_ACCEPT_FD), and if the message contained any, they will be
+installed into the receiving process after the KDBUS_CMD_RECV ioctl returns.

###
"after"??? When exactly?

By the way, what was the answer to this question?

I've corrected the wording on this. The file descriptors are installed when the RECV ioctl is called, so they are ready to use when the call returns.

Thanks,
Daniel

#52 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Greg Kroah-Hartman
Quoted 8 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus.

Pardon my ignorance, but we've always been told that adding new ioctl()s to the kernel is a very big no-no. But given the seniority of the folks stewarding this kdbus effort, there must be a good rationale ;-)

So, can the rationale behind introducing new ioctl()s be further explained? It would be even better if it's included in the documentation patch itself.

Thanks,
Darwish

#53 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 10 lines · Ahmed S. Darwish
Quoted 8 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus.

Quoted 8 lines

Pardon my ignorance, but we've always been told that adding new ioctl()s to the kernel is a very big no-no. But given the seniority of the folks stewarding this kdbus effort, there must be a good rationale ;-)

So, can the rationale behind introducing new ioctl()s be further explained? It would be even better if it's included in the documentation patch itself.

The main reason to use an ioctl is that you want to atomically set and/or get something "complex" through the user/kernel boundary. For simple device attributes, sysfs works great, for configuring devices, configfs works great, but for data streams / structures / etc. an ioctl is the correct thing to use.

Examples of new ioctls being added to the kernel are all over the place, look at all of the special-purpose ioctls the filesystems keep creating (they aren't adding new syscalls), look at the monstrosity that is the DRM layer, look at other complex things like openvswitch, or "simpler" device-specific interfaces like the MEI one, or even more complex ones like the MMC interface. These are all valid uses of ioctls as they are device/filesystem specific ways to interact with the kernel.

The thing is, almost no one pays attention to these new ioctls as they are domain-specific interfaces, with open userspace programs talking to them, and they work well. ioctl is a powerful and useful interface, and if we were to suddenly require no new ioctls, and require everything to be a syscall, we would do nothing except make apis more complex (hint, you now have to do extra validation on your file descriptor passed to you to determine if it really is what you can properly operate your ioctl on), and cause no real benefit at all.

Yes, people abuse ioctls at times, but really, they are needed.

And remember, I was one of the people who long ago thought we should not be adding more ioctls, but I have seen the folly of my ways, and chalk it up to youthful ignorance :)

Hope this helps explain things better,

greg k-h

#54 lore raw

Re: [PATCH 01/13] kdbus: add documentation

Quoted 26 lines · Greg Kroah-Hartman
Quoted 10 lines · Ahmed S. Darwish
Quoted 8 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus.

Quoted 8 lines

Pardon my ignorance, but we've always been told that adding new ioctl()s to the kernel is a very big no-no. But given the seniority of the folks stewarding this kdbus effort, there must be a good rationale ;-)

So, can the rationale behind introducing new ioctl()s be further explained? It would be even better if it's included in the documentation patch itself.

The main reason to use an ioctl is that you want to atomically set and/or get something "complex" through the user/kernel boundary. For simple device attributes, sysfs works great, for configuring devices, configfs works great, but for data streams / structures / etc. an ioctl is the correct thing to use.

Quoted 6 lines

Examples of new ioctls being added to the kernel are all over the place, look at all of the special-purpose ioctls the filesystems keep creating (they aren't adding new syscalls), look at the monstrosity that is the DRM layer, look at other complex things like openvswitch, or "simpler" device-specific interfaces like the MEI one, or even more complex ones like the MMC interface.

Oops, I meant, MIC, not MMC, sorry about that.

#55 lore raw

Re: [PATCH 01/13] kdbus: add documentation

In reply to Greg Kroah-Hartman
Quoted 43 lines · Greg Kroah-Hartman
Quoted 10 lines · Ahmed S. Darwish
Quoted 8 lines · Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbus is a system for low-latency, low-overhead, easy to use interprocess communication (IPC).

The interface to all functions in this driver is implemented via ioctls on files exposed through a filesystem called 'kdbusfs'. The default mount point of kdbusfs is /sys/fs/kdbus.

Quoted 8 lines

Pardon my ignorance, but we've always been told that adding new ioctl()s to the kernel is a very big no-no. But given the seniority of the folks stewarding this kdbus effort, there must be a good rationale ;-)

So, can the rationale behind introducing new ioctl()s be further explained? It would be even better if it's included in the documentation patch itself.

The main reason to use an ioctl is that you want to atomically set and/or get something "complex" through the user/kernel boundary. For simple device attributes, sysfs works great, for configuring devices, configfs works great, but for data streams / structures / etc. an ioctl is the correct thing to use.

Examples of new ioctls being added to the kernel are all over the place, look at all of the special-purpose ioctls the filesystems keep creating (they aren't adding new syscalls), look at the monstrosity that is the DRM layer, look at other complex things like openvswitch, or "simpler" device-specific interfaces like the MEI one, or even more complex ones like the MMC interface. These are all valid uses of ioctls as they are device/filesystem specific ways to interact with the kernel.

The thing is, almost no one pays attention to these new ioctls as they are domain-specific interfaces, with open userspace programs talking to them, and they work well. ioctl is a powerful and useful interface, and if we were to suddenly require no new ioctls, and require everything to be a syscall, we would do nothing except make apis more complex (hint, you now have to do extra validation on your file descriptor passed to you to determine if it really is what you can properly operate your ioctl on), and cause no real benefit at all.

Quoted 6 lines

Yes, people abuse ioctls at times, but really, they are needed.

And remember, I was one of the people who long ago thought we should not be adding more ioctls, but I have seen the folly of my ways, and chalk it up to youthful ignorance :)

Exactly, and that's why I wondered about the sudden change of heart ;-)

Thanks for taking the time to write this.

Regards,
Darwish

#56 lore raw

PATCH v3 2/13 kdbus: add header file

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

This patch adds the header file which describes the low-level transport protocol used by various ioctls. The header file is located in include/uapi/linux/ as it is shared between kernel and userspace, and it only contains data structure definitionsi, enums and #defines for constants.

---
 include/uapi/linux/Kbuild  |    1 +
 include/uapi/linux/kdbus.h | 1049 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 1050 insertions(+)
 create mode 100644 include/uapi/linux/kdbus.h
include/uapi/linux/Kbuild +1 -0
index 00b100023c47..7c6d0cfe28f0 100644
@@ -213,6 +213,7 @@ header-y += ixjuser.h
 header-y += jffs2.h
 header-y += joystick.h
 header-y += kcmp.h
+header-y += kdbus.h
 header-y += kdev_t.h
 header-y += kd.h
 header-y += kernelcapi.h
include/uapi/linux/kdbus.h new file +1049 -0

1,049 lines not on this page · raw message

Signature · 1 line
2.2.1
#57 lore raw

PATCH v3 3/13 kdbus: add driver skeleton, ioctl entry points and utility functions

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

Add the basic driver structure.

handle.c is the main ioctl command dispatcher that calls into other parts of the driver.

main.c contains the code that creates the initial domain at startup, and util.c has utility functions such as item iterators that are shared with other files.

limits.h describes limits on things like maximum data structure sizes, number of messages per users and suchlike. Some of the numbers currently picked are rough ideas of what what might be sufficient and are probably rather conservative.

---
 Documentation/ioctl/ioctl-number.txt |    1 +
 ipc/kdbus/handle.c                   | 1134 ++++++++++++++++++++++++++++++++++
 ipc/kdbus/handle.h                   |   20 +
 ipc/kdbus/limits.h                   |   95 +++
 ipc/kdbus/main.c                     |   72 +++
 ipc/kdbus/util.c                     |  317 ++++++++++
 ipc/kdbus/util.h                     |  133 ++++
 7 files changed, 1772 insertions(+)
 create mode 100644 ipc/kdbus/handle.c
 create mode 100644 ipc/kdbus/handle.h
 create mode 100644 ipc/kdbus/limits.h
 create mode 100644 ipc/kdbus/main.c
 create mode 100644 ipc/kdbus/util.c
 create mode 100644 ipc/kdbus/util.h
Documentation/ioctl/ioctl-number.txt +1 -0
index 8136e1fd30fd..54e091ebb862 100644
@@ -292,6 +292,7 @@ Code  Seq#(hex)	Include File		Comments
 0x92	00-0F	drivers/usb/mon/mon_bin.c
 0x93	60-7F	linux/auto_fs.h
 0x94	all	fs/btrfs/ioctl.h
+0x95	all	uapi/linux/kdbus.h	kdbus IPC driver
 0x97	00-7F	fs/ceph/ioctl.h		Ceph file system
 0x99	00-0F				537-Addinboard driver
 					<mailto:[email protected]>
ipc/kdbus/handle.c new file +1134 -0

1,134 lines not on this page · raw message

ipc/kdbus/handle.h new file +20 -0
new file mode 100644
index 000000000000..32809dad3720
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 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
+
+extern const struct file_operations kdbus_handle_ep_ops;
+extern const struct file_operations kdbus_handle_control_ops;
+
+#endif
ipc/kdbus/limits.h new file +95 -0

95 lines not on this page · raw message

ipc/kdbus/main.c new file +72 -0

72 lines not on this page · raw message

ipc/kdbus/util.c new file +317 -0

317 lines not on this page · raw message

ipc/kdbus/util.h new file +133 -0

133 lines not on this page · raw message

Signature · 1 line
2.2.1
#58 lore raw

PATCH v3 4/13 kdbus: add connection pool implementation

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

A pool for data received from the kernel is installed for every connection of the bus, and it is used to copy data from the kernel to userspace clients, for messages and other information.

It is accessed when one of the following ioctls is issued:

* KDBUS_CMD_MSG_RECV, to receive a message
* KDBUS_CMD_NAME_LIST, to dump the name registry
* KDBUS_CMD_CONN_INFO, to retrieve information on a connection

The offsets returned by either one of the aforementioned ioctls describe offsets inside the pool. Internally, the pool is organized in slices, that are dynamically allocated on demand. The overall size of the pool is chosen by the connection when it connects to the bus with KDBUS_CMD_HELLO.

In order to make the slice available for subsequent calls, KDBUS_CMD_FREE has to be called on the offset.

To access the memory, the caller is expected to mmap() it to its task.

---
 ipc/kdbus/pool.c | 784 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/pool.h |  47 ++++
 2 files changed, 831 insertions(+)
 create mode 100644 ipc/kdbus/pool.c
 create mode 100644 ipc/kdbus/pool.h
ipc/kdbus/pool.c new file +784 -0
new file mode 100644
index 000000000000..2bdb645518ea
@@ -0,0 +1,784 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <[email protected]>
+ *
+ * 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
+ * @busy:		The currently used size
+ * @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 direcly 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 busy;
+	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
+ * @child:		Child slice
+ * @free:		Unused 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;
+	struct kdbus_pool_slice *child;
+
+	bool free: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
+ * @kvec:	kvec to copy into the new slice, may be %NULL
+ * @iovec:	iovec to copy into the new slice, may be %NULL
+ * @vec_count:	Number of elements in @kvec or @iovec
+ *
+ * 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,
+						struct kvec *kvec,
+						struct iovec *iovec,
+						size_t vec_count)
+{
+	size_t slice_size = KDBUS_ALIGN8(size);
+	struct rb_node *n, *found = NULL;
+	struct kdbus_pool_slice *s;
+	int ret = 0;
+
+	if (WARN_ON(kvec && iovec))
+		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 = -ENOBUFS;
+		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);
+	WARN_ON(s->child);
+
+	s->ref_kernel = true;
+	s->free = false;
+	pool->busy += s->size;
+	mutex_unlock(&pool->lock);
+
+	if (kvec)
+		ret = kdbus_pool_slice_copy_kvec(s, 0, kvec, vec_count, size);
+
+	if (iovec)
+		ret = kdbus_pool_slice_copy_iovec(s, 0, iovec, vec_count, size);
+
+	if (ret < 0) {
+		kdbus_pool_slice_release(s);
+		return ERR_PTR(ret);
+	}
+
+	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;
+	struct kdbus_pool_slice *child = slice->child;
+
+	/* 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);
+	pool->busy -= slice->size;
+
+	/* 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;
+	slice->child = NULL;
+	kdbus_pool_add_free_slice(pool, slice);
+
+	if (child) {
+		/* Only allow one level of recursion */
+		WARN_ON(child->child);
+		WARN_ON(!child->ref_kernel);
+		child->ref_kernel = false;
+		__kdbus_pool_slice_release(child);
+	}
+}
+
+/**
+ * kdbus_pool_slice_release() - drop kernel-reference on allocated slice
+ * @slice:		Slice allocated from the 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;
+	__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;
+
+	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_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_set_child() - Set child of a slice
+ * @slice:	Slice to add a child to
+ * @child:	Child to set, may be %NULL
+ *
+ * Set @child as child of @slice, so it will be freed automatically when
+ * @slice goes away.
+ */
+void kdbus_pool_slice_set_child(struct kdbus_pool_slice *slice,
+				struct kdbus_pool_slice *child)
+{
+	if (WARN_ON(child && slice->pool != child->pool))
+		return;
+
+	WARN_ON(slice->child);
+	slice->child = child;
+}
+
+/**
+ * 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, VM_NORESERVE);
+	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->busy = 0;
+	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_remain() - the number of free bytes in the pool
+ * @pool:		The receiver's pool
+ *
+ * Return: the number of unallocated bytes in the pool
+ */
+size_t kdbus_pool_remain(struct kdbus_pool *pool)
+{
+	size_t size;
+
+	mutex_lock(&pool->lock);
+	size = pool->size - pool->busy;
+	mutex_unlock(&pool->lock);
+
+	return size;
+}
+
+/**
+ * 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, size_t off,
+			    struct iovec *iov, size_t iov_len, size_t total_len)
+{
+	struct file *f = slice->pool->f;
+	struct iov_iter iter;
+	struct kiocb kiocb;
+	ssize_t len;
+
+	BUG_ON(off + total_len > slice->size);
+
+	init_sync_kiocb(&kiocb, f);
+	kiocb.ki_pos = slice->off + off;
+	kiocb.ki_nbytes = total_len;
+	iov_iter_init(&iter, WRITE, iov, iov_len, total_len);
+
+	len = f->f_op->write_iter(&kiocb, &iter);
+	if (len < 0)
+		return len;
+
+	if (len != total_len)
+		return -EFAULT;
+
+	return 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,
+				   size_t off, struct kvec *kvec,
+				   size_t kvec_len, size_t total_len)
+{
+	struct file *f = slice->pool->f;
+	struct iov_iter iter;
+	mm_segment_t old_fs;
+	struct kiocb kiocb;
+	ssize_t len;
+
+	BUG_ON(off + total_len > slice->size);
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+
+	init_sync_kiocb(&kiocb, f);
+	kiocb.ki_pos = slice->off + off;
+	kiocb.ki_nbytes = total_len;
+	iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len);
+	len = f->f_op->write_iter(&kiocb, &iter);
+	set_fs(old_fs);
+
+	if (len < 0)
+		return len;
+
+	if (len != total_len)
+		return -EFAULT;
+
+	return len;
+}
+
+static int kdbus_pool_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;
+	int ret = 0;
+
+	BUG_ON(slice_src->size != slice_dst->size);
+	BUG_ON(slice_src->free || slice_dst->free);
+
+	mutex_lock(&i_dst->i_mutex);
+
+	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 = f_src->f_op->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;
+	}
+
+	mutex_unlock(&i_dst->i_mutex);
+
+	return ret;
+}
+
+/**
+ * kdbus_pool_slice_move() - move memory from one pool into another one
+ * @pool_dst:		The receiver's pool to copy to
+ * @slice:		Reference to the slice to copy from the source;
+ *			updated with the newly allocated slice in the
+ *			destination
+ *
+ * Move memory from one pool to another. A slice will be allocated in the
+ * destination pool, the original memory from the existing slice is copied
+ * over, and the existing slice will be released.
+ *
+ * Return: 0 on success, negative error number on failure.
+ */
+int kdbus_pool_slice_move(struct kdbus_pool *pool_dst,
+			  struct kdbus_pool_slice **slice)
+{
+	mm_segment_t old_fs;
+	struct kdbus_pool_slice *slice_new;
+	int ret;
+
+	slice_new = kdbus_pool_slice_alloc(pool_dst, (*slice)->size,
+					   NULL, NULL, 0);
+	if (IS_ERR(slice_new))
+		return PTR_ERR(slice_new);
+
+	old_fs = get_fs();
+	set_fs(get_ds());
+	ret = kdbus_pool_copy(slice_new, *slice);
+	set_fs(old_fs);
+	if (ret < 0)
+		goto exit_free;
+
+	kdbus_pool_slice_release(*slice);
+
+	*slice = slice_new;
+	return 0;
+
+exit_free:
+	kdbus_pool_slice_release(slice_new);
+	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);
+}
ipc/kdbus/pool.h new file +47 -0

47 lines not on this page · raw message

Signature · 1 line
2.2.1
#59 lore raw

PATCH v3 5/13 kdbus: add connection, queue handling and message validation code

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

This patch adds code to create and destroy connections, to validate incoming messages and to maintain the queue of messages that are associated with a connection.

Note that connection and queue have a 1:1 relation, the code is only split in two parts for cleaner separation and better readability.

---
 ipc/kdbus/connection.c | 2004 ++++++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/connection.h |  262 +++++++
 ipc/kdbus/item.c       |  309 ++++++++
 ipc/kdbus/item.h       |   57 ++
 ipc/kdbus/message.c    |  598 +++++++++++++++
 ipc/kdbus/message.h    |  133 ++++
 ipc/kdbus/queue.c      |  505 ++++++++++++
 ipc/kdbus/queue.h      |  108 +++
 ipc/kdbus/reply.c      |  262 +++++++
 ipc/kdbus/reply.h      |   68 ++
 ipc/kdbus/util.h       |    2 +-
 11 files changed, 4307 insertions(+), 1 deletion(-)
 create mode 100644 ipc/kdbus/connection.c
 create mode 100644 ipc/kdbus/connection.h
 create mode 100644 ipc/kdbus/item.c
 create mode 100644 ipc/kdbus/item.h
 create mode 100644 ipc/kdbus/message.c
 create mode 100644 ipc/kdbus/message.h
 create mode 100644 ipc/kdbus/queue.c
 create mode 100644 ipc/kdbus/queue.h
 create mode 100644 ipc/kdbus/reply.c
 create mode 100644 ipc/kdbus/reply.h
ipc/kdbus/connection.c new file +2004 -0
new file mode 100644
index 000000000000..75e2ea161a0e
@@ -0,0 +1,2004 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <tixxdz-Umm1ozX2/[email protected]>
+ *
+ * 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 "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)
+
+/*
+ * Check for maximum number of messages per individual user. This
+ * should prevent a single user from being able to fill the receiver's
+ * queue.
+ */
+static int kdbus_conn_queue_user_quota(const struct kdbus_conn *conn_src,
+				       struct kdbus_conn *conn_dst,
+				       struct kdbus_queue_entry *entry)
+{
+	struct kdbus_domain_user *user;
+
+	/*
+	 * When the kernel is the sender we do not do per user
+	 * accouting, instead we just count how many messages have
+	 * been queued and we check the quota limit when inserting
+	 * message into the receiver queue.
+	 */
+	if (!conn_src)
+		return 0;
+
+	/*
+	 * Per-user accounting can be expensive if we have many different
+	 * users on the bus. Allow one set of messages to pass through
+	 * un-accounted. Only once we hit that limit, we start accounting.
+	 */
+	if (conn_dst->queue.msg_count < KDBUS_CONN_MAX_MSGS_UNACCOUNTED)
+		return 0;
+
+	user = conn_src->user;
+
+	/* extend array to store the user message counters */
+	if (user->idr >= conn_dst->msg_users_max) {
+		unsigned int *users;
+		unsigned int i;
+
+		i = 8 + KDBUS_ALIGN8(user->idr);
+		users = krealloc(conn_dst->msg_users, i * sizeof(unsigned int),
+				 GFP_KERNEL | __GFP_ZERO);
+		if (!users)
+			return -ENOMEM;
+
+		conn_dst->msg_users = users;
+		conn_dst->msg_users_max = i;
+	}
+
+	if (conn_dst->msg_users[user->idr] >= KDBUS_CONN_MAX_MSGS_PER_USER)
+		return -ENOBUFS;
+
+	conn_dst->msg_users[user->idr]++;
+	entry->user = kdbus_domain_user_ref(user);
+	return 0;
+}
+
+/**
+ * kdbus_cmd_msg_recv() - receive a message from the queue
+ * @conn:		Connection to work on
+ * @recv:		The command as passed in by the ioctl
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int kdbus_cmd_msg_recv(struct kdbus_conn *conn,
+		       struct kdbus_cmd_recv *recv)
+{
+	bool install = !(recv->flags & KDBUS_RECV_PEEK);
+	struct kdbus_queue_entry *entry = NULL;
+	unsigned int lost_count;
+	int ret = 0;
+
+	if (recv->msg.offset > 0)
+		return -EINVAL;
+
+	mutex_lock(&conn->lock);
+	entry = kdbus_queue_entry_peek(&conn->queue, recv->priority,
+				       recv->flags & KDBUS_RECV_USE_PRIORITY);
+	if (IS_ERR(entry)) {
+		ret = PTR_ERR(entry);
+		goto exit_unlock;
+	}
+
+	/*
+	 * Make sure to never install fds into a connection that has
+	 * refused to receive any.
+	 */
+	if (WARN_ON(!(conn->flags & KDBUS_HELLO_ACCEPT_FD) &&
+	    entry->msg_res && entry->msg_res->fds_count > 0)) {
+		ret = -EINVAL;
+		goto exit_unlock;
+	}
+
+	/* just drop the message */
+	if (recv->flags & KDBUS_RECV_DROP) {
+		struct kdbus_reply *reply = kdbus_reply_ref(entry->reply);
+
+		kdbus_queue_entry_remove(conn, entry);
+		kdbus_pool_slice_release(entry->slice);
+
+		mutex_unlock(&conn->lock);
+
+		if (reply) {
+			/*
+			 * See if the reply object is still linked in
+			 * reply_dst, and kill it. Notify the waiting peer
+			 * that there won't be an answer (-EPIPE).
+			 */
+			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,
+							entry->msg.src_id,
+							entry->msg.cookie);
+			}
+			mutex_unlock(&reply->reply_dst->lock);
+		}
+
+		kdbus_notify_flush(conn->ep->bus);
+		kdbus_queue_entry_free(entry);
+		kdbus_reply_unref(reply);
+
+		return 0;
+	}
+
+	/*
+	 * If there have been lost broadcast messages, report the number
+	 * in the overloaded recv->dropped_msgs field and return -EOVERFLOW.
+	 */
+	lost_count = atomic_read(&conn->lost_count);
+	if (lost_count) {
+		recv->dropped_msgs = lost_count;
+		atomic_sub(lost_count, &conn->lost_count);
+		ret = -EOVERFLOW;
+		goto exit_unlock;
+	}
+
+	/*
+	 * PEEK just returns the location of the next message. Do not install
+	 * file descriptors or anything else. This is usually used to
+	 * determine the sender of the next queued message.
+	 *
+	 * File descriptor numbers referenced in the message items
+	 * are undefined, they are only valid with the full receive
+	 * not with peek.
+	 *
+	 * Only if no PEEK is specified, the FDs are installed and the message
+	 * is dropped from internal queues.
+	 */
+	ret = kdbus_queue_entry_install(entry, conn, &recv->msg.return_flags,
+					install);
+	if (ret < 0)
+		goto exit_unlock;
+
+	/* Give the offset+size back to the caller. */
+	kdbus_pool_slice_publish(entry->slice, &recv->msg.offset,
+				 &recv->msg.msg_size);
+
+	if (install) {
+		kdbus_queue_entry_remove(conn, entry);
+		kdbus_pool_slice_release(entry->slice);
+		kdbus_queue_entry_free(entry);
+	}
+
+exit_unlock:
+	mutex_unlock(&conn->lock);
+	kdbus_notify_flush(conn->ep->bus);
+	return ret;
+}
+
+static int kdbus_conn_check_access(struct kdbus_conn *conn_src,
+				   const struct cred *conn_src_creds,
+				   struct kdbus_conn *conn_dst,
+				   const struct kdbus_msg *msg,
+				   struct kdbus_reply **reply_wake)
+{
+	/*
+	 * If the message is a reply, its cookie_reply field must match any
+	 * of the connection's expected replies. Otherwise, access to send the
+	 * message will be denied.
+	 */
+	if (reply_wake && msg->cookie_reply > 0) {
+		struct kdbus_reply *r;
+
+		/*
+		 * The connection that we are replying to has not
+		 * issued any request or perhaps we have already
+		 * replied, in anycase the supplied cookie_reply is
+		 * no more valid, so fail.
+		 */
+		if (atomic_read(&conn_dst->request_count) == 0)
+			return -EPERM;
+
+		mutex_lock(&conn_dst->lock);
+		r = kdbus_reply_find(conn_src, conn_dst, msg->cookie_reply);
+		if (r) {
+			if (r->sync)
+				*reply_wake = kdbus_reply_ref(r);
+			kdbus_reply_unlink(r);
+		}
+		mutex_unlock(&conn_dst->lock);
+
+		return r ? 0 : -EPERM;
+	}
+
+	/* ... otherwise, ask the policy DBs for permission */
+	if (!kdbus_conn_policy_talk(conn_src, conn_src_creds, conn_dst))
+		return -EPERM;
+
+	return 0;
+}
+
+/* Callers should take the conn_dst lock */
+static struct kdbus_queue_entry *
+kdbus_conn_entry_make(struct kdbus_conn *conn_dst,
+		      const struct kdbus_kmsg *kmsg)
+{
+	/* The remote connection was disconnected */
+	if (!kdbus_conn_active(conn_dst))
+		return ERR_PTR(-ECONNRESET);
+
+	/* The connection does not accept file descriptors */
+	if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
+	    kmsg->res && kmsg->res->fds_count > 0)
+		return ERR_PTR(-ECOMM);
+
+	return kdbus_queue_entry_alloc(conn_dst->pool, kmsg);
+}
+
+/*
+ * 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,
+					const struct kdbus_kmsg *kmsg,
+					struct kdbus_reply *reply_wake)
+{
+	struct kdbus_queue_entry *entry;
+	int remote_ret;
+	int 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(conn_dst, kmsg);
+		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
+ * @kmsg:		The kmsg to queue
+ * @reply:		The reply tracker to attach to the queue entry
+ *
+ * Return: 0 on success. negative error otherwise.
+ */
+int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
+			    struct kdbus_conn *conn_dst,
+			    const struct kdbus_kmsg *kmsg,
+			    struct kdbus_reply *reply)
+{
+	struct kdbus_queue_entry *entry;
+	int ret;
+
+	kdbus_conn_lock2(conn_src, conn_dst);
+
+	/*
+	 * Limit the maximum number of queued messages. This applies
+	 * to all messages, user messages and kernel notifications
+	 *
+	 * The kernel sends notifications to subscribed connections
+	 * only. If the connection do not clean its queue, no further
+	 * message delivery.
+	 * Kernel is able to queue KDBUS_CONN_MAX_MSGS messages, this
+	 * includes all type of notifications.
+	 */
+	if (conn_dst->queue.msg_count >= KDBUS_CONN_MAX_MSGS) {
+		ret = -ENOBUFS;
+		goto exit_unlock;
+	}
+
+	entry = kdbus_conn_entry_make(conn_dst, kmsg);
+	if (IS_ERR(entry)) {
+		ret = PTR_ERR(entry);
+		goto exit_unlock;
+	}
+
+	/* limit the number of queued messages from the same individual user */
+	ret = kdbus_conn_queue_user_quota(conn_src, conn_dst, entry);
+	if (ret < 0)
+		goto exit_queue_free;
+
+	/*
+	 * Remember the reply associated with this queue entry, so we can
+	 * move the reply entry's connection when a connection moves from an
+	 * activator to an implementer.
+	 */
+	entry->reply = kdbus_reply_ref(reply);
+
+	if (reply) {
+		kdbus_reply_link(reply);
+		if (!reply->sync)
+			schedule_delayed_work(&conn_src->work, 0);
+	}
+
+	/* link the message into the receiver's entry */
+	kdbus_queue_entry_add(&conn_dst->queue, entry);
+
+	/* wake up poll() */
+	wake_up_interruptible(&conn_dst->wait);
+
+	ret = 0;
+	goto exit_unlock;
+
+exit_queue_free:
+	kdbus_queue_entry_free(entry);
+exit_unlock:
+	kdbus_conn_unlock2(conn_src, conn_dst);
+	return ret;
+}
+
+/**
+ * kdbus_conn_wait_reply() - Wait for the reply of a synchronous send
+ *			     operation
+ * @conn_src:		The sending connection (origin)
+ * @conn_dst:		The replying connection
+ * @cmd_send:		Payload of SEND command
+ * @ioctl_file:		struct file used to issue this ioctl
+ * @cancel_fd:		Pinned file that reflects KDBUS_ITEM_CANCEL_FD
+ *			item, used to cancel the blocking send call
+ * @reply_wait:		The tracked reply that we are waiting for.
+ * @expire:		Reply timeout
+ *
+ * Return: 0 on success. negative error otherwise.
+ */
+static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
+				 struct kdbus_conn *conn_dst,
+				 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, conn_src,
+						&cmd_send->reply.return_flags,
+						true);
+		kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset,
+					 &cmd_send->reply.msg_size);
+		kdbus_pool_slice_release(entry->slice);
+		kdbus_queue_entry_free(entry);
+	}
+	kdbus_reply_unlink(reply_wait);
+	mutex_unlock(&conn_src->lock);
+
+	return ret;
+}
+
+/**
+ * kdbus_cmd_msg_send() - send a message
+ * @conn_src:		Connection
+ * @cmd:		Payload of SEND command
+ * @ioctl_file:		struct file used to issue this ioctl
+ * @kmsg:		Message to send
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int kdbus_cmd_msg_send(struct kdbus_conn *conn_src,
+		       struct kdbus_cmd_send *cmd,
+		       struct file *ioctl_file,
+		       struct kdbus_kmsg *kmsg)
+{
+	bool sync = cmd->flags & KDBUS_SEND_SYNC_REPLY;
+	struct kdbus_name_entry *name_entry = NULL;
+	struct kdbus_reply *reply_wait = NULL;
+	struct kdbus_reply *reply_wake = NULL;
+	struct kdbus_msg *msg = &kmsg->msg;
+	struct kdbus_conn *conn_dst = NULL;
+	struct kdbus_bus *bus = conn_src->ep->bus;
+	struct file *cancel_fd = NULL;
+	struct kdbus_item *item;
+	int ret = 0;
+
+	/* assign domain-global message sequence number */
+	if (WARN_ON(kmsg->seq > 0))
+		return -EINVAL;
+
+	KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
+		switch (item->type) {
+		case KDBUS_ITEM_CANCEL_FD:
+			/* install cancel_fd only if synchronous */
+			if (!sync)
+				break;
+
+			if (cancel_fd) {
+				ret = -EEXIST;
+				goto exit_put_cancelfd;
+			}
+
+			cancel_fd = fget(item->fds[0]);
+			if (IS_ERR(cancel_fd))
+				return PTR_ERR(cancel_fd);
+
+			if (!cancel_fd->f_op->poll) {
+				ret = -EINVAL;
+				goto exit_put_cancelfd;
+			}
+			break;
+
+		default:
+			ret = -EINVAL;
+			goto exit_put_cancelfd;
+		}
+	}
+
+	kmsg->seq = atomic64_inc_return(&bus->domain->msg_seq_last);
+
+	if (msg->dst_id == KDBUS_DST_ID_BROADCAST) {
+		kdbus_bus_broadcast(bus, conn_src, kmsg);
+		goto exit_put_cancelfd;
+	}
+
+	if (kmsg->res && kmsg->res->dst_name) {
+		/*
+		 * Lock the destination name so it will not get dropped or
+		 * moved between activator/implementer while we try to queue a
+		 * message. We also rely on this to read-lock the entire
+		 * registry so kdbus_meta_conn_collect() will have a consistent
+		 * view of all acquired names on both connections.
+		 * If kdbus_name_lock() gets changed to a per-name lock, we
+		 * really need to read-lock the whole registry here.
+		 */
+		name_entry = kdbus_name_lock(bus->name_registry,
+					     kmsg->res->dst_name);
+		if (!name_entry) {
+			ret = -ESRCH;
+			goto exit_put_cancelfd;
+		}
+
+		/*
+		 * 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 != name_entry->conn->id) {
+			ret = -EREMCHG;
+			goto exit_name_unlock;
+		}
+
+		if (!name_entry->conn && name_entry->activator)
+			conn_dst = kdbus_conn_ref(name_entry->activator);
+		else
+			conn_dst = kdbus_conn_ref(name_entry->conn);
+
+		if ((msg->flags & KDBUS_MSG_NO_AUTO_START) &&
+		    kdbus_conn_is_activator(conn_dst)) {
+			ret = -EADDRNOTAVAIL;
+			goto exit_unref;
+		}
+	} else {
+		/* unicast message to unique name */
+		conn_dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id);
+		if (!conn_dst)
+			return -ENXIO;
+
+		/*
+		 * Special-purpose connections are not allowed to be addressed
+		 * via their unique IDs.
+		 */
+		if (!kdbus_conn_is_ordinary(conn_dst)) {
+			ret = -ENXIO;
+			goto exit_unref;
+		}
+	}
+
+	/*
+	 * Record the sequence number of the registered name;
+	 * it will be passed on to the queue, in case messages
+	 * addressed to a name need to be moved from or to
+	 * activator connections of the same name.
+	 */
+	if (name_entry)
+		kmsg->dst_name_id = name_entry->name_id;
+
+	if (conn_src) {
+		u64 attach_flags;
+
+		/*
+		 * If we got here due to an interrupted system call, our reply
+		 * wait object is still queued on conn_dst, with the former
+		 * cookie. Look it up, and in case it exists, go dormant right
+		 * away again, and don't queue the message again.
+		 *
+		 * We also need to make sure that conn_src did really
+		 * issue a request or if the request did not get
+		 * canceled on the way before looking up any reply
+		 * object.
+		 */
+		if (sync && atomic_read(&conn_src->request_count) > 0) {
+			mutex_lock(&conn_src->lock);
+			reply_wait = kdbus_reply_find(conn_dst, conn_src,
+						      kmsg->msg.cookie);
+			if (reply_wait) {
+				if (reply_wait->interrupted) {
+					kdbus_reply_ref(reply_wait);
+					reply_wait->interrupted = false;
+				} else {
+					reply_wait = NULL;
+				}
+			}
+			mutex_unlock(&conn_src->lock);
+
+			if (reply_wait)
+				goto wait_sync;
+		}
+
+		/* Calculate attach flags of conn_src & conn_dst */
+		attach_flags = kdbus_meta_calc_attach_flags(conn_src, conn_dst);
+
+		/*
+		 * If this connection did not fake its metadata then
+		 * lets augment its metadata by the current valid
+		 * metadata
+		 */
+		if (!conn_src->faked_meta) {
+			ret = kdbus_meta_proc_collect(kmsg->proc_meta,
+						      attach_flags);
+			if (ret < 0)
+				goto exit_unref;
+		}
+
+		/*
+		 * If requested, then we always send the current
+		 * description and owned names of source connection
+		 */
+		ret = kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
+					      attach_flags);
+		if (ret < 0)
+			goto exit_unref;
+
+		if (msg->flags & KDBUS_MSG_EXPECT_REPLY) {
+			ret = kdbus_conn_check_access(conn_src, current_cred(),
+						      conn_dst, msg, NULL);
+			if (ret < 0)
+				goto exit_unref;
+
+			reply_wait = kdbus_reply_new(conn_dst, conn_src, msg,
+						     name_entry, sync);
+			if (IS_ERR(reply_wait)) {
+				ret = PTR_ERR(reply_wait);
+				reply_wait = NULL;
+				goto exit_unref;
+			}
+		} else if (msg->flags & KDBUS_MSG_SIGNAL) {
+			if (!kdbus_match_db_match_kmsg(conn_dst->match_db,
+						       conn_src, kmsg)) {
+				ret = -EPERM;
+				goto exit_unref;
+			}
+
+			/*
+			 * A receiver needs TALK access to the sender
+			 * in order to receive signals.
+			 */
+			ret = kdbus_conn_check_access(conn_dst, NULL, conn_src,
+						      msg, NULL);
+			if (ret < 0)
+				goto exit_unref;
+		} else {
+			ret = kdbus_conn_check_access(conn_src, current_cred(),
+						      conn_dst, msg,
+						      &reply_wake);
+			if (ret < 0)
+				goto exit_unref;
+		}
+	}
+
+	/*
+	 * Forward to monitors before queuing the message. Otherwise, the
+	 * receiver might queue a reply before the original message is queued
+	 * on the monitors.
+	 * We never guarantee consistent ordering across connections, but for
+	 * monitors we should at least make sure they get the message before
+	 * anyone else.
+	 */
+	kdbus_bus_eavesdrop(bus, conn_src, kmsg);
+
+	if (reply_wake) {
+		/*
+		 * If we're synchronously responding to a message, allocate a
+		 * queue item and attach it to the reply tracking object.
+		 * The connection's queue will never get to see it.
+		 */
+		ret = kdbus_conn_entry_sync_attach(conn_dst, kmsg, reply_wake);
+		if (ret < 0)
+			goto exit_unref;
+	} else {
+		/*
+		 * Otherwise, put it in the queue and wait for the connection
+		 * to dequeue and receive the message.
+		 */
+		ret = kdbus_conn_entry_insert(conn_src, conn_dst,
+					      kmsg, reply_wait);
+		if (ret < 0)
+			goto exit_unref;
+	}
+
+wait_sync:
+	/* no reason to keep names locked for replies */
+	name_entry = kdbus_name_unlock(bus->name_registry, name_entry);
+
+	if (sync) {
+		ktime_t now = ktime_get();
+		ktime_t expire = ns_to_ktime(msg->timeout_ns);
+
+		if (likely(ktime_compare(now, expire) < 0))
+			ret = kdbus_conn_wait_reply(conn_src, conn_dst, cmd,
+						    ioctl_file, cancel_fd,
+						    reply_wait, expire);
+		else
+			ret = -ETIMEDOUT;
+	}
+
+exit_unref:
+	kdbus_reply_unref(reply_wait);
+	kdbus_reply_unref(reply_wake);
+	kdbus_conn_unref(conn_dst);
+exit_name_unlock:
+	kdbus_name_unlock(bus->name_registry, name_entry);
+exit_put_cancelfd:
+	if (cancel_fd)
+		fput(cancel_fd);
+
+	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 -EALREADY;
+	}
+	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_remove_by_conn(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->msg.src_id,
+						entry->msg.cookie);
+
+		kdbus_queue_entry_remove(conn, entry);
+		kdbus_pool_slice_release(entry->slice);
+		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) {
+				if (r->sync) {
+					kdbus_sync_reply_wakeup(r, -EPIPE);
+					kdbus_reply_unlink(r);
+					continue;
+				}
+
+				/* 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_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;
+}
+
+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->names_queue_list));
+	WARN_ON(!list_empty(&conn->reply_list));
+
+	if (conn->user) {
+		atomic_dec(&conn->user->connections);
+		kdbus_domain_user_unref(conn->user);
+	}
+
+	kdbus_meta_proc_unref(conn->meta);
+	kdbus_match_db_free(conn->match_db);
+	kdbus_pool_free(conn->pool);
+	kdbus_ep_unref(conn->ep);
+	put_cred(conn->cred);
+	kfree(conn->description);
+	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_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;
+
+#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);
+}
+
+/**
+ * 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.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
+			     struct kdbus_conn *conn_src,
+			     u64 name_id)
+{
+	struct kdbus_queue_entry *q, *q_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(!mutex_is_locked(&conn_dst->ep->bus->lock)))
+		return -EINVAL;
+
+	if (WARN_ON(conn_src == conn_dst))
+		return -EINVAL;
+
+	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(q, q_tmp, &conn_src->queue.msg_list, entry) {
+		/* filter messages for a specific name */
+		if (name_id > 0 && q->dst_name_id != name_id)
+			continue;
+
+		kdbus_queue_entry_remove(conn_src, q);
+
+		if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
+		    q->msg_res && q->msg_res->fds_count > 0) {
+			atomic_inc(&conn_dst->lost_count);
+			continue;
+		}
+
+		ret = kdbus_queue_entry_move(conn_dst, q);
+		if (ret < 0) {
+			atomic_inc(&conn_dst->lost_count);
+			kdbus_queue_entry_free(q);
+		}
+	}
+	kdbus_conn_unlock2(conn_src, conn_dst);
+
+	/* wake up poll() */
+	wake_up_interruptible(&conn_dst->wait);
+
+	return ret;
+}
+
+/**
+ * kdbus_cmd_conn_info() - retrieve info about a connection
+ * @conn:		Connection
+ * @cmd_info:		The command as passed in by the ioctl
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_cmd_conn_info(struct kdbus_conn *conn,
+			struct kdbus_cmd_info *cmd_info)
+{
+	struct kdbus_meta_conn *conn_meta = NULL;
+	struct kdbus_pool_slice *slice = NULL;
+	struct kdbus_name_entry *entry = NULL;
+	struct kdbus_conn *owner_conn = NULL;
+	struct kdbus_item *meta_items = NULL;
+	struct kdbus_info info = {};
+	struct kvec kvec[2];
+	size_t meta_size;
+	u64 attach_flags;
+	int ret = 0;
+
+	if (cmd_info->id == 0) {
+		const char *name;
+
+		name = kdbus_items_get_str(cmd_info->items,
+					   KDBUS_ITEMS_SIZE(cmd_info, items),
+					   KDBUS_ITEM_NAME);
+		if (IS_ERR(name))
+			return -EINVAL;
+
+		if (!kdbus_name_is_valid(name, false))
+			return -EINVAL;
+
+		entry = kdbus_name_lock(conn->ep->bus->name_registry, name);
+		if (!entry || !kdbus_conn_policy_see_name(conn, current_cred(),
+							  name)) {
+			/* pretend a name doesn't exist if you cannot see it */
+			ret = -ESRCH;
+			goto exit;
+		}
+
+		if (entry->conn)
+			owner_conn = kdbus_conn_ref(entry->conn);
+	} else {
+		owner_conn = kdbus_bus_find_conn_by_id(conn->ep->bus,
+						       cmd_info->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;
+		}
+	}
+
+	info.id = owner_conn->id;
+	info.flags = owner_conn->flags;
+
+	/* mask out what information the connection wants to pass us */
+	attach_flags = cmd_info->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, NULL, owner_conn,
+				      attach_flags);
+	if (ret < 0)
+		goto exit;
+
+	meta_items = kdbus_meta_export(owner_conn->meta, conn_meta,
+				       attach_flags, &meta_size);
+	if (IS_ERR(meta_items)) {
+		ret = PTR_ERR(meta_items);
+		meta_items = NULL;
+		goto exit;
+	}
+
+	kdbus_kvec_set(&kvec[0], &info, sizeof(info), &info.size);
+	kdbus_kvec_set(&kvec[1], meta_items, meta_size, &info.size);
+
+	slice = kdbus_pool_slice_alloc(conn->pool, info.size,
+				       kvec, NULL, ARRAY_SIZE(kvec));
+	if (IS_ERR(slice)) {
+		ret = PTR_ERR(slice);
+		slice = NULL;
+		goto exit;
+	}
+
+	/* write back the offset */
+	kdbus_pool_slice_publish(slice, &cmd_info->offset,
+				 &cmd_info->info_size);
+	ret = 0;
+
+	kdbus_pool_slice_release(slice);
+exit:
+	kfree(meta_items);
+	kdbus_meta_conn_unref(conn_meta);
+	kdbus_conn_unref(owner_conn);
+	kdbus_name_unlock(conn->ep->bus->name_registry, entry);
+
+	return ret;
+}
+
+/**
+ * kdbus_cmd_conn_update() - update the attach-flags of a connection or
+ *			     the policy entries of a policy holding one
+ * @conn:		Connection
+ * @cmd:		The command as passed in by the ioctl
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_cmd_conn_update(struct kdbus_conn *conn,
+			  const struct kdbus_cmd_update *cmd)
+{
+	struct kdbus_bus *bus = conn->ep->bus;
+	bool send_flags_provided = false;
+	bool recv_flags_provided = false;
+	bool policy_provided = false;
+	const struct kdbus_item *item;
+	u64 attach_send;
+	u64 attach_recv;
+	int ret;
+
+	KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
+		switch (item->type) {
+		case KDBUS_ITEM_ATTACH_FLAGS_SEND:
+			/*
+			 * Only ordinary or monitor connections may update
+			 * their attach-flags-send. attach-flags-recv can
+			 * additionally be updated by activators.
+			 */
+			if (!kdbus_conn_is_ordinary(conn) &&
+			    !kdbus_conn_is_monitor(conn))
+				return -EOPNOTSUPP;
+
+			ret = kdbus_sanitize_attach_flags(item->data64[0],
+							  &attach_send);
+			if (ret < 0)
+				return ret;
+
+			send_flags_provided = true;
+			break;
+
+		case KDBUS_ITEM_ATTACH_FLAGS_RECV:
+			if (!kdbus_conn_is_ordinary(conn) &&
+			    !kdbus_conn_is_monitor(conn) &&
+			    !kdbus_conn_is_activator(conn))
+				return -EOPNOTSUPP;
+
+			ret = kdbus_sanitize_attach_flags(item->data64[0],
+							  &attach_recv);
+			if (ret < 0)
+				return ret;
+
+			recv_flags_provided = true;
+			break;
+
+		case KDBUS_ITEM_NAME:
+		case KDBUS_ITEM_POLICY_ACCESS:
+			/*
+			 * Only policy holders may update their policy
+			 * entries. Policy holders are privileged
+			 * connections.
+			 */
+			if (!kdbus_conn_is_policy_holder(conn))
+				return -EOPNOTSUPP;
+
+			policy_provided = true;
+			break;
+
+		default:
+			return -EINVAL;
+		}
+	}
+
+	if (policy_provided) {
+		ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items,
+				       KDBUS_ITEMS_SIZE(cmd, items),
+				       1, true, conn);
+		if (ret < 0)
+			return ret;
+	}
+
+	if (send_flags_provided) {
+		/*
+		 * The attach flags send must always satisfy the
+		 * bus requirements.
+		 */
+		if (bus->attach_flags_req & ~attach_send)
+			return -EINVAL;
+
+		atomic64_set(&conn->attach_flags_send, attach_send);
+	}
+
+	if (recv_flags_provided)
+		atomic64_set(&conn->attach_flags_recv, attach_recv);
+
+	return 0;
+}
+
+/**
+ * kdbus_conn_new() - create a new connection
+ * @ep:			The endpoint the connection is connected to
+ * @hello:		The kdbus_cmd_hello as passed in by the user
+ * @privileged:		Whether to create a privileged connection
+ *
+ * Return: a new kdbus_conn on success, ERR_PTR on failure
+ */
+struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
+				  struct kdbus_cmd_hello *hello,
+				  bool privileged)
+{
+#ifdef CONFIG_DEBUG_LOCK_ALLOC
+	static struct lock_class_key __key;
+#endif
+	const struct kdbus_creds *creds = NULL;
+	struct kdbus_pool_slice *slice = NULL;
+	const struct kdbus_pids *pids = NULL;
+	struct kdbus_item_list items = {};
+	struct kdbus_bus *bus = ep->bus;
+	const struct kdbus_item *item;
+	const char *conn_description = NULL;
+	const char *seclabel = NULL;
+	const char *name = NULL;
+	struct kdbus_conn *conn;
+	u64 attach_flags_send;
+	u64 attach_flags_recv;
+	bool is_policy_holder;
+	bool is_activator;
+	bool is_monitor;
+	struct kvec kvec[2];
+	int ret;
+
+	struct {
+		/* bloom item */
+		u64 size;
+		u64 type;
+		struct kdbus_bloom_parameter bloom;
+	} bloom_item;
+
+	is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
+	is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
+	is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER;
+
+	/* can only be one of monitor/activator/policy_holder */
+	if (is_monitor + is_activator + is_policy_holder > 1)
+		return ERR_PTR(-EINVAL);
+
+	/* Monitors are disallowed on custom endpoints */
+	if (is_monitor && ep->has_policy)
+		return ERR_PTR(-EOPNOTSUPP);
+
+	/* only privileged connections can activate and monitor */
+	if (!privileged && (is_activator || is_policy_holder || is_monitor))
+		return ERR_PTR(-EPERM);
+
+	KDBUS_ITEMS_FOREACH(item, hello->items,
+			    KDBUS_ITEMS_SIZE(hello, items)) {
+		switch (item->type) {
+		case KDBUS_ITEM_NAME:
+			if (!is_activator && !is_policy_holder)
+				return ERR_PTR(-EINVAL);
+
+			if (name)
+				return ERR_PTR(-EINVAL);
+
+			if (!kdbus_name_is_valid(item->str, true))
+				return ERR_PTR(-EINVAL);
+
+			name = item->str;
+			break;
+
+		case KDBUS_ITEM_CREDS:
+			/* privileged processes can impersonate somebody else */
+			if (!privileged)
+				return ERR_PTR(-EPERM);
+
+			if (item->size != KDBUS_ITEM_SIZE(sizeof(*creds)))
+				return ERR_PTR(-EINVAL);
+
+			creds = &item->creds;
+			break;
+
+		case KDBUS_ITEM_PIDS:
+			/* privileged processes can impersonate somebody else */
+			if (!privileged)
+				return ERR_PTR(-EPERM);
+
+			if (item->size != KDBUS_ITEM_SIZE(sizeof(*pids)))
+				return ERR_PTR(-EINVAL);
+
+			pids = &item->pids;
+			break;
+
+		case KDBUS_ITEM_SECLABEL:
+			/* privileged processes can impersonate somebody else */
+			if (!privileged)
+				return ERR_PTR(-EPERM);
+
+			seclabel = item->str;
+			break;
+
+		case KDBUS_ITEM_CONN_DESCRIPTION:
+			/* human-readable connection name (debugging) */
+			if (conn_description)
+				return ERR_PTR(-EINVAL);
+
+			conn_description = item->str;
+			break;
+
+		case KDBUS_ITEM_POLICY_ACCESS:
+		case KDBUS_ITEM_BLOOM_MASK:
+		case KDBUS_ITEM_ID:
+		case KDBUS_ITEM_NAME_ADD:
+		case KDBUS_ITEM_NAME_REMOVE:
+		case KDBUS_ITEM_NAME_CHANGE:
+		case KDBUS_ITEM_ID_ADD:
+		case KDBUS_ITEM_ID_REMOVE:
+			/* will be handled by policy and match code */
+			break;
+
+		default:
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	if ((is_activator || is_policy_holder) && !name)
+		return ERR_PTR(-EINVAL);
+
+	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);
+
+	/* Let userspace know which flags are enforced by the bus */
+	hello->attach_flags_send = bus->attach_flags_req | KDBUS_FLAG_KERNEL;
+
+	/*
+	 * The attach flags must always satisfy the bus
+	 * requirements.
+	 */
+	if (bus->attach_flags_req & ~attach_flags_send)
+		return ERR_PTR(-ECONNREFUSED);
+
+	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->names_queue_list);
+	INIT_LIST_HEAD(&conn->reply_list);
+	atomic_set(&conn->name_count, 0);
+	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_current_cred();
+	init_waitqueue_head(&conn->wait);
+	kdbus_queue_init(&conn->queue);
+	conn->privileged = privileged;
+	conn->ep = kdbus_ep_ref(ep);
+	conn->id = atomic64_inc_return(&bus->conn_seq_last);
+	conn->flags = hello->flags;
+	atomic64_set(&conn->attach_flags_send, attach_flags_send);
+	atomic64_set(&conn->attach_flags_recv, attach_flags_recv);
+	/* init entry, so we can remove it unconditionally */
+	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));
+
+	conn->meta = kdbus_meta_proc_new();
+	if (IS_ERR(conn->meta)) {
+		ret = PTR_ERR(conn->meta);
+		conn->meta = NULL;
+		goto exit_unref;
+	}
+
+	/* privileged processes can impersonate somebody else */
+	if (creds || pids || seclabel) {
+		ret = kdbus_meta_proc_fake(conn->meta, creds, pids, seclabel);
+		if (ret < 0)
+			goto exit_unref;
+
+		conn->faked_meta = true;
+	} else {
+		ret = kdbus_meta_proc_collect(conn->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;
+	}
+
+	/*
+	 * 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).
+	 */
+	if (ep->user) {
+		conn->user = kdbus_domain_user_ref(ep->user);
+	} else {
+		conn->user = kdbus_domain_get_user(ep->bus->domain,
+						   current_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[0], &items, sizeof(items), &items.size);
+	kdbus_kvec_set(&kvec[1], &bloom_item, bloom_item.size, &items.size);
+
+	slice = kdbus_pool_slice_alloc(conn->pool, items.size, kvec, NULL,
+				       ARRAY_SIZE(kvec));
+	if (IS_ERR(slice)) {
+		ret = PTR_ERR(slice);
+		slice = NULL;
+		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);
+}
+
+/**
+ * kdbus_conn_connect() - introduce a connection to a bus
+ * @conn:		Connection
+ * @hello:		Hello parameters
+ *
+ * This puts life into a kdbus-conn object. A connection to the bus is
+ * established and the peer will be reachable via the bus (if it is an ordinary
+ * connection).
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_conn_connect(struct kdbus_conn *conn, struct kdbus_cmd_hello *hello)
+{
+	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(&bus->lock);
+	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);
+	mutex_unlock(&bus->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(conn->ep->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;
+		const char *name;
+
+		name = kdbus_items_get_str(hello->items,
+					   KDBUS_ITEMS_SIZE(hello, items),
+					   KDBUS_ITEM_NAME);
+		if (WARN_ON(!name)) {
+			ret = -EINVAL;
+			goto exit_disconnect;
+		}
+
+		ret = kdbus_name_acquire(bus->name_registry, conn, name,
+					 &flags);
+		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_has_name() - check if a connection owns a name
+ * @conn:		Connection
+ * @name:		Well-know name to check for
+ *
+ * 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_entry *e;
+	bool match = false;
+
+	/* No need to go further if we do not own names */
+	if (atomic_read(&conn->name_count) == 0)
+		return false;
+
+	mutex_lock(&conn->lock);
+	list_for_each_entry(e, &conn->names_list, conn_entry) {
+		if (strcmp(e->name, name) == 0) {
+			match = true;
+			break;
+		}
+	}
+	mutex_unlock(&conn->lock);
+
+	return match;
+}
+
+/* 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_entry *ne;
+	bool pass = false;
+	int res;
+
+	down_read(&db->entries_rwlock);
+	mutex_lock(&whom->lock);
+
+	list_for_each_entry(ne, &whom->names_list, conn_entry) {
+		res = kdbus_policy_query_unlocked(db, conn_creds ? : conn->cred,
+						  ne->name,
+						  kdbus_strhash(ne->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->has_policy) {
+		res = kdbus_policy_query(&conn->ep->policy_db, conn_creds,
+					 name, hash);
+		if (res < KDBUS_POLICY_OWN)
+			return false;
+	}
+
+	if (conn->privileged)
+		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->has_policy &&
+	    !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db,
+					 to, KDBUS_POLICY_TALK))
+		return false;
+
+	if (conn->privileged)
+		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->has_policy)
+		return true;
+
+	res = kdbus_policy_query_unlocked(&conn->ep->policy_db,
+					  conn_creds ? : conn->cred,
+					  name, kdbus_strhash(name));
+	return res >= KDBUS_POLICY_SEE;
+}
+
+/**
+ * kdbus_conn_policy_see_name() - 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.
+ *
+ * Return: true if allowed, false if not.
+ */
+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;
+}
+
+/**
+ * kdbus_conn_policy_see() - verify a connection can see a given peer
+ * @conn:		Connection to verify whether it sees a peer
+ * @conn_creds:		Credentials of @conn to use for policy check
+ * @whom:		Peer destination that is to be 'seen'
+ *
+ * This checks whether @conn is able to see @whom.
+ *
+ * Return: true if allowed, false if not.
+ */
+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->has_policy ||
+	       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
+ * @kmsg:		The message carrying the notification
+ *
+ * This checks whether @conn is allowed to see the kernel notification @kmsg.
+ *
+ * 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_kmsg *kmsg)
+{
+	if (WARN_ON(kmsg->msg.src_id != KDBUS_SRC_ID_KERNEL))
+		return false;
+
+	/*
+	 * 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}: As new peers cannot have names, and all
+	 *     names are dropped before a peer is removed, those notifications
+	 *     cannot be seen on custom endpoints. Thus, we only pass them
+	 *     through on default endpoints.
+	 */
+
+	switch (kmsg->notify_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,
+						  kmsg->notify_name);
+
+	case KDBUS_ITEM_ID_ADD:
+	case KDBUS_ITEM_ID_REMOVE:
+		return !conn->ep->has_policy;
+
+	default:
+		WARN(1, "Invalid type for notification broadcast: %llu\n",
+		     (unsigned long long)kmsg->notify_type);
+		return false;
+	}
+}
ipc/kdbus/connection.h new file +262 -0

262 lines not on this page · raw message

ipc/kdbus/item.c new file +309 -0

309 lines not on this page · raw message

ipc/kdbus/item.h new file +57 -0

57 lines not on this page · raw message

ipc/kdbus/message.c new file +598 -0

368 lines not on this page · raw message

ipc/kdbus/message.h new file +133 -0

133 lines not on this page · raw message

ipc/kdbus/queue.c new file +505 -0

505 lines not on this page · raw message

ipc/kdbus/queue.h new file +108 -0

108 lines not on this page · raw message

ipc/kdbus/reply.c new file +262 -0

262 lines not on this page · raw message

ipc/kdbus/reply.h new file +68 -0

68 lines not on this page · raw message

ipc/kdbus/util.h +1 -1
index 33d31f6274e0..241bbcc1c19f 100644

Lines of this file are not shown. View the raw message.

The rest of this diff is not shown. View the raw message.

Signature · 1 line
2.2.1

Part of the diff is not shown here. View the raw message.

#60 lore raw

PATCH v3 6/13 kdbus: add node and filesystem implementation

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

kdbusfs is a filesystem that will expose a fresh kdbus domain context each time it is mounted. Per mount point, there will be a 'control' node, which can be used to create buses. fs.c contains the implementation of that pseudo-fs. Exported inodes of 'file' type have their i_fop set to either kdbus_handle_control_ops or kdbus_handle_ep_ops, depending on their type. The actual dispatching of file operations is done from handle.c

node.c is an implementation of a kdbus object that has an id and children, organized in an R/B tree. The tree is used by the filesystem code for lookup and iterator functions, and to deactivate children once the parent is deactivated. Every inode exported by kdbusfs is backed by a kdbus_node, hence it is embedded in struct kdbus_ep, struct kdbus_bus and struct kdbus_domain.

---
 include/uapi/linux/magic.h |   2 +
 ipc/kdbus/fs.c             | 519 ++++++++++++++++++++++++++
 ipc/kdbus/fs.h             |  25 ++
 ipc/kdbus/node.c           | 910 +++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/node.h           |  87 +++++
 5 files changed, 1543 insertions(+)
 create mode 100644 ipc/kdbus/fs.c
 create mode 100644 ipc/kdbus/fs.h
 create mode 100644 ipc/kdbus/node.c
 create mode 100644 ipc/kdbus/node.h
include/uapi/linux/magic.h +2 -0
index 7d664ea85ebd..1cf05c066158 100644
@@ -74,4 +74,6 @@
 #define BTRFS_TEST_MAGIC	0x73727279
 #define NSFS_MAGIC		0x6e736673
 
+#define KDBUS_SUPER_MAGIC	0x44427573
+
 #endif /* __LINUX_MAGIC_H__ */
ipc/kdbus/fs.c new file +519 -0

519 lines not on this page · raw message

ipc/kdbus/fs.h new file +25 -0
new file mode 100644
index 000000000000..5c38a5774392
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 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);
+
+#endif
ipc/kdbus/node.c new file +910 -0

910 lines not on this page · raw message

ipc/kdbus/node.h new file +87 -0

87 lines not on this page · raw message

Signature · 1 line
2.2.1
#61 lore raw

PATCH v3 7/13 kdbus: add code to gather metadata

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

A connection chooses which metadata it wants to have attached to each message it receives with kdbus_cmd_hello.attach_flags. The metadata will be attached as items to the messages. All metadata refers to information about the sending task at sending time, unless otherwise stated. Also, the metadata is copied, not referenced, so even if the sending task doesn't exist anymore at the time the message is received, the information is still preserved.

See kdbus.txt for more details on which metadata can currently be attached to messages.

---
 ipc/kdbus/metadata.c | 1066 ++++++++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/metadata.h |   52 +++
 2 files changed, 1118 insertions(+)
 create mode 100644 ipc/kdbus/metadata.c
 create mode 100644 ipc/kdbus/metadata.h
ipc/kdbus/metadata.c new file +1066 -0
new file mode 100644
index 000000000000..101561dfe5ac
@@ -0,0 +1,1066 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <[email protected]>
+ *
+ * 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/user_namespace.h>
+#include <linux/version.h>
+
+#include "bus.h"
+#include "connection.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
+ * @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
+ * @auxgrps:		Auxiliary groups
+ * @n_auxgrps:		Number of items in @auxgrps
+ * @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
+ * @caps:		Capabilities
+ * @caps_namespace:	User-namespace of @caps
+ * @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 */
+	kuid_t uid, euid, suid, fsuid;
+	kgid_t gid, egid, sgid, fsgid;
+
+	/* KDBUS_ITEM_PIDS */
+	struct pid *pid;
+	struct pid *tgid;
+	struct pid *ppid;
+
+	/* KDBUS_ITEM_AUXGROUPS */
+	kgid_t *auxgrps;
+	size_t n_auxgrps;
+
+	/* 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_CAPS */
+	struct caps {
+		/* binary compatible to kdbus_caps */
+		u32 last_cap;
+		struct {
+			u32 caps[_KERNEL_CAPABILITY_U32S];
+		} set[4];
+	} caps;
+	struct user_namespace *caps_namespace;
+
+	/* 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;
+};
+
+/**
+ * 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);
+	put_user_ns(mp->caps_namespace);
+	put_pid(mp->ppid);
+	put_pid(mp->tgid);
+	put_pid(mp->pid);
+
+	kfree(mp->seclabel);
+	kfree(mp->auxgrps);
+	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_creds(struct kdbus_meta_proc *mp)
+{
+	mp->uid		= current_uid();
+	mp->euid	= current_euid();
+	mp->suid	= current_suid();
+	mp->fsuid	= current_fsuid();
+
+	mp->gid		= current_gid();
+	mp->egid	= current_egid();
+	mp->sgid	= current_sgid();
+	mp->fsgid	= current_fsgid();
+
+	mp->valid |= KDBUS_ATTACH_CREDS;
+}
+
+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 int kdbus_meta_proc_collect_auxgroups(struct kdbus_meta_proc *mp)
+{
+	struct group_info *info;
+	size_t i;
+
+	info = get_current_groups();
+
+	if (info->ngroups > 0) {
+		mp->auxgrps = kmalloc_array(info->ngroups, sizeof(kgid_t),
+					    GFP_KERNEL);
+		if (!mp->auxgrps) {
+			put_group_info(info);
+			return -ENOMEM;
+		}
+
+		for (i = 0; i < info->ngroups; i++)
+			mp->auxgrps[i] = GROUP_AT(info, i);
+	}
+
+	mp->n_auxgrps = info->ngroups;
+	put_group_info(info);
+	mp->valid |= KDBUS_ATTACH_AUXGROUPS;
+
+	return 0;
+}
+
+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 mm_struct *mm;
+
+	mm = get_task_mm(current);
+	if (!mm)
+		return;
+
+	down_read(&mm->mmap_sem);
+	if (mm->exe_file) {
+		mp->exe_path = mm->exe_file->f_path;
+		path_get(&mp->exe_path);
+		get_fs_root(current->fs, &mp->root_path);
+		mp->valid |= KDBUS_ATTACH_EXE;
+	}
+	up_read(&mm->mmap_sem);
+
+	mmput(mm);
+}
+
+static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp)
+{
+	struct mm_struct *mm;
+	char *cmdline;
+
+	mm = get_task_mm(current);
+	if (!mm)
+		return 0;
+
+	if (!mm->arg_end) {
+		mmput(mm);
+		return 0;
+	}
+
+	cmdline = strndup_user((const char __user *)mm->arg_start,
+			       mm->arg_end - mm->arg_start);
+	mmput(mm);
+
+	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 void kdbus_meta_proc_collect_caps(struct kdbus_meta_proc *mp)
+{
+	const struct cred *c = current_cred();
+	int i;
+
+	/* ABI: "last_cap" equals /proc/sys/kernel/cap_last_cap */
+	mp->caps.last_cap = CAP_LAST_CAP;
+	mp->caps_namespace = get_user_ns(current_user_ns());
+
+	CAP_FOR_EACH_U32(i) {
+		mp->caps.set[0].caps[i] = c->cap_inheritable.cap[i];
+		mp->caps.set[1].caps[i] = c->cap_permitted.cap[i];
+		mp->caps.set[2].caps[i] = c->cap_effective.cap[i];
+		mp->caps.set[3].caps[i] = c->cap_bset.cap[i];
+	}
+
+	/* clear unused bits */
+	for (i = 0; i < 4; i++)
+		mp->caps.set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
+						CAP_LAST_U32_VALID_MASK;
+
+	mp->valid |= KDBUS_ATTACH_CAPS;
+}
+
+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)
+		return 0;
+
+	mutex_lock(&mp->lock);
+
+	if ((what & KDBUS_ATTACH_CREDS) &&
+	    !(mp->collected & KDBUS_ATTACH_CREDS)) {
+		kdbus_meta_proc_collect_creds(mp);
+		mp->collected |= KDBUS_ATTACH_CREDS;
+	}
+
+	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_AUXGROUPS) &&
+	    !(mp->collected & KDBUS_ATTACH_AUXGROUPS)) {
+		ret = kdbus_meta_proc_collect_auxgroups(mp);
+		if (ret < 0)
+			goto exit_unlock;
+		mp->collected |= KDBUS_ATTACH_AUXGROUPS;
+	}
+
+	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_CAPS) &&
+	    !(mp->collected & KDBUS_ATTACH_CAPS)) {
+		kdbus_meta_proc_collect_caps(mp);
+		mp->collected |= KDBUS_ATTACH_CAPS;
+	}
+
+	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_proc_fake() - Fill process metadata from faked credentials
+ * @mp:		Metadata
+ * @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. A call to this function
+ * is considered an alternative to calling kdbus_meta_add_current(), which
+ * derives the same information from the 'current' task.
+ *
+ * This call uses the current task's namespaces to resolve the given
+ * information.
+ *
+ * Return: 0 on success, negative error number otherwise.
+ */
+int kdbus_meta_proc_fake(struct kdbus_meta_proc *mp,
+			 const struct kdbus_creds *creds,
+			 const struct kdbus_pids *pids,
+			 const char *seclabel)
+{
+	int ret;
+
+	if (!mp)
+		return 0;
+
+	mutex_lock(&mp->lock);
+
+	if (creds && !(mp->collected & KDBUS_ATTACH_CREDS)) {
+		struct user_namespace *ns = current_user_ns();
+
+		mp->uid		= make_kuid(ns, creds->uid);
+		mp->euid	= make_kuid(ns, creds->euid);
+		mp->suid	= make_kuid(ns, creds->suid);
+		mp->fsuid	= make_kuid(ns, creds->fsuid);
+
+		mp->gid		= make_kgid(ns, creds->gid);
+		mp->egid	= make_kgid(ns, creds->egid);
+		mp->sgid	= make_kgid(ns, creds->sgid);
+		mp->fsgid	= make_kgid(ns, creds->fsgid);
+
+		if ((creds->uid   != (uid_t)-1 && !uid_valid(mp->uid))   ||
+		    (creds->euid  != (uid_t)-1 && !uid_valid(mp->euid))  ||
+		    (creds->suid  != (uid_t)-1 && !uid_valid(mp->suid))  ||
+		    (creds->fsuid != (uid_t)-1 && !uid_valid(mp->fsuid)) ||
+		    (creds->gid   != (gid_t)-1 && !gid_valid(mp->gid))   ||
+		    (creds->egid  != (gid_t)-1 && !gid_valid(mp->egid))  ||
+		    (creds->sgid  != (gid_t)-1 && !gid_valid(mp->sgid))  ||
+		    (creds->fsgid != (gid_t)-1 && !gid_valid(mp->fsgid))) {
+			ret = -EINVAL;
+			goto exit_unlock;
+		}
+
+		mp->valid |= KDBUS_ATTACH_CREDS;
+		mp->collected |= KDBUS_ATTACH_CREDS;
+	}
+
+	if (pids && !(mp->collected & KDBUS_ATTACH_PIDS)) {
+		mp->pid = get_pid(find_vpid(pids->tid));
+		mp->tgid = get_pid(find_vpid(pids->pid));
+		mp->ppid = get_pid(find_vpid(pids->ppid));
+
+		if ((pids->tid != 0 && !mp->pid) ||
+		    (pids->pid != 0 && !mp->tgid) ||
+		    (pids->ppid != 0 && !mp->ppid)) {
+			put_pid(mp->pid);
+			put_pid(mp->tgid);
+			put_pid(mp->ppid);
+			mp->pid = NULL;
+			mp->tgid = NULL;
+			mp->ppid = NULL;
+			ret = -EINVAL;
+			goto exit_unlock;
+		}
+
+		mp->valid |= KDBUS_ATTACH_PIDS;
+		mp->collected |= KDBUS_ATTACH_PIDS;
+	}
+
+	if (seclabel && !(mp->collected & KDBUS_ATTACH_SECLABEL)) {
+		mp->seclabel = kstrdup(seclabel, GFP_KERNEL);
+		if (!mp->seclabel) {
+			ret = -ENOMEM;
+			goto exit_unlock;
+		}
+
+		mp->valid |= KDBUS_ATTACH_SECLABEL;
+		mp->collected |= KDBUS_ATTACH_SECLABEL;
+	}
+
+	ret = 0;
+
+exit_unlock:
+	mutex_unlock(&mp->lock);
+	return ret;
+}
+
+/**
+ * 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,
+					      struct kdbus_kmsg *kmsg)
+{
+	struct timespec ts;
+
+	ktime_get_ts(&ts);
+	mc->ts.monotonic_ns = timespec_to_ns(&ts);
+
+	ktime_get_real_ts(&ts);
+	mc->ts.realtime_ns = timespec_to_ns(&ts);
+
+	if (kmsg)
+		mc->ts.seqnum = kmsg->seq;
+
+	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_entry *e;
+	struct kdbus_item *item;
+	size_t slen, size;
+
+	size = 0;
+	list_for_each_entry(e, &conn->names_list, conn_entry)
+		size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_name) +
+					strlen(e->name) + 1);
+
+	if (!size)
+		return 0;
+
+	item = kmalloc(size, GFP_KERNEL);
+	if (!item)
+		return -ENOMEM;
+
+	mc->owned_names_items = item;
+	mc->owned_names_size = size;
+
+	list_for_each_entry(e, &conn->names_list, conn_entry) {
+		slen = strlen(e->name) + 1;
+		kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL,
+			       sizeof(struct kdbus_name) + slen);
+		item->name.flags = e->flags;
+		memcpy(item->name.name, e->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 + 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
+ * @kmsg:	Kmsg to collect data from
+ * @conn:	Connection to collect data from
+ * @what:	Attach flags to collect
+ *
+ * This collects connection metadata from @kmsg and @conn and saves it in @mc.
+ *
+ * Return: 0 on success, negative error code on failure.
+ */
+int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc,
+			    struct kdbus_kmsg *kmsg,
+			    struct kdbus_conn *conn,
+			    u64 what)
+{
+	int ret;
+
+	if (!mc)
+		return 0;
+
+	if (conn)
+		mutex_lock(&conn->lock);
+	mutex_lock(&mc->lock);
+
+	if (kmsg && (what & KDBUS_ATTACH_TIMESTAMP) &&
+	    !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) {
+		kdbus_meta_conn_collect_timestamp(mc, kmsg);
+		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);
+	if (conn)
+		mutex_unlock(&conn->lock);
+	return ret;
+}
+
+/**
+ * kdbus_meta_export() - export information from metadata into buffer
+ * @mp:		Process metadata, or NULL
+ * @mc:		Connection metadata, or NULL
+ * @mask:	Mask of KDBUS_ATTACH_* flags to export
+ * @sz:		Pointer to return the buffer size
+ *
+ * This function exports information from metadata to allocated buffer.
+ * Only information that is requested in @mask and that has been collected
+ * before is exported.
+ *
+ * All information will be translated using the current namespaces.
+ *
+ * Return: An array of items on success, ERR_PTR value on errors. On success,
+ * @sz is also set to the number of bytes returned in the items array. The
+ * caller must release the buffer via kfree().
+ */
+struct kdbus_item *kdbus_meta_export(struct kdbus_meta_proc *mp,
+				     struct kdbus_meta_conn *mc,
+				     u64 mask,
+				     size_t *sz)
+{
+	struct user_namespace *user_ns = current_user_ns();
+	struct kdbus_item *item, *items = NULL;
+	char *exe_pathname = NULL;
+	void *exe_page = NULL;
+	size_t size = 0;
+	u64 valid = 0;
+	int ret;
+
+	if (WARN_ON(!sz))
+		return ERR_PTR(-EINVAL);
+
+	if (mp) {
+		mutex_lock(&mp->lock);
+		valid |= mp ? mp->valid : 0;
+		mutex_unlock(&mp->lock);
+	}
+
+	if (mc) {
+		mutex_lock(&mc->lock);
+		valid |= mc ? mc->valid : 0;
+		mutex_unlock(&mc->lock);
+	}
+
+	mask &= valid;
+	mask &= kdbus_meta_attach_mask;
+
+	/*
+	 * TODO: We currently have no sane way of translating a set of caps
+	 * between different user namespaces. Until that changes, we have
+	 * to drop such items.
+	 */
+	if (mp && mp->caps_namespace != user_ns)
+		mask &= ~KDBUS_ATTACH_CAPS;
+
+	if (!mask) {
+		*sz = 0;
+		return NULL;
+	}
+
+	/* process metadata */
+
+	if (mp && (mask & KDBUS_ATTACH_CREDS))
+		size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
+
+	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->n_auxgrps * sizeof(u32));
+
+	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 (mp && (mask & KDBUS_ATTACH_EXE)) {
+		struct path p;
+
+		/*
+		 * TODO: 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, &mp->root_path)) {
+			exe_page = (void *)__get_free_page(GFP_TEMPORARY);
+			if (!exe_page) {
+				path_put(&p);
+				ret = -ENOMEM;
+				goto exit;
+			}
+
+			exe_pathname = d_path(&mp->exe_path, exe_page,
+					      PAGE_SIZE);
+			if (IS_ERR(exe_pathname)) {
+				path_put(&p);
+				ret = PTR_ERR(exe_pathname);
+				goto exit;
+			}
+
+			size += KDBUS_ITEM_SIZE(strlen(exe_pathname) + 1);
+		} else {
+			mask &= ~KDBUS_ATTACH_EXE;
+		}
+		path_put(&p);
+	}
+
+	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(mp->caps));
+
+	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 += 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));
+
+	if (!size) {
+		*sz = 0;
+		ret = 0;
+		goto exit;
+	}
+
+	items = kzalloc(size, GFP_KERNEL);
+	if (!items) {
+		ret = -ENOMEM;
+		goto exit;
+	}
+
+	item = items;
+
+	/* process metadata */
+
+	if (mp && (mask & KDBUS_ATTACH_CREDS)) {
+		struct kdbus_creds creds = {
+			.uid	= kdbus_from_kuid_keep(mp->uid),
+			.euid	= kdbus_from_kuid_keep(mp->euid),
+			.suid	= kdbus_from_kuid_keep(mp->suid),
+			.fsuid	= kdbus_from_kuid_keep(mp->fsuid),
+			.gid	= kdbus_from_kgid_keep(mp->gid),
+			.egid	= kdbus_from_kgid_keep(mp->egid),
+			.sgid	= kdbus_from_kgid_keep(mp->sgid),
+			.fsgid	= kdbus_from_kgid_keep(mp->fsgid),
+		};
+
+		item = kdbus_item_set(item, KDBUS_ITEM_CREDS, &creds,
+				      sizeof(creds));
+	}
+
+	if (mp && (mask & KDBUS_ATTACH_PIDS)) {
+		struct kdbus_pids pids = {
+			.pid = pid_vnr(mp->tgid),
+			.tid = pid_vnr(mp->pid),
+			.ppid = pid_vnr(mp->ppid),
+		};
+
+		item = kdbus_item_set(item, KDBUS_ITEM_PIDS, &pids,
+				      sizeof(pids));
+	}
+
+	if (mp && (mask & KDBUS_ATTACH_AUXGROUPS)) {
+		int i;
+
+		kdbus_item_set(item, KDBUS_ITEM_AUXGROUPS, NULL,
+			       mp->n_auxgrps * sizeof(u32));
+
+		for (i = 0; i < mp->n_auxgrps; i++)
+			item->data32[i] = from_kgid_munged(user_ns,
+							   mp->auxgrps[i]);
+
+		item = KDBUS_ITEM_NEXT(item);
+	}
+
+	if (mp && (mask & KDBUS_ATTACH_TID_COMM))
+		item = kdbus_item_set(item, KDBUS_ITEM_TID_COMM, mp->tid_comm,
+				      strlen(mp->tid_comm) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_PID_COMM))
+		item = kdbus_item_set(item, KDBUS_ITEM_PID_COMM, mp->pid_comm,
+				      strlen(mp->pid_comm) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_EXE))
+		item = kdbus_item_set(item, KDBUS_ITEM_EXE, exe_pathname,
+				      strlen(exe_pathname) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_CMDLINE))
+		item = kdbus_item_set(item, KDBUS_ITEM_CMDLINE, mp->cmdline,
+				      strlen(mp->cmdline) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_CGROUP))
+		item = kdbus_item_set(item, KDBUS_ITEM_CGROUP, mp->cgroup,
+				      strlen(mp->cgroup) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_CAPS))
+		item = kdbus_item_set(item, KDBUS_ITEM_CAPS, &mp->caps,
+				      sizeof(mp->caps));
+
+	if (mp && (mask & KDBUS_ATTACH_SECLABEL))
+		item = kdbus_item_set(item, KDBUS_ITEM_SECLABEL, mp->seclabel,
+				      strlen(mp->seclabel) + 1);
+
+	if (mp && (mask & KDBUS_ATTACH_AUDIT)) {
+		struct kdbus_audit a = {
+			.loginuid = from_kuid(user_ns, mp->audit_loginuid),
+			.sessionid = mp->audit_sessionid,
+		};
+
+		item = kdbus_item_set(item, KDBUS_ITEM_AUDIT, &a, sizeof(a));
+	}
+
+	/* connection metadata */
+
+	if (mc && (mask & KDBUS_ATTACH_NAMES)) {
+		memcpy(item, mc->owned_names_items, mc->owned_names_size);
+		item = (struct kdbus_item *)
+				((u8 *)item + mc->owned_names_size);
+	}
+
+	if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION))
+		item = kdbus_item_set(item, KDBUS_ITEM_CONN_DESCRIPTION,
+				      mc->conn_description,
+				      strlen(mc->conn_description) + 1);
+
+	if (mc && (mask & KDBUS_ATTACH_TIMESTAMP))
+		item = kdbus_item_set(item, KDBUS_ITEM_TIMESTAMP, &mc->ts,
+				      sizeof(mc->ts));
+
+	/* sanity check: the buffer should be completely written now */
+	WARN_ON((u8 *)item != (u8 *)items + size);
+
+	*sz = size;
+	ret = 0;
+
+exit:
+	if (exe_page)
+		free_page((unsigned long)exe_page);
+	return ret < 0 ? ERR_PTR(ret) : items;
+}
+
+/**
+ * kdbus_meta_calc_attach_flags() - calculate attach flags for a sender
+ *				    and a receiver
+ * @sender:		Sending connection
+ * @receiver:		Receiving connection
+ *
+ * Return: the attach flags both the sender and the receiver have opted-in
+ * for.
+ */
+u64 kdbus_meta_calc_attach_flags(const struct kdbus_conn *sender,
+				 const struct kdbus_conn *receiver)
+{
+	return atomic64_read(&sender->attach_flags_send) &
+	       atomic64_read(&receiver->attach_flags_recv);
+}
ipc/kdbus/metadata.h new file +52 -0

52 lines not on this page · raw message

Signature · 1 line
2.2.1
#62 lore raw

PATCH v3 8/13 kdbus: add code for notifications and matches

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

This patch adds code for matches and notifications.

Notifications are broadcast messages generated by the kernel, which notify subscribes when connections are created or destroyed, when well-known-names have been claimed, released or changed ownership, or when reply messages have timed out.

Matches are used to tell the kernel driver which broadcast messages a connection is interested in. Matches can either be specific on one of the kernel-generated notification types, or carry a bloom filter mask to match against a message from userspace. The latter is a way to pre-filter messages from other connections in order to mitigate unnecessary wakeups.

---
 ipc/kdbus/match.c  | 535 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/match.h  |  32 ++++
 ipc/kdbus/notify.c | 244 ++++++++++++++++++++++++
 ipc/kdbus/notify.h |  30 +++
 4 files changed, 841 insertions(+)
 create mode 100644 ipc/kdbus/match.c
 create mode 100644 ipc/kdbus/match.h
 create mode 100644 ipc/kdbus/notify.c
 create mode 100644 ipc/kdbus/notify.h
ipc/kdbus/match.c new file +535 -0
new file mode 100644
index 000000000000..d4f21848f66b
@@ -0,0 +1,535 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <[email protected]>
+ *
+ * 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 "item.h"
+#include "match.h"
+#include "message.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 agains
+ * @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
+ * @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;
+	};
+	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_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;
+
+	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;
+
+	down_write(&mdb->mdb_rwlock);
+	list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
+		kdbus_match_entry_free(entry);
+	up_write(&mdb->mdb_rwlock);
+
+	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_rules(const struct kdbus_match_entry *entry,
+			      struct kdbus_conn *conn_src,
+			      struct kdbus_kmsg *kmsg)
+{
+	struct kdbus_match_rule *r;
+
+	/*
+	 * Walk all the rules and bail out immediately
+	 * if any of them is unsatisfied.
+	 */
+
+	list_for_each_entry(r, &entry->rules_list, rules_entry) {
+		if (conn_src) {
+			/* messages from userspace */
+
+			switch (r->type) {
+			case KDBUS_ITEM_BLOOM_MASK:
+				if (!kdbus_match_bloom(kmsg->bloom_filter,
+						       &r->bloom_mask,
+						       conn_src))
+					return false;
+				break;
+
+			case KDBUS_ITEM_ID:
+				if (r->src_id != conn_src->id &&
+				    r->src_id != KDBUS_MATCH_ID_ANY)
+					return false;
+
+				break;
+
+			case KDBUS_ITEM_NAME:
+				if (!kdbus_conn_has_name(conn_src, r->name))
+					return false;
+
+				break;
+
+			default:
+				return false;
+			}
+		} else {
+			/* kernel notifications */
+
+			if (kmsg->notify_type != r->type)
+				return false;
+
+			switch (r->type) {
+			case KDBUS_ITEM_ID_ADD:
+				if (r->new_id != KDBUS_MATCH_ID_ANY &&
+				    r->new_id != kmsg->notify_new_id)
+					return false;
+
+				break;
+
+			case KDBUS_ITEM_ID_REMOVE:
+				if (r->old_id != KDBUS_MATCH_ID_ANY &&
+				    r->old_id != kmsg->notify_old_id)
+					return false;
+
+				break;
+
+			case KDBUS_ITEM_NAME_ADD:
+			case KDBUS_ITEM_NAME_CHANGE:
+			case KDBUS_ITEM_NAME_REMOVE:
+				if ((r->old_id != KDBUS_MATCH_ID_ANY &&
+				     r->old_id != kmsg->notify_old_id) ||
+				    (r->new_id != KDBUS_MATCH_ID_ANY &&
+				     r->new_id != kmsg->notify_new_id) ||
+				    (r->name && kmsg->notify_name &&
+				     strcmp(r->name, kmsg->notify_name) != 0))
+					return false;
+
+				break;
+
+			default:
+				return false;
+			}
+		}
+	}
+
+	return true;
+}
+
+/**
+ * kdbus_match_db_match_kmsg() - match a kmsg object agains the database entries
+ * @mdb:		The match database
+ * @conn_src:		The connection object originating the message
+ * @kmsg:		The kmsg to perform the match on
+ *
+ * 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.
+ *
+ * Return: true if there was a matching database entry, false otherwise.
+ */
+bool kdbus_match_db_match_kmsg(struct kdbus_match_db *mdb,
+			       struct kdbus_conn *conn_src,
+			       struct kdbus_kmsg *kmsg)
+{
+	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, kmsg);
+		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 : -ENOENT;
+}
+
+/**
+ * kdbus_match_db_add() - add an entry to the match database
+ * @conn:		The connection that was used in the ioctl call
+ * @cmd:		The command as provided by the ioctl call
+ *
+ * This function is used in the context of the KDBUS_CMD_MATCH_ADD ioctl
+ * interface.
+ *
+ * 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_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 at when adding an entry. The flags are unused.
+ *
+ * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME and KDBUS_ITEM_ID
+ * are used to match messages from userspace, while the others apply to
+ * kernel-generated notifications.
+ *
+ * Return: 0 on success, negative errno on failure
+ */
+int kdbus_match_db_add(struct kdbus_conn *conn,
+		       struct kdbus_cmd_match *cmd)
+{
+	struct kdbus_match_entry *entry = NULL;
+	struct kdbus_match_db *mdb = conn->match_db;
+	struct kdbus_item *item;
+	int ret = 0;
+
+	kdbus_conn_assert_active(conn);
+
+	entry = kzalloc(sizeof(*entry), GFP_KERNEL);
+	if (!entry)
+		return -ENOMEM;
+
+	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;
+			break;
+		}
+
+		rule->type = item->type;
+		INIT_LIST_HEAD(&rule->rules_entry);
+
+		switch (item->type) {
+		/* First matches for userspace messages */
+		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;
+			}
+
+			/* we get an array of n generations of bloom masks */
+			rule->bloom_mask.generations = generations;
+
+			break;
+		}
+
+		case KDBUS_ITEM_NAME:
+			/*
+			 * Do not allow wildcard for now, since we
+			 * must validate the wildcard first
+			 */
+			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;
+
+		/* Now matches for kernel messages */
+		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;
+
+		default:
+			ret = -EINVAL;
+			break;
+		}
+
+		if (ret < 0) {
+			kdbus_match_rule_free(rule);
+			break;
+		}
+
+		list_add_tail(&rule->rules_entry, &entry->rules_list);
+	}
+
+	if (ret < 0)
+		goto exit;
+
+	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);
+	}
+
+	up_write(&mdb->mdb_rwlock);
+
+exit:
+	if (ret < 0)
+		kdbus_match_entry_free(entry);
+
+	return ret;
+}
+
+/**
+ * kdbus_match_db_remove() - remove an entry from the match database
+ * @conn:		The connection that was used in the ioctl call
+ * @cmd:		Pointer to the match data structure
+ *
+ * This function is used in the context of the KDBUS_CMD_MATCH_REMOVE
+ * ioctl interface.
+ *
+ * Return: 0 on success, negative errno on failure.
+ */
+int kdbus_match_db_remove(struct kdbus_conn *conn,
+			  struct kdbus_cmd_match *cmd)
+{
+	struct kdbus_match_db *mdb = conn->match_db;
+	int ret;
+
+	kdbus_conn_assert_active(conn);
+
+	down_write(&mdb->mdb_rwlock);
+	ret = kdbus_match_db_remove_unlocked(mdb, cmd->cookie);
+	up_write(&mdb->mdb_rwlock);
+
+	return ret;
+}
ipc/kdbus/match.h new file +32 -0
new file mode 100644
index 000000000000..81aed4a99721
@@ -0,0 +1,32 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <[email protected]>
+ *
+ * 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_kmsg;
+struct kdbus_match_db;
+
+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_kmsg(struct kdbus_match_db *db,
+			       struct kdbus_conn *conn_src,
+			       struct kdbus_kmsg *kmsg);
+
+#endif
ipc/kdbus/notify.c new file +244 -0

244 lines not on this page · raw message

ipc/kdbus/notify.h new file +30 -0
new file mode 100644
index 000000000000..22039c123647
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 Djalal Harouni <[email protected]>
+ *
+ * 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
Signature · 1 line
2.2.1
#63 lore raw

PATCH v3 9/13 kdbus: add code for buses, domains and endpoints

In reply to Greg Kroah-Hartman

From: Daniel Mack <[email protected]>

Add the logic to handle the following entities:

Domain:
A domain is an unamed object containing a number of buses. A domain is automatically created when an instance of kdbusfs is mounted, and destroyed when it is unmounted. Every domain offers its own "control" device node to create buses. Domains have no connection to each other and cannot see nor talk to each other.

Bus:
A bus is a named object inside a domain. Clients exchange messages over a bus. Multiple buses themselves have no connection to each other; messages can only be exchanged on the same bus. The default entry point to a bus, where clients establish the connection to, is the "bus" device node /sys/fs/kdbus/<bus name>/bus. Common operating system setups create one "system bus" per system, and one "user bus" for every logged-in user. Applications or services may create their own private named buses.

Endpoint:
An endpoint provides the device node to talk to a bus. Opening an endpoint creates a new connection to the bus to which the endpoint belongs. Every bus has a default endpoint called "bus". A bus can optionally offer additional endpoints with custom names to provide a restricted access to the same bus. Custom endpoints carry additional policy which can be used to give sandboxed processes only a locked-down, limited, filtered access to the same bus.

See Documentation/kdbus.txt for more details.

---
 ipc/kdbus/bus.c      | 553 +++++++++++++++++++++++++++++++++++++++++++++++++++
 ipc/kdbus/bus.h      | 103 ++++++++++
 ipc/kdbus/domain.c   | 350 ++++++++++++++++++++++++++++++++
 ipc/kdbus/domain.h   |  84 ++++++++
 ipc/kdbus/endpoint.c | 232 +++++++++++++++++++++
 ipc/kdbus/endpoint.h |  68 +++++++
 6 files changed, 1390 insertions(+)
 create mode 100644 ipc/kdbus/bus.c
 create mode 100644 ipc/kdbus/bus.h
 create mode 100644 ipc/kdbus/domain.c
 create mode 100644 ipc/kdbus/domain.h
 create mode 100644 ipc/kdbus/endpoint.c
 create mode 100644 ipc/kdbus/endpoint.h
ipc/kdbus/bus.c new file +553 -0
new file mode 100644
index 000000000000..ffcde832116c
@@ -0,0 +1,553 @@
+/*
+ * Copyright (C) 2013-2014 Kay Sievers
+ * Copyright (C) 2013-2014 Greg Kroah-Hartman <[email protected]>
+ * Copyright (C) 2013-2014 Daniel Mack <[email protected]>
+ * Copyright (C) 2013-2014 David Herrmann <[email protected]>
+ * Copyright (C) 2013-2014 Linux Foundation
+ * Copyright (C) 2014 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 "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_domain_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);
+}
+
+/**
+ * kdbus_bus_new() - create a kdbus_cmd_make from user-supplied data
+ * @domain:		The domain to work on
+ * @make:		Information as passed in by userspace
+ * @uid:		The uid of the bus node
+ * @gid:		The gid of the bus node
+ *
+ * This function is part of the connection ioctl() interface and will parse
+ * the user-supplied data in order to create a new kdbus_bus.
+ *
+ * Return: the new bus on success, ERR_PTR on failure.
+ */
+struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain,
+				const struct kdbus_cmd_make *make,
+				kuid_t uid, kgid_t gid)
+{
+	const struct kdbus_bloom_parameter *bloom = NULL;
+	const u64 *pattach_owner = NULL;
+	const u64 *pattach_recv = NULL;
+	const struct kdbus_item *item;
+	const char *name = NULL;
+	struct kdbus_bus *b;
+	u64 attach_owner;
+	u64 attach_recv;
+	int ret;
+
+	KDBUS_ITEMS_FOREACH(item, make->items, KDBUS_ITEMS_SIZE(make, items)) {
+		switch (item->type) {
+		case KDBUS_ITEM_MAKE_NAME:
+			if (name)
+				return ERR_PTR(-EEXIST);
+
+			name = item->str;
+			break;
+
+		case KDBUS_ITEM_BLOOM_PARAMETER:
+			if (bloom)
+				return ERR_PTR(-EEXIST);
+
+			bloom = &item->bloom_parameter;
+			break;
+
+		case KDBUS_ITEM_ATTACH_FLAGS_SEND:
+			if (pattach_owner)
+				return ERR_PTR(-EEXIST);
+
+			pattach_owner = &item->data64[0];
+			break;
+
+		case KDBUS_ITEM_ATTACH_FLAGS_RECV:
+			if (pattach_recv)
+				return ERR_PTR(-EEXIST);
+
+			pattach_recv = &item->data64[0];
+			break;
+
+		default:
+			return ERR_PTR(-EINVAL);
+		}
+	}
+
+	if (!name || !bloom)
+		return ERR_PTR(-EBADMSG);
+
+	if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE)
+		return ERR_PTR(-EINVAL);
+	if (!KDBUS_IS_ALIGNED8(bloom->size))
+		return ERR_PTR(-EINVAL);
+	if (bloom->n_hash < 1)
+		return ERR_PTR(-EINVAL);
+
+	ret = kdbus_sanitize_attach_flags(pattach_recv ? *pattach_recv : 0,
+					  &attach_recv);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0,
+					  &attach_owner);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid);
+	if (ret < 0)
+		return ERR_PTR(ret);
+
+	b = kzalloc(sizeof(*b), GFP_KERNEL);
+	if (!b)
+		return ERR_PTR(-ENOMEM);
+
+	kdbus_node_init(&b->node, KDBUS_NODE_BUS);
+
+	b->node.free_cb = kdbus_bus_free;
+	b->node.release_cb = kdbus_bus_release;
+	b->node.uid = uid;
+	b->node.gid = gid;
+	b->node.mode = S_IRUSR | S_IXUSR;
+
+	b->access = make->flags & (KDBUS_MAKE_ACCESS_WORLD |
+				   KDBUS_MAKE_ACCESS_GROUP);
+	if (b->access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
+		b->node.mode |= S_IRGRP | S_IXGRP;
+	if (b->access & KDBUS_MAKE_ACCESS_WORLD)
+		b->node.mode |= S_IROTH | S_IXOTH;
+
+	b->bus_flags = make->flags;
+	b->bloom = *bloom;
+	b->attach_flags_req = attach_recv;
+	b->attach_flags_owner = attach_owner;
+	mutex_init(&b->lock);
+	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);
+	atomic64_set(&b->conn_seq_last, 0);
+	b->domain = kdbus_domain_ref(domain);
+	kdbus_policy_db_init(&b->policy_db);
+	b->id = atomic64_inc_return(&domain->bus_seq_last);
+
+	/* generate unique bus id */
+	generate_random_uuid(b->id128);
+
+	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_domain_get_user(domain, current_uid());
+	if (IS_ERR(b->creator)) {
+		ret = PTR_ERR(b->creator);
+		b->creator = NULL;
+		goto exit_unref;
+	}
+
+	return b;
+
+exit_unref:
+	kdbus_node_deactivate(&b->node);
+	kdbus_node_unref(&b->node);
+	return ERR_PTR(ret);
+}
+
+/**
+ * kdbus_bus_ref() - increase the reference counter of a kdbus_bus
+ * @bus:		The bus to reference
+ *
+ * Every user of a bus, except for its creator, must add a reference to the
+ * kdbus_bus using this function.
+ *
+ * Return: the bus itself
+ */
+struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus)
+{
+	if (bus)
+		kdbus_node_ref(&bus->node);
+	return bus;
+}
+
+/**
+ * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus
+ * @bus:		The bus to unref
+ *
+ * Release a reference. If the reference count drops to 0, the bus will be
+ * freed.
+ *
+ * Return: NULL
+ */
+struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus)
+{
+	if (bus)
+		kdbus_node_unref(&bus->node);
+	return NULL;
+}
+
+/**
+ * kdbus_bus_activate() - activate a bus
+ * @bus:		Bus
+ *
+ * Activate a bus and make it available to user-space.
+ *
+ * Returns: 0 on success, negative error code on failure
+ */
+int kdbus_bus_activate(struct kdbus_bus *bus)
+{
+	struct kdbus_ep *ep;
+	int ret;
+
+	if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) {
+		atomic_dec(&bus->creator->buses);
+		return -EMFILE;
+	}
+
+	/*
+	 * kdbus_bus_activate() must not be called multiple times, so if
+	 * kdbus_node_activate() didn't activate the node, it must already be
+	 * dead.
+	 */
+	if (!kdbus_node_activate(&bus->node)) {
+		atomic_dec(&bus->creator->buses);
+		return -ESHUTDOWN;
+	}
+
+	/*
+	 * Create a new default endpoint for this bus. If activation succeeds,
+	 * we drop our own reference, effectively causing the endpoint to be
+	 * deactivated and released when the parent domain is.
+	 */
+	ep = kdbus_ep_new(bus, "bus", bus->access,
+			  bus->node.uid, bus->node.gid, false);
+	if (IS_ERR(ep))
+		return PTR_ERR(ep);
+
+	ret = kdbus_ep_activate(ep);
+	if (ret < 0)
+		kdbus_ep_deactivate(ep);
+	kdbus_ep_unref(ep);
+
+	return 0;
+}
+
+/**
+ * kdbus_bus_deactivate() - deactivate a bus
+ * @bus:               The kdbus reference
+ *
+ * The passed bus will be disconnected and the associated endpoint will be
+ * unref'ed.
+ */
+void kdbus_bus_deactivate(struct kdbus_bus *bus)
+{
+	kdbus_node_deactivate(&bus->node);
+}
+
+/**
+ * kdbus_bus_find_conn_by_id() - find a connection with a given id
+ * @bus:		The bus to look for the connection
+ * @id:			The 64-bit connection id
+ *
+ * Looks up a connection with a given id. The returned connection
+ * is ref'ed, and needs to be unref'ed by the user. Returns NULL if
+ * the connection can't be found.
+ */
+struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id)
+{
+	struct kdbus_conn *conn, *found = NULL;
+
+	down_read(&bus->conn_rwlock);
+	hash_for_each_possible(bus->conn_hash, conn, hentry, id)
+		if (conn->id == id) {
+			found = kdbus_conn_ref(conn);
+			break;
+		}
+	up_read(&bus->conn_rwlock);
+
+	return found;
+}
+
+/**
+ * kdbus_bus_broadcast() - send a message to all subscribed connections
+ * @bus:	The bus the connections are connected to
+ * @conn_src:	The source connection, may be %NULL for kernel notifications
+ * @kmsg:	The message to send.
+ *
+ * Send @kmsg to all connections that are currently active on the bus.
+ * Connections must still have matches installed in order to let the message
+ * pass.
+ */
+void kdbus_bus_broadcast(struct kdbus_bus *bus,
+			 struct kdbus_conn *conn_src,
+			 struct kdbus_kmsg *kmsg)
+{
+	struct kdbus_conn *conn_dst;
+	unsigned int i;
+	int ret;
+
+	/*
+	 * Make sure broadcast are queued on monitors before we send it out to
+	 * anyone else. Otherwise, connections might react to broadcasts before
+	 * the monitor gets the broadcast queued. In the worst case, the
+	 * monitor sees a reaction to the broadcast before the broadcast itself.
+	 * We don't give ordering guarantees across connections (and monitors
+	 * can re-construct order via sequence numbers), but we should at least
+	 * try to avoid re-ordering for monitors.
+	 */
+	kdbus_bus_eavesdrop(bus, conn_src, kmsg);
+
+	down_read(&bus->conn_rwlock);
+
+	hash_for_each(bus->conn_hash, i, conn_dst, hentry) {
+		if (conn_dst->id == kmsg->msg.src_id)
+			continue;
+		if (!kdbus_conn_is_ordinary(conn_dst))
+			continue;
+
+		/*
+		 * Check if there is a match for the kmsg object in
+		 * the destination connection match db
+		 */
+		if (!kdbus_match_db_match_kmsg(conn_dst->match_db, conn_src,
+					       kmsg))
+			continue;
+
+		if (conn_src) {
+			u64 attach_flags;
+
+			/*
+			 * Anyone can send broadcasts, as they have no
+			 * destination. But a receiver needs TALK access to
+			 * the sender in order to receive broadcasts.
+			 */
+			if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
+				continue;
+
+			attach_flags = kdbus_meta_calc_attach_flags(conn_src,
+								    conn_dst);
+
+			/*
+			 * Keep sending messages even if we cannot acquire the
+			 * requested metadata. It's up to the receiver to drop
+			 * messages that lack expected metadata.
+			 */
+			if (!conn_src->faked_meta)
+				kdbus_meta_proc_collect(kmsg->proc_meta,
+							attach_flags);
+			kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
+						attach_flags);
+		} else {
+			/*
+			 * Check if there is a policy db that prevents the
+			 * destination connection from receiving this kernel
+			 * notification
+			 */
+			if (!kdbus_conn_policy_see_notification(conn_dst, NULL,
+								kmsg))
+				continue;
+		}
+
+		ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
+		if (ret < 0)
+			atomic_inc(&conn_dst->lost_count);
+	}
+
+	up_read(&bus->conn_rwlock);
+}
+
+/**
+ * kdbus_bus_eavesdrop() - send a message to all subscribed monitors
+ * @bus:	The bus the monitors are connected to
+ * @conn_src:	The source connection, may be %NULL for kernel notifications
+ * @kmsg:	The message to send.
+ *
+ * Send @kmsg to all monitors that are currently active on the bus. Monitors
+ * must still have matches installed in order to let the message pass.
+ */
+void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
+			 struct kdbus_conn *conn_src,
+			 struct kdbus_kmsg *kmsg)
+{
+	struct kdbus_conn *conn_dst;
+	int ret;
+
+	/*
+	 * Monitor connections get all messages; ignore possible errors
+	 * when sending messages to monitor connections.
+	 */
+
+	down_read(&bus->conn_rwlock);
+	list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) {
+		/*
+		 * Collect metadata requested by the destination connection.
+		 * Ignore errors, as receivers need to check metadata
+		 * availability, anyway. So it's still better to send messages
+		 * that lack data, than to skip it entirely.
+		 */
+		if (conn_src) {
+			u64 attach_flags;
+
+			attach_flags = kdbus_meta_calc_attach_flags(conn_src,
+								    conn_dst);
+			if (!conn_src->faked_meta)
+				kdbus_meta_proc_collect(kmsg->proc_meta,
+							attach_flags);
+			kdbus_meta_conn_collect(kmsg->conn_meta, kmsg, conn_src,
+						attach_flags);
+		}
+
+		ret = kdbus_conn_entry_insert(conn_src, conn_dst, kmsg, NULL);
+		if (ret < 0)
+			atomic_inc(&conn_dst->lost_count);
+	}
+	up_read(&bus->conn_rwlock);
+}
+
+/**
+ * kdbus_cmd_bus_creator_info() - get information on a bus creator
+ * @conn:	The querying connection
+ * @cmd_info:	The command buffer, as passed in from the ioctl
+ *
+ * Gather information on the creator of the bus @conn is connected to.
+ *
+ * Return: 0 on success, error otherwise.
+ */
+int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn,
+			       struct kdbus_cmd_info *cmd_info)
+{
+	struct kdbus_bus *bus = conn->ep->bus;
+	struct kdbus_pool_slice *slice = NULL;
+	struct kdbus_item_header item_hdr;
+	struct kdbus_item *meta_items;
+	struct kdbus_info info = {};
+	size_t meta_size, name_len;
+	struct kvec kvec[5];
+	u64 attach_flags;
+	size_t cnt = 0;
+	int ret;
+
+	info.id = bus->id;
+	info.flags = bus->bus_flags;
+
+	name_len = strlen(bus->node.name) + 1;
+
+	/* mask out what information the bus owner wants to pass us */
+	attach_flags = cmd_info->flags & bus->attach_flags_owner;
+
+	meta_items = kdbus_meta_export(bus->creator_meta, NULL, attach_flags,
+				       &meta_size);
+	if (IS_ERR(meta_items))
+		return PTR_ERR(meta_items);
+
+	item_hdr.type = KDBUS_ITEM_MAKE_NAME;
+	item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len;
+
+	kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
+	kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &info.size);
+	kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &info.size);
+	cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size);
+
+	if (meta_items && meta_size)
+		kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &info.size);
+
+	slice = kdbus_pool_slice_alloc(conn->pool, info.size, kvec, NULL, cnt);
+	if (IS_ERR(slice)) {
+		ret = PTR_ERR(slice);
+		slice = NULL;
+		goto exit;
+	}
+
+	/* write back the offset */
+	kdbus_pool_slice_publish(slice, &cmd_info->offset,
+				 &cmd_info->info_size);
+	ret = 0;
+
+	kdbus_pool_slice_release(slice);
+exit:
+	kfree(meta_items);
+	return ret;
+}
ipc/kdbus/bus.h new file +103 -0

103 lines not on this page · raw message

ipc/kdbus/domain.c new file +350 -0

350 lines not on this page · raw message

ipc/kdbus/domain.h new file +84 -0

84 lines not on this page · raw message

ipc/kdbus/endpoint.c new file +232 -0

232 lines not on this page · raw message

ipc/kdbus/endpoint.h new file +68 -0

68 lines not on this page · raw message

Signature · 1 line
2.2.1