├── .dir-locals.el ├── .gitignore ├── Changelog ├── Documentation └── kdbus │ ├── .gitignore │ ├── Makefile │ ├── kdbus.bus.xml │ ├── kdbus.connection.xml │ ├── kdbus.endpoint.xml │ ├── kdbus.fs.xml │ ├── kdbus.item.xml │ ├── kdbus.match.xml │ ├── kdbus.message.xml │ ├── kdbus.name.xml │ ├── kdbus.policy.xml │ ├── kdbus.pool.xml │ ├── kdbus.xml │ └── stylesheet.xsl ├── Makefile ├── Makefile.docs ├── README ├── include └── uapi │ └── linux │ └── kdbus.h ├── ipc └── kdbus │ ├── Makefile │ ├── bus.c │ ├── bus.h │ ├── connection.c │ ├── connection.h │ ├── domain.c │ ├── domain.h │ ├── endpoint.c │ ├── endpoint.h │ ├── fs.c │ ├── fs.h │ ├── handle.c │ ├── handle.h │ ├── item.c │ ├── item.h │ ├── limits.h │ ├── main.c │ ├── match.c │ ├── match.h │ ├── message.c │ ├── message.h │ ├── metadata.c │ ├── metadata.h │ ├── names.c │ ├── names.h │ ├── node.c │ ├── node.h │ ├── notify.c │ ├── notify.h │ ├── policy.c │ ├── policy.h │ ├── pool.c │ ├── pool.h │ ├── queue.c │ ├── queue.h │ ├── reply.c │ ├── reply.h │ ├── util.c │ └── util.h ├── samples └── kdbus │ ├── .gitignore │ ├── Makefile │ ├── kdbus-api.h │ └── kdbus-workers.c ├── tools └── testing │ └── selftests │ ├── kdbus │ ├── .gitignore │ ├── Makefile │ ├── kdbus-enum.c │ ├── kdbus-enum.h │ ├── kdbus-test.c │ ├── kdbus-test.h │ ├── kdbus-util.c │ ├── kdbus-util.h │ ├── test-activator.c │ ├── test-benchmark.c │ ├── test-bus.c │ ├── test-chat.c │ ├── test-connection.c │ ├── test-daemon.c │ ├── test-endpoint.c │ ├── test-fd.c │ ├── test-free.c │ ├── test-match.c │ ├── test-message.c │ ├── test-metadata-ns.c │ ├── test-monitor.c │ ├── test-names.c │ ├── test-policy-ns.c │ ├── test-policy-priv.c │ ├── test-policy.c │ ├── test-sync.c │ └── test-timeout.c │ └── lib.mk └── usr └── include └── linux └── kdbus.h /.dir-locals.el: -------------------------------------------------------------------------------- 1 | ; Sets emacs variables based on mode. 2 | ; A list of (major-mode . ((var1 . value1) (var2 . value2))) 3 | ; Mode can be nil, which gives default values. 4 | 5 | ((nil . ((indent-tabs-mode . t) 6 | (tab-width . 8))) 7 | ) 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.cmd 2 | *.ko 3 | *.mod.c 4 | modules.order 5 | Module.symvers 6 | *.o 7 | *.swp 8 | .tmp_versions 9 | tags 10 | -------------------------------------------------------------------------------- /Changelog: -------------------------------------------------------------------------------- 1 | since v3: 2 | 3 | * Drop KDBUS_FLAG_KERNEL and the 'kernel_flags' member from all 4 | struct kdbus_cmd_*, and introduce a new KDBUS_FLAGS_NEGOTIATE 5 | instead. Requested by Michael Kerrisk. 6 | 7 | * Transform kdbus.txt into DocBook man-pages for better readablity, 8 | and extend the documentation significantly. Requested by Michael 9 | Kerrisk and Christoph Hellwig. 10 | 11 | * Add a walk-through example for using the low-level ioctl API from 12 | userspace. 13 | 14 | * Consolidate some 'struct kdbus_cmd_*' types to make the API 15 | interface easier to grasp. 16 | 17 | * Drop 'struct kdbus_item_list'. The information stored in this 18 | struct was redundant as all ioctls report the returned size 19 | in the command struct already. 20 | 21 | * KDBUS_CMD_NAME_ACQUIRE now returns the KDBUS_NAME_IN_QUEUE flag 22 | in cmd->return_flags rather than modifying cmd->flags. 23 | 24 | * Get rid of the need for a 2nd pool slice at install time. This 25 | avoids pool fragmentation, message memory footprint and complexity. 26 | 27 | * Separate flags from attach_flags in struct kdbus_cmd_info. 28 | 29 | * Fix handling of messages with file descriptors with regard to 30 | monitor connections that don't accept file descriptors. 31 | 32 | * Revisited and reimplemented the quota logic. 50% are now always 33 | kept reserved for the connection to receive notification etc, 34 | and the rest is accounted per remote peer to avoid denial of 35 | service attacks. 36 | 37 | * Make use of new functions introduced with 4.0-rc1 38 | (vfs_iter_write(), {kstrdup,kfree}_const()) 39 | 40 | * Some internal restructuring and cleanups. 41 | 42 | since v2: 43 | 44 | * Add FS_USERNS_MOUNT to the file system flags, so users can mount 45 | their own kdbusfs instances without being root in the parent 46 | user-ns. Spotted by Andy Lutomirski. 47 | 48 | * Rewrite major parts of the metadata implementation to allow for 49 | per-recipient namespace translations. For this, namespaces are 50 | now not pinned by domains anymore. Instead, metadata is recorded 51 | in kernel scope, and exported into the currently active namespaces 52 | at the time of message installing. 53 | 54 | * Split PID and TID from KDBUS_ITEM_CREDS into KDBUS_ITEM_PIDS. 55 | The starttime is there to detect re-used PIDs, so move it to that 56 | new item type as well. Consequently, introduce struct kdbus_pids 57 | to accommodate the information. Requested by Andy Lutomirski. 58 | 59 | * Add {e,s,fs}{u,g}id to KDBUS_ITEM_CREDS, so users have a way to 60 | get more fine-grained credential information. 61 | 62 | * Removed KDBUS_CMD_CANCEL. The interface was not usable from 63 | threaded userspace implementation due to inherent races. Instead, 64 | add an item type CANCEL_FD which can be used to pass a file 65 | descriptor to the CMD_SEND ioctl. When the SEND is done 66 | synchronously, it will get cancelled as soon as the passed 67 | FD signals POLLIN. 68 | 69 | * Dropped startttime from KDBUS_ITEM_PIDS 70 | 71 | * Restrict names of custom endpoints to names with a "-" prefix, 72 | just like we do for buses. 73 | 74 | * Provide module-parameter "kdbus.attach_flags_mask" to specify the 75 | a mask of metadata items that is applied on all exported items. 76 | 77 | * Monitors are now entirely invisible (IOW, there won't be any 78 | notification when they are created) and they don't need to install 79 | filters for broadcast messages anymore. 80 | 81 | * All information exposed via a connection's pool now also reports 82 | the length in addition to the offset. That way, userspace 83 | applications can mmap() only parts of the pool on demand. 84 | 85 | * Due to the metadata rework, KDBUS_ITEM_PAYLOAD_OFF items now 86 | describe the offset relative to the pool, where they used to be 87 | relative to the message header. 88 | 89 | * Added return_flags bitmask to all kdbus_cmd_* structs, so the 90 | kernel can report details of the command processing. This is 91 | mostly reserved for future extensions. 92 | 93 | * Some fixes in kdbus.txt and tests, spotted by Harald Hoyer, Andy 94 | Lutomirski, Michele Curti, Sergei Zviagintsev, Sheng Yong, Torstein 95 | Husebø and Hristo Venev. 96 | 97 | * Fixed compiler warnings in test-message by Michele Curti 98 | 99 | * Unexpected items are now rejected with -EINVAL 100 | 101 | * Split signal and broadcast handling. Unicast signals are now 102 | supported, and messages have a new KDBUS_MSG_SIGNAL flag. 103 | 104 | * KDBUS_CMD_MSG_SEND was renamed to KDBUS_CMD_SEND, and now takes 105 | a struct kdbus_cmd_send instead of a kdbus_msg. 106 | 107 | * KDBUS_CMD_MSG_RECV was renamed to KDBUS_CMD_RECV. 108 | 109 | * Test case memory leak plugged, and various other cleanups and 110 | fixes, by Rui Miguel Silva. 111 | 112 | * Build fix for s390 113 | 114 | * Test case fix for 32bit archs 115 | 116 | * The test framework now supports mount, pid and user namespaces. 117 | 118 | * The test framework learned a --tap command line parameter to 119 | format its output in the "Test Anything Protocol". This format 120 | is chosen by default when "make kselftest" is invoked. 121 | 122 | * Fixed buses and custom endpoints name validation, reported by 123 | Andy Lutomirski. 124 | 125 | * copy_from_user() return code issue fixed, reported by 126 | Dan Carpenter. 127 | 128 | * Avoid signed int overflow on archs without atomic_sub 129 | 130 | * Avoid variable size stack items. Fixes a sparse warning in queue.c. 131 | 132 | * New test case for kernel notification quota 133 | 134 | * Switched back to enums for the list of ioctls. This has advantages 135 | for userspace code as gdb, for instance, is able to resolve the 136 | numbers into names. Added features can easily be detected with 137 | autotools, and new iotcls can get #defines as well. Having #defines 138 | for the initial set of ioctls is uncecessary. 139 | 140 | 141 | since RFC v1: 142 | 143 | * Most notably, kdbus exposes its control files, buses and endpoints 144 | via an own file system now, called kdbusfs. 145 | 146 | * Each time a file system of this type is mounted, a new kdbus 147 | domain is created. 148 | 149 | * By default, kdbus is expected to be mounted in /sys/fs/kdbus 150 | 151 | * The layout inside each mount point is the same as before, except 152 | that domains are not hierarchically nested anymore. 153 | 154 | * Domains are therefore also unnamed now. 155 | 156 | * Unmounting a kdbusfs will automatically also detroy the 157 | associated domain. 158 | 159 | * Hence, the action of creating a kdbus domain is now as 160 | privileged as mounting a file system. 161 | 162 | * This way, we can get around creating dev nodes for everything, 163 | which is last but not least something that is not limited by 164 | 20-bit minor numbers. 165 | 166 | * Rework the metadata attachment logic to address concerns raised by 167 | Andy Lutomirsky and Alan Cox: 168 | 169 | * Split the attach_flags in kdbus_cmd_hello into two parts, 170 | attach_flags_send and attach_flags_recv. Also, split the 171 | existing KDBUS_ITEM_ATTACH_FLAGS into 172 | KDBUS_ITEM_ATTACH_FLAGS_SEND and KDBUS_ITEM_ATTACH_FLAGS_RECV, 173 | and allow updating both connection details through 174 | KDBUS_CMD_CONN_UPDATE. 175 | 176 | * Only attach metadata to the final message in the receiver's pool 177 | if both the sender's attach_flags_send and the receiver's 178 | attach_flags_recv bit are set. 179 | 180 | * Add an optional metadata mask to the bus during its creation, so 181 | bus owners can denote their minimal requirements of metadata to 182 | be attached by connections of the bus. 183 | 184 | * Namespaces are now pinned by a domain at its creation time, and 185 | metadata items are automatically translated into these namespaces. 186 | Unless that cannot be done (currently only capabilities), in which 187 | case the items are dropped. For hide_pid enabled domains, drop all 188 | items except for such not revealing anything about the task. 189 | 190 | * Capabilities are now only checked at open() time, and the 191 | information is cached for the lifetime of a file descriptor. 192 | Reported by Eric W. Biederman, Andy Lutomirski and Thomas Gleixner. 193 | 194 | * Make functions that create new objects return the newly allocated 195 | memory directly, rather than in a referenced function arguments. 196 | That implies using ERR_PTR/PTR_ERR logic in many areas. Requested by 197 | Al Viro. 198 | 199 | * Rename two details in kdbus.h to not overload the term 'name' too 200 | much: 201 | 202 | KDBUS_ITEM_CONN_NAME → KDBUS_ITEM_CONN_DESCRIPTION 203 | KDBUS_ATTACH_CONN_NAME → KDBUS_ATTACH_CONN_DESCRIPTION 204 | 205 | * Documentation fixes, by Peter Meerwald and others. 206 | 207 | * Some memory leaks plugged, and another match test added, by 208 | Rui Miguel Silva 209 | 210 | * Per-user message count quota logic fixed, and new test added. 211 | By John de la Garza. 212 | 213 | * More test code for CONN_INFO ioctl 214 | 215 | * Added a kdbus_node object embedded by domains, endpoints and buses 216 | to track children in a generic way. A kdbus_node is always exposed 217 | as inode in kdbusfs. 218 | 219 | * Add a new attach flags constant called _KDBUS_ATTACH_ANY (~0) 220 | which automatically degrades to _KDBUS_ATTACH_ALL in the kernel. 221 | That way, old clients can opt-in for whethever newer kernels might 222 | offer to send. 223 | 224 | * Use #defines rather than an enum for the ioctl signatures, so when 225 | new ones are added, usespace can use #ifdeffery to determine the 226 | function set at compile time. Suggested by Arnd Bergmann. 227 | 228 | * Moved the driver to ipc/kdbus, as suggested by Arnd Bergmann. 229 | -------------------------------------------------------------------------------- /Documentation/kdbus/.gitignore: -------------------------------------------------------------------------------- 1 | *.7 2 | *.html 3 | -------------------------------------------------------------------------------- /Documentation/kdbus/Makefile: -------------------------------------------------------------------------------- 1 | DOCS := \ 2 | kdbus.xml \ 3 | kdbus.bus.xml \ 4 | kdbus.connection.xml \ 5 | kdbus.endpoint.xml \ 6 | kdbus.fs.xml \ 7 | kdbus.item.xml \ 8 | kdbus.match.xml \ 9 | kdbus.message.xml \ 10 | kdbus.name.xml \ 11 | kdbus.policy.xml \ 12 | kdbus.pool.xml 13 | 14 | XMLFILES := $(addprefix $(obj)/,$(DOCS)) 15 | MANFILES := $(patsubst %.xml, %.7, $(XMLFILES)) 16 | HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES)) 17 | 18 | XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl --skip-validation 19 | 20 | quiet_cmd_db2man = MAN $@ 21 | cmd_db2man = xmlto man $(XMLTO_ARGS) -o $(obj) $< 22 | %.7: %.xml 23 | @(which xmlto > /dev/null 2>&1) || \ 24 | (echo "*** You need to install xmlto ***"; \ 25 | exit 1) 26 | $(call cmd,db2man) 27 | 28 | quiet_cmd_db2html = HTML $@ 29 | cmd_db2html = xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $< 30 | %.html: %.xml 31 | @(which xmlto > /dev/null 2>&1) || \ 32 | (echo "*** You need to install xmlto ***"; \ 33 | exit 1) 34 | $(call cmd,db2html) 35 | 36 | mandocs: $(MANFILES) 37 | 38 | htmldocs: $(HTMLFILES) 39 | 40 | clean-files := $(MANFILES) $(HTMLFILES) 41 | 42 | # we don't support other %docs targets right now 43 | %docs: 44 | @true 45 | -------------------------------------------------------------------------------- /Documentation/kdbus/kdbus.fs.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | 7 | 8 | kdbus.fs 9 | kdbus.fs 10 | 11 | 12 | 13 | kdbus.fs 14 | 7 15 | 16 | 17 | 18 | kdbus.fs 19 | kdbus file system 20 | 21 | 22 | 23 | File-system Layout 24 | 25 | 26 | The kdbusfs pseudo filesystem provides access to 27 | kdbus entities, such as buses and 28 | endpoints. Each time the filesystem is mounted, 29 | a new, isolated kdbus instance is created, which is independent from the 30 | other instances. 31 | 32 | 33 | The system-wide standard mount point for kdbusfs is 34 | /sys/fs/kdbus. 35 | 36 | 37 | 38 | Buses are represented as directories in the file system layout, whereas 39 | endpoints are exposed as files inside these directories. At the top-level, 40 | a control node is present, which can be opened to 41 | create new buses via the KDBUS_CMD_BUS_MAKE ioctl. 42 | Each bus shows a default endpoint called 43 | bus, which can be opened to either create a connection 44 | with the KDBUS_CMD_HELLO ioctl, or to create new 45 | custom endpoints for the bus with 46 | KDBUS_CMD_ENDPOINT_MAKE. See 47 | 48 | kdbus.bus 49 | 7 50 | , 51 | 52 | kdbus.connection 53 | 7 54 | and 55 | 56 | kdbus.endpoint 57 | 7 58 | 59 | for more details. 60 | 61 | 62 | Following, you can see an example layout of the 63 | kdbusfs filesystem: 64 | 65 | 66 | /sys/fs/kdbus/ ; mount-point 67 | |-- 0-system ; bus directory 68 | | |-- bus ; default endpoint 69 | | `-- 1017-custom ; custom endpoint 70 | |-- 1000-user ; bus directory 71 | | |-- bus ; default endpoint 72 | | |-- 1000-service-A ; custom endpoint 73 | | `-- 1000-service-B ; custom endpoint 74 | `-- control ; control file 75 | 76 | 77 | 78 | 79 | Mounting instances 80 | 81 | In order to get a new and separate kdbus environment, a new instance 82 | of kdbusfs can be mounted like this: 83 | 84 | 85 | # mount -t kdbusfs kdbusfs /tmp/new_kdbus/ 86 | 87 | 88 | 89 | 90 | See Also 91 | 92 | 93 | 94 | kdbus 95 | 7 96 | 97 | 98 | 99 | 100 | kdbus.bus 101 | 7 102 | 103 | 104 | 105 | 106 | kdbus.connection 107 | 7 108 | 109 | 110 | 111 | 112 | kdbus.endpoint 113 | 7 114 | 115 | 116 | 117 | 118 | mount 119 | 8 120 | 121 | 122 | 123 | 124 | 125 | -------------------------------------------------------------------------------- /Documentation/kdbus/stylesheet.xsl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 1 4 | ansi 5 | 80 6 | 0 7 | A4 8 | 2 9 | 1 10 | 1 11 | 12 | 16 | 17 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # Out-of-tree kdbus 3 | # This makefile builds the out-of-tree kdbus module and all complementary 4 | # elements, including samples and documentation provided alongside the module. 5 | # 6 | # This Makefile serves two purposes. It serves as main Makefile for this 7 | # project, but also as entry point for the out-of-tree kernel makefile hook. 8 | # Therefore, this makefile is split into two parts. To avoid any conflicts, we 9 | # move fixups, etc., into separate makefiles that are called from within here. 10 | # 11 | 12 | # 13 | # Kernel Makefile 14 | # This part builds the kernel module and everything related. It uses the kbuild 15 | # infrastructure to hook into the obj- build of the kernel. 16 | # Both the actual module and the samples are added. The Documentation cannot be 17 | # added here, as the kernel doesn't support that for out-of-tree modules. 18 | # 19 | 20 | obj-$(CONFIG_KDBUS) += ipc/kdbus/ 21 | obj-$(CONFIG_SAMPLES) += samples/kdbus/ 22 | 23 | # 24 | # Project Makefile 25 | # Everything below is part of the out-of-tree module and builds the related 26 | # tools if the kernel makefile cannot be used. 27 | # 28 | 29 | KERNELVER ?= $(shell uname -r) 30 | KERNELDIR ?= /lib/modules/$(KERNELVER)/build 31 | PWD := $(shell pwd) 32 | EXTRA_CFLAGS += -I$(PWD)/include -DKDBUS_SUPER_MAGIC=0x4442757 33 | HOST_EXTRACFLAGS += -I$(PWD)/usr/include 34 | 35 | # 36 | # Default Target 37 | # By default, build the out-of-tree module and everything that belongs into the 38 | # same build. 39 | # 40 | all: module 41 | 42 | # 43 | # Module Target 44 | # The 'module' target maps to the default out-of-tree target of the current 45 | # tree. This builds the obj-{y,m} contents and also any hostprogs. We need a 46 | # fixup for cflags and configuration options. Everything else is taken directly 47 | # from the kernel makefiles. 48 | # 49 | module: 50 | $(MAKE) -C $(KERNELDIR) M=$(PWD) EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \ 51 | HOST_EXTRACFLAGS="$(HOST_EXTRACFLAGS)" KDBUS_EXT=$(EXT) \ 52 | CONFIG_KDBUS=m CONFIG_SAMPLES=y CONFIG_SAMPLE_KDBUS=y 53 | 54 | # 55 | # Documentation Target 56 | # The out-of-tree support in the upstream makefile lacks integration with 57 | # documentation targets. Therefore, we need a fixup makefile to make sure our 58 | # documentation makefile works properly. 59 | # 60 | %docs: 61 | $(MAKE) -f Makefile.docs $@ 62 | 63 | # 64 | # Test 65 | # This builds the self-tests, as 'kselftest' does not provide any out-of-tree 66 | # integration.. 67 | # 68 | tests: 69 | CFLAGS="-g -O0" $(MAKE) -C tools/testing/selftests/kdbus/ 70 | 71 | # 72 | # Print Differences 73 | # This compares the out-of-tree source with an upstream source and prints any 74 | # differences. This should be used by maintainers to make sure we include all 75 | # changes that are present in the in-tree sources. 76 | # 77 | diff: 78 | -@diff -q -u include/uapi/linux/kdbus.h ./$(KERNELSRC)/include/uapi/linux/kdbus.h 79 | -@diff -q -u -r ipc/kdbus/ ./$(KERNELSRC)/ipc/kdbus 80 | -@diff -q -u -r samples/kdbus/ ./$(KERNELSRC)/samples/kdbus 81 | -@diff -q -u -r Documentation/kdbus/ ./$(KERNELSRC)/Documentation/kdbus 82 | -@diff -q -u -r tools/testing/selftests/kdbus/ ./$(KERNELSRC)/tools/testing/selftests/kdbus 83 | 84 | clean: 85 | rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c 86 | rm -f ipc/kdbus/{*.ko,*.o,.*.cmd,*.order,*.mod.c} 87 | rm -f Module.markers Module.symvers modules.order 88 | rm -f samples/kdbus/{kdbus-workers,*.o,modules.order,Module.symvers} 89 | rm -rf samples/kdbus/{.*.cmd,.tmp_versions} 90 | rm -f Documentation/kdbus/{*.7,*.html} 91 | rm -f tools/testing/selftests/kdbus/{*.o,kdbus-test} 92 | rm -rf .tmp_versions Modules.symvers $(hostprogs-y) 93 | 94 | install: module 95 | mkdir -p /lib/modules/$(KERNELVER)/kernel/ipc/kdbus$(EXT)/ 96 | cp -f ipc/kdbus/kdbus$(EXT).ko /lib/modules/$(KERNELVER)/kernel/ipc/kdbus$(EXT)/ 97 | depmod $(KERNELVER) 98 | 99 | uninstall: 100 | rm -f /lib/modules/$(KERNELVER)/kernel/ipc/kdbus/kdbus$(EXT).ko 101 | rm -f /lib/modules/$(KERNELVER)/kernel/drivers/kdbus/kdbus$(EXT).ko 102 | rm -f /lib/modules/$(KERNELVER)/kernel/drivers/misc/kdbus/kdbus$(EXT).ko 103 | 104 | tt-prepare: module tests 105 | -sudo sh -c 'dmesg -c > /dev/null' 106 | -sudo umount /sys/fs/kdbus$(EXT) 107 | -sudo sh -c 'rmmod kdbus$(EXT)' 108 | sudo sh -c 'insmod ipc/kdbus/kdbus$(EXT).ko' 109 | sudo mount -t kdbus$(EXT)fs kdbus$(EXT)fs /sys/fs/kdbus$(EXT) 110 | 111 | tt: tt-prepare 112 | tools/testing/selftests/kdbus/kdbus-test -m kdbus$(EXT) ; (R=$$? ; dmesg ; exit $$R) 113 | 114 | stt: tt-prepare 115 | sudo tools/testing/selftests/kdbus/kdbus-test -m kdbus$(EXT) ; (R=$$? ; dmesg ; exit $$R) 116 | 117 | www_target = www.freedesktop.org:/srv/www.freedesktop.org/www/software/systemd 118 | 119 | doc-sync: htmldocs 120 | rsync -rlv --delete-excluded --include="*.html" --exclude="*" --omit-dir-times Documentation/kdbus/ $(www_target)/kdbus/ 121 | 122 | .PHONY: all module tests clean install uninstall tt-prepare tt stt 123 | -------------------------------------------------------------------------------- /Makefile.docs: -------------------------------------------------------------------------------- 1 | cmd = $(cmd_$(1)) 2 | srctree = $(shell pwd) 3 | src = Documentation/kdbus 4 | obj = $(srctree)/$(src) 5 | 6 | include Documentation/kdbus/Makefile 7 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | Linux kernel D-Bus implementation 2 | 3 | See kdbus.txt in this repository for kernel-side details. 4 | 5 | The userspace side is developed in systemd: 6 | https://github.com/systemd/systemd/tree/master/src/libsystemd/sd-bus 7 | 8 | Development repos: 9 | https://github.com/gregkh/kdbus 10 | https://code.google.com/p/d-bus/ 11 | 12 | See also: 13 | https://review.tizen.org/git/?p=platform/upstream/glib.git;a=shortlog;h=refs/heads/kdbus-integration 14 | https://review.tizen.org/git/?p=platform/upstream/dbus.git;a=shortlog;h=refs/heads/kdbus-dev 15 | 16 | The code is LGPLv2+. We need to make sure, that we are able to freely 17 | share and copy code with the userspace library, which has the same licence. 18 | -------------------------------------------------------------------------------- /ipc/kdbus/Makefile: -------------------------------------------------------------------------------- 1 | # 2 | # By setting KDBUS_EXT=2, the kdbus module will be built as kdbus2.ko, and 3 | # KBUILD_MODNAME=kdbus2. This has the effect that all exported objects have 4 | # different names than usually (kdbus2fs, /sys/fs/kdbus2/) and you can run 5 | # your test-infrastructure against the kdbus2.ko, while running your system 6 | # on kdbus.ko. 7 | # 8 | # To just build the module, use: 9 | # make KDBUS_EXT=2 M=ipc/kdbus 10 | # 11 | 12 | kdbus$(KDBUS_EXT)-y := \ 13 | bus.o \ 14 | connection.o \ 15 | endpoint.o \ 16 | fs.o \ 17 | handle.o \ 18 | item.o \ 19 | main.o \ 20 | match.o \ 21 | message.o \ 22 | metadata.o \ 23 | names.o \ 24 | node.o \ 25 | notify.o \ 26 | domain.o \ 27 | policy.o \ 28 | pool.o \ 29 | reply.o \ 30 | queue.o \ 31 | util.o 32 | 33 | obj-$(CONFIG_KDBUS) += kdbus$(KDBUS_EXT).o 34 | -------------------------------------------------------------------------------- /ipc/kdbus/bus.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_BUS_H 16 | #define __KDBUS_BUS_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "metadata.h" 26 | #include "names.h" 27 | #include "node.h" 28 | #include "policy.h" 29 | 30 | struct kdbus_conn; 31 | struct kdbus_domain; 32 | struct kdbus_staging; 33 | struct kdbus_user; 34 | 35 | /** 36 | * struct kdbus_bus - bus in a domain 37 | * @node: kdbus_node 38 | * @id: ID of this bus in the domain 39 | * @bus_flags: Simple pass-through flags from userspace to userspace 40 | * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other 41 | * connections can see or query 42 | * @id128: Unique random 128 bit ID of this bus 43 | * @bloom: Bloom parameters 44 | * @domain: Domain of this bus 45 | * @creator: Creator of the bus 46 | * @creator_meta: Meta information about the bus creator 47 | * @last_message_id: Last used message id 48 | * @policy_db: Policy database for this bus 49 | * @name_registry: Name registry of this bus 50 | * @conn_rwlock: Read/Write lock for all lists of child connections 51 | * @conn_hash: Map of connection IDs 52 | * @monitors_list: Connections that monitor this bus 53 | * @notify_list: List of pending kernel-generated messages 54 | * @notify_lock: Notification list lock 55 | * @notify_flush_lock: Notification flushing lock 56 | */ 57 | struct kdbus_bus { 58 | struct kdbus_node node; 59 | 60 | /* static */ 61 | u64 id; 62 | u64 bus_flags; 63 | u64 attach_flags_owner; 64 | u8 id128[16]; 65 | struct kdbus_bloom_parameter bloom; 66 | struct kdbus_domain *domain; 67 | struct kdbus_user *creator; 68 | struct kdbus_meta_proc *creator_meta; 69 | 70 | /* protected by own locks */ 71 | atomic64_t last_message_id; 72 | struct kdbus_policy_db policy_db; 73 | struct kdbus_name_registry *name_registry; 74 | 75 | /* protected by conn_rwlock */ 76 | struct rw_semaphore conn_rwlock; 77 | DECLARE_HASHTABLE(conn_hash, 8); 78 | struct list_head monitors_list; 79 | 80 | /* protected by notify_lock */ 81 | struct list_head notify_list; 82 | spinlock_t notify_lock; 83 | struct mutex notify_flush_lock; 84 | }; 85 | 86 | struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus); 87 | struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus); 88 | 89 | struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id); 90 | void kdbus_bus_broadcast(struct kdbus_bus *bus, 91 | struct kdbus_conn *conn_src, 92 | struct kdbus_staging *staging); 93 | void kdbus_bus_eavesdrop(struct kdbus_bus *bus, 94 | struct kdbus_conn *conn_src, 95 | struct kdbus_staging *staging); 96 | 97 | struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain, 98 | void __user *argp); 99 | int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp); 100 | 101 | #endif 102 | -------------------------------------------------------------------------------- /ipc/kdbus/connection.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_CONNECTION_H 16 | #define __KDBUS_CONNECTION_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "limits.h" 24 | #include "metadata.h" 25 | #include "pool.h" 26 | #include "queue.h" 27 | #include "util.h" 28 | 29 | #define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \ 30 | KDBUS_HELLO_POLICY_HOLDER | \ 31 | KDBUS_HELLO_MONITOR) 32 | 33 | struct kdbus_name_entry; 34 | struct kdbus_quota; 35 | struct kdbus_staging; 36 | 37 | /** 38 | * struct kdbus_conn - connection to a bus 39 | * @kref: Reference count 40 | * @active: Active references to the connection 41 | * @id: Connection ID 42 | * @flags: KDBUS_HELLO_* flags 43 | * @attach_flags_send: KDBUS_ATTACH_* flags for sending 44 | * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving 45 | * @description: Human-readable connection description, used for 46 | * debugging. This field is only set when the 47 | * connection is created. 48 | * @ep: The endpoint this connection belongs to 49 | * @lock: Connection data lock 50 | * @hentry: Entry in ID <-> connection map 51 | * @ep_entry: Entry in endpoint 52 | * @monitor_entry: Entry in monitor, if the connection is a monitor 53 | * @reply_list: List of connections this connection should 54 | * reply to 55 | * @work: Delayed work to handle timeouts 56 | * activator for 57 | * @match_db: Subscription filter to broadcast messages 58 | * @meta_proc: Process metadata of connection creator, or NULL 59 | * @meta_fake: Faked metadata, or NULL 60 | * @pool: The user's buffer to receive messages 61 | * @user: Owner of the connection 62 | * @cred: The credentials of the connection at creation time 63 | * @pid: Pid at creation time 64 | * @root_path: Root path at creation time 65 | * @request_count: Number of pending requests issued by this 66 | * connection that are waiting for replies from 67 | * other peers 68 | * @lost_count: Number of lost broadcast messages 69 | * @wait: Wake up this endpoint 70 | * @queue: The message queue associated with this connection 71 | * @quota: Array of per-user quota indexed by user->id 72 | * @n_quota: Number of elements in quota array 73 | * @names_list: List of well-known names 74 | * @name_count: Number of owned well-known names 75 | * @privileged: Whether this connection is privileged on the domain 76 | * @owner: Owned by the same user as the bus owner 77 | */ 78 | struct kdbus_conn { 79 | struct kref kref; 80 | atomic_t active; 81 | #ifdef CONFIG_DEBUG_LOCK_ALLOC 82 | struct lockdep_map dep_map; 83 | #endif 84 | u64 id; 85 | u64 flags; 86 | atomic64_t attach_flags_send; 87 | atomic64_t attach_flags_recv; 88 | const char *description; 89 | struct kdbus_ep *ep; 90 | struct mutex lock; 91 | struct hlist_node hentry; 92 | struct list_head ep_entry; 93 | struct list_head monitor_entry; 94 | struct list_head reply_list; 95 | struct delayed_work work; 96 | struct kdbus_match_db *match_db; 97 | struct kdbus_meta_proc *meta_proc; 98 | struct kdbus_meta_fake *meta_fake; 99 | struct kdbus_pool *pool; 100 | struct kdbus_user *user; 101 | const struct cred *cred; 102 | struct pid *pid; 103 | struct path root_path; 104 | atomic_t request_count; 105 | atomic_t lost_count; 106 | wait_queue_head_t wait; 107 | struct kdbus_queue queue; 108 | 109 | struct kdbus_quota *quota; 110 | unsigned int n_quota; 111 | 112 | /* protected by registry->rwlock */ 113 | struct list_head names_list; 114 | unsigned int name_count; 115 | 116 | bool privileged:1; 117 | bool owner:1; 118 | }; 119 | 120 | struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn); 121 | struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn); 122 | bool kdbus_conn_active(const struct kdbus_conn *conn); 123 | int kdbus_conn_acquire(struct kdbus_conn *conn); 124 | void kdbus_conn_release(struct kdbus_conn *conn); 125 | int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty); 126 | bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name); 127 | int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u, 128 | size_t memory, size_t fds); 129 | void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u, 130 | size_t memory, size_t fds); 131 | void kdbus_conn_lost_message(struct kdbus_conn *c); 132 | int kdbus_conn_entry_insert(struct kdbus_conn *conn_src, 133 | struct kdbus_conn *conn_dst, 134 | struct kdbus_staging *staging, 135 | struct kdbus_reply *reply, 136 | const struct kdbus_name_entry *name); 137 | void kdbus_conn_move_messages(struct kdbus_conn *conn_dst, 138 | struct kdbus_conn *conn_src, 139 | u64 name_id); 140 | 141 | /* policy */ 142 | bool kdbus_conn_policy_own_name(struct kdbus_conn *conn, 143 | const struct cred *conn_creds, 144 | const char *name); 145 | bool kdbus_conn_policy_talk(struct kdbus_conn *conn, 146 | const struct cred *conn_creds, 147 | struct kdbus_conn *to); 148 | bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn, 149 | const struct cred *curr_creds, 150 | const char *name); 151 | bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn, 152 | const struct cred *curr_creds, 153 | const struct kdbus_msg *msg); 154 | 155 | /* command dispatcher */ 156 | struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file, 157 | void __user *argp); 158 | int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp); 159 | int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp); 160 | int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp); 161 | int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp); 162 | int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp); 163 | int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp); 164 | 165 | /** 166 | * kdbus_conn_is_ordinary() - Check if connection is ordinary 167 | * @conn: The connection to check 168 | * 169 | * Return: Non-zero if the connection is an ordinary connection 170 | */ 171 | static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn) 172 | { 173 | return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN); 174 | } 175 | 176 | /** 177 | * kdbus_conn_is_activator() - Check if connection is an activator 178 | * @conn: The connection to check 179 | * 180 | * Return: Non-zero if the connection is an activator 181 | */ 182 | static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn) 183 | { 184 | return conn->flags & KDBUS_HELLO_ACTIVATOR; 185 | } 186 | 187 | /** 188 | * kdbus_conn_is_policy_holder() - Check if connection is a policy holder 189 | * @conn: The connection to check 190 | * 191 | * Return: Non-zero if the connection is a policy holder 192 | */ 193 | static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn) 194 | { 195 | return conn->flags & KDBUS_HELLO_POLICY_HOLDER; 196 | } 197 | 198 | /** 199 | * kdbus_conn_is_monitor() - Check if connection is a monitor 200 | * @conn: The connection to check 201 | * 202 | * Return: Non-zero if the connection is a monitor 203 | */ 204 | static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn) 205 | { 206 | return conn->flags & KDBUS_HELLO_MONITOR; 207 | } 208 | 209 | /** 210 | * kdbus_conn_lock2() - Lock two connections 211 | * @a: connection A to lock or NULL 212 | * @b: connection B to lock or NULL 213 | * 214 | * Lock two connections at once. As we need to have a stable locking order, we 215 | * always lock the connection with lower memory address first. 216 | */ 217 | static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b) 218 | { 219 | if (a < b) { 220 | if (a) 221 | mutex_lock(&a->lock); 222 | if (b && b != a) 223 | mutex_lock_nested(&b->lock, !!a); 224 | } else { 225 | if (b) 226 | mutex_lock(&b->lock); 227 | if (a && a != b) 228 | mutex_lock_nested(&a->lock, !!b); 229 | } 230 | } 231 | 232 | /** 233 | * kdbus_conn_unlock2() - Unlock two connections 234 | * @a: connection A to unlock or NULL 235 | * @b: connection B to unlock or NULL 236 | * 237 | * Unlock two connections at once. See kdbus_conn_lock2(). 238 | */ 239 | static inline void kdbus_conn_unlock2(struct kdbus_conn *a, 240 | struct kdbus_conn *b) 241 | { 242 | if (a) 243 | mutex_unlock(&a->lock); 244 | if (b && b != a) 245 | mutex_unlock(&b->lock); 246 | } 247 | 248 | /** 249 | * kdbus_conn_assert_active() - lockdep assert on active lock 250 | * @conn: connection that shall be active 251 | * 252 | * This verifies via lockdep that the caller holds an active reference to the 253 | * given connection. 254 | */ 255 | static inline void kdbus_conn_assert_active(struct kdbus_conn *conn) 256 | { 257 | lockdep_assert_held(conn); 258 | } 259 | 260 | #endif 261 | -------------------------------------------------------------------------------- /ipc/kdbus/domain.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include "bus.h" 25 | #include "domain.h" 26 | #include "handle.h" 27 | #include "item.h" 28 | #include "limits.h" 29 | #include "util.h" 30 | 31 | static void kdbus_domain_control_free(struct kdbus_node *node) 32 | { 33 | kfree(node); 34 | } 35 | 36 | static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain, 37 | unsigned int access) 38 | { 39 | struct kdbus_node *node; 40 | int ret; 41 | 42 | node = kzalloc(sizeof(*node), GFP_KERNEL); 43 | if (!node) 44 | return ERR_PTR(-ENOMEM); 45 | 46 | kdbus_node_init(node, KDBUS_NODE_CONTROL); 47 | 48 | node->free_cb = kdbus_domain_control_free; 49 | node->mode = domain->node.mode; 50 | node->mode = S_IRUSR | S_IWUSR; 51 | if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) 52 | node->mode |= S_IRGRP | S_IWGRP; 53 | if (access & KDBUS_MAKE_ACCESS_WORLD) 54 | node->mode |= S_IROTH | S_IWOTH; 55 | 56 | ret = kdbus_node_link(node, &domain->node, "control"); 57 | if (ret < 0) 58 | goto exit_free; 59 | 60 | return node; 61 | 62 | exit_free: 63 | kdbus_node_deactivate(node); 64 | kdbus_node_unref(node); 65 | return ERR_PTR(ret); 66 | } 67 | 68 | static void kdbus_domain_free(struct kdbus_node *node) 69 | { 70 | struct kdbus_domain *domain = 71 | container_of(node, struct kdbus_domain, node); 72 | 73 | put_user_ns(domain->user_namespace); 74 | ida_destroy(&domain->user_ida); 75 | idr_destroy(&domain->user_idr); 76 | kfree(domain); 77 | } 78 | 79 | /** 80 | * kdbus_domain_new() - create a new domain 81 | * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*) 82 | * 83 | * Return: a new kdbus_domain on success, ERR_PTR on failure 84 | */ 85 | struct kdbus_domain *kdbus_domain_new(unsigned int access) 86 | { 87 | struct kdbus_domain *d; 88 | int ret; 89 | 90 | d = kzalloc(sizeof(*d), GFP_KERNEL); 91 | if (!d) 92 | return ERR_PTR(-ENOMEM); 93 | 94 | kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN); 95 | 96 | d->node.free_cb = kdbus_domain_free; 97 | d->node.mode = S_IRUSR | S_IXUSR; 98 | if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) 99 | d->node.mode |= S_IRGRP | S_IXGRP; 100 | if (access & KDBUS_MAKE_ACCESS_WORLD) 101 | d->node.mode |= S_IROTH | S_IXOTH; 102 | 103 | mutex_init(&d->lock); 104 | idr_init(&d->user_idr); 105 | ida_init(&d->user_ida); 106 | 107 | /* Pin user namespace so we can guarantee domain-unique bus * names. */ 108 | d->user_namespace = get_user_ns(current_user_ns()); 109 | 110 | ret = kdbus_node_link(&d->node, NULL, NULL); 111 | if (ret < 0) 112 | goto exit_unref; 113 | 114 | return d; 115 | 116 | exit_unref: 117 | kdbus_node_deactivate(&d->node); 118 | kdbus_node_unref(&d->node); 119 | return ERR_PTR(ret); 120 | } 121 | 122 | /** 123 | * kdbus_domain_ref() - take a domain reference 124 | * @domain: Domain 125 | * 126 | * Return: the domain itself 127 | */ 128 | struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain) 129 | { 130 | if (domain) 131 | kdbus_node_ref(&domain->node); 132 | return domain; 133 | } 134 | 135 | /** 136 | * kdbus_domain_unref() - drop a domain reference 137 | * @domain: Domain 138 | * 139 | * When the last reference is dropped, the domain internal structure 140 | * is freed. 141 | * 142 | * Return: NULL 143 | */ 144 | struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain) 145 | { 146 | if (domain) 147 | kdbus_node_unref(&domain->node); 148 | return NULL; 149 | } 150 | 151 | /** 152 | * kdbus_domain_populate() - populate static domain nodes 153 | * @domain: domain to populate 154 | * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes 155 | * 156 | * Allocate and activate static sub-nodes of the given domain. This will fail if 157 | * you call it on a non-active node or if the domain was already populated. 158 | * 159 | * Return: 0 on success, negative error code on failure. 160 | */ 161 | int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access) 162 | { 163 | struct kdbus_node *control; 164 | 165 | /* 166 | * Create a control-node for this domain. We drop our own reference 167 | * immediately, effectively causing the node to be deactivated and 168 | * released when the parent domain is. 169 | */ 170 | control = kdbus_domain_control_new(domain, access); 171 | if (IS_ERR(control)) 172 | return PTR_ERR(control); 173 | 174 | kdbus_node_activate(control); 175 | kdbus_node_unref(control); 176 | return 0; 177 | } 178 | 179 | /** 180 | * kdbus_user_lookup() - lookup a kdbus_user object 181 | * @domain: domain of the user 182 | * @uid: uid of the user; INVALID_UID for an anon user 183 | * 184 | * Lookup the kdbus user accounting object for the given domain. If INVALID_UID 185 | * is passed, a new anonymous user is created which is private to the caller. 186 | * 187 | * Return: The user object is returned, ERR_PTR on failure. 188 | */ 189 | struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid) 190 | { 191 | struct kdbus_user *u = NULL, *old = NULL; 192 | int ret; 193 | 194 | mutex_lock(&domain->lock); 195 | 196 | if (uid_valid(uid)) { 197 | old = idr_find(&domain->user_idr, __kuid_val(uid)); 198 | /* 199 | * If the object is about to be destroyed, ignore it and 200 | * replace the slot in the IDR later on. 201 | */ 202 | if (old && kref_get_unless_zero(&old->kref)) { 203 | mutex_unlock(&domain->lock); 204 | return old; 205 | } 206 | } 207 | 208 | u = kzalloc(sizeof(*u), GFP_KERNEL); 209 | if (!u) { 210 | ret = -ENOMEM; 211 | goto exit; 212 | } 213 | 214 | kref_init(&u->kref); 215 | u->domain = kdbus_domain_ref(domain); 216 | u->uid = uid; 217 | atomic_set(&u->buses, 0); 218 | atomic_set(&u->connections, 0); 219 | 220 | if (uid_valid(uid)) { 221 | if (old) { 222 | idr_replace(&domain->user_idr, u, __kuid_val(uid)); 223 | old->uid = INVALID_UID; /* mark old as removed */ 224 | } else { 225 | ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid), 226 | __kuid_val(uid) + 1, GFP_KERNEL); 227 | if (ret < 0) 228 | goto exit; 229 | } 230 | } 231 | 232 | /* 233 | * Allocate the smallest possible index for this user; used 234 | * in arrays for accounting user quota in receiver queues. 235 | */ 236 | ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL); 237 | if (ret < 0) 238 | goto exit; 239 | 240 | u->id = ret; 241 | mutex_unlock(&domain->lock); 242 | return u; 243 | 244 | exit: 245 | if (u) { 246 | if (uid_valid(u->uid)) 247 | idr_remove(&domain->user_idr, __kuid_val(u->uid)); 248 | kdbus_domain_unref(u->domain); 249 | kfree(u); 250 | } 251 | mutex_unlock(&domain->lock); 252 | return ERR_PTR(ret); 253 | } 254 | 255 | static void __kdbus_user_free(struct kref *kref) 256 | { 257 | struct kdbus_user *user = container_of(kref, struct kdbus_user, kref); 258 | 259 | WARN_ON(atomic_read(&user->buses) > 0); 260 | WARN_ON(atomic_read(&user->connections) > 0); 261 | 262 | mutex_lock(&user->domain->lock); 263 | ida_simple_remove(&user->domain->user_ida, user->id); 264 | if (uid_valid(user->uid)) 265 | idr_remove(&user->domain->user_idr, __kuid_val(user->uid)); 266 | mutex_unlock(&user->domain->lock); 267 | 268 | kdbus_domain_unref(user->domain); 269 | kfree(user); 270 | } 271 | 272 | /** 273 | * kdbus_user_ref() - take a user reference 274 | * @u: User 275 | * 276 | * Return: @u is returned 277 | */ 278 | struct kdbus_user *kdbus_user_ref(struct kdbus_user *u) 279 | { 280 | if (u) 281 | kref_get(&u->kref); 282 | return u; 283 | } 284 | 285 | /** 286 | * kdbus_user_unref() - drop a user reference 287 | * @u: User 288 | * 289 | * Return: NULL 290 | */ 291 | struct kdbus_user *kdbus_user_unref(struct kdbus_user *u) 292 | { 293 | if (u) 294 | kref_put(&u->kref, __kdbus_user_free); 295 | return NULL; 296 | } 297 | -------------------------------------------------------------------------------- /ipc/kdbus/domain.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_DOMAIN_H 16 | #define __KDBUS_DOMAIN_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "node.h" 24 | 25 | /** 26 | * struct kdbus_domain - domain for buses 27 | * @node: Underlying API node 28 | * @lock: Domain data lock 29 | * @last_id: Last used object id 30 | * @user_idr: Set of all users indexed by UID 31 | * @user_ida: Set of all users to compute small indices 32 | * @user_namespace: User namespace, pinned at creation time 33 | * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs) 34 | */ 35 | struct kdbus_domain { 36 | struct kdbus_node node; 37 | struct mutex lock; 38 | atomic64_t last_id; 39 | struct idr user_idr; 40 | struct ida user_ida; 41 | struct user_namespace *user_namespace; 42 | struct dentry *dentry; 43 | }; 44 | 45 | /** 46 | * struct kdbus_user - resource accounting for users 47 | * @kref: Reference counter 48 | * @domain: Domain of the user 49 | * @id: Index of this user 50 | * @uid: UID of the user 51 | * @buses: Number of buses the user has created 52 | * @connections: Number of connections the user has created 53 | */ 54 | struct kdbus_user { 55 | struct kref kref; 56 | struct kdbus_domain *domain; 57 | unsigned int id; 58 | kuid_t uid; 59 | atomic_t buses; 60 | atomic_t connections; 61 | }; 62 | 63 | #define kdbus_domain_from_node(_node) \ 64 | container_of((_node), struct kdbus_domain, node) 65 | 66 | struct kdbus_domain *kdbus_domain_new(unsigned int access); 67 | struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain); 68 | struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain); 69 | int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access); 70 | 71 | #define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */ 72 | 73 | struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid); 74 | struct kdbus_user *kdbus_user_ref(struct kdbus_user *u); 75 | struct kdbus_user *kdbus_user_unref(struct kdbus_user *u); 76 | 77 | #endif 78 | -------------------------------------------------------------------------------- /ipc/kdbus/endpoint.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | 25 | #include "bus.h" 26 | #include "connection.h" 27 | #include "domain.h" 28 | #include "endpoint.h" 29 | #include "handle.h" 30 | #include "item.h" 31 | #include "message.h" 32 | #include "policy.h" 33 | 34 | static void kdbus_ep_free(struct kdbus_node *node) 35 | { 36 | struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); 37 | 38 | WARN_ON(!list_empty(&ep->conn_list)); 39 | 40 | kdbus_policy_db_clear(&ep->policy_db); 41 | kdbus_bus_unref(ep->bus); 42 | kdbus_user_unref(ep->user); 43 | kfree(ep); 44 | } 45 | 46 | static void kdbus_ep_release(struct kdbus_node *node, bool was_active) 47 | { 48 | struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node); 49 | 50 | /* disconnect all connections to this endpoint */ 51 | for (;;) { 52 | struct kdbus_conn *conn; 53 | 54 | mutex_lock(&ep->lock); 55 | conn = list_first_entry_or_null(&ep->conn_list, 56 | struct kdbus_conn, 57 | ep_entry); 58 | if (!conn) { 59 | mutex_unlock(&ep->lock); 60 | break; 61 | } 62 | 63 | /* take reference, release lock, disconnect without lock */ 64 | kdbus_conn_ref(conn); 65 | mutex_unlock(&ep->lock); 66 | 67 | kdbus_conn_disconnect(conn, false); 68 | kdbus_conn_unref(conn); 69 | } 70 | } 71 | 72 | /** 73 | * kdbus_ep_new() - create a new endpoint 74 | * @bus: The bus this endpoint will be created for 75 | * @name: The name of the endpoint 76 | * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*) 77 | * @uid: The uid of the node 78 | * @gid: The gid of the node 79 | * @is_custom: Whether this is a custom endpoint 80 | * 81 | * This function will create a new endpoint with the given 82 | * name and properties for a given bus. 83 | * 84 | * Return: a new kdbus_ep on success, ERR_PTR on failure. 85 | */ 86 | struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, 87 | unsigned int access, kuid_t uid, kgid_t gid, 88 | bool is_custom) 89 | { 90 | struct kdbus_ep *e; 91 | int ret; 92 | 93 | /* 94 | * Validate only custom endpoints names, default endpoints 95 | * with a "bus" name are created when the bus is created 96 | */ 97 | if (is_custom) { 98 | ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace, 99 | uid); 100 | if (ret < 0) 101 | return ERR_PTR(ret); 102 | } 103 | 104 | e = kzalloc(sizeof(*e), GFP_KERNEL); 105 | if (!e) 106 | return ERR_PTR(-ENOMEM); 107 | 108 | kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT); 109 | 110 | e->node.free_cb = kdbus_ep_free; 111 | e->node.release_cb = kdbus_ep_release; 112 | e->node.uid = uid; 113 | e->node.gid = gid; 114 | e->node.mode = S_IRUSR | S_IWUSR; 115 | if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD)) 116 | e->node.mode |= S_IRGRP | S_IWGRP; 117 | if (access & KDBUS_MAKE_ACCESS_WORLD) 118 | e->node.mode |= S_IROTH | S_IWOTH; 119 | 120 | mutex_init(&e->lock); 121 | INIT_LIST_HEAD(&e->conn_list); 122 | kdbus_policy_db_init(&e->policy_db); 123 | e->bus = kdbus_bus_ref(bus); 124 | 125 | ret = kdbus_node_link(&e->node, &bus->node, name); 126 | if (ret < 0) 127 | goto exit_unref; 128 | 129 | /* 130 | * Transactions on custom endpoints are never accounted on the global 131 | * user limits. Instead, for each custom endpoint, we create a custom, 132 | * unique user, which all transactions are accounted on. Regardless of 133 | * the user using that endpoint, it is always accounted on the same 134 | * user-object. This budget is not shared with ordinary users on 135 | * non-custom endpoints. 136 | */ 137 | if (is_custom) { 138 | e->user = kdbus_user_lookup(bus->domain, INVALID_UID); 139 | if (IS_ERR(e->user)) { 140 | ret = PTR_ERR(e->user); 141 | e->user = NULL; 142 | goto exit_unref; 143 | } 144 | } 145 | 146 | return e; 147 | 148 | exit_unref: 149 | kdbus_node_deactivate(&e->node); 150 | kdbus_node_unref(&e->node); 151 | return ERR_PTR(ret); 152 | } 153 | 154 | /** 155 | * kdbus_ep_ref() - increase the reference counter of a kdbus_ep 156 | * @ep: The endpoint to reference 157 | * 158 | * Every user of an endpoint, except for its creator, must add a reference to 159 | * the kdbus_ep instance using this function. 160 | * 161 | * Return: the ep itself 162 | */ 163 | struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep) 164 | { 165 | if (ep) 166 | kdbus_node_ref(&ep->node); 167 | return ep; 168 | } 169 | 170 | /** 171 | * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep 172 | * @ep: The ep to unref 173 | * 174 | * Release a reference. If the reference count drops to 0, the ep will be 175 | * freed. 176 | * 177 | * Return: NULL 178 | */ 179 | struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep) 180 | { 181 | if (ep) 182 | kdbus_node_unref(&ep->node); 183 | return NULL; 184 | } 185 | 186 | /** 187 | * kdbus_ep_is_privileged() - check whether a file is privileged 188 | * @ep: endpoint to operate on 189 | * @file: file to test 190 | * 191 | * Return: True if @file is privileged in the domain of @ep. 192 | */ 193 | bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file) 194 | { 195 | return !ep->user && 196 | file_ns_capable(file, ep->bus->domain->user_namespace, 197 | CAP_IPC_OWNER); 198 | } 199 | 200 | /** 201 | * kdbus_ep_is_owner() - check whether a file should be treated as bus owner 202 | * @ep: endpoint to operate on 203 | * @file: file to test 204 | * 205 | * Return: True if @file should be treated as bus owner on @ep 206 | */ 207 | bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file) 208 | { 209 | return !ep->user && 210 | (uid_eq(file->f_cred->euid, ep->bus->node.uid) || 211 | kdbus_ep_is_privileged(ep, file)); 212 | } 213 | 214 | /** 215 | * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE 216 | * @bus: bus to operate on 217 | * @argp: command payload 218 | * 219 | * Return: NULL or newly created endpoint on success, ERR_PTR on failure. 220 | */ 221 | struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp) 222 | { 223 | const char *item_make_name; 224 | struct kdbus_ep *ep = NULL; 225 | struct kdbus_cmd *cmd; 226 | int ret; 227 | 228 | struct kdbus_arg argv[] = { 229 | { .type = KDBUS_ITEM_NEGOTIATE }, 230 | { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true }, 231 | }; 232 | struct kdbus_args args = { 233 | .allowed_flags = KDBUS_FLAG_NEGOTIATE | 234 | KDBUS_MAKE_ACCESS_GROUP | 235 | KDBUS_MAKE_ACCESS_WORLD, 236 | .argv = argv, 237 | .argc = ARRAY_SIZE(argv), 238 | }; 239 | 240 | ret = kdbus_args_parse(&args, argp, &cmd); 241 | if (ret < 0) 242 | return ERR_PTR(ret); 243 | if (ret > 0) 244 | return NULL; 245 | 246 | item_make_name = argv[1].item->str; 247 | 248 | ep = kdbus_ep_new(bus, item_make_name, cmd->flags, 249 | current_euid(), current_egid(), true); 250 | if (IS_ERR(ep)) { 251 | ret = PTR_ERR(ep); 252 | ep = NULL; 253 | goto exit; 254 | } 255 | 256 | if (!kdbus_node_activate(&ep->node)) { 257 | ret = -ESHUTDOWN; 258 | goto exit; 259 | } 260 | 261 | exit: 262 | ret = kdbus_args_clear(&args, ret); 263 | if (ret < 0) { 264 | if (ep) { 265 | kdbus_node_deactivate(&ep->node); 266 | kdbus_ep_unref(ep); 267 | } 268 | return ERR_PTR(ret); 269 | } 270 | return ep; 271 | } 272 | 273 | /** 274 | * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE 275 | * @ep: endpoint to operate on 276 | * @argp: command payload 277 | * 278 | * Return: >=0 on success, negative error code on failure. 279 | */ 280 | int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp) 281 | { 282 | struct kdbus_cmd *cmd; 283 | int ret; 284 | 285 | struct kdbus_arg argv[] = { 286 | { .type = KDBUS_ITEM_NEGOTIATE }, 287 | { .type = KDBUS_ITEM_NAME, .multiple = true }, 288 | { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true }, 289 | }; 290 | struct kdbus_args args = { 291 | .allowed_flags = KDBUS_FLAG_NEGOTIATE, 292 | .argv = argv, 293 | .argc = ARRAY_SIZE(argv), 294 | }; 295 | 296 | ret = kdbus_args_parse(&args, argp, &cmd); 297 | if (ret != 0) 298 | return ret; 299 | 300 | ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size, 301 | 0, true, ep); 302 | return kdbus_args_clear(&args, ret); 303 | } 304 | -------------------------------------------------------------------------------- /ipc/kdbus/endpoint.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_ENDPOINT_H 16 | #define __KDBUS_ENDPOINT_H 17 | 18 | #include 19 | #include 20 | #include 21 | #include "node.h" 22 | #include "policy.h" 23 | 24 | struct kdbus_bus; 25 | struct kdbus_user; 26 | 27 | /** 28 | * struct kdbus_ep - endpoint to access a bus 29 | * @node: The kdbus node 30 | * @lock: Endpoint data lock 31 | * @bus: Bus behind this endpoint 32 | * @user: Custom enpoints account against an anonymous user 33 | * @policy_db: Uploaded policy 34 | * @conn_list: Connections of this endpoint 35 | * 36 | * An endpoint offers access to a bus; the default endpoint node name is "bus". 37 | * Additional custom endpoints to the same bus can be created and they can 38 | * carry their own policies/filters. 39 | */ 40 | struct kdbus_ep { 41 | struct kdbus_node node; 42 | struct mutex lock; 43 | 44 | /* static */ 45 | struct kdbus_bus *bus; 46 | struct kdbus_user *user; 47 | 48 | /* protected by own locks */ 49 | struct kdbus_policy_db policy_db; 50 | 51 | /* protected by ep->lock */ 52 | struct list_head conn_list; 53 | }; 54 | 55 | #define kdbus_ep_from_node(_node) \ 56 | container_of((_node), struct kdbus_ep, node) 57 | 58 | struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name, 59 | unsigned int access, kuid_t uid, kgid_t gid, 60 | bool policy); 61 | struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep); 62 | struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep); 63 | 64 | bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file); 65 | bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file); 66 | 67 | struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp); 68 | int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp); 69 | 70 | #endif 71 | -------------------------------------------------------------------------------- /ipc/kdbus/fs.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUSFS_H 15 | #define __KDBUSFS_H 16 | 17 | #include 18 | 19 | struct kdbus_node; 20 | 21 | int kdbus_fs_init(void); 22 | void kdbus_fs_exit(void); 23 | void kdbus_fs_flush(struct kdbus_node *node); 24 | 25 | #define kdbus_node_from_inode(_inode) \ 26 | ((struct kdbus_node *)(_inode)->i_private) 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /ipc/kdbus/handle.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUS_HANDLE_H 15 | #define __KDBUS_HANDLE_H 16 | 17 | #include 18 | #include 19 | 20 | extern const struct file_operations kdbus_handle_ops; 21 | 22 | /** 23 | * kdbus_arg - information and state of a single ioctl command item 24 | * @type: item type 25 | * @item: set by the parser to the first found item of this type 26 | * @multiple: whether multiple items of this type are allowed 27 | * @mandatory: whether at least one item of this type is required 28 | * 29 | * This structure describes a single item in an ioctl command payload. The 30 | * caller has to pre-fill the type and flags, the parser will then use this 31 | * information to verify the ioctl payload. @item is set by the parser to point 32 | * to the first occurrence of the item. 33 | */ 34 | struct kdbus_arg { 35 | u64 type; 36 | struct kdbus_item *item; 37 | bool multiple : 1; 38 | bool mandatory : 1; 39 | }; 40 | 41 | /** 42 | * kdbus_args - information and state of ioctl command parser 43 | * @allowed_flags: set of flags this command supports 44 | * @argc: number of items in @argv 45 | * @argv: array of items this command supports 46 | * @user: set by parser to user-space location of current command 47 | * @cmd: set by parser to kernel copy of command payload 48 | * @cmd_buf: inline buf to avoid kmalloc() on small cmds 49 | * @items: points to item array in @cmd 50 | * @items_size: size of @items in bytes 51 | * @is_cmd: whether this is a command-payload or msg-payload 52 | * 53 | * This structure is used to parse ioctl command payloads on each invocation. 54 | * The ioctl handler has to pre-fill the flags and allowed items before passing 55 | * the object to kdbus_args_parse(). The parser will copy the command payload 56 | * into kernel-space and verify the correctness of the data. 57 | * 58 | * We use a 256 bytes buffer for small command payloads, to be allocated on 59 | * stack on syscall entrance. 60 | */ 61 | struct kdbus_args { 62 | u64 allowed_flags; 63 | size_t argc; 64 | struct kdbus_arg *argv; 65 | 66 | struct kdbus_cmd __user *user; 67 | struct kdbus_cmd *cmd; 68 | u8 cmd_buf[256]; 69 | 70 | struct kdbus_item *items; 71 | size_t items_size; 72 | bool is_cmd : 1; 73 | }; 74 | 75 | int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp, 76 | size_t type_size, size_t items_offset, void **out); 77 | int kdbus_args_clear(struct kdbus_args *args, int ret); 78 | 79 | #define kdbus_args_parse(_args, _argp, _v) \ 80 | ({ \ 81 | BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ 82 | offsetof(struct kdbus_cmd, size)); \ 83 | BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ 84 | offsetof(struct kdbus_cmd, flags)); \ 85 | BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \ 86 | offsetof(struct kdbus_cmd, return_flags)); \ 87 | __kdbus_args_parse((_args), 1, (_argp), sizeof(**(_v)), \ 88 | offsetof(typeof(**(_v)), items), \ 89 | (void **)(_v)); \ 90 | }) 91 | 92 | #define kdbus_args_parse_msg(_args, _argp, _v) \ 93 | ({ \ 94 | BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \ 95 | offsetof(struct kdbus_cmd, size)); \ 96 | BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \ 97 | offsetof(struct kdbus_cmd, flags)); \ 98 | __kdbus_args_parse((_args), 0, (_argp), sizeof(**(_v)), \ 99 | offsetof(typeof(**(_v)), items), \ 100 | (void **)(_v)); \ 101 | }) 102 | 103 | #endif 104 | -------------------------------------------------------------------------------- /ipc/kdbus/item.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #include "item.h" 20 | #include "limits.h" 21 | #include "util.h" 22 | 23 | /* 24 | * This verifies the string at position @str with size @size is properly 25 | * zero-terminated and does not contain a 0-byte but at the end. 26 | */ 27 | static bool kdbus_str_valid(const char *str, size_t size) 28 | { 29 | return size > 0 && memchr(str, '\0', size) == str + size - 1; 30 | } 31 | 32 | /** 33 | * kdbus_item_validate_name() - validate an item containing a name 34 | * @item: Item to validate 35 | * 36 | * Return: zero on success or an negative error code on failure 37 | */ 38 | int kdbus_item_validate_name(const struct kdbus_item *item) 39 | { 40 | const char *name = item->str; 41 | unsigned int i; 42 | size_t len; 43 | 44 | if (item->size < KDBUS_ITEM_HEADER_SIZE + 2) 45 | return -EINVAL; 46 | 47 | if (item->size > KDBUS_ITEM_HEADER_SIZE + 48 | KDBUS_SYSNAME_MAX_LEN + 1) 49 | return -ENAMETOOLONG; 50 | 51 | if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item))) 52 | return -EINVAL; 53 | 54 | len = strlen(name); 55 | if (len == 0) 56 | return -EINVAL; 57 | 58 | for (i = 0; i < len; i++) { 59 | if (isalpha(name[i])) 60 | continue; 61 | if (isdigit(name[i])) 62 | continue; 63 | if (name[i] == '_') 64 | continue; 65 | if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.')) 66 | continue; 67 | 68 | return -EINVAL; 69 | } 70 | 71 | return 0; 72 | } 73 | 74 | /** 75 | * kdbus_item_validate() - validate a single item 76 | * @item: item to validate 77 | * 78 | * Return: 0 if item is valid, negative error code if not. 79 | */ 80 | int kdbus_item_validate(const struct kdbus_item *item) 81 | { 82 | size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item); 83 | size_t l; 84 | int ret; 85 | 86 | BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE != 87 | sizeof(struct kdbus_item_header)); 88 | 89 | if (item->size < KDBUS_ITEM_HEADER_SIZE) 90 | return -EINVAL; 91 | 92 | switch (item->type) { 93 | case KDBUS_ITEM_NEGOTIATE: 94 | if (payload_size % sizeof(u64) != 0) 95 | return -EINVAL; 96 | break; 97 | 98 | case KDBUS_ITEM_PAYLOAD_VEC: 99 | case KDBUS_ITEM_PAYLOAD_OFF: 100 | if (payload_size != sizeof(struct kdbus_vec)) 101 | return -EINVAL; 102 | if (item->vec.size == 0 || item->vec.size > SIZE_MAX) 103 | return -EINVAL; 104 | break; 105 | 106 | case KDBUS_ITEM_PAYLOAD_MEMFD: 107 | if (payload_size != sizeof(struct kdbus_memfd)) 108 | return -EINVAL; 109 | if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX) 110 | return -EINVAL; 111 | if (item->memfd.fd < 0) 112 | return -EBADF; 113 | break; 114 | 115 | case KDBUS_ITEM_FDS: 116 | if (payload_size % sizeof(int) != 0) 117 | return -EINVAL; 118 | break; 119 | 120 | case KDBUS_ITEM_CANCEL_FD: 121 | if (payload_size != sizeof(int)) 122 | return -EINVAL; 123 | break; 124 | 125 | case KDBUS_ITEM_BLOOM_PARAMETER: 126 | if (payload_size != sizeof(struct kdbus_bloom_parameter)) 127 | return -EINVAL; 128 | break; 129 | 130 | case KDBUS_ITEM_BLOOM_FILTER: 131 | /* followed by the bloom-mask, depends on the bloom-size */ 132 | if (payload_size < sizeof(struct kdbus_bloom_filter)) 133 | return -EINVAL; 134 | break; 135 | 136 | case KDBUS_ITEM_BLOOM_MASK: 137 | /* size depends on bloom-size of bus */ 138 | break; 139 | 140 | case KDBUS_ITEM_CONN_DESCRIPTION: 141 | case KDBUS_ITEM_MAKE_NAME: 142 | ret = kdbus_item_validate_name(item); 143 | if (ret < 0) 144 | return ret; 145 | break; 146 | 147 | case KDBUS_ITEM_ATTACH_FLAGS_SEND: 148 | case KDBUS_ITEM_ATTACH_FLAGS_RECV: 149 | case KDBUS_ITEM_ID: 150 | case KDBUS_ITEM_DST_ID: 151 | if (payload_size != sizeof(u64)) 152 | return -EINVAL; 153 | break; 154 | 155 | case KDBUS_ITEM_TIMESTAMP: 156 | if (payload_size != sizeof(struct kdbus_timestamp)) 157 | return -EINVAL; 158 | break; 159 | 160 | case KDBUS_ITEM_CREDS: 161 | if (payload_size != sizeof(struct kdbus_creds)) 162 | return -EINVAL; 163 | break; 164 | 165 | case KDBUS_ITEM_AUXGROUPS: 166 | if (payload_size % sizeof(u32) != 0) 167 | return -EINVAL; 168 | break; 169 | 170 | case KDBUS_ITEM_NAME: 171 | case KDBUS_ITEM_DST_NAME: 172 | case KDBUS_ITEM_PID_COMM: 173 | case KDBUS_ITEM_TID_COMM: 174 | case KDBUS_ITEM_EXE: 175 | case KDBUS_ITEM_CMDLINE: 176 | case KDBUS_ITEM_CGROUP: 177 | case KDBUS_ITEM_SECLABEL: 178 | if (!kdbus_str_valid(item->str, payload_size)) 179 | return -EINVAL; 180 | break; 181 | 182 | case KDBUS_ITEM_CAPS: 183 | if (payload_size < sizeof(u32)) 184 | return -EINVAL; 185 | if (payload_size < sizeof(u32) + 186 | 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32)) 187 | return -EINVAL; 188 | break; 189 | 190 | case KDBUS_ITEM_AUDIT: 191 | if (payload_size != sizeof(struct kdbus_audit)) 192 | return -EINVAL; 193 | break; 194 | 195 | case KDBUS_ITEM_POLICY_ACCESS: 196 | if (payload_size != sizeof(struct kdbus_policy_access)) 197 | return -EINVAL; 198 | break; 199 | 200 | case KDBUS_ITEM_NAME_ADD: 201 | case KDBUS_ITEM_NAME_REMOVE: 202 | case KDBUS_ITEM_NAME_CHANGE: 203 | if (payload_size < sizeof(struct kdbus_notify_name_change)) 204 | return -EINVAL; 205 | l = payload_size - offsetof(struct kdbus_notify_name_change, 206 | name); 207 | if (l > 0 && !kdbus_str_valid(item->name_change.name, l)) 208 | return -EINVAL; 209 | break; 210 | 211 | case KDBUS_ITEM_ID_ADD: 212 | case KDBUS_ITEM_ID_REMOVE: 213 | if (payload_size != sizeof(struct kdbus_notify_id_change)) 214 | return -EINVAL; 215 | break; 216 | 217 | case KDBUS_ITEM_REPLY_TIMEOUT: 218 | case KDBUS_ITEM_REPLY_DEAD: 219 | if (payload_size != 0) 220 | return -EINVAL; 221 | break; 222 | 223 | default: 224 | break; 225 | } 226 | 227 | return 0; 228 | } 229 | 230 | /** 231 | * kdbus_items_validate() - validate items passed by user-space 232 | * @items: items to validate 233 | * @items_size: number of items 234 | * 235 | * This verifies that the passed items pointer is consistent and valid. 236 | * Furthermore, each item is checked for: 237 | * - valid "size" value 238 | * - payload is of expected type 239 | * - payload is fully included in the item 240 | * - string payloads are zero-terminated 241 | * 242 | * Return: 0 on success, negative error code on failure. 243 | */ 244 | int kdbus_items_validate(const struct kdbus_item *items, size_t items_size) 245 | { 246 | const struct kdbus_item *item; 247 | int ret; 248 | 249 | KDBUS_ITEMS_FOREACH(item, items, items_size) { 250 | if (!KDBUS_ITEM_VALID(item, items, items_size)) 251 | return -EINVAL; 252 | 253 | ret = kdbus_item_validate(item); 254 | if (ret < 0) 255 | return ret; 256 | } 257 | 258 | if (!KDBUS_ITEMS_END(item, items, items_size)) 259 | return -EINVAL; 260 | 261 | return 0; 262 | } 263 | 264 | /** 265 | * kdbus_item_set() - Set item content 266 | * @item: The item to modify 267 | * @type: The item type to set (KDBUS_ITEM_*) 268 | * @data: Data to copy to item->data, may be %NULL 269 | * @len: Number of bytes in @data 270 | * 271 | * This sets type, size and data fields of an item. If @data is NULL, the data 272 | * memory is cleared. 273 | * 274 | * Note that you must align your @data memory to 8 bytes. Trailing padding (in 275 | * case @len is not 8byte aligned) is cleared by this call. 276 | * 277 | * Returns: Pointer to the following item. 278 | */ 279 | struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, 280 | const void *data, size_t len) 281 | { 282 | item->type = type; 283 | item->size = KDBUS_ITEM_HEADER_SIZE + len; 284 | 285 | if (data) { 286 | memcpy(item->data, data, len); 287 | memset(item->data + len, 0, KDBUS_ALIGN8(len) - len); 288 | } else { 289 | memset(item->data, 0, KDBUS_ALIGN8(len)); 290 | } 291 | 292 | return KDBUS_ITEM_NEXT(item); 293 | } 294 | -------------------------------------------------------------------------------- /ipc/kdbus/item.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_ITEM_H 16 | #define __KDBUS_ITEM_H 17 | 18 | #include 19 | #include 20 | 21 | #include "util.h" 22 | 23 | /* generic access and iterators over a stream of items */ 24 | #define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size)) 25 | #define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is)) 26 | #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) 27 | #define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s)) 28 | #define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE) 29 | 30 | #define KDBUS_ITEMS_FOREACH(_i, _is, _s) \ 31 | for ((_i) = (_is); \ 32 | ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \ 33 | ((u8 *)(_i) >= (u8 *)(_is)); \ 34 | (_i) = KDBUS_ITEM_NEXT(_i)) 35 | 36 | #define KDBUS_ITEM_VALID(_i, _is, _s) \ 37 | ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \ 38 | (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \ 39 | (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \ 40 | (u8 *)(_i) >= (u8 *)(_is)) 41 | 42 | #define KDBUS_ITEMS_END(_i, _is, _s) \ 43 | ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s))) 44 | 45 | /** 46 | * struct kdbus_item_header - Describes the fix part of an item 47 | * @size: The total size of the item 48 | * @type: The item type, one of KDBUS_ITEM_* 49 | */ 50 | struct kdbus_item_header { 51 | u64 size; 52 | u64 type; 53 | }; 54 | 55 | int kdbus_item_validate_name(const struct kdbus_item *item); 56 | int kdbus_item_validate(const struct kdbus_item *item); 57 | int kdbus_items_validate(const struct kdbus_item *items, size_t items_size); 58 | struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type, 59 | const void *data, size_t len); 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /ipc/kdbus/limits.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUS_DEFAULTS_H 15 | #define __KDBUS_DEFAULTS_H 16 | 17 | #include 18 | 19 | /* maximum size of message header and items */ 20 | #define KDBUS_MSG_MAX_SIZE SZ_8K 21 | 22 | /* maximum number of memfd items per message */ 23 | #define KDBUS_MSG_MAX_MEMFD_ITEMS 16 24 | 25 | /* max size of ioctl command data */ 26 | #define KDBUS_CMD_MAX_SIZE SZ_32K 27 | 28 | /* maximum number of inflight fds in a target queue per user */ 29 | #define KDBUS_CONN_MAX_FDS_PER_USER 16 30 | 31 | /* maximum message payload size */ 32 | #define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M 33 | 34 | /* maximum size of bloom bit field in bytes */ 35 | #define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K 36 | 37 | /* maximum length of well-known bus name */ 38 | #define KDBUS_NAME_MAX_LEN 255 39 | 40 | /* maximum length of bus, domain, ep name */ 41 | #define KDBUS_SYSNAME_MAX_LEN 63 42 | 43 | /* maximum number of matches per connection */ 44 | #define KDBUS_MATCH_MAX 256 45 | 46 | /* maximum number of queued messages from the same individual user */ 47 | #define KDBUS_CONN_MAX_MSGS 256 48 | 49 | /* maximum number of well-known names per connection */ 50 | #define KDBUS_CONN_MAX_NAMES 256 51 | 52 | /* maximum number of queued requests waiting for a reply */ 53 | #define KDBUS_CONN_MAX_REQUESTS_PENDING 128 54 | 55 | /* maximum number of connections per user in one domain */ 56 | #define KDBUS_USER_MAX_CONN 1024 57 | 58 | /* maximum number of buses per user in one domain */ 59 | #define KDBUS_USER_MAX_BUSES 16 60 | 61 | #endif 62 | -------------------------------------------------------------------------------- /ipc/kdbus/main.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 | #include 16 | #include 17 | #include 18 | 19 | #include "util.h" 20 | #include "fs.h" 21 | #include "handle.h" 22 | #include "metadata.h" 23 | #include "node.h" 24 | 25 | /* 26 | * This is a simplified outline of the internal kdbus object relations, for 27 | * those interested in the inner life of the driver implementation. 28 | * 29 | * From a mount point's (domain's) perspective: 30 | * 31 | * struct kdbus_domain 32 | * |» struct kdbus_user *user (many, owned) 33 | * '» struct kdbus_node node (embedded) 34 | * |» struct kdbus_node children (many, referenced) 35 | * |» struct kdbus_node *parent (pinned) 36 | * '» struct kdbus_bus (many, pinned) 37 | * |» struct kdbus_node node (embedded) 38 | * '» struct kdbus_ep (many, pinned) 39 | * |» struct kdbus_node node (embedded) 40 | * |» struct kdbus_bus *bus (pinned) 41 | * |» struct kdbus_conn conn_list (many, pinned) 42 | * | |» struct kdbus_ep *ep (pinned) 43 | * | |» struct kdbus_name_entry *activator_of (owned) 44 | * | |» struct kdbus_match_db *match_db (owned) 45 | * | |» struct kdbus_meta *meta (owned) 46 | * | |» struct kdbus_match_db *match_db (owned) 47 | * | | '» struct kdbus_match_entry (many, owned) 48 | * | | 49 | * | |» struct kdbus_pool *pool (owned) 50 | * | | '» struct kdbus_pool_slice *slices (many, owned) 51 | * | | '» struct kdbus_pool *pool (pinned) 52 | * | | 53 | * | |» struct kdbus_user *user (pinned) 54 | * | `» struct kdbus_queue_entry entries (many, embedded) 55 | * | |» struct kdbus_pool_slice *slice (pinned) 56 | * | |» struct kdbus_conn_reply *reply (owned) 57 | * | '» struct kdbus_user *user (pinned) 58 | * | 59 | * '» struct kdbus_user *user (pinned) 60 | * '» struct kdbus_policy_db policy_db (embedded) 61 | * |» struct kdbus_policy_db_entry (many, owned) 62 | * | |» struct kdbus_conn (pinned) 63 | * | '» struct kdbus_ep (pinned) 64 | * | 65 | * '» struct kdbus_policy_db_cache_entry (many, owned) 66 | * '» struct kdbus_conn (pinned) 67 | * 68 | * For the life-time of a file descriptor derived from calling open() on a file 69 | * inside the mount point: 70 | * 71 | * struct kdbus_handle 72 | * |» struct kdbus_meta *meta (owned) 73 | * |» struct kdbus_ep *ep (pinned) 74 | * |» struct kdbus_conn *conn (owned) 75 | * '» struct kdbus_ep *ep (owned) 76 | */ 77 | 78 | /* kdbus mount-point /sys/fs/kdbus */ 79 | static struct kobject *kdbus_dir; 80 | 81 | static int __init kdbus_init(void) 82 | { 83 | int ret; 84 | 85 | kdbus_dir = kobject_create_and_add(KBUILD_MODNAME, fs_kobj); 86 | if (!kdbus_dir) 87 | return -ENOMEM; 88 | 89 | ret = kdbus_fs_init(); 90 | if (ret < 0) { 91 | pr_err("cannot register filesystem: %d\n", ret); 92 | goto exit_dir; 93 | } 94 | 95 | pr_info("initialized\n"); 96 | return 0; 97 | 98 | exit_dir: 99 | kobject_put(kdbus_dir); 100 | return ret; 101 | } 102 | 103 | static void __exit kdbus_exit(void) 104 | { 105 | kdbus_fs_exit(); 106 | kobject_put(kdbus_dir); 107 | ida_destroy(&kdbus_node_ida); 108 | } 109 | 110 | module_init(kdbus_init); 111 | module_exit(kdbus_exit); 112 | MODULE_LICENSE("GPL"); 113 | MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication"); 114 | MODULE_ALIAS_FS(KBUILD_MODNAME "fs"); 115 | -------------------------------------------------------------------------------- /ipc/kdbus/match.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_MATCH_H 16 | #define __KDBUS_MATCH_H 17 | 18 | struct kdbus_conn; 19 | struct kdbus_match_db; 20 | struct kdbus_staging; 21 | 22 | struct kdbus_match_db *kdbus_match_db_new(void); 23 | void kdbus_match_db_free(struct kdbus_match_db *db); 24 | int kdbus_match_db_add(struct kdbus_conn *conn, 25 | struct kdbus_cmd_match *cmd); 26 | int kdbus_match_db_remove(struct kdbus_conn *conn, 27 | struct kdbus_cmd_match *cmd); 28 | bool kdbus_match_db_match_msg(struct kdbus_match_db *db, 29 | struct kdbus_conn *conn_src, 30 | const struct kdbus_staging *staging); 31 | 32 | int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp); 33 | int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp); 34 | 35 | #endif 36 | -------------------------------------------------------------------------------- /ipc/kdbus/message.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUS_MESSAGE_H 15 | #define __KDBUS_MESSAGE_H 16 | 17 | #include 18 | #include 19 | #include 20 | 21 | struct kdbus_bus; 22 | struct kdbus_conn; 23 | struct kdbus_meta_conn; 24 | struct kdbus_meta_proc; 25 | struct kdbus_pool_slice; 26 | 27 | /** 28 | * struct kdbus_gaps - gaps in message to be filled later 29 | * @kref: Reference counter 30 | * @n_memfd_offs: Number of memfds 31 | * @memfd_offs: Offsets of kdbus_memfd items in target slice 32 | * @n_fds: Number of fds 33 | * @fds: Array of sent fds 34 | * @fds_offset: Offset of fd-array in target slice 35 | * 36 | * The 'gaps' object is used to track data that is needed to fill gaps in a 37 | * message at RECV time. Usually, we try to compile the whole message at SEND 38 | * time. This has the advantage, that we don't have to cache any information and 39 | * can keep the memory consumption small. Furthermore, all copy operations can 40 | * be combined into a single function call, which speeds up transactions 41 | * considerably. 42 | * However, things like file-descriptors can only be fully installed at RECV 43 | * time. The gaps object tracks this data and pins it until a message is 44 | * received. The gaps object is shared between all receivers of the same 45 | * message. 46 | */ 47 | struct kdbus_gaps { 48 | struct kref kref; 49 | 50 | /* state tracking for KDBUS_ITEM_PAYLOAD_MEMFD entries */ 51 | size_t n_memfds; 52 | u64 *memfd_offsets; 53 | struct file **memfd_files; 54 | 55 | /* state tracking for KDBUS_ITEM_FDS */ 56 | size_t n_fds; 57 | struct file **fd_files; 58 | u64 fd_offset; 59 | }; 60 | 61 | struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps); 62 | struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps); 63 | int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice, 64 | bool *out_incomplete); 65 | 66 | /** 67 | * struct kdbus_staging - staging area to import messages 68 | * @msg: User-supplied message 69 | * @gaps: Gaps-object created during import (or NULL if empty) 70 | * @msg_seqnum: Message sequence number 71 | * @notify_entry: Entry into list of kernel-generated notifications 72 | * @i_payload: Current relative index of start of payload 73 | * @n_payload: Total number of bytes needed for payload 74 | * @n_parts: Number of parts 75 | * @parts: Array of iovecs that make up the whole message 76 | * @meta_proc: Process metadata of the sender (or NULL if empty) 77 | * @meta_conn: Connection metadata of the sender (or NULL if empty) 78 | * @bloom_filter: Pointer to the bloom-item in @msg, or NULL 79 | * @dst_name: Pointer to the dst-name-item in @msg, or NULL 80 | * @notify: Pointer to the notification item in @msg, or NULL 81 | * 82 | * The kdbus_staging object is a temporary staging area to import user-supplied 83 | * messages into the kernel. It is only used during SEND and dropped once the 84 | * message is queued. Any data that cannot be collected during SEND, is 85 | * collected in a kdbus_gaps object and attached to the message queue. 86 | */ 87 | struct kdbus_staging { 88 | struct kdbus_msg *msg; 89 | struct kdbus_gaps *gaps; 90 | u64 msg_seqnum; 91 | struct list_head notify_entry; 92 | 93 | /* crafted iovecs to copy the message */ 94 | size_t i_payload; 95 | size_t n_payload; 96 | size_t n_parts; 97 | struct iovec *parts; 98 | 99 | /* metadata state */ 100 | struct kdbus_meta_proc *meta_proc; 101 | struct kdbus_meta_conn *meta_conn; 102 | 103 | /* cached pointers into @msg */ 104 | const struct kdbus_bloom_filter *bloom_filter; 105 | const char *dst_name; 106 | struct kdbus_item *notify; 107 | }; 108 | 109 | struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus, 110 | u64 dst, u64 cookie_timeout, 111 | size_t it_size, size_t it_type); 112 | struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus, 113 | struct kdbus_cmd_send *cmd, 114 | struct kdbus_msg *msg); 115 | struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging); 116 | struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging, 117 | struct kdbus_conn *src, 118 | struct kdbus_conn *dst); 119 | 120 | #endif 121 | -------------------------------------------------------------------------------- /ipc/kdbus/metadata.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_METADATA_H 16 | #define __KDBUS_METADATA_H 17 | 18 | #include 19 | 20 | struct kdbus_conn; 21 | struct kdbus_pool_slice; 22 | 23 | struct kdbus_meta_proc; 24 | struct kdbus_meta_conn; 25 | 26 | /** 27 | * struct kdbus_meta_fake - Fake metadata 28 | * @valid: Bitmask of collected and valid items 29 | * @uid: UID of process 30 | * @euid: EUID of process 31 | * @suid: SUID of process 32 | * @fsuid: FSUID of process 33 | * @gid: GID of process 34 | * @egid: EGID of process 35 | * @sgid: SGID of process 36 | * @fsgid: FSGID of process 37 | * @pid: PID of process 38 | * @tgid: TGID of process 39 | * @ppid: PPID of process 40 | * @seclabel: Seclabel 41 | */ 42 | struct kdbus_meta_fake { 43 | u64 valid; 44 | 45 | /* KDBUS_ITEM_CREDS */ 46 | kuid_t uid, euid, suid, fsuid; 47 | kgid_t gid, egid, sgid, fsgid; 48 | 49 | /* KDBUS_ITEM_PIDS */ 50 | struct pid *pid, *tgid, *ppid; 51 | 52 | /* KDBUS_ITEM_SECLABEL */ 53 | char *seclabel; 54 | }; 55 | 56 | struct kdbus_meta_proc *kdbus_meta_proc_new(void); 57 | struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp); 58 | struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp); 59 | int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what); 60 | 61 | struct kdbus_meta_fake *kdbus_meta_fake_new(void); 62 | struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf); 63 | int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf, 64 | const struct kdbus_creds *creds, 65 | const struct kdbus_pids *pids, 66 | const char *seclabel); 67 | 68 | struct kdbus_meta_conn *kdbus_meta_conn_new(void); 69 | struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc); 70 | struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc); 71 | int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc, 72 | struct kdbus_conn *conn, 73 | u64 msg_seqnum, u64 what); 74 | 75 | int kdbus_meta_emit(struct kdbus_meta_proc *mp, 76 | struct kdbus_meta_fake *mf, 77 | struct kdbus_meta_conn *mc, 78 | struct kdbus_conn *conn, 79 | u64 mask, 80 | struct kdbus_item **out_items, 81 | size_t *out_size); 82 | u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask); 83 | u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd, 84 | const struct kdbus_conn *rcv); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /ipc/kdbus/names.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_NAMES_H 16 | #define __KDBUS_NAMES_H 17 | 18 | #include 19 | #include 20 | 21 | struct kdbus_name_entry; 22 | struct kdbus_name_owner; 23 | struct kdbus_name_registry; 24 | 25 | /** 26 | * struct kdbus_name_registry - names registered for a bus 27 | * @entries_hash: Map of entries 28 | * @lock: Registry data lock 29 | * @name_seq_last: Last used sequence number to assign to a name entry 30 | */ 31 | struct kdbus_name_registry { 32 | DECLARE_HASHTABLE(entries_hash, 8); 33 | struct rw_semaphore rwlock; 34 | u64 name_seq_last; 35 | }; 36 | 37 | /** 38 | * struct kdbus_name_entry - well-know name entry 39 | * @name_id: sequence number of name entry to be able to uniquely 40 | * identify a name over its registration lifetime 41 | * @activator: activator of this name, or NULL 42 | * @queue: list of queued owners 43 | * @hentry: entry in registry map 44 | * @name: well-known name 45 | */ 46 | struct kdbus_name_entry { 47 | u64 name_id; 48 | struct kdbus_name_owner *activator; 49 | struct list_head queue; 50 | struct hlist_node hentry; 51 | char name[]; 52 | }; 53 | 54 | /** 55 | * struct kdbus_name_owner - owner of a well-known name 56 | * @flags: KDBUS_NAME_* flags of this owner 57 | * @conn: connection owning the name 58 | * @name: name that is owned 59 | * @conn_entry: link into @conn 60 | * @name_entry: link into @name 61 | */ 62 | struct kdbus_name_owner { 63 | u64 flags; 64 | struct kdbus_conn *conn; 65 | struct kdbus_name_entry *name; 66 | struct list_head conn_entry; 67 | struct list_head name_entry; 68 | }; 69 | 70 | bool kdbus_name_is_valid(const char *p, bool allow_wildcard); 71 | 72 | struct kdbus_name_registry *kdbus_name_registry_new(void); 73 | void kdbus_name_registry_free(struct kdbus_name_registry *reg); 74 | 75 | struct kdbus_name_entry * 76 | kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name); 77 | 78 | int kdbus_name_acquire(struct kdbus_name_registry *reg, 79 | struct kdbus_conn *conn, const char *name, 80 | u64 flags, u64 *return_flags); 81 | void kdbus_name_release_all(struct kdbus_name_registry *reg, 82 | struct kdbus_conn *conn); 83 | 84 | int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp); 85 | int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp); 86 | int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp); 87 | 88 | /** 89 | * kdbus_name_get_owner() - get current owner of a name 90 | * @name: name to get current owner of 91 | * 92 | * This returns a pointer to the current owner of a name (or its activator if 93 | * there is no owner). The caller must make sure @name is valid and does not 94 | * vanish. 95 | * 96 | * Return: Pointer to current owner or NULL if there is none. 97 | */ 98 | static inline struct kdbus_name_owner * 99 | kdbus_name_get_owner(struct kdbus_name_entry *name) 100 | { 101 | return list_first_entry_or_null(&name->queue, struct kdbus_name_owner, 102 | name_entry) ? : name->activator; 103 | } 104 | 105 | #endif 106 | -------------------------------------------------------------------------------- /ipc/kdbus/node.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUS_NODE_H 15 | #define __KDBUS_NODE_H 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | 22 | struct kdbus_node; 23 | 24 | enum kdbus_node_type { 25 | KDBUS_NODE_DOMAIN, 26 | KDBUS_NODE_CONTROL, 27 | KDBUS_NODE_BUS, 28 | KDBUS_NODE_ENDPOINT, 29 | }; 30 | 31 | typedef void (*kdbus_node_free_t) (struct kdbus_node *node); 32 | typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active); 33 | 34 | struct kdbus_node { 35 | atomic_t refcnt; 36 | atomic_t active; 37 | wait_queue_head_t waitq; 38 | 39 | /* static members */ 40 | unsigned int type; 41 | kdbus_node_free_t free_cb; 42 | kdbus_node_release_t release_cb; 43 | umode_t mode; 44 | kuid_t uid; 45 | kgid_t gid; 46 | 47 | /* valid once linked */ 48 | char *name; 49 | unsigned int hash; 50 | unsigned int id; 51 | struct kdbus_node *parent; /* may be NULL */ 52 | 53 | /* valid iff active */ 54 | struct mutex lock; 55 | struct rb_node rb; 56 | struct rb_root children; 57 | }; 58 | 59 | #define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb) 60 | 61 | extern struct ida kdbus_node_ida; 62 | 63 | void kdbus_node_init(struct kdbus_node *node, unsigned int type); 64 | 65 | int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent, 66 | const char *name); 67 | 68 | struct kdbus_node *kdbus_node_ref(struct kdbus_node *node); 69 | struct kdbus_node *kdbus_node_unref(struct kdbus_node *node); 70 | 71 | bool kdbus_node_is_active(struct kdbus_node *node); 72 | bool kdbus_node_is_deactivated(struct kdbus_node *node); 73 | bool kdbus_node_activate(struct kdbus_node *node); 74 | void kdbus_node_deactivate(struct kdbus_node *node); 75 | 76 | bool kdbus_node_acquire(struct kdbus_node *node); 77 | void kdbus_node_release(struct kdbus_node *node); 78 | 79 | struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node, 80 | const char *name); 81 | struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node, 82 | unsigned int hash); 83 | struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node, 84 | struct kdbus_node *prev); 85 | 86 | #endif 87 | -------------------------------------------------------------------------------- /ipc/kdbus/notify.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | 23 | #include "bus.h" 24 | #include "connection.h" 25 | #include "domain.h" 26 | #include "endpoint.h" 27 | #include "item.h" 28 | #include "message.h" 29 | #include "notify.h" 30 | 31 | static inline void kdbus_notify_add_tail(struct kdbus_staging *staging, 32 | struct kdbus_bus *bus) 33 | { 34 | spin_lock(&bus->notify_lock); 35 | list_add_tail(&staging->notify_entry, &bus->notify_list); 36 | spin_unlock(&bus->notify_lock); 37 | } 38 | 39 | static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id, 40 | u64 cookie, u64 msg_type) 41 | { 42 | struct kdbus_staging *s; 43 | 44 | s = kdbus_staging_new_kernel(bus, id, cookie, 0, msg_type); 45 | if (IS_ERR(s)) 46 | return PTR_ERR(s); 47 | 48 | kdbus_notify_add_tail(s, bus); 49 | return 0; 50 | } 51 | 52 | /** 53 | * kdbus_notify_reply_timeout() - queue a timeout reply 54 | * @bus: Bus which queues the messages 55 | * @id: The destination's connection ID 56 | * @cookie: The cookie to set in the reply. 57 | * 58 | * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached. 59 | * 60 | * Return: 0 on success, negative errno on failure. 61 | */ 62 | int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie) 63 | { 64 | return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT); 65 | } 66 | 67 | /** 68 | * kdbus_notify_reply_dead() - queue a 'dead' reply 69 | * @bus: Bus which queues the messages 70 | * @id: The destination's connection ID 71 | * @cookie: The cookie to set in the reply. 72 | * 73 | * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached. 74 | * 75 | * Return: 0 on success, negative errno on failure. 76 | */ 77 | int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie) 78 | { 79 | return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD); 80 | } 81 | 82 | /** 83 | * kdbus_notify_name_change() - queue a notification about a name owner change 84 | * @bus: Bus which queues the messages 85 | * @type: The type if the notification; KDBUS_ITEM_NAME_ADD, 86 | * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE 87 | * @old_id: The id of the connection that used to own the name 88 | * @new_id: The id of the new owner connection 89 | * @old_flags: The flags to pass in the KDBUS_ITEM flags field for 90 | * the old owner 91 | * @new_flags: The flags to pass in the KDBUS_ITEM flags field for 92 | * the new owner 93 | * @name: The name that was removed or assigned to a new owner 94 | * 95 | * Return: 0 on success, negative errno on failure. 96 | */ 97 | int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, 98 | u64 old_id, u64 new_id, 99 | u64 old_flags, u64 new_flags, 100 | const char *name) 101 | { 102 | size_t name_len, extra_size; 103 | struct kdbus_staging *s; 104 | 105 | name_len = strlen(name) + 1; 106 | extra_size = sizeof(struct kdbus_notify_name_change) + name_len; 107 | 108 | s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, 109 | extra_size, type); 110 | if (IS_ERR(s)) 111 | return PTR_ERR(s); 112 | 113 | s->notify->name_change.old_id.id = old_id; 114 | s->notify->name_change.old_id.flags = old_flags; 115 | s->notify->name_change.new_id.id = new_id; 116 | s->notify->name_change.new_id.flags = new_flags; 117 | memcpy(s->notify->name_change.name, name, name_len); 118 | 119 | kdbus_notify_add_tail(s, bus); 120 | return 0; 121 | } 122 | 123 | /** 124 | * kdbus_notify_id_change() - queue a notification about a unique ID change 125 | * @bus: Bus which queues the messages 126 | * @type: The type if the notification; KDBUS_ITEM_ID_ADD or 127 | * KDBUS_ITEM_ID_REMOVE 128 | * @id: The id of the connection that was added or removed 129 | * @flags: The flags to pass in the KDBUS_ITEM flags field 130 | * 131 | * Return: 0 on success, negative errno on failure. 132 | */ 133 | int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags) 134 | { 135 | struct kdbus_staging *s; 136 | size_t extra_size; 137 | 138 | extra_size = sizeof(struct kdbus_notify_id_change); 139 | s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0, 140 | extra_size, type); 141 | if (IS_ERR(s)) 142 | return PTR_ERR(s); 143 | 144 | s->notify->id_change.id = id; 145 | s->notify->id_change.flags = flags; 146 | 147 | kdbus_notify_add_tail(s, bus); 148 | return 0; 149 | } 150 | 151 | /** 152 | * kdbus_notify_flush() - send a list of collected messages 153 | * @bus: Bus which queues the messages 154 | * 155 | * The list is empty after sending the messages. 156 | */ 157 | void kdbus_notify_flush(struct kdbus_bus *bus) 158 | { 159 | LIST_HEAD(notify_list); 160 | struct kdbus_staging *s, *tmp; 161 | 162 | mutex_lock(&bus->notify_flush_lock); 163 | down_read(&bus->name_registry->rwlock); 164 | 165 | spin_lock(&bus->notify_lock); 166 | list_splice_init(&bus->notify_list, ¬ify_list); 167 | spin_unlock(&bus->notify_lock); 168 | 169 | list_for_each_entry_safe(s, tmp, ¬ify_list, notify_entry) { 170 | if (s->msg->dst_id != KDBUS_DST_ID_BROADCAST) { 171 | struct kdbus_conn *conn; 172 | 173 | conn = kdbus_bus_find_conn_by_id(bus, s->msg->dst_id); 174 | if (conn) { 175 | kdbus_bus_eavesdrop(bus, NULL, s); 176 | kdbus_conn_entry_insert(NULL, conn, s, NULL, 177 | NULL); 178 | kdbus_conn_unref(conn); 179 | } 180 | } else { 181 | kdbus_bus_broadcast(bus, NULL, s); 182 | } 183 | 184 | list_del(&s->notify_entry); 185 | kdbus_staging_free(s); 186 | } 187 | 188 | up_read(&bus->name_registry->rwlock); 189 | mutex_unlock(&bus->notify_flush_lock); 190 | } 191 | 192 | /** 193 | * kdbus_notify_free() - free a list of collected messages 194 | * @bus: Bus which queues the messages 195 | */ 196 | void kdbus_notify_free(struct kdbus_bus *bus) 197 | { 198 | struct kdbus_staging *s, *tmp; 199 | 200 | list_for_each_entry_safe(s, tmp, &bus->notify_list, notify_entry) { 201 | list_del(&s->notify_entry); 202 | kdbus_staging_free(s); 203 | } 204 | } 205 | -------------------------------------------------------------------------------- /ipc/kdbus/notify.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_NOTIFY_H 16 | #define __KDBUS_NOTIFY_H 17 | 18 | struct kdbus_bus; 19 | 20 | int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags); 21 | int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie); 22 | int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie); 23 | int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type, 24 | u64 old_id, u64 new_id, 25 | u64 old_flags, u64 new_flags, 26 | const char *name); 27 | void kdbus_notify_flush(struct kdbus_bus *bus); 28 | void kdbus_notify_free(struct kdbus_bus *bus); 29 | 30 | #endif 31 | -------------------------------------------------------------------------------- /ipc/kdbus/policy.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * 8 | * kdbus is free software; you can redistribute it and/or modify it under 9 | * the terms of the GNU Lesser General Public License as published by the 10 | * Free Software Foundation; either version 2.1 of the License, or (at 11 | * your option) any later version. 12 | */ 13 | 14 | #ifndef __KDBUS_POLICY_H 15 | #define __KDBUS_POLICY_H 16 | 17 | #include 18 | #include 19 | 20 | struct kdbus_conn; 21 | struct kdbus_item; 22 | 23 | /** 24 | * struct kdbus_policy_db - policy database 25 | * @entries_hash: Hashtable of entries 26 | * @entries_rwlock: Mutex to protect the database's access entries 27 | */ 28 | struct kdbus_policy_db { 29 | DECLARE_HASHTABLE(entries_hash, 6); 30 | struct rw_semaphore entries_rwlock; 31 | }; 32 | 33 | void kdbus_policy_db_init(struct kdbus_policy_db *db); 34 | void kdbus_policy_db_clear(struct kdbus_policy_db *db); 35 | 36 | int kdbus_policy_query_unlocked(struct kdbus_policy_db *db, 37 | const struct cred *cred, const char *name, 38 | unsigned int hash); 39 | int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred, 40 | const char *name, unsigned int hash); 41 | 42 | void kdbus_policy_remove_owner(struct kdbus_policy_db *db, 43 | const void *owner); 44 | int kdbus_policy_set(struct kdbus_policy_db *db, 45 | const struct kdbus_item *items, 46 | size_t items_size, 47 | size_t max_policies, 48 | bool allow_wildcards, 49 | const void *owner); 50 | 51 | #endif 52 | -------------------------------------------------------------------------------- /ipc/kdbus/pool.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_POOL_H 16 | #define __KDBUS_POOL_H 17 | 18 | #include 19 | 20 | struct kdbus_pool; 21 | struct kdbus_pool_slice; 22 | 23 | struct kdbus_pool *kdbus_pool_new(const char *name, size_t size); 24 | void kdbus_pool_free(struct kdbus_pool *pool); 25 | void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc); 26 | int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma); 27 | int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off); 28 | void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size); 29 | 30 | struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool, 31 | size_t size, bool accounted); 32 | void kdbus_pool_slice_release(struct kdbus_pool_slice *slice); 33 | void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice, 34 | u64 *out_offset, u64 *out_size); 35 | off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice); 36 | size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice); 37 | int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst, 38 | const struct kdbus_pool_slice *slice_src); 39 | ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice, 40 | loff_t off, struct kvec *kvec, 41 | size_t kvec_count, size_t total_len); 42 | ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, 43 | loff_t off, struct iovec *iov, 44 | size_t iov_count, size_t total_len); 45 | 46 | #endif 47 | -------------------------------------------------------------------------------- /ipc/kdbus/queue.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | #include "util.h" 33 | #include "domain.h" 34 | #include "connection.h" 35 | #include "item.h" 36 | #include "message.h" 37 | #include "metadata.h" 38 | #include "queue.h" 39 | #include "reply.h" 40 | 41 | /** 42 | * kdbus_queue_init() - initialize data structure related to a queue 43 | * @queue: The queue to initialize 44 | */ 45 | void kdbus_queue_init(struct kdbus_queue *queue) 46 | { 47 | INIT_LIST_HEAD(&queue->msg_list); 48 | queue->msg_prio_queue = RB_ROOT; 49 | } 50 | 51 | /** 52 | * kdbus_queue_peek() - Retrieves an entry from a queue 53 | * @queue: The queue 54 | * @priority: The minimum priority of the entry to peek 55 | * @use_priority: Boolean flag whether or not to peek by priority 56 | * 57 | * Look for a entry in a queue, either by priority, or the oldest one (FIFO). 58 | * The entry is not freed, put off the queue's lists or anything else. 59 | * 60 | * Return: the peeked queue entry on success, NULL if no suitable msg is found 61 | */ 62 | struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, 63 | s64 priority, bool use_priority) 64 | { 65 | struct kdbus_queue_entry *e; 66 | 67 | if (list_empty(&queue->msg_list)) 68 | return NULL; 69 | 70 | if (use_priority) { 71 | /* get next entry with highest priority */ 72 | e = rb_entry(queue->msg_prio_highest, 73 | struct kdbus_queue_entry, prio_node); 74 | 75 | /* no entry with the requested priority */ 76 | if (e->priority > priority) 77 | return NULL; 78 | } else { 79 | /* ignore the priority, return the next entry in the entry */ 80 | e = list_first_entry(&queue->msg_list, 81 | struct kdbus_queue_entry, entry); 82 | } 83 | 84 | return e; 85 | } 86 | 87 | static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry) 88 | { 89 | struct kdbus_queue *queue = &entry->conn->queue; 90 | struct rb_node **n, *pn = NULL; 91 | bool highest = true; 92 | 93 | lockdep_assert_held(&entry->conn->lock); 94 | if (WARN_ON(!list_empty(&entry->entry))) 95 | return; 96 | 97 | /* sort into priority entry tree */ 98 | n = &queue->msg_prio_queue.rb_node; 99 | while (*n) { 100 | struct kdbus_queue_entry *e; 101 | 102 | pn = *n; 103 | e = rb_entry(pn, struct kdbus_queue_entry, prio_node); 104 | 105 | /* existing node for this priority, add to its list */ 106 | if (likely(entry->priority == e->priority)) { 107 | list_add_tail(&entry->prio_entry, &e->prio_entry); 108 | goto prio_done; 109 | } 110 | 111 | if (entry->priority < e->priority) { 112 | n = &pn->rb_left; 113 | } else { 114 | n = &pn->rb_right; 115 | highest = false; 116 | } 117 | } 118 | 119 | /* cache highest-priority entry */ 120 | if (highest) 121 | queue->msg_prio_highest = &entry->prio_node; 122 | 123 | /* new node for this priority */ 124 | rb_link_node(&entry->prio_node, pn, n); 125 | rb_insert_color(&entry->prio_node, &queue->msg_prio_queue); 126 | INIT_LIST_HEAD(&entry->prio_entry); 127 | 128 | prio_done: 129 | /* add to unsorted fifo list */ 130 | list_add_tail(&entry->entry, &queue->msg_list); 131 | } 132 | 133 | static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry) 134 | { 135 | struct kdbus_queue *queue = &entry->conn->queue; 136 | 137 | lockdep_assert_held(&entry->conn->lock); 138 | if (list_empty(&entry->entry)) 139 | return; 140 | 141 | list_del_init(&entry->entry); 142 | 143 | if (list_empty(&entry->prio_entry)) { 144 | /* 145 | * Single entry for this priority, update cached 146 | * highest-priority entry, remove the tree node. 147 | */ 148 | if (queue->msg_prio_highest == &entry->prio_node) 149 | queue->msg_prio_highest = rb_next(&entry->prio_node); 150 | 151 | rb_erase(&entry->prio_node, &queue->msg_prio_queue); 152 | } else { 153 | struct kdbus_queue_entry *q; 154 | 155 | /* 156 | * Multiple entries for this priority entry, get next one in 157 | * the list. Update cached highest-priority entry, store the 158 | * new one as the tree node. 159 | */ 160 | q = list_first_entry(&entry->prio_entry, 161 | struct kdbus_queue_entry, prio_entry); 162 | list_del(&entry->prio_entry); 163 | 164 | if (queue->msg_prio_highest == &entry->prio_node) 165 | queue->msg_prio_highest = &q->prio_node; 166 | 167 | rb_replace_node(&entry->prio_node, &q->prio_node, 168 | &queue->msg_prio_queue); 169 | } 170 | } 171 | 172 | /** 173 | * kdbus_queue_entry_new() - allocate a queue entry 174 | * @src: source connection, or NULL 175 | * @dst: destination connection 176 | * @s: staging object carrying the message 177 | * 178 | * Allocates a queue entry based on a given msg and allocate space for 179 | * the message payload and the requested metadata in the connection's pool. 180 | * The entry is not actually added to the queue's lists at this point. 181 | * 182 | * Return: the allocated entry on success, or an ERR_PTR on failures. 183 | */ 184 | struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, 185 | struct kdbus_conn *dst, 186 | struct kdbus_staging *s) 187 | { 188 | struct kdbus_queue_entry *entry; 189 | int ret; 190 | 191 | entry = kzalloc(sizeof(*entry), GFP_KERNEL); 192 | if (!entry) 193 | return ERR_PTR(-ENOMEM); 194 | 195 | INIT_LIST_HEAD(&entry->entry); 196 | entry->priority = s->msg->priority; 197 | entry->conn = kdbus_conn_ref(dst); 198 | entry->gaps = kdbus_gaps_ref(s->gaps); 199 | 200 | entry->slice = kdbus_staging_emit(s, src, dst); 201 | if (IS_ERR(entry->slice)) { 202 | ret = PTR_ERR(entry->slice); 203 | entry->slice = NULL; 204 | goto error; 205 | } 206 | 207 | entry->user = src ? kdbus_user_ref(src->user) : NULL; 208 | return entry; 209 | 210 | error: 211 | kdbus_queue_entry_free(entry); 212 | return ERR_PTR(ret); 213 | } 214 | 215 | /** 216 | * kdbus_queue_entry_free() - free resources of an entry 217 | * @entry: The entry to free 218 | * 219 | * Removes resources allocated by a queue entry, along with the entry itself. 220 | * Note that the entry's slice is not freed at this point. 221 | */ 222 | void kdbus_queue_entry_free(struct kdbus_queue_entry *entry) 223 | { 224 | if (!entry) 225 | return; 226 | 227 | lockdep_assert_held(&entry->conn->lock); 228 | 229 | kdbus_queue_entry_unlink(entry); 230 | kdbus_reply_unref(entry->reply); 231 | 232 | if (entry->slice) { 233 | kdbus_conn_quota_dec(entry->conn, entry->user, 234 | kdbus_pool_slice_size(entry->slice), 235 | entry->gaps ? entry->gaps->n_fds : 0); 236 | kdbus_pool_slice_release(entry->slice); 237 | } 238 | 239 | kdbus_user_unref(entry->user); 240 | kdbus_gaps_unref(entry->gaps); 241 | kdbus_conn_unref(entry->conn); 242 | kfree(entry); 243 | } 244 | 245 | /** 246 | * kdbus_queue_entry_install() - install message components into the 247 | * receiver's process 248 | * @entry: The queue entry to install 249 | * @return_flags: Pointer to store the return flags for userspace 250 | * @install_fds: Whether or not to install associated file descriptors 251 | * 252 | * Return: 0 on success. 253 | */ 254 | int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, 255 | u64 *return_flags, bool install_fds) 256 | { 257 | bool incomplete_fds = false; 258 | int ret; 259 | 260 | lockdep_assert_held(&entry->conn->lock); 261 | 262 | ret = kdbus_gaps_install(entry->gaps, entry->slice, &incomplete_fds); 263 | if (ret < 0) 264 | return ret; 265 | 266 | if (incomplete_fds) 267 | *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS; 268 | return 0; 269 | } 270 | 271 | /** 272 | * kdbus_queue_entry_enqueue() - enqueue an entry 273 | * @entry: entry to enqueue 274 | * @reply: reply to link to this entry (or NULL if none) 275 | * 276 | * This enqueues an unqueued entry into the message queue of the linked 277 | * connection. It also binds a reply object to the entry so we can remember it 278 | * when the message is moved. 279 | * 280 | * Once this call returns (and the connection lock is released), this entry can 281 | * be dequeued by the target connection. Note that the entry will not be removed 282 | * from the queue until it is destroyed. 283 | */ 284 | void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, 285 | struct kdbus_reply *reply) 286 | { 287 | lockdep_assert_held(&entry->conn->lock); 288 | 289 | if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry))) 290 | return; 291 | 292 | entry->reply = kdbus_reply_ref(reply); 293 | kdbus_queue_entry_link(entry); 294 | } 295 | 296 | /** 297 | * kdbus_queue_entry_move() - move queue entry 298 | * @e: queue entry to move 299 | * @dst: destination connection to queue the entry on 300 | * 301 | * This moves a queue entry onto a different connection. It allocates a new 302 | * slice on the target connection and copies the message over. If the copy 303 | * succeeded, we move the entry from @src to @dst. 304 | * 305 | * On failure, the entry is left untouched. 306 | * 307 | * The queue entry must be queued right now, and after the call succeeds it will 308 | * be queued on the destination, but no longer on the source. 309 | * 310 | * The caller must hold the connection lock of the source *and* destination. 311 | * 312 | * Return: 0 on success, negative error code on failure. 313 | */ 314 | int kdbus_queue_entry_move(struct kdbus_queue_entry *e, 315 | struct kdbus_conn *dst) 316 | { 317 | struct kdbus_pool_slice *slice = NULL; 318 | struct kdbus_conn *src = e->conn; 319 | size_t size, fds; 320 | int ret; 321 | 322 | lockdep_assert_held(&src->lock); 323 | lockdep_assert_held(&dst->lock); 324 | 325 | if (WARN_ON(list_empty(&e->entry))) 326 | return -EINVAL; 327 | if (src == dst) 328 | return 0; 329 | 330 | size = kdbus_pool_slice_size(e->slice); 331 | fds = e->gaps ? e->gaps->n_fds : 0; 332 | 333 | ret = kdbus_conn_quota_inc(dst, e->user, size, fds); 334 | if (ret < 0) 335 | return ret; 336 | 337 | slice = kdbus_pool_slice_alloc(dst->pool, size, true); 338 | if (IS_ERR(slice)) { 339 | ret = PTR_ERR(slice); 340 | slice = NULL; 341 | goto error; 342 | } 343 | 344 | ret = kdbus_pool_slice_copy(slice, e->slice); 345 | if (ret < 0) 346 | goto error; 347 | 348 | kdbus_queue_entry_unlink(e); 349 | kdbus_conn_quota_dec(src, e->user, size, fds); 350 | kdbus_pool_slice_release(e->slice); 351 | kdbus_conn_unref(e->conn); 352 | 353 | e->slice = slice; 354 | e->conn = kdbus_conn_ref(dst); 355 | kdbus_queue_entry_link(e); 356 | 357 | return 0; 358 | 359 | error: 360 | kdbus_pool_slice_release(slice); 361 | kdbus_conn_quota_dec(dst, e->user, size, fds); 362 | return ret; 363 | } 364 | -------------------------------------------------------------------------------- /ipc/kdbus/queue.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_QUEUE_H 16 | #define __KDBUS_QUEUE_H 17 | 18 | #include 19 | #include 20 | 21 | struct kdbus_conn; 22 | struct kdbus_pool_slice; 23 | struct kdbus_reply; 24 | struct kdbus_staging; 25 | struct kdbus_user; 26 | 27 | /** 28 | * struct kdbus_queue - a connection's message queue 29 | * @msg_list: List head for kdbus_queue_entry objects 30 | * @msg_prio_queue: RB tree root for messages, sorted by priority 31 | * @msg_prio_highest: Link to the RB node referencing the message with the 32 | * highest priority in the tree. 33 | */ 34 | struct kdbus_queue { 35 | struct list_head msg_list; 36 | struct rb_root msg_prio_queue; 37 | struct rb_node *msg_prio_highest; 38 | }; 39 | 40 | /** 41 | * struct kdbus_queue_entry - messages waiting to be read 42 | * @entry: Entry in the connection's list 43 | * @prio_node: Entry in the priority queue tree 44 | * @prio_entry: Queue tree node entry in the list of one priority 45 | * @priority: Message priority 46 | * @dst_name_id: The sequence number of the name this message is 47 | * addressed to, 0 for messages sent to an ID 48 | * @conn: Connection this entry is queued on 49 | * @gaps: Gaps object to fill message gaps at RECV time 50 | * @user: User used for accounting 51 | * @slice: Slice in the receiver's pool for the message 52 | * @reply: The reply block if a reply to this message is expected 53 | */ 54 | struct kdbus_queue_entry { 55 | struct list_head entry; 56 | struct rb_node prio_node; 57 | struct list_head prio_entry; 58 | 59 | s64 priority; 60 | u64 dst_name_id; 61 | 62 | struct kdbus_conn *conn; 63 | struct kdbus_gaps *gaps; 64 | struct kdbus_user *user; 65 | struct kdbus_pool_slice *slice; 66 | struct kdbus_reply *reply; 67 | }; 68 | 69 | void kdbus_queue_init(struct kdbus_queue *queue); 70 | struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue, 71 | s64 priority, bool use_priority); 72 | 73 | struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src, 74 | struct kdbus_conn *dst, 75 | struct kdbus_staging *s); 76 | void kdbus_queue_entry_free(struct kdbus_queue_entry *entry); 77 | int kdbus_queue_entry_install(struct kdbus_queue_entry *entry, 78 | u64 *return_flags, bool install_fds); 79 | void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry, 80 | struct kdbus_reply *reply); 81 | int kdbus_queue_entry_move(struct kdbus_queue_entry *entry, 82 | struct kdbus_conn *dst); 83 | 84 | #endif /* __KDBUS_QUEUE_H */ 85 | -------------------------------------------------------------------------------- /ipc/kdbus/reply.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include "bus.h" 9 | #include "connection.h" 10 | #include "endpoint.h" 11 | #include "message.h" 12 | #include "metadata.h" 13 | #include "names.h" 14 | #include "domain.h" 15 | #include "item.h" 16 | #include "notify.h" 17 | #include "policy.h" 18 | #include "reply.h" 19 | #include "util.h" 20 | 21 | /** 22 | * kdbus_reply_new() - Allocate and set up a new kdbus_reply object 23 | * @reply_src: The connection a reply is expected from 24 | * @reply_dst: The connection this reply object belongs to 25 | * @msg: Message associated with the reply 26 | * @name_entry: Name entry used to send the message 27 | * @sync: Whether or not to make this reply synchronous 28 | * 29 | * Allocate and fill a new kdbus_reply object. 30 | * 31 | * Return: New kdbus_conn object on success, ERR_PTR on error. 32 | */ 33 | struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, 34 | struct kdbus_conn *reply_dst, 35 | const struct kdbus_msg *msg, 36 | struct kdbus_name_entry *name_entry, 37 | bool sync) 38 | { 39 | struct kdbus_reply *r; 40 | int ret; 41 | 42 | if (atomic_inc_return(&reply_dst->request_count) > 43 | KDBUS_CONN_MAX_REQUESTS_PENDING) { 44 | ret = -EMLINK; 45 | goto exit_dec_request_count; 46 | } 47 | 48 | r = kzalloc(sizeof(*r), GFP_KERNEL); 49 | if (!r) { 50 | ret = -ENOMEM; 51 | goto exit_dec_request_count; 52 | } 53 | 54 | kref_init(&r->kref); 55 | INIT_LIST_HEAD(&r->entry); 56 | r->reply_src = kdbus_conn_ref(reply_src); 57 | r->reply_dst = kdbus_conn_ref(reply_dst); 58 | r->cookie = msg->cookie; 59 | r->name_id = name_entry ? name_entry->name_id : 0; 60 | r->deadline_ns = msg->timeout_ns; 61 | 62 | if (sync) { 63 | r->sync = true; 64 | r->waiting = true; 65 | } 66 | 67 | return r; 68 | 69 | exit_dec_request_count: 70 | atomic_dec(&reply_dst->request_count); 71 | return ERR_PTR(ret); 72 | } 73 | 74 | static void __kdbus_reply_free(struct kref *kref) 75 | { 76 | struct kdbus_reply *reply = 77 | container_of(kref, struct kdbus_reply, kref); 78 | 79 | atomic_dec(&reply->reply_dst->request_count); 80 | kdbus_conn_unref(reply->reply_src); 81 | kdbus_conn_unref(reply->reply_dst); 82 | kfree(reply); 83 | } 84 | 85 | /** 86 | * kdbus_reply_ref() - Increase reference on kdbus_reply 87 | * @r: The reply, may be %NULL 88 | * 89 | * Return: The reply object with an extra reference 90 | */ 91 | struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r) 92 | { 93 | if (r) 94 | kref_get(&r->kref); 95 | return r; 96 | } 97 | 98 | /** 99 | * kdbus_reply_unref() - Decrease reference on kdbus_reply 100 | * @r: The reply, may be %NULL 101 | * 102 | * Return: NULL 103 | */ 104 | struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r) 105 | { 106 | if (r) 107 | kref_put(&r->kref, __kdbus_reply_free); 108 | return NULL; 109 | } 110 | 111 | /** 112 | * kdbus_reply_link() - Link reply object into target connection 113 | * @r: Reply to link 114 | */ 115 | void kdbus_reply_link(struct kdbus_reply *r) 116 | { 117 | if (WARN_ON(!list_empty(&r->entry))) 118 | return; 119 | 120 | list_add(&r->entry, &r->reply_dst->reply_list); 121 | kdbus_reply_ref(r); 122 | } 123 | 124 | /** 125 | * kdbus_reply_unlink() - Unlink reply object from target connection 126 | * @r: Reply to unlink 127 | */ 128 | void kdbus_reply_unlink(struct kdbus_reply *r) 129 | { 130 | if (!list_empty(&r->entry)) { 131 | list_del_init(&r->entry); 132 | kdbus_reply_unref(r); 133 | } 134 | } 135 | 136 | /** 137 | * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply 138 | * @reply: The reply object 139 | * @err: Error code to set on the remote side 140 | * 141 | * Wake up remote peer (method origin) with the appropriate synchronous reply 142 | * code. 143 | */ 144 | void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err) 145 | { 146 | if (WARN_ON(!reply->sync)) 147 | return; 148 | 149 | reply->waiting = false; 150 | reply->err = err; 151 | wake_up_interruptible(&reply->reply_dst->wait); 152 | } 153 | 154 | /** 155 | * kdbus_reply_find() - Find the corresponding reply object 156 | * @replying: The replying connection or NULL 157 | * @reply_dst: The connection the reply will be sent to 158 | * (method origin) 159 | * @cookie: The cookie of the requesting message 160 | * 161 | * Lookup a reply object that should be sent as a reply by 162 | * @replying to @reply_dst with the given cookie. 163 | * 164 | * Callers must take the @reply_dst lock. 165 | * 166 | * Return: the corresponding reply object or NULL if not found 167 | */ 168 | struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, 169 | struct kdbus_conn *reply_dst, 170 | u64 cookie) 171 | { 172 | struct kdbus_reply *r; 173 | 174 | list_for_each_entry(r, &reply_dst->reply_list, entry) { 175 | if (r->cookie == cookie && 176 | (!replying || r->reply_src == replying)) 177 | return r; 178 | } 179 | 180 | return NULL; 181 | } 182 | 183 | /** 184 | * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a 185 | * connection for exceeded timeouts 186 | * @work: Work struct of the connection to scan 187 | * 188 | * Walk the list of replies stored with a connection and look for entries 189 | * that have exceeded their timeout. If such an entry is found, a timeout 190 | * notification is sent to the waiting peer, and the reply is removed from 191 | * the list. 192 | * 193 | * The work is rescheduled to the nearest timeout found during the list 194 | * iteration. 195 | */ 196 | void kdbus_reply_list_scan_work(struct work_struct *work) 197 | { 198 | struct kdbus_conn *conn = 199 | container_of(work, struct kdbus_conn, work.work); 200 | struct kdbus_reply *reply, *reply_tmp; 201 | u64 deadline = ~0ULL; 202 | u64 now; 203 | 204 | now = ktime_get_ns(); 205 | 206 | mutex_lock(&conn->lock); 207 | if (!kdbus_conn_active(conn)) { 208 | mutex_unlock(&conn->lock); 209 | return; 210 | } 211 | 212 | list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) { 213 | /* 214 | * If the reply block is waiting for synchronous I/O, 215 | * the timeout is handled by wait_event_*_timeout(), 216 | * so we don't have to care for it here. 217 | */ 218 | if (reply->sync && !reply->interrupted) 219 | continue; 220 | 221 | WARN_ON(reply->reply_dst != conn); 222 | 223 | if (reply->deadline_ns > now) { 224 | /* remember next timeout */ 225 | if (deadline > reply->deadline_ns) 226 | deadline = reply->deadline_ns; 227 | 228 | continue; 229 | } 230 | 231 | /* 232 | * A zero deadline means the connection died, was 233 | * cleaned up already and the notification was sent. 234 | * Don't send notifications for reply trackers that were 235 | * left in an interrupted syscall state. 236 | */ 237 | if (reply->deadline_ns != 0 && !reply->interrupted) 238 | kdbus_notify_reply_timeout(conn->ep->bus, conn->id, 239 | reply->cookie); 240 | 241 | kdbus_reply_unlink(reply); 242 | } 243 | 244 | /* rearm delayed work with next timeout */ 245 | if (deadline != ~0ULL) 246 | schedule_delayed_work(&conn->work, 247 | nsecs_to_jiffies(deadline - now)); 248 | 249 | mutex_unlock(&conn->lock); 250 | 251 | kdbus_notify_flush(conn->ep->bus); 252 | } 253 | -------------------------------------------------------------------------------- /ipc/kdbus/reply.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_REPLY_H 16 | #define __KDBUS_REPLY_H 17 | 18 | /** 19 | * struct kdbus_reply - an entry of kdbus_conn's list of replies 20 | * @kref: Ref-count of this object 21 | * @entry: The entry of the connection's reply_list 22 | * @reply_src: The connection the reply will be sent from 23 | * @reply_dst: The connection the reply will be sent to 24 | * @queue_entry: The queue entry item that is prepared by the replying 25 | * connection 26 | * @deadline_ns: The deadline of the reply, in nanoseconds 27 | * @cookie: The cookie of the requesting message 28 | * @name_id: ID of the well-known name the original msg was sent to 29 | * @sync: The reply block is waiting for synchronous I/O 30 | * @waiting: The condition to synchronously wait for 31 | * @interrupted: The sync reply was left in an interrupted state 32 | * @err: The error code for the synchronous reply 33 | */ 34 | struct kdbus_reply { 35 | struct kref kref; 36 | struct list_head entry; 37 | struct kdbus_conn *reply_src; 38 | struct kdbus_conn *reply_dst; 39 | struct kdbus_queue_entry *queue_entry; 40 | u64 deadline_ns; 41 | u64 cookie; 42 | u64 name_id; 43 | bool sync:1; 44 | bool waiting:1; 45 | bool interrupted:1; 46 | int err; 47 | }; 48 | 49 | struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src, 50 | struct kdbus_conn *reply_dst, 51 | const struct kdbus_msg *msg, 52 | struct kdbus_name_entry *name_entry, 53 | bool sync); 54 | 55 | struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r); 56 | struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r); 57 | 58 | void kdbus_reply_link(struct kdbus_reply *r); 59 | void kdbus_reply_unlink(struct kdbus_reply *r); 60 | 61 | struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying, 62 | struct kdbus_conn *reply_dst, 63 | u64 cookie); 64 | 65 | void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err); 66 | void kdbus_reply_list_scan_work(struct work_struct *work); 67 | 68 | #endif /* __KDBUS_REPLY_H */ 69 | -------------------------------------------------------------------------------- /ipc/kdbus/util.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | #include "limits.h" 27 | #include "util.h" 28 | 29 | /** 30 | * kdbus_copy_from_user() - copy aligned data from user-space 31 | * @dest: target buffer in kernel memory 32 | * @user_ptr: user-provided source buffer 33 | * @size: memory size to copy from user 34 | * 35 | * This copies @size bytes from @user_ptr into the kernel, just like 36 | * copy_from_user() does. But we enforce an 8-byte alignment and reject any 37 | * unaligned user-space pointers. 38 | * 39 | * Return: 0 on success, negative error code on failure. 40 | */ 41 | int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size) 42 | { 43 | if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr)) 44 | return -EFAULT; 45 | 46 | if (copy_from_user(dest, user_ptr, size)) 47 | return -EFAULT; 48 | 49 | return 0; 50 | } 51 | 52 | /** 53 | * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name 54 | * @name: user-supplied name to verify 55 | * @user_ns: user-namespace to act in 56 | * @kuid: Kernel internal uid of user 57 | * 58 | * This verifies that the user-supplied name @name has their UID as prefix. This 59 | * is the default name-spacing policy we enforce on user-supplied names for 60 | * public kdbus entities like buses and endpoints. 61 | * 62 | * The user must supply names prefixed with "-", whereas the UID is 63 | * interpreted in the user-namespace of the domain. If the user fails to supply 64 | * such a prefixed name, we reject it. 65 | * 66 | * Return: 0 on success, negative error code on failure 67 | */ 68 | int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, 69 | kuid_t kuid) 70 | { 71 | uid_t uid; 72 | char prefix[16]; 73 | 74 | /* 75 | * The kuid must have a mapping into the userns of the domain 76 | * otherwise do not allow creation of buses nor endpoints. 77 | */ 78 | uid = from_kuid(user_ns, kuid); 79 | if (uid == (uid_t) -1) 80 | return -EINVAL; 81 | 82 | snprintf(prefix, sizeof(prefix), "%u-", uid); 83 | if (strncmp(name, prefix, strlen(prefix)) != 0) 84 | return -EINVAL; 85 | 86 | return 0; 87 | } 88 | 89 | /** 90 | * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space 91 | * @flags: Attach flags provided by userspace 92 | * @attach_flags: A pointer where to store the valid attach flags 93 | * 94 | * Convert attach-flags provided by user-space into a valid mask. If the mask 95 | * is invalid, an error is returned. The sanitized attach flags are stored in 96 | * the output parameter. 97 | * 98 | * Return: 0 on success, negative error on failure. 99 | */ 100 | int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags) 101 | { 102 | /* 'any' degrades to 'all' for compatibility */ 103 | if (flags == _KDBUS_ATTACH_ANY) 104 | flags = _KDBUS_ATTACH_ALL; 105 | 106 | /* reject unknown attach flags */ 107 | if (flags & ~_KDBUS_ATTACH_ALL) 108 | return -EINVAL; 109 | 110 | *attach_flags = flags; 111 | return 0; 112 | } 113 | 114 | /** 115 | * kdbus_kvec_set - helper utility to assemble kvec arrays 116 | * @kvec: kvec entry to use 117 | * @src: Source address to set in @kvec 118 | * @len: Number of bytes in @src 119 | * @total_len: Pointer to total length variable 120 | * 121 | * Set @src and @len in @kvec, and increase @total_len by @len. 122 | */ 123 | void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len) 124 | { 125 | kvec->iov_base = src; 126 | kvec->iov_len = len; 127 | *total_len += len; 128 | } 129 | 130 | static const char * const zeros = "\0\0\0\0\0\0\0"; 131 | 132 | /** 133 | * kdbus_kvec_pad - conditionally write a padding kvec 134 | * @kvec: kvec entry to use 135 | * @len: Total length used for kvec array 136 | * 137 | * Check if the current total byte length of the array in @len is aligned to 138 | * 8 bytes. If it isn't, fill @kvec with padding information and increase @len 139 | * by the number of bytes stored in @kvec. 140 | * 141 | * Return: the number of added padding bytes. 142 | */ 143 | size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len) 144 | { 145 | size_t pad = KDBUS_ALIGN8(*len) - *len; 146 | 147 | if (!pad) 148 | return 0; 149 | 150 | kvec->iov_base = (void *)zeros; 151 | kvec->iov_len = pad; 152 | 153 | *len += pad; 154 | 155 | return pad; 156 | } 157 | -------------------------------------------------------------------------------- /ipc/kdbus/util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Greg Kroah-Hartman 4 | * Copyright (C) 2013-2015 Daniel Mack 5 | * Copyright (C) 2013-2015 David Herrmann 6 | * Copyright (C) 2013-2015 Linux Foundation 7 | * Copyright (C) 2014-2015 Djalal Harouni 8 | * 9 | * kdbus is free software; you can redistribute it and/or modify it under 10 | * the terms of the GNU Lesser General Public License as published by the 11 | * Free Software Foundation; either version 2.1 of the License, or (at 12 | * your option) any later version. 13 | */ 14 | 15 | #ifndef __KDBUS_UTIL_H 16 | #define __KDBUS_UTIL_H 17 | 18 | #include 19 | #include 20 | 21 | #include 22 | 23 | /* all exported addresses are 64 bit */ 24 | #define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr)) 25 | 26 | /* all exported sizes are 64 bit and data aligned to 64 bit */ 27 | #define KDBUS_ALIGN8(s) ALIGN((s), 8) 28 | #define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8)) 29 | 30 | /** 31 | * kdbus_member_set_user - write a structure member to user memory 32 | * @_s: Variable to copy from 33 | * @_b: Buffer to write to 34 | * @_t: Structure type 35 | * @_m: Member name in the passed structure 36 | * 37 | * Return: the result of copy_to_user() 38 | */ 39 | #define kdbus_member_set_user(_s, _b, _t, _m) \ 40 | ({ \ 41 | u64 __user *_sz = \ 42 | (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \ 43 | copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \ 44 | }) 45 | 46 | /** 47 | * kdbus_strhash - calculate a hash 48 | * @str: String 49 | * 50 | * Return: hash value 51 | */ 52 | static inline unsigned int kdbus_strhash(const char *str) 53 | { 54 | unsigned long hash = init_name_hash(); 55 | 56 | while (*str) 57 | hash = partial_name_hash(*str++, hash); 58 | 59 | return end_name_hash(hash); 60 | } 61 | 62 | int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns, 63 | kuid_t kuid); 64 | int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags); 65 | 66 | int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size); 67 | 68 | struct kvec; 69 | 70 | void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len); 71 | size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len); 72 | 73 | #endif 74 | -------------------------------------------------------------------------------- /samples/kdbus/.gitignore: -------------------------------------------------------------------------------- 1 | kdbus-workers 2 | -------------------------------------------------------------------------------- /samples/kdbus/Makefile: -------------------------------------------------------------------------------- 1 | # kbuild trick to avoid linker error. Can be omitted if a module is built. 2 | obj- := dummy.o 3 | 4 | hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers 5 | 6 | always := $(hostprogs-y) 7 | 8 | HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include 9 | HOSTLOADLIBES_kdbus-workers := -lrt 10 | -------------------------------------------------------------------------------- /samples/kdbus/kdbus-api.h: -------------------------------------------------------------------------------- 1 | #ifndef KDBUS_API_H 2 | #define KDBUS_API_H 3 | 4 | #include 5 | #include 6 | 7 | #define KDBUS_ALIGN8(l) (((l) + 7) & ~7) 8 | #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) 9 | #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) 10 | #define KDBUS_ITEM_NEXT(item) \ 11 | (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) 12 | #define KDBUS_FOREACH(iter, first, _size) \ 13 | for ((iter) = (first); \ 14 | ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ 15 | ((uint8_t *)(iter) >= (uint8_t *)(first)); \ 16 | (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) 17 | 18 | static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd) 19 | { 20 | int ret = ioctl(control_fd, KDBUS_CMD_BUS_MAKE, cmd); 21 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 22 | } 23 | 24 | static inline int kdbus_cmd_endpoint_make(int bus_fd, struct kdbus_cmd *cmd) 25 | { 26 | int ret = ioctl(bus_fd, KDBUS_CMD_ENDPOINT_MAKE, cmd); 27 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 28 | } 29 | 30 | static inline int kdbus_cmd_endpoint_update(int ep_fd, struct kdbus_cmd *cmd) 31 | { 32 | int ret = ioctl(ep_fd, KDBUS_CMD_ENDPOINT_UPDATE, cmd); 33 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 34 | } 35 | 36 | static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd) 37 | { 38 | int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd); 39 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 40 | } 41 | 42 | static inline int kdbus_cmd_update(int fd, struct kdbus_cmd *cmd) 43 | { 44 | int ret = ioctl(fd, KDBUS_CMD_UPDATE, cmd); 45 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 46 | } 47 | 48 | static inline int kdbus_cmd_byebye(int conn_fd, struct kdbus_cmd *cmd) 49 | { 50 | int ret = ioctl(conn_fd, KDBUS_CMD_BYEBYE, cmd); 51 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 52 | } 53 | 54 | static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd) 55 | { 56 | int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd); 57 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 58 | } 59 | 60 | static inline int kdbus_cmd_conn_info(int conn_fd, struct kdbus_cmd_info *cmd) 61 | { 62 | int ret = ioctl(conn_fd, KDBUS_CMD_CONN_INFO, cmd); 63 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 64 | } 65 | 66 | static inline int kdbus_cmd_bus_creator_info(int conn_fd, struct kdbus_cmd_info *cmd) 67 | { 68 | int ret = ioctl(conn_fd, KDBUS_CMD_BUS_CREATOR_INFO, cmd); 69 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 70 | } 71 | 72 | static inline int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd) 73 | { 74 | int ret = ioctl(fd, KDBUS_CMD_LIST, cmd); 75 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 76 | } 77 | 78 | static inline int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd) 79 | { 80 | int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd); 81 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 82 | } 83 | 84 | static inline int kdbus_cmd_recv(int conn_fd, struct kdbus_cmd_recv *cmd) 85 | { 86 | int ret = ioctl(conn_fd, KDBUS_CMD_RECV, cmd); 87 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 88 | } 89 | 90 | static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd) 91 | { 92 | int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd); 93 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 94 | } 95 | 96 | static inline int kdbus_cmd_name_release(int conn_fd, struct kdbus_cmd *cmd) 97 | { 98 | int ret = ioctl(conn_fd, KDBUS_CMD_NAME_RELEASE, cmd); 99 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 100 | } 101 | 102 | static inline int kdbus_cmd_match_add(int conn_fd, struct kdbus_cmd_match *cmd) 103 | { 104 | int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_ADD, cmd); 105 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 106 | } 107 | 108 | static inline int kdbus_cmd_match_remove(int conn_fd, struct kdbus_cmd_match *cmd) 109 | { 110 | int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_REMOVE, cmd); 111 | return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0; 112 | } 113 | 114 | #endif /* KDBUS_API_H */ 115 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/.gitignore: -------------------------------------------------------------------------------- 1 | kdbus-test 2 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/Makefile: -------------------------------------------------------------------------------- 1 | CFLAGS += -I../../../../usr/include/ 2 | CFLAGS += -I../../../../samples/kdbus/ 3 | CFLAGS += -I../../../../include/uapi/ 4 | CFLAGS += -std=gnu99 5 | CFLAGS += -DKBUILD_MODNAME=\"kdbus\" -D_GNU_SOURCE 6 | LDLIBS = -pthread -lcap -lm 7 | 8 | OBJS= \ 9 | kdbus-enum.o \ 10 | kdbus-util.o \ 11 | kdbus-test.o \ 12 | kdbus-test.o \ 13 | test-activator.o \ 14 | test-benchmark.o \ 15 | test-bus.o \ 16 | test-chat.o \ 17 | test-connection.o \ 18 | test-daemon.o \ 19 | test-endpoint.o \ 20 | test-fd.o \ 21 | test-free.o \ 22 | test-match.o \ 23 | test-message.o \ 24 | test-metadata-ns.o \ 25 | test-monitor.o \ 26 | test-names.o \ 27 | test-policy.o \ 28 | test-policy-ns.o \ 29 | test-policy-priv.o \ 30 | test-sync.o \ 31 | test-timeout.o 32 | 33 | all: kdbus-test 34 | 35 | include ../lib.mk 36 | 37 | %.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h 38 | $(CC) $(CFLAGS) -c $< -o $@ 39 | 40 | kdbus-test: $(OBJS) 41 | $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@ 42 | 43 | TEST_PROGS := kdbus-test 44 | 45 | run_tests: 46 | ./kdbus-test --tap 47 | 48 | clean: 49 | rm -f *.o kdbus-test 50 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/kdbus-enum.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * 4 | * kdbus is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU Lesser General Public License as published by the 6 | * Free Software Foundation; either version 2.1 of the License, or (at 7 | * your option) any later version. 8 | */ 9 | 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | 19 | #include "kdbus-util.h" 20 | #include "kdbus-enum.h" 21 | 22 | struct kdbus_enum_table { 23 | long long id; 24 | const char *name; 25 | }; 26 | 27 | #define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[] 28 | #define ENUM(_id) { .id = _id, .name = STRINGIFY(_id) } 29 | #define LOOKUP(what) \ 30 | const char *enum_##what(long long id) \ 31 | { \ 32 | for (size_t i = 0; i < ELEMENTSOF(kdbus_table_##what); i++) \ 33 | if (id == kdbus_table_##what[i].id) \ 34 | return kdbus_table_##what[i].name; \ 35 | return "UNKNOWN"; \ 36 | } 37 | 38 | TABLE(CMD) = { 39 | ENUM(KDBUS_CMD_BUS_MAKE), 40 | ENUM(KDBUS_CMD_ENDPOINT_MAKE), 41 | ENUM(KDBUS_CMD_HELLO), 42 | ENUM(KDBUS_CMD_SEND), 43 | ENUM(KDBUS_CMD_RECV), 44 | ENUM(KDBUS_CMD_LIST), 45 | ENUM(KDBUS_CMD_NAME_RELEASE), 46 | ENUM(KDBUS_CMD_CONN_INFO), 47 | ENUM(KDBUS_CMD_MATCH_ADD), 48 | ENUM(KDBUS_CMD_MATCH_REMOVE), 49 | }; 50 | LOOKUP(CMD); 51 | 52 | TABLE(MSG) = { 53 | ENUM(_KDBUS_ITEM_NULL), 54 | ENUM(KDBUS_ITEM_PAYLOAD_VEC), 55 | ENUM(KDBUS_ITEM_PAYLOAD_OFF), 56 | ENUM(KDBUS_ITEM_PAYLOAD_MEMFD), 57 | ENUM(KDBUS_ITEM_FDS), 58 | ENUM(KDBUS_ITEM_BLOOM_PARAMETER), 59 | ENUM(KDBUS_ITEM_BLOOM_FILTER), 60 | ENUM(KDBUS_ITEM_DST_NAME), 61 | ENUM(KDBUS_ITEM_MAKE_NAME), 62 | ENUM(KDBUS_ITEM_ATTACH_FLAGS_SEND), 63 | ENUM(KDBUS_ITEM_ATTACH_FLAGS_RECV), 64 | ENUM(KDBUS_ITEM_ID), 65 | ENUM(KDBUS_ITEM_NAME), 66 | ENUM(KDBUS_ITEM_TIMESTAMP), 67 | ENUM(KDBUS_ITEM_CREDS), 68 | ENUM(KDBUS_ITEM_PIDS), 69 | ENUM(KDBUS_ITEM_AUXGROUPS), 70 | ENUM(KDBUS_ITEM_OWNED_NAME), 71 | ENUM(KDBUS_ITEM_TID_COMM), 72 | ENUM(KDBUS_ITEM_PID_COMM), 73 | ENUM(KDBUS_ITEM_EXE), 74 | ENUM(KDBUS_ITEM_CMDLINE), 75 | ENUM(KDBUS_ITEM_CGROUP), 76 | ENUM(KDBUS_ITEM_CAPS), 77 | ENUM(KDBUS_ITEM_SECLABEL), 78 | ENUM(KDBUS_ITEM_AUDIT), 79 | ENUM(KDBUS_ITEM_CONN_DESCRIPTION), 80 | ENUM(KDBUS_ITEM_NAME_ADD), 81 | ENUM(KDBUS_ITEM_NAME_REMOVE), 82 | ENUM(KDBUS_ITEM_NAME_CHANGE), 83 | ENUM(KDBUS_ITEM_ID_ADD), 84 | ENUM(KDBUS_ITEM_ID_REMOVE), 85 | ENUM(KDBUS_ITEM_REPLY_TIMEOUT), 86 | ENUM(KDBUS_ITEM_REPLY_DEAD), 87 | }; 88 | LOOKUP(MSG); 89 | 90 | TABLE(PAYLOAD) = { 91 | ENUM(KDBUS_PAYLOAD_KERNEL), 92 | ENUM(KDBUS_PAYLOAD_DBUS), 93 | }; 94 | LOOKUP(PAYLOAD); 95 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/kdbus-enum.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * 4 | * kdbus is free software; you can redistribute it and/or modify it under 5 | * the terms of the GNU Lesser General Public License as published by the 6 | * Free Software Foundation; either version 2.1 of the License, or (at 7 | * your option) any later version. 8 | */ 9 | 10 | #pragma once 11 | 12 | const char *enum_CMD(long long id); 13 | const char *enum_MSG(long long id); 14 | const char *enum_MATCH(long long id); 15 | const char *enum_PAYLOAD(long long id); 16 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/kdbus-test.h: -------------------------------------------------------------------------------- 1 | #ifndef _TEST_KDBUS_H_ 2 | #define _TEST_KDBUS_H_ 3 | 4 | struct kdbus_test_env { 5 | char *buspath; 6 | const char *root; 7 | const char *module; 8 | int control_fd; 9 | struct kdbus_conn *conn; 10 | }; 11 | 12 | enum { 13 | TEST_OK, 14 | TEST_SKIP, 15 | TEST_ERR, 16 | }; 17 | 18 | #define ASSERT_RETURN_VAL(cond, val) \ 19 | if (!(cond)) { \ 20 | fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ 21 | #cond, __func__, __FILE__, __LINE__); \ 22 | return val; \ 23 | } 24 | 25 | #define ASSERT_EXIT_VAL(cond, val) \ 26 | if (!(cond)) { \ 27 | fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ 28 | #cond, __func__, __FILE__, __LINE__); \ 29 | _exit(val); \ 30 | } 31 | 32 | #define ASSERT_BREAK(cond) \ 33 | if (!(cond)) { \ 34 | fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \ 35 | #cond, __func__, __FILE__, __LINE__); \ 36 | break; \ 37 | } 38 | 39 | #define ASSERT_RETURN(cond) \ 40 | ASSERT_RETURN_VAL(cond, TEST_ERR) 41 | 42 | #define ASSERT_EXIT(cond) \ 43 | ASSERT_EXIT_VAL(cond, EXIT_FAILURE) 44 | 45 | int kdbus_test_activator(struct kdbus_test_env *env); 46 | int kdbus_test_benchmark(struct kdbus_test_env *env); 47 | int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env); 48 | int kdbus_test_benchmark_uds(struct kdbus_test_env *env); 49 | int kdbus_test_bus_make(struct kdbus_test_env *env); 50 | int kdbus_test_byebye(struct kdbus_test_env *env); 51 | int kdbus_test_chat(struct kdbus_test_env *env); 52 | int kdbus_test_conn_info(struct kdbus_test_env *env); 53 | int kdbus_test_conn_update(struct kdbus_test_env *env); 54 | int kdbus_test_daemon(struct kdbus_test_env *env); 55 | int kdbus_test_custom_endpoint(struct kdbus_test_env *env); 56 | int kdbus_test_fd_passing(struct kdbus_test_env *env); 57 | int kdbus_test_free(struct kdbus_test_env *env); 58 | int kdbus_test_hello(struct kdbus_test_env *env); 59 | int kdbus_test_match_bloom(struct kdbus_test_env *env); 60 | int kdbus_test_match_id_add(struct kdbus_test_env *env); 61 | int kdbus_test_match_id_remove(struct kdbus_test_env *env); 62 | int kdbus_test_match_replace(struct kdbus_test_env *env); 63 | int kdbus_test_match_name_add(struct kdbus_test_env *env); 64 | int kdbus_test_match_name_change(struct kdbus_test_env *env); 65 | int kdbus_test_match_name_remove(struct kdbus_test_env *env); 66 | int kdbus_test_message_basic(struct kdbus_test_env *env); 67 | int kdbus_test_message_prio(struct kdbus_test_env *env); 68 | int kdbus_test_message_quota(struct kdbus_test_env *env); 69 | int kdbus_test_memory_access(struct kdbus_test_env *env); 70 | int kdbus_test_metadata_ns(struct kdbus_test_env *env); 71 | int kdbus_test_monitor(struct kdbus_test_env *env); 72 | int kdbus_test_name_basic(struct kdbus_test_env *env); 73 | int kdbus_test_name_conflict(struct kdbus_test_env *env); 74 | int kdbus_test_name_queue(struct kdbus_test_env *env); 75 | int kdbus_test_name_takeover(struct kdbus_test_env *env); 76 | int kdbus_test_policy(struct kdbus_test_env *env); 77 | int kdbus_test_policy_ns(struct kdbus_test_env *env); 78 | int kdbus_test_policy_priv(struct kdbus_test_env *env); 79 | int kdbus_test_sync_byebye(struct kdbus_test_env *env); 80 | int kdbus_test_sync_reply(struct kdbus_test_env *env); 81 | int kdbus_test_timeout(struct kdbus_test_env *env); 82 | int kdbus_test_writable_pool(struct kdbus_test_env *env); 83 | 84 | #endif /* _TEST_KDBUS_H_ */ 85 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/kdbus-util.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2013-2015 Kay Sievers 3 | * Copyright (C) 2013-2015 Daniel Mack 4 | * 5 | * kdbus is free software; you can redistribute it and/or modify it under 6 | * the terms of the GNU Lesser General Public License as published by the 7 | * Free Software Foundation; either version 2.1 of the License, or (at 8 | * your option) any later version. 9 | */ 10 | 11 | #pragma once 12 | 13 | #define BIT(X) (1 << (X)) 14 | 15 | #include 16 | #include 17 | #include 18 | 19 | #define _STRINGIFY(x) #x 20 | #define STRINGIFY(x) _STRINGIFY(x) 21 | #define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0])) 22 | 23 | #define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr)) 24 | 25 | #define KDBUS_ALIGN8(l) (((l) + 7) & ~7) 26 | #define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data) 27 | #define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE) 28 | 29 | #define KDBUS_ITEM_NEXT(item) \ 30 | (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size)) 31 | #define KDBUS_ITEM_FOREACH(item, head, first) \ 32 | for ((item) = (head)->first; \ 33 | ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \ 34 | ((uint8_t *)(item) >= (uint8_t *)(head)); \ 35 | (item) = KDBUS_ITEM_NEXT(item)) 36 | #define KDBUS_FOREACH(iter, first, _size) \ 37 | for ((iter) = (first); \ 38 | ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \ 39 | ((uint8_t *)(iter) >= (uint8_t *)(first)); \ 40 | (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size))) 41 | 42 | #define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL)) 43 | 44 | /* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */ 45 | #define KDBUS_ATTACH_ITEMS_TYPE_SUM \ 46 | ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \ 47 | ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \ 48 | (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR)) 49 | 50 | #define POOL_SIZE (16 * 1024LU * 1024LU) 51 | 52 | #define UNPRIV_UID 65534 53 | #define UNPRIV_GID 65534 54 | 55 | /* Dump as user of process, useful for user namespace testing */ 56 | #define SUID_DUMP_USER 1 57 | 58 | extern int kdbus_util_verbose; 59 | 60 | #define kdbus_printf(X...) \ 61 | if (kdbus_util_verbose) \ 62 | printf(X) 63 | 64 | #define RUN_UNPRIVILEGED(child_uid, child_gid, _child_, _parent_) ({ \ 65 | pid_t pid, rpid; \ 66 | int ret; \ 67 | \ 68 | pid = fork(); \ 69 | if (pid == 0) { \ 70 | ret = drop_privileges(child_uid, child_gid); \ 71 | ASSERT_EXIT_VAL(ret == 0, ret); \ 72 | \ 73 | _child_; \ 74 | _exit(0); \ 75 | } else if (pid > 0) { \ 76 | _parent_; \ 77 | rpid = waitpid(pid, &ret, 0); \ 78 | ASSERT_RETURN(rpid == pid); \ 79 | ASSERT_RETURN(WIFEXITED(ret)); \ 80 | ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ 81 | ret = TEST_OK; \ 82 | } else { \ 83 | ret = pid; \ 84 | } \ 85 | \ 86 | ret; \ 87 | }) 88 | 89 | #define RUN_UNPRIVILEGED_CONN(_var_, _bus_, _code_) \ 90 | RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ \ 91 | struct kdbus_conn *_var_; \ 92 | _var_ = kdbus_hello(_bus_, 0, NULL, 0); \ 93 | ASSERT_EXIT(_var_); \ 94 | _code_; \ 95 | kdbus_conn_free(_var_); \ 96 | }), ({ 0; })) 97 | 98 | #define RUN_CLONE_CHILD(clone_ret, flags, _setup_, _child_body_, \ 99 | _parent_setup_, _parent_body_) ({ \ 100 | pid_t pid, rpid; \ 101 | int ret; \ 102 | int efd = -1; \ 103 | \ 104 | _setup_; \ 105 | efd = eventfd(0, EFD_CLOEXEC); \ 106 | ASSERT_RETURN(efd >= 0); \ 107 | *(clone_ret) = 0; \ 108 | pid = syscall(__NR_clone, flags, NULL); \ 109 | if (pid == 0) { \ 110 | eventfd_t event_status = 0; \ 111 | ret = prctl(PR_SET_PDEATHSIG, SIGKILL); \ 112 | ASSERT_EXIT(ret == 0); \ 113 | ret = eventfd_read(efd, &event_status); \ 114 | if (ret < 0 || event_status != 1) { \ 115 | kdbus_printf("error eventfd_read()\n"); \ 116 | _exit(EXIT_FAILURE); \ 117 | } \ 118 | _child_body_; \ 119 | _exit(0); \ 120 | } else if (pid > 0) { \ 121 | _parent_setup_; \ 122 | ret = eventfd_write(efd, 1); \ 123 | ASSERT_RETURN(ret >= 0); \ 124 | _parent_body_; \ 125 | rpid = waitpid(pid, &ret, 0); \ 126 | ASSERT_RETURN(rpid == pid); \ 127 | ASSERT_RETURN(WIFEXITED(ret)); \ 128 | ASSERT_RETURN(WEXITSTATUS(ret) == 0); \ 129 | ret = TEST_OK; \ 130 | } else { \ 131 | ret = -errno; \ 132 | *(clone_ret) = -errno; \ 133 | } \ 134 | close(efd); \ 135 | ret; \ 136 | }) 137 | 138 | /* Enums for parent if it should drop privs or not */ 139 | enum kdbus_drop_parent { 140 | DO_NOT_DROP, 141 | DROP_SAME_UNPRIV, 142 | DROP_OTHER_UNPRIV, 143 | }; 144 | 145 | struct kdbus_conn { 146 | int fd; 147 | uint64_t id; 148 | unsigned char *buf; 149 | }; 150 | 151 | int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask); 152 | int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask); 153 | 154 | int sys_memfd_create(const char *name, __u64 size); 155 | int sys_memfd_seal_set(int fd); 156 | off_t sys_memfd_get_size(int fd, off_t *size); 157 | 158 | int kdbus_list(struct kdbus_conn *conn, uint64_t flags); 159 | int kdbus_name_release(struct kdbus_conn *conn, const char *name); 160 | int kdbus_name_acquire(struct kdbus_conn *conn, const char *name, 161 | uint64_t *flags); 162 | void kdbus_msg_free(struct kdbus_msg *msg); 163 | int kdbus_msg_recv(struct kdbus_conn *conn, 164 | struct kdbus_msg **msg, uint64_t *offset); 165 | int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms, 166 | struct kdbus_msg **msg_out, uint64_t *offset); 167 | int kdbus_free(const struct kdbus_conn *conn, uint64_t offset); 168 | int kdbus_msg_dump(const struct kdbus_conn *conn, 169 | const struct kdbus_msg *msg); 170 | int kdbus_create_bus(int control_fd, const char *name, 171 | uint64_t owner_meta, char **path); 172 | int kdbus_msg_send(const struct kdbus_conn *conn, const char *name, 173 | uint64_t cookie, uint64_t flags, uint64_t timeout, 174 | int64_t priority, uint64_t dst_id); 175 | int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name, 176 | uint64_t cookie, uint64_t flags, uint64_t timeout, 177 | int64_t priority, uint64_t dst_id, int cancel_fd); 178 | int kdbus_msg_send_reply(const struct kdbus_conn *conn, 179 | uint64_t reply_cookie, 180 | uint64_t dst_id); 181 | struct kdbus_conn *kdbus_hello(const char *path, uint64_t hello_flags, 182 | const struct kdbus_item *item, 183 | size_t item_size); 184 | struct kdbus_conn *kdbus_hello_registrar(const char *path, const char *name, 185 | const struct kdbus_policy_access *access, 186 | size_t num_access, uint64_t flags); 187 | struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name, 188 | const struct kdbus_policy_access *access, 189 | size_t num_access); 190 | bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type); 191 | int kdbus_bus_creator_info(struct kdbus_conn *conn, 192 | uint64_t flags, 193 | uint64_t *offset); 194 | int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id, 195 | const char *name, uint64_t flags, uint64_t *offset); 196 | void kdbus_conn_free(struct kdbus_conn *conn); 197 | int kdbus_conn_update_attach_flags(struct kdbus_conn *conn, 198 | uint64_t attach_flags_send, 199 | uint64_t attach_flags_recv); 200 | int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name, 201 | const struct kdbus_policy_access *access, 202 | size_t num_access); 203 | 204 | int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie, 205 | uint64_t type, uint64_t id); 206 | int kdbus_add_match_empty(struct kdbus_conn *conn); 207 | 208 | int all_uids_gids_are_mapped(void); 209 | int drop_privileges(uid_t uid, gid_t gid); 210 | uint64_t now(clockid_t clock); 211 | char *unique_name(const char *prefix); 212 | 213 | int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid); 214 | int test_is_capable(int cap, ...); 215 | int config_user_ns_is_enabled(void); 216 | int config_auditsyscall_is_enabled(void); 217 | int config_cgroups_is_enabled(void); 218 | int config_security_is_enabled(void); 219 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-activator.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "kdbus-test.h" 18 | #include "kdbus-util.h" 19 | #include "kdbus-enum.h" 20 | 21 | static int kdbus_starter_poll(struct kdbus_conn *conn) 22 | { 23 | int ret; 24 | struct pollfd fd; 25 | 26 | fd.fd = conn->fd; 27 | fd.events = POLLIN | POLLPRI | POLLHUP; 28 | fd.revents = 0; 29 | 30 | ret = poll(&fd, 1, 100); 31 | if (ret == 0) 32 | return -ETIMEDOUT; 33 | else if (ret > 0) { 34 | if (fd.revents & POLLIN) 35 | return 0; 36 | 37 | if (fd.revents & (POLLHUP | POLLERR)) 38 | ret = -ECONNRESET; 39 | } 40 | 41 | return ret; 42 | } 43 | 44 | /* Ensure that kdbus activator logic is safe */ 45 | static int kdbus_priv_activator(struct kdbus_test_env *env) 46 | { 47 | int ret; 48 | struct kdbus_msg *msg = NULL; 49 | uint64_t cookie = 0xdeadbeef; 50 | uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; 51 | struct kdbus_conn *activator; 52 | struct kdbus_conn *service; 53 | struct kdbus_conn *client; 54 | struct kdbus_conn *holder; 55 | struct kdbus_policy_access *access; 56 | 57 | access = (struct kdbus_policy_access[]){ 58 | { 59 | .type = KDBUS_POLICY_ACCESS_USER, 60 | .id = getuid(), 61 | .access = KDBUS_POLICY_OWN, 62 | }, 63 | { 64 | .type = KDBUS_POLICY_ACCESS_USER, 65 | .id = getuid(), 66 | .access = KDBUS_POLICY_TALK, 67 | }, 68 | }; 69 | 70 | activator = kdbus_hello_activator(env->buspath, "foo.priv.activator", 71 | access, 2); 72 | ASSERT_RETURN(activator); 73 | 74 | service = kdbus_hello(env->buspath, 0, NULL, 0); 75 | ASSERT_RETURN(service); 76 | 77 | client = kdbus_hello(env->buspath, 0, NULL, 0); 78 | ASSERT_RETURN(client); 79 | 80 | /* 81 | * Make sure that other users can't TALK to the activator 82 | */ 83 | 84 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 85 | /* Try to talk using the ID */ 86 | ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0, 87 | 0, activator->id); 88 | ASSERT_EXIT(ret == -ENXIO); 89 | 90 | /* Try to talk to the name */ 91 | ret = kdbus_msg_send(unpriv, "foo.priv.activator", 92 | 0xdeadbeef, 0, 0, 0, 93 | KDBUS_DST_ID_NAME); 94 | ASSERT_EXIT(ret == -EPERM); 95 | })); 96 | ASSERT_RETURN(ret >= 0); 97 | 98 | /* 99 | * Make sure that we did not receive anything, so the 100 | * service will not be started automatically 101 | */ 102 | 103 | ret = kdbus_starter_poll(activator); 104 | ASSERT_RETURN(ret == -ETIMEDOUT); 105 | 106 | /* 107 | * Now try to emulate the starter/service logic and 108 | * acquire the name. 109 | */ 110 | 111 | cookie++; 112 | ret = kdbus_msg_send(service, "foo.priv.activator", cookie, 113 | 0, 0, 0, KDBUS_DST_ID_NAME); 114 | ASSERT_RETURN(ret == 0); 115 | 116 | ret = kdbus_starter_poll(activator); 117 | ASSERT_RETURN(ret == 0); 118 | 119 | /* Policies are still checked, access denied */ 120 | 121 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 122 | ret = kdbus_name_acquire(unpriv, "foo.priv.activator", 123 | &flags); 124 | ASSERT_RETURN(ret == -EPERM); 125 | })); 126 | ASSERT_RETURN(ret >= 0); 127 | 128 | ret = kdbus_name_acquire(service, "foo.priv.activator", 129 | &flags); 130 | ASSERT_RETURN(ret == 0); 131 | 132 | /* We read our previous starter message */ 133 | 134 | ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); 135 | ASSERT_RETURN(ret == 0); 136 | 137 | /* Try to talk, we still fail */ 138 | 139 | cookie++; 140 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 141 | /* Try to talk to the name */ 142 | ret = kdbus_msg_send(unpriv, "foo.priv.activator", 143 | cookie, 0, 0, 0, 144 | KDBUS_DST_ID_NAME); 145 | ASSERT_EXIT(ret == -EPERM); 146 | })); 147 | ASSERT_RETURN(ret >= 0); 148 | 149 | /* Still nothing to read */ 150 | 151 | ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); 152 | ASSERT_RETURN(ret == -ETIMEDOUT); 153 | 154 | /* We receive every thing now */ 155 | 156 | cookie++; 157 | ret = kdbus_msg_send(client, "foo.priv.activator", cookie, 158 | 0, 0, 0, KDBUS_DST_ID_NAME); 159 | ASSERT_RETURN(ret == 0); 160 | ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); 161 | ASSERT_RETURN(ret == 0 && msg->cookie == cookie); 162 | 163 | kdbus_msg_free(msg); 164 | 165 | /* Policies default to deny TALK now */ 166 | kdbus_conn_free(activator); 167 | 168 | cookie++; 169 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 170 | /* Try to talk to the name */ 171 | ret = kdbus_msg_send(unpriv, "foo.priv.activator", 172 | cookie, 0, 0, 0, 173 | KDBUS_DST_ID_NAME); 174 | ASSERT_EXIT(ret == -EPERM); 175 | })); 176 | ASSERT_RETURN(ret >= 0); 177 | 178 | ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); 179 | ASSERT_RETURN(ret == -ETIMEDOUT); 180 | 181 | /* Same user is able to TALK */ 182 | cookie++; 183 | ret = kdbus_msg_send(client, "foo.priv.activator", cookie, 184 | 0, 0, 0, KDBUS_DST_ID_NAME); 185 | ASSERT_RETURN(ret == 0); 186 | ret = kdbus_msg_recv_poll(service, 100, &msg, NULL); 187 | ASSERT_RETURN(ret == 0 && msg->cookie == cookie); 188 | 189 | kdbus_msg_free(msg); 190 | 191 | access = (struct kdbus_policy_access []){ 192 | { 193 | .type = KDBUS_POLICY_ACCESS_WORLD, 194 | .id = getuid(), 195 | .access = KDBUS_POLICY_TALK, 196 | }, 197 | }; 198 | 199 | holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator", 200 | access, 1, KDBUS_HELLO_POLICY_HOLDER); 201 | ASSERT_RETURN(holder); 202 | 203 | /* Now we are able to TALK to the name */ 204 | 205 | cookie++; 206 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 207 | /* Try to talk to the name */ 208 | ret = kdbus_msg_send(unpriv, "foo.priv.activator", 209 | cookie, 0, 0, 0, 210 | KDBUS_DST_ID_NAME); 211 | ASSERT_EXIT(ret == 0); 212 | })); 213 | ASSERT_RETURN(ret >= 0); 214 | 215 | ret = kdbus_msg_recv_poll(service, 100, NULL, NULL); 216 | ASSERT_RETURN(ret == 0); 217 | 218 | ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({ 219 | ret = kdbus_name_acquire(unpriv, "foo.priv.activator", 220 | &flags); 221 | ASSERT_RETURN(ret == -EPERM); 222 | })); 223 | ASSERT_RETURN(ret >= 0); 224 | 225 | kdbus_conn_free(service); 226 | kdbus_conn_free(client); 227 | kdbus_conn_free(holder); 228 | 229 | return 0; 230 | } 231 | 232 | int kdbus_test_activator(struct kdbus_test_env *env) 233 | { 234 | int ret; 235 | struct kdbus_conn *activator; 236 | struct pollfd fds[2]; 237 | bool activator_done = false; 238 | struct kdbus_policy_access access[2]; 239 | 240 | access[0].type = KDBUS_POLICY_ACCESS_USER; 241 | access[0].id = getuid(); 242 | access[0].access = KDBUS_POLICY_OWN; 243 | 244 | access[1].type = KDBUS_POLICY_ACCESS_WORLD; 245 | access[1].access = KDBUS_POLICY_TALK; 246 | 247 | activator = kdbus_hello_activator(env->buspath, "foo.test.activator", 248 | access, 2); 249 | ASSERT_RETURN(activator); 250 | 251 | ret = kdbus_add_match_empty(env->conn); 252 | ASSERT_RETURN(ret == 0); 253 | 254 | ret = kdbus_list(env->conn, KDBUS_LIST_NAMES | 255 | KDBUS_LIST_UNIQUE | 256 | KDBUS_LIST_ACTIVATORS | 257 | KDBUS_LIST_QUEUED); 258 | ASSERT_RETURN(ret == 0); 259 | 260 | ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef, 261 | 0, 0, 0, KDBUS_DST_ID_NAME); 262 | ASSERT_RETURN(ret == 0); 263 | 264 | fds[0].fd = activator->fd; 265 | fds[1].fd = env->conn->fd; 266 | 267 | kdbus_printf("-- entering poll loop ...\n"); 268 | 269 | for (;;) { 270 | int i, nfds = sizeof(fds) / sizeof(fds[0]); 271 | 272 | for (i = 0; i < nfds; i++) { 273 | fds[i].events = POLLIN | POLLPRI; 274 | fds[i].revents = 0; 275 | } 276 | 277 | ret = poll(fds, nfds, 3000); 278 | ASSERT_RETURN(ret >= 0); 279 | 280 | ret = kdbus_list(env->conn, KDBUS_LIST_NAMES); 281 | ASSERT_RETURN(ret == 0); 282 | 283 | if ((fds[0].revents & POLLIN) && !activator_done) { 284 | uint64_t flags = KDBUS_NAME_REPLACE_EXISTING; 285 | 286 | kdbus_printf("Starter was called back!\n"); 287 | 288 | ret = kdbus_name_acquire(env->conn, 289 | "foo.test.activator", &flags); 290 | ASSERT_RETURN(ret == 0); 291 | 292 | activator_done = true; 293 | } 294 | 295 | if (fds[1].revents & POLLIN) { 296 | kdbus_msg_recv(env->conn, NULL, NULL); 297 | break; 298 | } 299 | } 300 | 301 | /* Check if all uids/gids are mapped */ 302 | if (!all_uids_gids_are_mapped()) 303 | return TEST_SKIP; 304 | 305 | /* Check now capabilities, so we run the previous tests */ 306 | ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); 307 | ASSERT_RETURN(ret >= 0); 308 | 309 | if (!ret) 310 | return TEST_SKIP; 311 | 312 | ret = kdbus_priv_activator(env); 313 | ASSERT_RETURN(ret == 0); 314 | 315 | kdbus_conn_free(activator); 316 | 317 | return TEST_OK; 318 | } 319 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-bus.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "kdbus-api.h" 15 | #include "kdbus-util.h" 16 | #include "kdbus-enum.h" 17 | #include "kdbus-test.h" 18 | 19 | static struct kdbus_item *kdbus_get_item(struct kdbus_info *info, 20 | uint64_t type) 21 | { 22 | struct kdbus_item *item; 23 | 24 | KDBUS_ITEM_FOREACH(item, info, items) 25 | if (item->type == type) 26 | return item; 27 | 28 | return NULL; 29 | } 30 | 31 | static int test_bus_creator_info(const char *bus_path) 32 | { 33 | int ret; 34 | uint64_t offset; 35 | struct kdbus_conn *conn; 36 | struct kdbus_info *info; 37 | struct kdbus_item *item; 38 | char *tmp, *busname; 39 | 40 | /* extract the bus-name from @bus_path */ 41 | tmp = strdup(bus_path); 42 | ASSERT_RETURN(tmp); 43 | busname = strrchr(tmp, '/'); 44 | ASSERT_RETURN(busname); 45 | *busname = 0; 46 | busname = strrchr(tmp, '/'); 47 | ASSERT_RETURN(busname); 48 | ++busname; 49 | 50 | conn = kdbus_hello(bus_path, 0, NULL, 0); 51 | ASSERT_RETURN(conn); 52 | 53 | ret = kdbus_bus_creator_info(conn, _KDBUS_ATTACH_ALL, &offset); 54 | ASSERT_RETURN(ret == 0); 55 | 56 | info = (struct kdbus_info *)(conn->buf + offset); 57 | 58 | item = kdbus_get_item(info, KDBUS_ITEM_MAKE_NAME); 59 | ASSERT_RETURN(item); 60 | ASSERT_RETURN(!strcmp(item->str, busname)); 61 | 62 | ret = kdbus_free(conn, offset); 63 | ASSERT_RETURN_VAL(ret == 0, ret); 64 | 65 | free(tmp); 66 | kdbus_conn_free(conn); 67 | return 0; 68 | } 69 | 70 | int kdbus_test_bus_make(struct kdbus_test_env *env) 71 | { 72 | struct { 73 | struct kdbus_cmd cmd; 74 | 75 | /* bloom size item */ 76 | struct { 77 | uint64_t size; 78 | uint64_t type; 79 | struct kdbus_bloom_parameter bloom; 80 | } bs; 81 | 82 | /* name item */ 83 | uint64_t n_size; 84 | uint64_t n_type; 85 | char name[64]; 86 | } bus_make; 87 | char s[PATH_MAX], *name; 88 | int ret, control_fd2; 89 | uid_t uid; 90 | 91 | name = unique_name(""); 92 | ASSERT_RETURN(name); 93 | 94 | snprintf(s, sizeof(s), "%s/control", env->root); 95 | env->control_fd = open(s, O_RDWR|O_CLOEXEC); 96 | ASSERT_RETURN(env->control_fd >= 0); 97 | 98 | control_fd2 = open(s, O_RDWR|O_CLOEXEC); 99 | ASSERT_RETURN(control_fd2 >= 0); 100 | 101 | memset(&bus_make, 0, sizeof(bus_make)); 102 | 103 | bus_make.bs.size = sizeof(bus_make.bs); 104 | bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER; 105 | bus_make.bs.bloom.size = 64; 106 | bus_make.bs.bloom.n_hash = 1; 107 | 108 | bus_make.n_type = KDBUS_ITEM_MAKE_NAME; 109 | 110 | uid = getuid(); 111 | 112 | /* missing uid prefix */ 113 | snprintf(bus_make.name, sizeof(bus_make.name), "foo"); 114 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 115 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 116 | sizeof(bus_make.bs) + bus_make.n_size; 117 | ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); 118 | ASSERT_RETURN(ret == -EINVAL); 119 | 120 | /* non alphanumeric character */ 121 | snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid); 122 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 123 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 124 | sizeof(bus_make.bs) + bus_make.n_size; 125 | ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); 126 | ASSERT_RETURN(ret == -EINVAL); 127 | 128 | /* '-' at the end */ 129 | snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid); 130 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 131 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 132 | sizeof(bus_make.bs) + bus_make.n_size; 133 | ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); 134 | ASSERT_RETURN(ret == -EINVAL); 135 | 136 | /* create a new bus */ 137 | snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-1", uid, name); 138 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 139 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 140 | sizeof(bus_make.bs) + bus_make.n_size; 141 | ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); 142 | ASSERT_RETURN(ret == 0); 143 | 144 | ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); 145 | ASSERT_RETURN(ret == -EEXIST); 146 | 147 | snprintf(s, sizeof(s), "%s/%u-%s-1/bus", env->root, uid, name); 148 | ASSERT_RETURN(access(s, F_OK) == 0); 149 | 150 | ret = test_bus_creator_info(s); 151 | ASSERT_RETURN(ret == 0); 152 | 153 | /* can't use the same fd for bus make twice, even though a different 154 | * bus name is used 155 | */ 156 | snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); 157 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 158 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 159 | sizeof(bus_make.bs) + bus_make.n_size; 160 | ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd); 161 | ASSERT_RETURN(ret == -EBADFD); 162 | 163 | /* create a new bus, with different fd and different bus name */ 164 | snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name); 165 | bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1; 166 | bus_make.cmd.size = sizeof(struct kdbus_cmd) + 167 | sizeof(bus_make.bs) + bus_make.n_size; 168 | ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd); 169 | ASSERT_RETURN(ret == 0); 170 | 171 | close(control_fd2); 172 | free(name); 173 | 174 | return TEST_OK; 175 | } 176 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-chat.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "kdbus-test.h" 15 | #include "kdbus-util.h" 16 | #include "kdbus-enum.h" 17 | 18 | int kdbus_test_chat(struct kdbus_test_env *env) 19 | { 20 | int ret, cookie; 21 | struct kdbus_conn *conn_a, *conn_b; 22 | struct pollfd fds[2]; 23 | uint64_t flags; 24 | int count; 25 | 26 | conn_a = kdbus_hello(env->buspath, 0, NULL, 0); 27 | conn_b = kdbus_hello(env->buspath, 0, NULL, 0); 28 | ASSERT_RETURN(conn_a && conn_b); 29 | 30 | flags = KDBUS_NAME_ALLOW_REPLACEMENT; 31 | ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags); 32 | ASSERT_RETURN(ret == 0); 33 | 34 | ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL); 35 | ASSERT_RETURN(ret == 0); 36 | 37 | flags = KDBUS_NAME_QUEUE; 38 | ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags); 39 | ASSERT_RETURN(ret == 0); 40 | 41 | ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL); 42 | ASSERT_RETURN(ret == 0); 43 | 44 | flags = 0; 45 | ret = kdbus_name_acquire(conn_a, "foo.bar.double", &flags); 46 | ASSERT_RETURN(ret == 0); 47 | ASSERT_RETURN(!(flags & KDBUS_NAME_ACQUIRED)); 48 | 49 | ret = kdbus_name_release(conn_a, "foo.bar.double"); 50 | ASSERT_RETURN(ret == 0); 51 | 52 | ret = kdbus_name_release(conn_a, "foo.bar.double"); 53 | ASSERT_RETURN(ret == -ESRCH); 54 | 55 | ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | 56 | KDBUS_LIST_NAMES | 57 | KDBUS_LIST_QUEUED | 58 | KDBUS_LIST_ACTIVATORS); 59 | ASSERT_RETURN(ret == 0); 60 | 61 | ret = kdbus_add_match_empty(conn_a); 62 | ASSERT_RETURN(ret == 0); 63 | 64 | ret = kdbus_add_match_empty(conn_b); 65 | ASSERT_RETURN(ret == 0); 66 | 67 | cookie = 0; 68 | ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0, 69 | KDBUS_DST_ID_BROADCAST); 70 | ASSERT_RETURN(ret == 0); 71 | 72 | fds[0].fd = conn_a->fd; 73 | fds[1].fd = conn_b->fd; 74 | 75 | kdbus_printf("-- entering poll loop ...\n"); 76 | 77 | for (count = 0;; count++) { 78 | int i, nfds = sizeof(fds) / sizeof(fds[0]); 79 | 80 | for (i = 0; i < nfds; i++) { 81 | fds[i].events = POLLIN | POLLPRI | POLLHUP; 82 | fds[i].revents = 0; 83 | } 84 | 85 | ret = poll(fds, nfds, 3000); 86 | ASSERT_RETURN(ret >= 0); 87 | 88 | if (fds[0].revents & POLLIN) { 89 | if (count > 2) 90 | kdbus_name_release(conn_a, "foo.bar.baz"); 91 | 92 | ret = kdbus_msg_recv(conn_a, NULL, NULL); 93 | ASSERT_RETURN(ret == 0); 94 | ret = kdbus_msg_send(conn_a, NULL, 95 | 0xc0000000 | cookie++, 96 | 0, 0, 0, conn_b->id); 97 | ASSERT_RETURN(ret == 0); 98 | } 99 | 100 | if (fds[1].revents & POLLIN) { 101 | ret = kdbus_msg_recv(conn_b, NULL, NULL); 102 | ASSERT_RETURN(ret == 0); 103 | ret = kdbus_msg_send(conn_b, NULL, 104 | 0xc0000000 | cookie++, 105 | 0, 0, 0, conn_a->id); 106 | ASSERT_RETURN(ret == 0); 107 | } 108 | 109 | ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE | 110 | KDBUS_LIST_NAMES | 111 | KDBUS_LIST_QUEUED | 112 | KDBUS_LIST_ACTIVATORS); 113 | ASSERT_RETURN(ret == 0); 114 | 115 | if (count > 10) 116 | break; 117 | } 118 | 119 | kdbus_printf("-- closing bus connections\n"); 120 | kdbus_conn_free(conn_a); 121 | kdbus_conn_free(conn_b); 122 | 123 | return TEST_OK; 124 | } 125 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-daemon.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "kdbus-test.h" 15 | #include "kdbus-util.h" 16 | #include "kdbus-enum.h" 17 | 18 | int kdbus_test_daemon(struct kdbus_test_env *env) 19 | { 20 | struct pollfd fds[2]; 21 | int count; 22 | int ret; 23 | 24 | /* This test doesn't make any sense in non-interactive mode */ 25 | if (!kdbus_util_verbose) 26 | return TEST_OK; 27 | 28 | printf("Created connection %llu on bus '%s'\n", 29 | (unsigned long long) env->conn->id, env->buspath); 30 | 31 | ret = kdbus_name_acquire(env->conn, "com.example.kdbus-test", NULL); 32 | ASSERT_RETURN(ret == 0); 33 | printf(" Aquired name: com.example.kdbus-test\n"); 34 | 35 | fds[0].fd = env->conn->fd; 36 | fds[1].fd = STDIN_FILENO; 37 | 38 | printf("Monitoring connections:\n"); 39 | 40 | for (count = 0;; count++) { 41 | int i, nfds = sizeof(fds) / sizeof(fds[0]); 42 | 43 | for (i = 0; i < nfds; i++) { 44 | fds[i].events = POLLIN | POLLPRI | POLLHUP; 45 | fds[i].revents = 0; 46 | } 47 | 48 | ret = poll(fds, nfds, -1); 49 | if (ret <= 0) 50 | break; 51 | 52 | if (fds[0].revents & POLLIN) { 53 | ret = kdbus_msg_recv(env->conn, NULL, NULL); 54 | ASSERT_RETURN(ret == 0); 55 | } 56 | 57 | /* stdin */ 58 | if (fds[1].revents & POLLIN) 59 | break; 60 | } 61 | 62 | printf("Closing bus connection\n"); 63 | 64 | return TEST_OK; 65 | } 66 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-endpoint.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "kdbus-api.h" 16 | #include "kdbus-util.h" 17 | #include "kdbus-enum.h" 18 | #include "kdbus-test.h" 19 | 20 | #define KDBUS_SYSNAME_MAX_LEN 63 21 | 22 | static int install_name_add_match(struct kdbus_conn *conn, const char *name) 23 | { 24 | struct { 25 | struct kdbus_cmd_match cmd; 26 | struct { 27 | uint64_t size; 28 | uint64_t type; 29 | struct kdbus_notify_name_change chg; 30 | } item; 31 | char name[64]; 32 | } buf; 33 | int ret; 34 | 35 | /* install the match rule */ 36 | memset(&buf, 0, sizeof(buf)); 37 | buf.item.type = KDBUS_ITEM_NAME_ADD; 38 | buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY; 39 | buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY; 40 | strncpy(buf.name, name, sizeof(buf.name) - 1); 41 | buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1; 42 | buf.cmd.size = sizeof(buf.cmd) + buf.item.size; 43 | 44 | ret = kdbus_cmd_match_add(conn->fd, &buf.cmd); 45 | if (ret < 0) 46 | return ret; 47 | 48 | return 0; 49 | } 50 | 51 | static int create_endpoint(const char *buspath, uid_t uid, const char *name, 52 | uint64_t flags) 53 | { 54 | struct { 55 | struct kdbus_cmd cmd; 56 | 57 | /* name item */ 58 | struct { 59 | uint64_t size; 60 | uint64_t type; 61 | /* max should be KDBUS_SYSNAME_MAX_LEN */ 62 | char str[128]; 63 | } name; 64 | } ep_make; 65 | int fd, ret; 66 | 67 | fd = open(buspath, O_RDWR); 68 | if (fd < 0) 69 | return fd; 70 | 71 | memset(&ep_make, 0, sizeof(ep_make)); 72 | 73 | snprintf(ep_make.name.str, 74 | /* Use the KDBUS_SYSNAME_MAX_LEN or sizeof(str) */ 75 | KDBUS_SYSNAME_MAX_LEN > strlen(name) ? 76 | KDBUS_SYSNAME_MAX_LEN : sizeof(ep_make.name.str), 77 | "%u-%s", uid, name); 78 | 79 | ep_make.name.type = KDBUS_ITEM_MAKE_NAME; 80 | ep_make.name.size = KDBUS_ITEM_HEADER_SIZE + 81 | strlen(ep_make.name.str) + 1; 82 | 83 | ep_make.cmd.flags = flags; 84 | ep_make.cmd.size = sizeof(ep_make.cmd) + ep_make.name.size; 85 | 86 | ret = kdbus_cmd_endpoint_make(fd, &ep_make.cmd); 87 | if (ret < 0) { 88 | kdbus_printf("error creating endpoint: %d (%m)\n", ret); 89 | return ret; 90 | } 91 | 92 | return fd; 93 | } 94 | 95 | static int unpriv_test_custom_ep(const char *buspath) 96 | { 97 | int ret, ep_fd1, ep_fd2; 98 | char *ep1, *ep2, *tmp1, *tmp2; 99 | 100 | tmp1 = strdup(buspath); 101 | tmp2 = strdup(buspath); 102 | ASSERT_RETURN(tmp1 && tmp2); 103 | 104 | ret = asprintf(&ep1, "%s/%u-%s", dirname(tmp1), getuid(), "apps1"); 105 | ASSERT_RETURN(ret >= 0); 106 | 107 | ret = asprintf(&ep2, "%s/%u-%s", dirname(tmp2), getuid(), "apps2"); 108 | ASSERT_RETURN(ret >= 0); 109 | 110 | free(tmp1); 111 | free(tmp2); 112 | 113 | /* endpoint only accessible to current uid */ 114 | ep_fd1 = create_endpoint(buspath, getuid(), "apps1", 0); 115 | ASSERT_RETURN(ep_fd1 >= 0); 116 | 117 | /* endpoint world accessible */ 118 | ep_fd2 = create_endpoint(buspath, getuid(), "apps2", 119 | KDBUS_MAKE_ACCESS_WORLD); 120 | ASSERT_RETURN(ep_fd2 >= 0); 121 | 122 | ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ 123 | int ep_fd; 124 | struct kdbus_conn *ep_conn; 125 | 126 | /* 127 | * Make sure that we are not able to create custom 128 | * endpoints 129 | */ 130 | ep_fd = create_endpoint(buspath, getuid(), 131 | "unpriv_costum_ep", 0); 132 | ASSERT_EXIT(ep_fd == -EPERM); 133 | 134 | /* 135 | * Endpoint "apps1" only accessible to same users, 136 | * that own the endpoint. Access denied by VFS 137 | */ 138 | ep_conn = kdbus_hello(ep1, 0, NULL, 0); 139 | ASSERT_EXIT(!ep_conn && errno == EACCES); 140 | 141 | /* Endpoint "apps2" world accessible */ 142 | ep_conn = kdbus_hello(ep2, 0, NULL, 0); 143 | ASSERT_EXIT(ep_conn); 144 | 145 | kdbus_conn_free(ep_conn); 146 | 147 | _exit(EXIT_SUCCESS); 148 | }), 149 | ({ 0; })); 150 | ASSERT_RETURN(ret == 0); 151 | 152 | close(ep_fd1); 153 | close(ep_fd2); 154 | free(ep1); 155 | free(ep2); 156 | 157 | return 0; 158 | } 159 | 160 | static int update_endpoint(int fd, const char *name) 161 | { 162 | int len = strlen(name) + 1; 163 | struct { 164 | struct kdbus_cmd cmd; 165 | 166 | /* name item */ 167 | struct { 168 | uint64_t size; 169 | uint64_t type; 170 | char str[KDBUS_ALIGN8(len)]; 171 | } name; 172 | 173 | struct { 174 | uint64_t size; 175 | uint64_t type; 176 | struct kdbus_policy_access access; 177 | } access; 178 | } ep_update; 179 | int ret; 180 | 181 | memset(&ep_update, 0, sizeof(ep_update)); 182 | 183 | ep_update.name.size = KDBUS_ITEM_HEADER_SIZE + len; 184 | ep_update.name.type = KDBUS_ITEM_NAME; 185 | strncpy(ep_update.name.str, name, sizeof(ep_update.name.str) - 1); 186 | 187 | ep_update.access.size = sizeof(ep_update.access); 188 | ep_update.access.type = KDBUS_ITEM_POLICY_ACCESS; 189 | ep_update.access.access.type = KDBUS_POLICY_ACCESS_WORLD; 190 | ep_update.access.access.access = KDBUS_POLICY_SEE; 191 | 192 | ep_update.cmd.size = sizeof(ep_update); 193 | 194 | ret = kdbus_cmd_endpoint_update(fd, &ep_update.cmd); 195 | if (ret < 0) { 196 | kdbus_printf("error updating endpoint: %d (%m)\n", ret); 197 | return ret; 198 | } 199 | 200 | return 0; 201 | } 202 | 203 | int kdbus_test_custom_endpoint(struct kdbus_test_env *env) 204 | { 205 | char *ep, *tmp; 206 | int ret, ep_fd; 207 | struct kdbus_msg *msg; 208 | struct kdbus_conn *ep_conn; 209 | struct kdbus_conn *reader; 210 | const char *name = "foo.bar.baz"; 211 | const char *epname = "foo"; 212 | char fake_ep[KDBUS_SYSNAME_MAX_LEN + 1] = {'\0'}; 213 | 214 | memset(fake_ep, 'X', sizeof(fake_ep) - 1); 215 | 216 | /* Try to create a custom endpoint with a long name */ 217 | ret = create_endpoint(env->buspath, getuid(), fake_ep, 0); 218 | ASSERT_RETURN(ret == -ENAMETOOLONG); 219 | 220 | /* Try to create a custom endpoint with a different uid */ 221 | ret = create_endpoint(env->buspath, getuid() + 1, "foobar", 0); 222 | ASSERT_RETURN(ret == -EINVAL); 223 | 224 | /* create a custom endpoint, and open a connection on it */ 225 | ep_fd = create_endpoint(env->buspath, getuid(), "foo", 0); 226 | ASSERT_RETURN(ep_fd >= 0); 227 | 228 | tmp = strdup(env->buspath); 229 | ASSERT_RETURN(tmp); 230 | 231 | ret = asprintf(&ep, "%s/%u-%s", dirname(tmp), getuid(), epname); 232 | free(tmp); 233 | ASSERT_RETURN(ret >= 0); 234 | 235 | /* Register a connection that listen to broadcasts */ 236 | reader = kdbus_hello(ep, 0, NULL, 0); 237 | ASSERT_RETURN(reader); 238 | 239 | /* Register to kernel signals */ 240 | ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD, 241 | KDBUS_MATCH_ID_ANY); 242 | ASSERT_RETURN(ret == 0); 243 | 244 | ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE, 245 | KDBUS_MATCH_ID_ANY); 246 | ASSERT_RETURN(ret == 0); 247 | 248 | ret = install_name_add_match(reader, name); 249 | ASSERT_RETURN(ret == 0); 250 | 251 | /* Monitor connections are not supported on custom endpoints */ 252 | ep_conn = kdbus_hello(ep, KDBUS_HELLO_MONITOR, NULL, 0); 253 | ASSERT_RETURN(!ep_conn && errno == EOPNOTSUPP); 254 | 255 | ep_conn = kdbus_hello(ep, 0, NULL, 0); 256 | ASSERT_RETURN(ep_conn); 257 | 258 | /* Check that the reader got the IdAdd notification */ 259 | ret = kdbus_msg_recv(reader, &msg, NULL); 260 | ASSERT_RETURN(ret == 0); 261 | ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD); 262 | ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id); 263 | kdbus_msg_free(msg); 264 | 265 | /* 266 | * Add a name add match on the endpoint connection, acquire name from 267 | * the unfiltered connection, and make sure the filtered connection 268 | * did not get the notification on the name owner change. Also, the 269 | * endpoint connection may not be able to call conn_info, neither on 270 | * the name nor on the ID. 271 | */ 272 | ret = install_name_add_match(ep_conn, name); 273 | ASSERT_RETURN(ret == 0); 274 | 275 | ret = kdbus_name_acquire(env->conn, name, NULL); 276 | ASSERT_RETURN(ret == 0); 277 | 278 | ret = kdbus_msg_recv(ep_conn, NULL, NULL); 279 | ASSERT_RETURN(ret == -EAGAIN); 280 | 281 | ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); 282 | ASSERT_RETURN(ret == -ESRCH); 283 | 284 | ret = kdbus_conn_info(ep_conn, 0, "random.crappy.name", 0, NULL); 285 | ASSERT_RETURN(ret == -ESRCH); 286 | 287 | ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); 288 | ASSERT_RETURN(ret == -ENXIO); 289 | 290 | ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL); 291 | ASSERT_RETURN(ret == -ENXIO); 292 | 293 | /* Check that the reader did not receive the name notification */ 294 | ret = kdbus_msg_recv(reader, NULL, NULL); 295 | ASSERT_RETURN(ret == -EAGAIN); 296 | 297 | /* 298 | * Release the name again, update the custom endpoint policy, 299 | * and try again. This time, the connection on the custom endpoint 300 | * should have gotten it. 301 | */ 302 | ret = kdbus_name_release(env->conn, name); 303 | ASSERT_RETURN(ret == 0); 304 | 305 | /* Check that the reader did not receive the name notification */ 306 | ret = kdbus_msg_recv(reader, NULL, NULL); 307 | ASSERT_RETURN(ret == -EAGAIN); 308 | 309 | ret = update_endpoint(ep_fd, name); 310 | ASSERT_RETURN(ret == 0); 311 | 312 | ret = kdbus_name_acquire(env->conn, name, NULL); 313 | ASSERT_RETURN(ret == 0); 314 | 315 | ret = kdbus_msg_recv(ep_conn, &msg, NULL); 316 | ASSERT_RETURN(ret == 0); 317 | ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD); 318 | ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0); 319 | ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id); 320 | ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); 321 | kdbus_msg_free(msg); 322 | 323 | ret = kdbus_msg_recv(reader, &msg, NULL); 324 | ASSERT_RETURN(ret == 0); 325 | ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0); 326 | 327 | kdbus_msg_free(msg); 328 | 329 | ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL); 330 | ASSERT_RETURN(ret == 0); 331 | 332 | ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL); 333 | ASSERT_RETURN(ret == 0); 334 | 335 | /* If we have privileges test custom endpoints */ 336 | ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); 337 | ASSERT_RETURN(ret >= 0); 338 | 339 | /* 340 | * All uids/gids are mapped and we have the necessary caps 341 | */ 342 | if (ret && all_uids_gids_are_mapped()) { 343 | ret = unpriv_test_custom_ep(env->buspath); 344 | ASSERT_RETURN(ret == 0); 345 | } 346 | 347 | kdbus_conn_free(reader); 348 | kdbus_conn_free(ep_conn); 349 | close(ep_fd); 350 | 351 | return TEST_OK; 352 | } 353 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-free.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | 12 | #include "kdbus-api.h" 13 | #include "kdbus-util.h" 14 | #include "kdbus-enum.h" 15 | #include "kdbus-test.h" 16 | 17 | static int sample_ioctl_call(struct kdbus_test_env *env) 18 | { 19 | int ret; 20 | struct kdbus_cmd_list cmd_list = { 21 | .flags = KDBUS_LIST_QUEUED, 22 | .size = sizeof(cmd_list), 23 | }; 24 | 25 | ret = kdbus_cmd_list(env->conn->fd, &cmd_list); 26 | ASSERT_RETURN(ret == 0); 27 | 28 | /* DON'T FREE THIS SLICE OF MEMORY! */ 29 | 30 | return TEST_OK; 31 | } 32 | 33 | int kdbus_test_free(struct kdbus_test_env *env) 34 | { 35 | int ret; 36 | struct kdbus_cmd_free cmd_free = {}; 37 | 38 | /* free an unallocated buffer */ 39 | cmd_free.size = sizeof(cmd_free); 40 | cmd_free.flags = 0; 41 | cmd_free.offset = 0; 42 | ret = kdbus_cmd_free(env->conn->fd, &cmd_free); 43 | ASSERT_RETURN(ret == -ENXIO); 44 | 45 | /* free a buffer out of the pool's bounds */ 46 | cmd_free.size = sizeof(cmd_free); 47 | cmd_free.offset = POOL_SIZE + 1; 48 | ret = kdbus_cmd_free(env->conn->fd, &cmd_free); 49 | ASSERT_RETURN(ret == -ENXIO); 50 | 51 | /* 52 | * The user application is responsible for freeing the allocated 53 | * memory with the KDBUS_CMD_FREE ioctl, so let's test what happens 54 | * if we forget about it. 55 | */ 56 | 57 | ret = sample_ioctl_call(env); 58 | ASSERT_RETURN(ret == 0); 59 | 60 | ret = sample_ioctl_call(env); 61 | ASSERT_RETURN(ret == 0); 62 | 63 | return TEST_OK; 64 | } 65 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-monitor.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | 18 | #include "kdbus-util.h" 19 | #include "kdbus-enum.h" 20 | 21 | #include "kdbus-util.h" 22 | #include "kdbus-enum.h" 23 | #include "kdbus-test.h" 24 | 25 | int kdbus_test_monitor(struct kdbus_test_env *env) 26 | { 27 | struct kdbus_conn *monitor, *conn; 28 | unsigned int cookie = 0xdeadbeef; 29 | struct kdbus_msg *msg; 30 | uint64_t offset = 0; 31 | int ret; 32 | 33 | conn = kdbus_hello(env->buspath, 0, NULL, 0); 34 | ASSERT_RETURN(conn); 35 | 36 | /* add matches to make sure the monitor do not trigger an item add or 37 | * remove on connect and disconnect, respectively. 38 | */ 39 | ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD, 40 | KDBUS_MATCH_ID_ANY); 41 | ASSERT_RETURN(ret == 0); 42 | 43 | ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE, 44 | KDBUS_MATCH_ID_ANY); 45 | ASSERT_RETURN(ret == 0); 46 | 47 | /* register a monitor */ 48 | monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0); 49 | ASSERT_RETURN(monitor); 50 | 51 | /* make sure we did not receive a monitor connect notification */ 52 | ret = kdbus_msg_recv(conn, &msg, &offset); 53 | ASSERT_RETURN(ret == -EAGAIN); 54 | 55 | /* check that a monitor cannot acquire a name */ 56 | ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL); 57 | ASSERT_RETURN(ret == -EOPNOTSUPP); 58 | 59 | ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id); 60 | ASSERT_RETURN(ret == 0); 61 | 62 | /* the recipient should have gotten the message */ 63 | ret = kdbus_msg_recv(conn, &msg, &offset); 64 | ASSERT_RETURN(ret == 0); 65 | ASSERT_RETURN(msg->cookie == cookie); 66 | kdbus_msg_free(msg); 67 | kdbus_free(conn, offset); 68 | 69 | /* and so should the monitor */ 70 | ret = kdbus_msg_recv(monitor, &msg, &offset); 71 | ASSERT_RETURN(ret == 0); 72 | ASSERT_RETURN(msg->cookie == cookie); 73 | 74 | kdbus_msg_free(msg); 75 | kdbus_free(monitor, offset); 76 | 77 | /* Installing matches for monitors must fais must fail */ 78 | ret = kdbus_add_match_empty(monitor); 79 | ASSERT_RETURN(ret == -EOPNOTSUPP); 80 | 81 | cookie++; 82 | ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, 83 | KDBUS_DST_ID_BROADCAST); 84 | ASSERT_RETURN(ret == 0); 85 | 86 | /* The monitor should get the message. */ 87 | ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); 88 | ASSERT_RETURN(ret == 0); 89 | ASSERT_RETURN(msg->cookie == cookie); 90 | 91 | kdbus_msg_free(msg); 92 | kdbus_free(monitor, offset); 93 | 94 | /* 95 | * Since we are the only monitor, update the attach flags 96 | * and tell we are not interessted in attach flags recv 97 | */ 98 | 99 | ret = kdbus_conn_update_attach_flags(monitor, 100 | _KDBUS_ATTACH_ALL, 101 | 0); 102 | ASSERT_RETURN(ret == 0); 103 | 104 | cookie++; 105 | ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, 106 | KDBUS_DST_ID_BROADCAST); 107 | ASSERT_RETURN(ret == 0); 108 | 109 | ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); 110 | ASSERT_RETURN(ret == 0); 111 | ASSERT_RETURN(msg->cookie == cookie); 112 | 113 | ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); 114 | ASSERT_RETURN(ret == 0); 115 | 116 | kdbus_msg_free(msg); 117 | kdbus_free(monitor, offset); 118 | 119 | /* 120 | * Now we are interested in KDBUS_ITEM_TIMESTAMP and 121 | * KDBUS_ITEM_CREDS 122 | */ 123 | ret = kdbus_conn_update_attach_flags(monitor, 124 | _KDBUS_ATTACH_ALL, 125 | KDBUS_ATTACH_TIMESTAMP | 126 | KDBUS_ATTACH_CREDS); 127 | ASSERT_RETURN(ret == 0); 128 | 129 | cookie++; 130 | ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, 131 | KDBUS_DST_ID_BROADCAST); 132 | ASSERT_RETURN(ret == 0); 133 | 134 | ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset); 135 | ASSERT_RETURN(ret == 0); 136 | ASSERT_RETURN(msg->cookie == cookie); 137 | 138 | ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP); 139 | ASSERT_RETURN(ret == 1); 140 | 141 | ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS); 142 | ASSERT_RETURN(ret == 1); 143 | 144 | /* the KDBUS_ITEM_PID_COMM was not requested */ 145 | ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM); 146 | ASSERT_RETURN(ret == 0); 147 | 148 | kdbus_msg_free(msg); 149 | kdbus_free(monitor, offset); 150 | 151 | kdbus_conn_free(monitor); 152 | /* make sure we did not receive a monitor disconnect notification */ 153 | ret = kdbus_msg_recv(conn, &msg, &offset); 154 | ASSERT_RETURN(ret == -EAGAIN); 155 | 156 | kdbus_conn_free(conn); 157 | 158 | /* Make sure that monitor as unprivileged is not allowed */ 159 | ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1); 160 | ASSERT_RETURN(ret >= 0); 161 | 162 | if (ret && all_uids_gids_are_mapped()) { 163 | ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({ 164 | monitor = kdbus_hello(env->buspath, 165 | KDBUS_HELLO_MONITOR, 166 | NULL, 0); 167 | ASSERT_EXIT(!monitor && errno == EPERM); 168 | 169 | _exit(EXIT_SUCCESS); 170 | }), 171 | ({ 0; })); 172 | ASSERT_RETURN(ret == 0); 173 | } 174 | 175 | return TEST_OK; 176 | } 177 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-names.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | 15 | #include "kdbus-api.h" 16 | #include "kdbus-util.h" 17 | #include "kdbus-enum.h" 18 | #include "kdbus-test.h" 19 | 20 | struct test_name { 21 | const char *name; 22 | __u64 owner_id; 23 | __u64 flags; 24 | }; 25 | 26 | static bool conn_test_names(const struct kdbus_conn *conn, 27 | const struct test_name *tests, 28 | unsigned int n_tests) 29 | { 30 | struct kdbus_cmd_list cmd_list = {}; 31 | struct kdbus_info *name, *list; 32 | unsigned int i; 33 | int ret; 34 | 35 | cmd_list.size = sizeof(cmd_list); 36 | cmd_list.flags = KDBUS_LIST_NAMES | 37 | KDBUS_LIST_ACTIVATORS | 38 | KDBUS_LIST_QUEUED; 39 | 40 | ret = kdbus_cmd_list(conn->fd, &cmd_list); 41 | ASSERT_RETURN(ret == 0); 42 | 43 | list = (struct kdbus_info *)(conn->buf + cmd_list.offset); 44 | 45 | for (i = 0; i < n_tests; i++) { 46 | const struct test_name *t = tests + i; 47 | bool found = false; 48 | 49 | KDBUS_FOREACH(name, list, cmd_list.list_size) { 50 | struct kdbus_item *item; 51 | 52 | KDBUS_ITEM_FOREACH(item, name, items) { 53 | if (item->type != KDBUS_ITEM_OWNED_NAME || 54 | strcmp(item->name.name, t->name) != 0) 55 | continue; 56 | 57 | if (t->owner_id == name->id && 58 | t->flags == item->name.flags) { 59 | found = true; 60 | break; 61 | } 62 | } 63 | } 64 | 65 | if (!found) 66 | return false; 67 | } 68 | 69 | return true; 70 | } 71 | 72 | static bool conn_is_name_primary_owner(const struct kdbus_conn *conn, 73 | const char *needle) 74 | { 75 | struct test_name t = { 76 | .name = needle, 77 | .owner_id = conn->id, 78 | .flags = KDBUS_NAME_PRIMARY, 79 | }; 80 | 81 | return conn_test_names(conn, &t, 1); 82 | } 83 | 84 | int kdbus_test_name_basic(struct kdbus_test_env *env) 85 | { 86 | struct kdbus_conn *conn; 87 | char *name, *dot_name, *invalid_name, *wildcard_name; 88 | int ret; 89 | 90 | name = "foo.bla.blaz"; 91 | dot_name = ".bla.blaz"; 92 | invalid_name = "foo"; 93 | wildcard_name = "foo.bla.bl.*"; 94 | 95 | /* create a 2nd connection */ 96 | conn = kdbus_hello(env->buspath, 0, NULL, 0); 97 | ASSERT_RETURN(conn != NULL); 98 | 99 | /* acquire name "foo.bar.xxx" name */ 100 | ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL); 101 | ASSERT_RETURN(ret == 0); 102 | 103 | /* Name is not valid, must fail */ 104 | ret = kdbus_name_acquire(env->conn, dot_name, NULL); 105 | ASSERT_RETURN(ret == -EINVAL); 106 | 107 | ret = kdbus_name_acquire(env->conn, invalid_name, NULL); 108 | ASSERT_RETURN(ret == -EINVAL); 109 | 110 | ret = kdbus_name_acquire(env->conn, wildcard_name, NULL); 111 | ASSERT_RETURN(ret == -EINVAL); 112 | 113 | /* check that we can acquire a name */ 114 | ret = kdbus_name_acquire(env->conn, name, NULL); 115 | ASSERT_RETURN(ret == 0); 116 | 117 | ret = conn_is_name_primary_owner(env->conn, name); 118 | ASSERT_RETURN(ret == true); 119 | 120 | /* ... and release it again */ 121 | ret = kdbus_name_release(env->conn, name); 122 | ASSERT_RETURN(ret == 0); 123 | 124 | ret = conn_is_name_primary_owner(env->conn, name); 125 | ASSERT_RETURN(ret == false); 126 | 127 | /* check that we can't release it again */ 128 | ret = kdbus_name_release(env->conn, name); 129 | ASSERT_RETURN(ret == -ESRCH); 130 | 131 | /* check that we can't release a name that we don't own */ 132 | ret = kdbus_name_release(env->conn, "foo.bar.xxx"); 133 | ASSERT_RETURN(ret == -EADDRINUSE); 134 | 135 | /* Name is not valid, must fail */ 136 | ret = kdbus_name_release(env->conn, dot_name); 137 | ASSERT_RETURN(ret == -ESRCH); 138 | 139 | ret = kdbus_name_release(env->conn, invalid_name); 140 | ASSERT_RETURN(ret == -ESRCH); 141 | 142 | ret = kdbus_name_release(env->conn, wildcard_name); 143 | ASSERT_RETURN(ret == -ESRCH); 144 | 145 | kdbus_conn_free(conn); 146 | 147 | return TEST_OK; 148 | } 149 | 150 | int kdbus_test_name_conflict(struct kdbus_test_env *env) 151 | { 152 | struct kdbus_conn *conn; 153 | char *name; 154 | int ret; 155 | 156 | name = "foo.bla.blaz"; 157 | 158 | /* create a 2nd connection */ 159 | conn = kdbus_hello(env->buspath, 0, NULL, 0); 160 | ASSERT_RETURN(conn != NULL); 161 | 162 | /* allow the new connection to own the same name */ 163 | /* acquire name from the 1st connection */ 164 | ret = kdbus_name_acquire(env->conn, name, NULL); 165 | ASSERT_RETURN(ret == 0); 166 | 167 | ret = conn_is_name_primary_owner(env->conn, name); 168 | ASSERT_RETURN(ret == true); 169 | 170 | /* check that we also can't acquire it again from the 2nd connection */ 171 | ret = kdbus_name_acquire(conn, name, NULL); 172 | ASSERT_RETURN(ret == -EEXIST); 173 | 174 | kdbus_conn_free(conn); 175 | 176 | return TEST_OK; 177 | } 178 | 179 | int kdbus_test_name_queue(struct kdbus_test_env *env) 180 | { 181 | struct kdbus_conn *conn; 182 | struct test_name t[2]; 183 | const char *name; 184 | uint64_t flags; 185 | int ret; 186 | 187 | name = "foo.bla.blaz"; 188 | 189 | flags = 0; 190 | 191 | /* create a 2nd connection */ 192 | conn = kdbus_hello(env->buspath, 0, NULL, 0); 193 | ASSERT_RETURN(conn != NULL); 194 | 195 | /* allow the new connection to own the same name */ 196 | /* acquire name from the 1st connection */ 197 | ret = kdbus_name_acquire(env->conn, name, &flags); 198 | ASSERT_RETURN(ret == 0); 199 | 200 | ret = conn_is_name_primary_owner(env->conn, name); 201 | ASSERT_RETURN(ret == true); 202 | 203 | /* queue the 2nd connection as waiting owner */ 204 | flags = KDBUS_NAME_QUEUE; 205 | ret = kdbus_name_acquire(conn, name, &flags); 206 | ASSERT_RETURN(ret == 0); 207 | ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE); 208 | 209 | t[0].name = name; 210 | t[0].owner_id = env->conn->id; 211 | t[0].flags = KDBUS_NAME_PRIMARY; 212 | t[1].name = name; 213 | t[1].owner_id = conn->id; 214 | t[1].flags = KDBUS_NAME_QUEUE | KDBUS_NAME_IN_QUEUE; 215 | ret = conn_test_names(conn, t, 2); 216 | ASSERT_RETURN(ret == true); 217 | 218 | /* release name from 1st connection */ 219 | ret = kdbus_name_release(env->conn, name); 220 | ASSERT_RETURN(ret == 0); 221 | 222 | /* now the name should be owned by the 2nd connection */ 223 | t[0].name = name; 224 | t[0].owner_id = conn->id; 225 | t[0].flags = KDBUS_NAME_PRIMARY | KDBUS_NAME_QUEUE; 226 | ret = conn_test_names(conn, t, 1); 227 | ASSERT_RETURN(ret == true); 228 | 229 | kdbus_conn_free(conn); 230 | 231 | return TEST_OK; 232 | } 233 | 234 | int kdbus_test_name_takeover(struct kdbus_test_env *env) 235 | { 236 | struct kdbus_conn *conn; 237 | struct test_name t; 238 | const char *name; 239 | uint64_t flags; 240 | int ret; 241 | 242 | name = "foo.bla.blaz"; 243 | 244 | flags = KDBUS_NAME_ALLOW_REPLACEMENT; 245 | 246 | /* create a 2nd connection */ 247 | conn = kdbus_hello(env->buspath, 0, NULL, 0); 248 | ASSERT_RETURN(conn != NULL); 249 | 250 | /* acquire name for 1st connection */ 251 | ret = kdbus_name_acquire(env->conn, name, &flags); 252 | ASSERT_RETURN(ret == 0); 253 | 254 | t.name = name; 255 | t.owner_id = env->conn->id; 256 | t.flags = KDBUS_NAME_ALLOW_REPLACEMENT | KDBUS_NAME_PRIMARY; 257 | ret = conn_test_names(conn, &t, 1); 258 | ASSERT_RETURN(ret == true); 259 | 260 | /* now steal name with 2nd connection */ 261 | flags = KDBUS_NAME_REPLACE_EXISTING; 262 | ret = kdbus_name_acquire(conn, name, &flags); 263 | ASSERT_RETURN(ret == 0); 264 | ASSERT_RETURN(flags & KDBUS_NAME_ACQUIRED); 265 | 266 | ret = conn_is_name_primary_owner(conn, name); 267 | ASSERT_RETURN(ret == true); 268 | 269 | kdbus_conn_free(conn); 270 | 271 | return TEST_OK; 272 | } 273 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-policy.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include "kdbus-test.h" 11 | #include "kdbus-util.h" 12 | #include "kdbus-enum.h" 13 | 14 | int kdbus_test_policy(struct kdbus_test_env *env) 15 | { 16 | struct kdbus_conn *conn_a, *conn_b; 17 | struct kdbus_policy_access access; 18 | int ret; 19 | 20 | /* Invalid name */ 21 | conn_a = kdbus_hello_registrar(env->buspath, ".example.a", 22 | NULL, 0, KDBUS_HELLO_POLICY_HOLDER); 23 | ASSERT_RETURN(conn_a == NULL); 24 | 25 | conn_a = kdbus_hello_registrar(env->buspath, "example", 26 | NULL, 0, KDBUS_HELLO_POLICY_HOLDER); 27 | ASSERT_RETURN(conn_a == NULL); 28 | 29 | conn_a = kdbus_hello_registrar(env->buspath, "com.example.a", 30 | NULL, 0, KDBUS_HELLO_POLICY_HOLDER); 31 | ASSERT_RETURN(conn_a); 32 | 33 | conn_b = kdbus_hello_registrar(env->buspath, "com.example.b", 34 | NULL, 0, KDBUS_HELLO_POLICY_HOLDER); 35 | ASSERT_RETURN(conn_b); 36 | 37 | /* 38 | * Verify there cannot be any duplicate entries, except for specific vs. 39 | * wildcard entries. 40 | */ 41 | 42 | access = (struct kdbus_policy_access){ 43 | .type = KDBUS_POLICY_ACCESS_USER, 44 | .id = geteuid(), 45 | .access = KDBUS_POLICY_SEE, 46 | }; 47 | 48 | ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1); 49 | ASSERT_RETURN(ret == 0); 50 | 51 | ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); 52 | ASSERT_RETURN(ret == -EEXIST); 53 | 54 | ret = kdbus_conn_update_policy(conn_b, "com.example.a.*", &access, 1); 55 | ASSERT_RETURN(ret == 0); 56 | 57 | ret = kdbus_conn_update_policy(conn_a, "com.example.a.*", &access, 1); 58 | ASSERT_RETURN(ret == -EEXIST); 59 | 60 | ret = kdbus_conn_update_policy(conn_a, "com.example.*", &access, 1); 61 | ASSERT_RETURN(ret == 0); 62 | 63 | ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1); 64 | ASSERT_RETURN(ret == 0); 65 | 66 | ret = kdbus_conn_update_policy(conn_b, "com.example.*", &access, 1); 67 | ASSERT_RETURN(ret == -EEXIST); 68 | 69 | /* Invalid name */ 70 | ret = kdbus_conn_update_policy(conn_b, ".example.*", &access, 1); 71 | ASSERT_RETURN(ret == -EINVAL); 72 | 73 | ret = kdbus_conn_update_policy(conn_b, "example", &access, 1); 74 | ASSERT_RETURN(ret == -EINVAL); 75 | 76 | kdbus_conn_free(conn_b); 77 | kdbus_conn_free(conn_a); 78 | 79 | return TEST_OK; 80 | } 81 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-sync.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #include "kdbus-api.h" 18 | #include "kdbus-test.h" 19 | #include "kdbus-util.h" 20 | #include "kdbus-enum.h" 21 | 22 | static struct kdbus_conn *conn_a, *conn_b; 23 | static unsigned int cookie = 0xdeadbeef; 24 | 25 | static void nop_handler(int sig) {} 26 | 27 | static int interrupt_sync(struct kdbus_conn *conn_src, 28 | struct kdbus_conn *conn_dst) 29 | { 30 | pid_t pid; 31 | int ret, status; 32 | struct kdbus_msg *msg = NULL; 33 | struct sigaction sa = { 34 | .sa_handler = nop_handler, 35 | .sa_flags = SA_NOCLDSTOP|SA_RESTART, 36 | }; 37 | 38 | cookie++; 39 | pid = fork(); 40 | ASSERT_RETURN_VAL(pid >= 0, pid); 41 | 42 | if (pid == 0) { 43 | ret = sigaction(SIGINT, &sa, NULL); 44 | ASSERT_EXIT(ret == 0); 45 | 46 | ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, 47 | KDBUS_MSG_EXPECT_REPLY, 48 | 100000000ULL, 0, conn_src->id, -1); 49 | ASSERT_EXIT(ret == -ETIMEDOUT); 50 | 51 | _exit(EXIT_SUCCESS); 52 | } 53 | 54 | ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); 55 | ASSERT_RETURN(ret == 0 && msg->cookie == cookie); 56 | 57 | kdbus_msg_free(msg); 58 | 59 | ret = kill(pid, SIGINT); 60 | ASSERT_RETURN_VAL(ret == 0, ret); 61 | 62 | ret = waitpid(pid, &status, 0); 63 | ASSERT_RETURN_VAL(ret >= 0, ret); 64 | 65 | if (WIFSIGNALED(status)) 66 | return TEST_ERR; 67 | 68 | ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL); 69 | ASSERT_RETURN(ret == -ETIMEDOUT); 70 | 71 | return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; 72 | } 73 | 74 | static int close_epipe_sync(const char *bus) 75 | { 76 | pid_t pid; 77 | int ret, status; 78 | struct kdbus_conn *conn_src; 79 | struct kdbus_conn *conn_dst; 80 | struct kdbus_msg *msg = NULL; 81 | 82 | conn_src = kdbus_hello(bus, 0, NULL, 0); 83 | ASSERT_RETURN(conn_src); 84 | 85 | ret = kdbus_add_match_empty(conn_src); 86 | ASSERT_RETURN(ret == 0); 87 | 88 | conn_dst = kdbus_hello(bus, 0, NULL, 0); 89 | ASSERT_RETURN(conn_dst); 90 | 91 | cookie++; 92 | pid = fork(); 93 | ASSERT_RETURN_VAL(pid >= 0, pid); 94 | 95 | if (pid == 0) { 96 | uint64_t dst_id; 97 | 98 | /* close our reference */ 99 | dst_id = conn_dst->id; 100 | kdbus_conn_free(conn_dst); 101 | 102 | ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); 103 | ASSERT_EXIT(ret == 0 && msg->cookie == cookie); 104 | ASSERT_EXIT(msg->src_id == dst_id); 105 | 106 | cookie++; 107 | ret = kdbus_msg_send_sync(conn_src, NULL, cookie, 108 | KDBUS_MSG_EXPECT_REPLY, 109 | 100000000ULL, 0, dst_id, -1); 110 | ASSERT_EXIT(ret == -EPIPE); 111 | 112 | _exit(EXIT_SUCCESS); 113 | } 114 | 115 | ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0, 116 | KDBUS_DST_ID_BROADCAST); 117 | ASSERT_RETURN(ret == 0); 118 | 119 | cookie++; 120 | ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL); 121 | ASSERT_RETURN(ret == 0 && msg->cookie == cookie); 122 | 123 | kdbus_msg_free(msg); 124 | 125 | /* destroy connection */ 126 | kdbus_conn_free(conn_dst); 127 | kdbus_conn_free(conn_src); 128 | 129 | ret = waitpid(pid, &status, 0); 130 | ASSERT_RETURN_VAL(ret >= 0, ret); 131 | 132 | if (!WIFEXITED(status)) 133 | return TEST_ERR; 134 | 135 | return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; 136 | } 137 | 138 | static int cancel_fd_sync(struct kdbus_conn *conn_src, 139 | struct kdbus_conn *conn_dst) 140 | { 141 | pid_t pid; 142 | int cancel_fd; 143 | int ret, status; 144 | uint64_t counter = 1; 145 | struct kdbus_msg *msg = NULL; 146 | 147 | cancel_fd = eventfd(0, 0); 148 | ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); 149 | 150 | cookie++; 151 | pid = fork(); 152 | ASSERT_RETURN_VAL(pid >= 0, pid); 153 | 154 | if (pid == 0) { 155 | ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, 156 | KDBUS_MSG_EXPECT_REPLY, 157 | 100000000ULL, 0, conn_src->id, 158 | cancel_fd); 159 | ASSERT_EXIT(ret == -ECANCELED); 160 | 161 | _exit(EXIT_SUCCESS); 162 | } 163 | 164 | ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); 165 | ASSERT_RETURN(ret == 0 && msg->cookie == cookie); 166 | 167 | kdbus_msg_free(msg); 168 | 169 | ret = write(cancel_fd, &counter, sizeof(counter)); 170 | ASSERT_RETURN(ret == sizeof(counter)); 171 | 172 | ret = waitpid(pid, &status, 0); 173 | ASSERT_RETURN_VAL(ret >= 0, ret); 174 | 175 | if (WIFSIGNALED(status)) 176 | return TEST_ERR; 177 | 178 | return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR; 179 | } 180 | 181 | static int no_cancel_sync(struct kdbus_conn *conn_src, 182 | struct kdbus_conn *conn_dst) 183 | { 184 | pid_t pid; 185 | int cancel_fd; 186 | int ret, status; 187 | struct kdbus_msg *msg = NULL; 188 | 189 | /* pass eventfd, but never signal it so it shouldn't have any effect */ 190 | 191 | cancel_fd = eventfd(0, 0); 192 | ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd); 193 | 194 | cookie++; 195 | pid = fork(); 196 | ASSERT_RETURN_VAL(pid >= 0, pid); 197 | 198 | if (pid == 0) { 199 | ret = kdbus_msg_send_sync(conn_dst, NULL, cookie, 200 | KDBUS_MSG_EXPECT_REPLY, 201 | 100000000ULL, 0, conn_src->id, 202 | cancel_fd); 203 | ASSERT_EXIT(ret == 0); 204 | 205 | _exit(EXIT_SUCCESS); 206 | } 207 | 208 | ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL); 209 | ASSERT_RETURN_VAL(ret == 0 && msg->cookie == cookie, -1); 210 | 211 | kdbus_msg_free(msg); 212 | 213 | ret = kdbus_msg_send_reply(conn_src, cookie, conn_dst->id); 214 | ASSERT_RETURN_VAL(ret >= 0, ret); 215 | 216 | ret = waitpid(pid, &status, 0); 217 | ASSERT_RETURN_VAL(ret >= 0, ret); 218 | 219 | if (WIFSIGNALED(status)) 220 | return -1; 221 | 222 | return (status == EXIT_SUCCESS) ? 0 : -1; 223 | } 224 | 225 | static void *run_thread_reply(void *data) 226 | { 227 | int ret; 228 | unsigned long status = TEST_OK; 229 | 230 | ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); 231 | if (ret < 0) 232 | goto exit_thread; 233 | 234 | kdbus_printf("Thread received message, sending reply ...\n"); 235 | 236 | /* using an unknown cookie must fail */ 237 | ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id); 238 | if (ret != -EBADSLT) { 239 | status = TEST_ERR; 240 | goto exit_thread; 241 | } 242 | 243 | ret = kdbus_msg_send_reply(conn_a, cookie, conn_b->id); 244 | if (ret != 0) { 245 | status = TEST_ERR; 246 | goto exit_thread; 247 | } 248 | 249 | exit_thread: 250 | pthread_exit(NULL); 251 | return (void *) status; 252 | } 253 | 254 | int kdbus_test_sync_reply(struct kdbus_test_env *env) 255 | { 256 | unsigned long status; 257 | pthread_t thread; 258 | int ret; 259 | 260 | conn_a = kdbus_hello(env->buspath, 0, NULL, 0); 261 | conn_b = kdbus_hello(env->buspath, 0, NULL, 0); 262 | ASSERT_RETURN(conn_a && conn_b); 263 | 264 | pthread_create(&thread, NULL, run_thread_reply, NULL); 265 | 266 | ret = kdbus_msg_send_sync(conn_b, NULL, cookie, 267 | KDBUS_MSG_EXPECT_REPLY, 268 | 5000000000ULL, 0, conn_a->id, -1); 269 | 270 | pthread_join(thread, (void *) &status); 271 | ASSERT_RETURN(status == 0); 272 | ASSERT_RETURN(ret == 0); 273 | 274 | ret = interrupt_sync(conn_a, conn_b); 275 | ASSERT_RETURN(ret == 0); 276 | 277 | ret = close_epipe_sync(env->buspath); 278 | ASSERT_RETURN(ret == 0); 279 | 280 | ret = cancel_fd_sync(conn_a, conn_b); 281 | ASSERT_RETURN(ret == 0); 282 | 283 | ret = no_cancel_sync(conn_a, conn_b); 284 | ASSERT_RETURN(ret == 0); 285 | 286 | kdbus_printf("-- closing bus connections\n"); 287 | 288 | kdbus_conn_free(conn_a); 289 | kdbus_conn_free(conn_b); 290 | 291 | return TEST_OK; 292 | } 293 | 294 | #define BYEBYE_ME ((void*)0L) 295 | #define BYEBYE_THEM ((void*)1L) 296 | 297 | static void *run_thread_byebye(void *data) 298 | { 299 | struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) }; 300 | int ret; 301 | 302 | ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL); 303 | if (ret == 0) { 304 | kdbus_printf("Thread received message, invoking BYEBYE ...\n"); 305 | kdbus_msg_recv(conn_a, NULL, NULL); 306 | if (data == BYEBYE_ME) 307 | kdbus_cmd_byebye(conn_b->fd, &cmd_byebye); 308 | else if (data == BYEBYE_THEM) 309 | kdbus_cmd_byebye(conn_a->fd, &cmd_byebye); 310 | } 311 | 312 | pthread_exit(NULL); 313 | return NULL; 314 | } 315 | 316 | int kdbus_test_sync_byebye(struct kdbus_test_env *env) 317 | { 318 | pthread_t thread; 319 | int ret; 320 | 321 | /* 322 | * This sends a synchronous message to a thread, which waits until it 323 | * received the message and then invokes BYEBYE on the *ORIGINAL* 324 | * connection. That is, on the same connection that synchronously waits 325 | * for an reply. 326 | * This should properly wake the connection up and cause ECONNRESET as 327 | * the connection is disconnected now. 328 | * 329 | * The second time, we do the same but invoke BYEBYE on the *TARGET* 330 | * connection. This should also wake up the synchronous sender as the 331 | * reply cannot be sent by a disconnected target. 332 | */ 333 | 334 | conn_a = kdbus_hello(env->buspath, 0, NULL, 0); 335 | conn_b = kdbus_hello(env->buspath, 0, NULL, 0); 336 | ASSERT_RETURN(conn_a && conn_b); 337 | 338 | pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_ME); 339 | 340 | ret = kdbus_msg_send_sync(conn_b, NULL, cookie, 341 | KDBUS_MSG_EXPECT_REPLY, 342 | 5000000000ULL, 0, conn_a->id, -1); 343 | 344 | ASSERT_RETURN(ret == -ECONNRESET); 345 | 346 | pthread_join(thread, NULL); 347 | 348 | kdbus_conn_free(conn_a); 349 | kdbus_conn_free(conn_b); 350 | 351 | conn_a = kdbus_hello(env->buspath, 0, NULL, 0); 352 | conn_b = kdbus_hello(env->buspath, 0, NULL, 0); 353 | ASSERT_RETURN(conn_a && conn_b); 354 | 355 | pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_THEM); 356 | 357 | ret = kdbus_msg_send_sync(conn_b, NULL, cookie, 358 | KDBUS_MSG_EXPECT_REPLY, 359 | 5000000000ULL, 0, conn_a->id, -1); 360 | 361 | ASSERT_RETURN(ret == -EPIPE); 362 | 363 | pthread_join(thread, NULL); 364 | 365 | kdbus_conn_free(conn_a); 366 | kdbus_conn_free(conn_b); 367 | 368 | return TEST_OK; 369 | } 370 | -------------------------------------------------------------------------------- /tools/testing/selftests/kdbus/test-timeout.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | 14 | #include "kdbus-api.h" 15 | #include "kdbus-test.h" 16 | #include "kdbus-util.h" 17 | #include "kdbus-enum.h" 18 | 19 | int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected) 20 | { 21 | struct kdbus_cmd_recv recv = { .size = sizeof(recv) }; 22 | struct kdbus_msg *msg; 23 | int ret; 24 | 25 | ret = kdbus_cmd_recv(conn->fd, &recv); 26 | if (ret < 0) { 27 | kdbus_printf("error receiving message: %d (%m)\n", ret); 28 | return ret; 29 | } 30 | 31 | msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset); 32 | 33 | ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL); 34 | ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL); 35 | ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL); 36 | 37 | *expected &= ~(1ULL << msg->cookie_reply); 38 | kdbus_printf("Got message timeout for cookie %llu\n", 39 | msg->cookie_reply); 40 | 41 | ret = kdbus_free(conn, recv.msg.offset); 42 | if (ret < 0) 43 | return ret; 44 | 45 | return 0; 46 | } 47 | 48 | int kdbus_test_timeout(struct kdbus_test_env *env) 49 | { 50 | struct kdbus_conn *conn_a, *conn_b; 51 | struct pollfd fd; 52 | int ret, i, n_msgs = 4; 53 | uint64_t expected = 0; 54 | uint64_t cookie = 0xdeadbeef; 55 | 56 | conn_a = kdbus_hello(env->buspath, 0, NULL, 0); 57 | conn_b = kdbus_hello(env->buspath, 0, NULL, 0); 58 | ASSERT_RETURN(conn_a && conn_b); 59 | 60 | fd.fd = conn_b->fd; 61 | 62 | /* 63 | * send messages that expect a reply (within 100 msec), 64 | * but never answer it. 65 | */ 66 | for (i = 0; i < n_msgs; i++, cookie++) { 67 | kdbus_printf("Sending message with cookie %llu ...\n", 68 | (unsigned long long)cookie); 69 | ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie, 70 | KDBUS_MSG_EXPECT_REPLY, 71 | (i + 1) * 100ULL * 1000000ULL, 0, 72 | conn_a->id) == 0); 73 | expected |= 1ULL << cookie; 74 | } 75 | 76 | for (;;) { 77 | fd.events = POLLIN | POLLPRI | POLLHUP; 78 | fd.revents = 0; 79 | 80 | ret = poll(&fd, 1, (n_msgs + 1) * 100); 81 | if (ret == 0) 82 | kdbus_printf("--- timeout\n"); 83 | if (ret <= 0) 84 | break; 85 | 86 | if (fd.revents & POLLIN) 87 | ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected)); 88 | 89 | if (expected == 0) 90 | break; 91 | } 92 | 93 | ASSERT_RETURN(expected == 0); 94 | 95 | kdbus_conn_free(conn_a); 96 | kdbus_conn_free(conn_b); 97 | 98 | return TEST_OK; 99 | } 100 | -------------------------------------------------------------------------------- /tools/testing/selftests/lib.mk: -------------------------------------------------------------------------------- 1 | # This mimics the top-level Makefile. We do it explicitly here so that this 2 | # Makefile can operate with or without the kbuild infrastructure. 3 | CC := $(CROSS_COMPILE)gcc 4 | 5 | define RUN_TESTS 6 | @for TEST in $(TEST_PROGS); do \ 7 | (./$$TEST && echo "selftests: $$TEST [PASS]") || echo "selftests: $$TEST [FAIL]"; \ 8 | done; 9 | endef 10 | 11 | run_tests: all 12 | $(RUN_TESTS) 13 | 14 | define INSTALL_RULE 15 | mkdir -p $(INSTALL_PATH) 16 | install -t $(INSTALL_PATH) $(TEST_PROGS) $(TEST_PROGS_EXTENDED) $(TEST_FILES) 17 | endef 18 | 19 | install: all 20 | ifdef INSTALL_PATH 21 | $(INSTALL_RULE) 22 | else 23 | $(error Error: set INSTALL_PATH to use install) 24 | endif 25 | 26 | define EMIT_TESTS 27 | @for TEST in $(TEST_PROGS); do \ 28 | echo "(./$$TEST && echo \"selftests: $$TEST [PASS]\") || echo \"selftests: $$TEST [FAIL]\""; \ 29 | done; 30 | endef 31 | 32 | emit_tests: 33 | $(EMIT_TESTS) 34 | 35 | .PHONY: run_tests all clean install emit_tests 36 | -------------------------------------------------------------------------------- /usr/include/linux/kdbus.h: -------------------------------------------------------------------------------- 1 | ../../../include/uapi/linux/kdbus.h --------------------------------------------------------------------------------