summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-22 01:12:47 -0300
committerAndré Fabian Silva Delgado <emulatorman@parabola.nu>2016-02-22 01:12:47 -0300
commit6d461a4fe7896faa1aec5a5417888cf179e46b9f (patch)
tree2e0f1a0b7a5418189c8d53592d33a44d0b356fc9
parent5c545e1fb127a4b11ddc5f1a5ed066b853dd1a1a (diff)
Linux-libre 4.4.2-gnupck-4.4.2-gnu
-rw-r--r--Documentation/Makefile2
-rw-r--r--Documentation/filesystems/aufs/README1
-rw-r--r--Documentation/filesystems/aufs/design/01intro.txt2
-rw-r--r--Documentation/filesystems/aufs/design/02struct.txt2
-rw-r--r--Documentation/filesystems/aufs/design/03atomic_open.txt2
-rw-r--r--Documentation/filesystems/aufs/design/03lookup.txt2
-rw-r--r--Documentation/filesystems/aufs/design/04branch.txt2
-rw-r--r--Documentation/filesystems/aufs/design/05wbr_policy.txt2
-rw-r--r--Documentation/filesystems/aufs/design/06fhsm.txt2
-rw-r--r--Documentation/filesystems/aufs/design/06mmap.txt2
-rw-r--r--Documentation/filesystems/aufs/design/06xattr.txt2
-rw-r--r--Documentation/filesystems/aufs/design/07export.txt2
-rw-r--r--Documentation/filesystems/aufs/design/08shwh.txt2
-rw-r--r--Documentation/filesystems/aufs/design/10dynop.txt2
-rw-r--r--Documentation/ioctl/ioctl-number.txt1
-rw-r--r--Documentation/kdbus/.gitignore2
-rw-r--r--Documentation/kdbus/Makefile44
-rw-r--r--Documentation/kdbus/kdbus.bus.xml344
-rw-r--r--Documentation/kdbus/kdbus.connection.xml1244
-rw-r--r--Documentation/kdbus/kdbus.endpoint.xml429
-rw-r--r--Documentation/kdbus/kdbus.fs.xml124
-rw-r--r--Documentation/kdbus/kdbus.item.xml839
-rw-r--r--Documentation/kdbus/kdbus.match.xml555
-rw-r--r--Documentation/kdbus/kdbus.message.xml1276
-rw-r--r--Documentation/kdbus/kdbus.name.xml711
-rw-r--r--Documentation/kdbus/kdbus.policy.xml406
-rw-r--r--Documentation/kdbus/kdbus.pool.xml326
-rw-r--r--Documentation/kdbus/kdbus.xml1012
-rw-r--r--Documentation/kdbus/stylesheet.xsl16
-rw-r--r--MAINTAINERS13
-rw-r--r--Makefile3
-rw-r--r--arch/parisc/include/asm/hugetlb.h20
-rw-r--r--arch/parisc/include/uapi/asm/siginfo.h4
-rw-r--r--arch/parisc/mm/hugetlbpage.c60
-rw-r--r--arch/x86/crypto/chacha20-ssse3-x86_64.S6
-rw-r--r--block/blk-merge.c31
-rw-r--r--crypto/af_alg.c55
-rw-r--r--crypto/ahash.c5
-rw-r--r--crypto/algif_hash.c169
-rw-r--r--crypto/algif_skcipher.c252
-rw-r--r--crypto/crc32c_generic.c1
-rw-r--r--crypto/crypto_user.c6
-rw-r--r--crypto/shash.c5
-rw-r--r--crypto/skcipher.c2
-rw-r--r--drivers/ata/ahci.c20
-rw-r--r--drivers/ata/libahci.c4
-rw-r--r--drivers/block/zram/zcomp.c4
-rw-r--r--drivers/block/zram/zcomp_lz4.c23
-rw-r--r--drivers/block/zram/zcomp_lzo.c23
-rw-r--r--drivers/block/zram/zram_drv.c7
-rw-r--r--drivers/crypto/atmel-sha.c23
-rw-r--r--drivers/crypto/caam/ctrl.c4
-rw-r--r--drivers/crypto/marvell/cesa.c2
-rw-r--r--drivers/crypto/sunxi-ss/sun4i-ss-core.c2
-rw-r--r--drivers/hid/hid-multitouch.c15
-rw-r--r--drivers/hid/usbhid/hid-core.c4
-rw-r--r--drivers/iommu/io-pgtable-arm.c11
-rw-r--r--drivers/md/md.c28
-rw-r--r--drivers/md/md.h2
-rw-r--r--drivers/md/multipath.c6
-rw-r--r--drivers/md/raid1.c6
-rw-r--r--drivers/md/raid10.c6
-rw-r--r--drivers/media/i2c/ir-kbd-i2c.c1
-rw-r--r--drivers/media/pci/saa7134/saa7134-alsa.c5
-rw-r--r--drivers/mtd/nand/nand_base.c3
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/regd.c2
-rw-r--r--drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c9
-rw-r--r--drivers/net/wireless/ti/wlcore/io.h10
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c10
-rw-r--r--drivers/pci/bus.c6
-rw-r--r--drivers/pci/host/pci-dra7xx.c3
-rw-r--r--drivers/pci/host/pci-exynos.c3
-rw-r--r--drivers/pci/host/pci-imx6.c3
-rw-r--r--drivers/pci/host/pci-tegra.c2
-rw-r--r--drivers/pci/host/pcie-rcar.c6
-rw-r--r--drivers/pci/host/pcie-spear13xx.c3
-rw-r--r--drivers/pci/host/pcie-xilinx.c3
-rw-r--r--drivers/tty/n_tty.c7
-rw-r--r--drivers/tty/tty_io.c44
-rw-r--r--drivers/tty/tty_mutex.c8
-rw-r--r--drivers/usb/class/cdc-acm.c9
-rw-r--r--drivers/usb/class/cdc-acm.h1
-rw-r--r--drivers/usb/core/hub.c8
-rw-r--r--drivers/usb/host/xhci-pci.c52
-rw-r--r--drivers/usb/phy/phy-msm-usb.c37
-rw-r--r--drivers/usb/serial/cp210x.c1
-rw-r--r--drivers/usb/serial/ftdi_sio.c1
-rw-r--r--drivers/usb/serial/ftdi_sio_ids.h1
-rw-r--r--drivers/usb/serial/option.c18
-rw-r--r--drivers/usb/serial/visor.c11
-rw-r--r--fs/aufs/aufs.h2
-rw-r--r--fs/aufs/branch.c2
-rw-r--r--fs/aufs/branch.h2
-rw-r--r--fs/aufs/cpup.c20
-rw-r--r--fs/aufs/cpup.h2
-rw-r--r--fs/aufs/dbgaufs.c2
-rw-r--r--fs/aufs/dbgaufs.h2
-rw-r--r--fs/aufs/dcsub.c2
-rw-r--r--fs/aufs/dcsub.h2
-rw-r--r--fs/aufs/debug.c2
-rw-r--r--fs/aufs/debug.h2
-rw-r--r--fs/aufs/dentry.c2
-rw-r--r--fs/aufs/dentry.h2
-rw-r--r--fs/aufs/dinfo.c2
-rw-r--r--fs/aufs/dir.c2
-rw-r--r--fs/aufs/dir.h2
-rw-r--r--fs/aufs/dynop.c2
-rw-r--r--fs/aufs/dynop.h2
-rw-r--r--fs/aufs/export.c2
-rw-r--r--fs/aufs/f_op.c2
-rw-r--r--fs/aufs/fhsm.c2
-rw-r--r--fs/aufs/file.c2
-rw-r--r--fs/aufs/file.h2
-rw-r--r--fs/aufs/finfo.c2
-rw-r--r--fs/aufs/fstype.h3
-rw-r--r--fs/aufs/hfsnotify.c2
-rw-r--r--fs/aufs/hfsplus.c2
-rw-r--r--fs/aufs/hnotify.c2
-rw-r--r--fs/aufs/i_op.c2
-rw-r--r--fs/aufs/i_op_add.c2
-rw-r--r--fs/aufs/i_op_del.c2
-rw-r--r--fs/aufs/i_op_ren.c2
-rw-r--r--fs/aufs/iinfo.c2
-rw-r--r--fs/aufs/inode.c2
-rw-r--r--fs/aufs/inode.h2
-rw-r--r--fs/aufs/ioctl.c2
-rw-r--r--fs/aufs/loop.c2
-rw-r--r--fs/aufs/loop.h2
-rw-r--r--fs/aufs/module.c2
-rw-r--r--fs/aufs/module.h2
-rw-r--r--fs/aufs/mvdown.c2
-rw-r--r--fs/aufs/opts.c2
-rw-r--r--fs/aufs/opts.h2
-rw-r--r--fs/aufs/plink.c2
-rw-r--r--fs/aufs/poll.c2
-rw-r--r--fs/aufs/posix_acl.c2
-rw-r--r--fs/aufs/procfs.c2
-rw-r--r--fs/aufs/rdu.c2
-rw-r--r--fs/aufs/rwsem.h2
-rw-r--r--fs/aufs/sbinfo.c2
-rw-r--r--fs/aufs/spl.h2
-rw-r--r--fs/aufs/super.c2
-rw-r--r--fs/aufs/super.h2
-rw-r--r--fs/aufs/sysaufs.c2
-rw-r--r--fs/aufs/sysaufs.h2
-rw-r--r--fs/aufs/sysfs.c2
-rw-r--r--fs/aufs/sysrq.c2
-rw-r--r--fs/aufs/vdir.c2
-rw-r--r--fs/aufs/vfsub.c2
-rw-r--r--fs/aufs/vfsub.h2
-rw-r--r--fs/aufs/wbr_policy.c2
-rw-r--r--fs/aufs/whout.c2
-rw-r--r--fs/aufs/whout.h2
-rw-r--r--fs/aufs/wkq.c2
-rw-r--r--fs/aufs/wkq.h2
-rw-r--r--fs/aufs/xattr.c2
-rw-r--r--fs/aufs/xino.c2
-rw-r--r--fs/ext4/crypto_key.c4
-rw-r--r--fs/file_table.c2
-rw-r--r--fs/nfs/nfs4proc.c1
-rw-r--r--fs/ocfs2/dlm/dlmmaster.c26
-rw-r--r--fs/ocfs2/dlm/dlmrecovery.c2
-rw-r--r--fs/ocfs2/dlmglue.c6
-rw-r--r--include/crypto/hash.h6
-rw-r--r--include/crypto/if_alg.h11
-rw-r--r--include/crypto/skcipher.h7
-rw-r--r--include/linux/console.h1
-rw-r--r--include/linux/hrtimer.h34
-rw-r--r--include/linux/tty.h1
-rw-r--r--include/sound/rawmidi.h4
-rw-r--r--include/uapi/linux/Kbuild1
-rw-r--r--include/uapi/linux/aufs_type.h2
-rw-r--r--include/uapi/linux/kdbus.h984
-rw-r--r--include/uapi/linux/magic.h2
-rw-r--r--init/Kconfig13
-rw-r--r--ipc/Makefile1
-rw-r--r--ipc/kdbus/Makefile33
-rw-r--r--ipc/kdbus/bus.c514
-rw-r--r--ipc/kdbus/bus.h101
-rw-r--r--ipc/kdbus/connection.c2227
-rw-r--r--ipc/kdbus/connection.h260
-rw-r--r--ipc/kdbus/domain.c296
-rw-r--r--ipc/kdbus/domain.h77
-rw-r--r--ipc/kdbus/endpoint.c303
-rw-r--r--ipc/kdbus/endpoint.h70
-rw-r--r--ipc/kdbus/fs.c508
-rw-r--r--ipc/kdbus/fs.h28
-rw-r--r--ipc/kdbus/handle.c691
-rw-r--r--ipc/kdbus/handle.h103
-rw-r--r--ipc/kdbus/item.c293
-rw-r--r--ipc/kdbus/item.h61
-rw-r--r--ipc/kdbus/limits.h61
-rw-r--r--ipc/kdbus/main.c111
-rw-r--r--ipc/kdbus/match.c546
-rw-r--r--ipc/kdbus/match.h35
-rw-r--r--ipc/kdbus/message.c1040
-rw-r--r--ipc/kdbus/message.h120
-rw-r--r--ipc/kdbus/metadata.c1347
-rw-r--r--ipc/kdbus/metadata.h86
-rw-r--r--ipc/kdbus/names.c854
-rw-r--r--ipc/kdbus/names.h105
-rw-r--r--ipc/kdbus/node.c948
-rw-r--r--ipc/kdbus/node.h87
-rw-r--r--ipc/kdbus/notify.c204
-rw-r--r--ipc/kdbus/notify.h30
-rw-r--r--ipc/kdbus/policy.c489
-rw-r--r--ipc/kdbus/policy.h51
-rw-r--r--ipc/kdbus/pool.c728
-rw-r--r--ipc/kdbus/pool.h46
-rw-r--r--ipc/kdbus/queue.c363
-rw-r--r--ipc/kdbus/queue.h84
-rw-r--r--ipc/kdbus/reply.c252
-rw-r--r--ipc/kdbus/reply.h68
-rw-r--r--ipc/kdbus/util.c156
-rw-r--r--ipc/kdbus/util.h73
-rw-r--r--kernel/panic.c3
-rw-r--r--kernel/printk/printk.c35
-rw-r--r--kernel/sched/core.c2
-rw-r--r--kernel/task_work.c1
-rw-r--r--kernel/time/hrtimer.c55
-rw-r--r--kernel/time/timer_list.c2
-rw-r--r--kernel/trace/trace.c2
-rw-r--r--kernel/trace/trace_stack.c7
-rw-r--r--lib/libcrc32c.c1
-rw-r--r--mm/backing-dev.c2
-rw-r--r--mm/zsmalloc.c14
-rw-r--r--samples/Kconfig7
-rw-r--r--samples/Makefile4
-rw-r--r--samples/kdbus/.gitignore1
-rw-r--r--samples/kdbus/Makefile9
-rw-r--r--samples/kdbus/kdbus-api.h114
-rw-r--r--samples/kdbus/kdbus-workers.c1346
-rw-r--r--security/integrity/evm/evm_main.c3
-rw-r--r--sound/core/compress_offload.c11
-rw-r--r--sound/core/oss/pcm_oss.c21
-rw-r--r--sound/core/rawmidi.c134
-rw-r--r--sound/core/seq/oss/seq_oss_init.c2
-rw-r--r--sound/core/seq/oss/seq_oss_synth.c2
-rw-r--r--sound/core/seq/seq_clientmgr.c3
-rw-r--r--sound/core/seq/seq_ports.c233
-rw-r--r--sound/core/seq/seq_timer.c87
-rw-r--r--sound/core/seq/seq_virmidi.c23
-rw-r--r--sound/core/timer.c98
-rw-r--r--sound/drivers/dummy.c35
-rw-r--r--sound/firewire/bebob/bebob_stream.c14
-rw-r--r--sound/isa/Kconfig4
-rw-r--r--sound/pci/Kconfig3
-rw-r--r--sound/pci/hda/hda_generic.c91
-rw-r--r--sound/pci/hda/hda_intel.c13
-rw-r--r--sound/pci/hda/hda_jack.c2
-rw-r--r--sound/pci/hda/hda_jack.h2
-rw-r--r--sound/pci/hda/patch_ca0132.c5
-rw-r--r--sound/pci/hda/patch_cirrus.c27
-rw-r--r--sound/pci/hda/patch_hdmi.c5
-rw-r--r--sound/pci/hda/patch_realtek.c85
-rw-r--r--sound/pci/hda/patch_sigmatel.c6
-rw-r--r--sound/soc/codecs/rt5645.c2
-rw-r--r--sound/soc/soc-pcm.c3
-rw-r--r--sound/sparc/Kconfig1
-rw-r--r--sound/usb/midi.c1
-rw-r--r--sound/usb/quirks.c18
-rw-r--r--tools/testing/selftests/Makefile1
-rw-r--r--tools/testing/selftests/kdbus/.gitignore1
-rw-r--r--tools/testing/selftests/kdbus/Makefile49
-rw-r--r--tools/testing/selftests/kdbus/kdbus-enum.c94
-rw-r--r--tools/testing/selftests/kdbus/kdbus-enum.h15
-rw-r--r--tools/testing/selftests/kdbus/kdbus-test.c905
-rw-r--r--tools/testing/selftests/kdbus/kdbus-test.h84
-rw-r--r--tools/testing/selftests/kdbus/kdbus-util.c1612
-rw-r--r--tools/testing/selftests/kdbus/kdbus-util.h218
-rw-r--r--tools/testing/selftests/kdbus/test-activator.c321
-rw-r--r--tools/testing/selftests/kdbus/test-benchmark.c451
-rw-r--r--tools/testing/selftests/kdbus/test-bus.c175
-rw-r--r--tools/testing/selftests/kdbus/test-chat.c124
-rw-r--r--tools/testing/selftests/kdbus/test-connection.c597
-rw-r--r--tools/testing/selftests/kdbus/test-daemon.c65
-rw-r--r--tools/testing/selftests/kdbus/test-endpoint.c352
-rw-r--r--tools/testing/selftests/kdbus/test-fd.c789
-rw-r--r--tools/testing/selftests/kdbus/test-free.c64
-rw-r--r--tools/testing/selftests/kdbus/test-match.c441
-rw-r--r--tools/testing/selftests/kdbus/test-message.c736
-rw-r--r--tools/testing/selftests/kdbus/test-metadata-ns.c500
-rw-r--r--tools/testing/selftests/kdbus/test-monitor.c176
-rw-r--r--tools/testing/selftests/kdbus/test-names.c272
-rw-r--r--tools/testing/selftests/kdbus/test-policy-ns.c632
-rw-r--r--tools/testing/selftests/kdbus/test-policy-priv.c1285
-rw-r--r--tools/testing/selftests/kdbus/test-policy.c80
-rw-r--r--tools/testing/selftests/kdbus/test-sync.c369
-rw-r--r--tools/testing/selftests/kdbus/test-timeout.c99
289 files changed, 1776 insertions, 34425 deletions
diff --git a/Documentation/Makefile b/Documentation/Makefile
index e2127a76b..bc0548201 100644
--- a/Documentation/Makefile
+++ b/Documentation/Makefile
@@ -1,4 +1,4 @@
subdir-y := accounting auxdisplay blackfin connector \
- filesystems filesystems ia64 kdbus laptops mic misc-devices \
+ filesystems filesystems ia64 laptops mic misc-devices \
networking pcmcia prctl ptp spi timers vDSO video4linux \
watchdog
diff --git a/Documentation/filesystems/aufs/README b/Documentation/filesystems/aufs/README
index e827ebfa8..ed1bafe08 100644
--- a/Documentation/filesystems/aufs/README
+++ b/Documentation/filesystems/aufs/README
@@ -371,6 +371,7 @@ Nikolay Pertsev made a donation (2014/5).
James B made a donation (2014/7 and 2015/7).
Stefano Di Biase made a donation (2014/8).
Daniel Epellei made a donation (2015/1).
+OmegaPhil made a donation (2016/1).
Thank you very much.
Donations are always, including future donations, very important and
diff --git a/Documentation/filesystems/aufs/design/01intro.txt b/Documentation/filesystems/aufs/design/01intro.txt
index 02a8c7b66..5d0121439 100644
--- a/Documentation/filesystems/aufs/design/01intro.txt
+++ b/Documentation/filesystems/aufs/design/01intro.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Introduction
----------------------------------------
diff --git a/Documentation/filesystems/aufs/design/02struct.txt b/Documentation/filesystems/aufs/design/02struct.txt
index 1a5e5d03b..783328a75 100644
--- a/Documentation/filesystems/aufs/design/02struct.txt
+++ b/Documentation/filesystems/aufs/design/02struct.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Basic Aufs Internal Structure
diff --git a/Documentation/filesystems/aufs/design/03atomic_open.txt b/Documentation/filesystems/aufs/design/03atomic_open.txt
index d2c983412..741ad6d66 100644
--- a/Documentation/filesystems/aufs/design/03atomic_open.txt
+++ b/Documentation/filesystems/aufs/design/03atomic_open.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2015 Junjiro R. Okajima
+# Copyright (C) 2015-2016 Junjiro R. Okajima
Support for a branch who has its ->atomic_open()
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/03lookup.txt b/Documentation/filesystems/aufs/design/03lookup.txt
index 7adf4cc97..5b6b000b5 100644
--- a/Documentation/filesystems/aufs/design/03lookup.txt
+++ b/Documentation/filesystems/aufs/design/03lookup.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Lookup in a Branch
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/04branch.txt b/Documentation/filesystems/aufs/design/04branch.txt
index 1d11dbebb..e68f4d3df 100644
--- a/Documentation/filesystems/aufs/design/04branch.txt
+++ b/Documentation/filesystems/aufs/design/04branch.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Branch Manipulation
diff --git a/Documentation/filesystems/aufs/design/05wbr_policy.txt b/Documentation/filesystems/aufs/design/05wbr_policy.txt
index 0419a9025..1726d5d06 100644
--- a/Documentation/filesystems/aufs/design/05wbr_policy.txt
+++ b/Documentation/filesystems/aufs/design/05wbr_policy.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Policies to Select One among Multiple Writable Branches
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/06fhsm.txt b/Documentation/filesystems/aufs/design/06fhsm.txt
index 0eb7a8217..84b46dc5b 100644
--- a/Documentation/filesystems/aufs/design/06fhsm.txt
+++ b/Documentation/filesystems/aufs/design/06fhsm.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2011-2015 Junjiro R. Okajima
+# Copyright (C) 2011-2016 Junjiro R. Okajima
File-based Hierarchical Storage Management (FHSM)
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/06mmap.txt b/Documentation/filesystems/aufs/design/06mmap.txt
index f22d2a10c..991c0b1fa 100644
--- a/Documentation/filesystems/aufs/design/06mmap.txt
+++ b/Documentation/filesystems/aufs/design/06mmap.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
mmap(2) -- File Memory Mapping
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/06xattr.txt b/Documentation/filesystems/aufs/design/06xattr.txt
index ec1e68c54..7bfa94f7b 100644
--- a/Documentation/filesystems/aufs/design/06xattr.txt
+++ b/Documentation/filesystems/aufs/design/06xattr.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2014-2015 Junjiro R. Okajima
+# Copyright (C) 2014-2016 Junjiro R. Okajima
Listing XATTR/EA and getting the value
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/07export.txt b/Documentation/filesystems/aufs/design/07export.txt
index 221d70c77..c23930b49 100644
--- a/Documentation/filesystems/aufs/design/07export.txt
+++ b/Documentation/filesystems/aufs/design/07export.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Export Aufs via NFS
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/08shwh.txt b/Documentation/filesystems/aufs/design/08shwh.txt
index 181dc021b..ad58ebe15 100644
--- a/Documentation/filesystems/aufs/design/08shwh.txt
+++ b/Documentation/filesystems/aufs/design/08shwh.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2005-2015 Junjiro R. Okajima
+# Copyright (C) 2005-2016 Junjiro R. Okajima
Show Whiteout Mode (shwh)
----------------------------------------------------------------------
diff --git a/Documentation/filesystems/aufs/design/10dynop.txt b/Documentation/filesystems/aufs/design/10dynop.txt
index 9d502b50a..49afc5899 100644
--- a/Documentation/filesystems/aufs/design/10dynop.txt
+++ b/Documentation/filesystems/aufs/design/10dynop.txt
@@ -1,5 +1,5 @@
-# Copyright (C) 2010-2015 Junjiro R. Okajima
+# Copyright (C) 2010-2016 Junjiro R. Okajima
Dynamically customizable FS operations
----------------------------------------------------------------------
diff --git a/Documentation/ioctl/ioctl-number.txt b/Documentation/ioctl/ioctl-number.txt
index 4838bad42..91261a32a 100644
--- a/Documentation/ioctl/ioctl-number.txt
+++ b/Documentation/ioctl/ioctl-number.txt
@@ -298,7 +298,6 @@ Code Seq#(hex) Include File Comments
0x92 00-0F drivers/usb/mon/mon_bin.c
0x93 60-7F linux/auto_fs.h
0x94 all fs/btrfs/ioctl.h
-0x95 all uapi/linux/kdbus.h kdbus IPC driver
0x97 00-7F fs/ceph/ioctl.h Ceph file system
0x99 00-0F 537-Addinboard driver
<mailto:buk@buks.ipn.de>
diff --git a/Documentation/kdbus/.gitignore b/Documentation/kdbus/.gitignore
deleted file mode 100644
index b4a77ccba..000000000
--- a/Documentation/kdbus/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-*.7
-*.html
diff --git a/Documentation/kdbus/Makefile b/Documentation/kdbus/Makefile
deleted file mode 100644
index 8caffe565..000000000
--- a/Documentation/kdbus/Makefile
+++ /dev/null
@@ -1,44 +0,0 @@
-DOCS := \
- kdbus.xml \
- 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
-
-XMLFILES := $(addprefix $(obj)/,$(DOCS))
-MANFILES := $(patsubst %.xml, %.7, $(XMLFILES))
-HTMLFILES := $(patsubst %.xml, %.html, $(XMLFILES))
-
-XMLTO_ARGS := -m $(srctree)/$(src)/stylesheet.xsl --skip-validation
-
-quiet_cmd_db2man = MAN $@
- cmd_db2man = xmlto man $(XMLTO_ARGS) -o $(obj) $<
-%.7: %.xml
- @(which xmlto > /dev/null 2>&1) || \
- (echo "*** You need to install xmlto ***"; \
- exit 1)
- $(call cmd,db2man)
-
-quiet_cmd_db2html = HTML $@
- cmd_db2html = xmlto html-nochunks $(XMLTO_ARGS) -o $(obj) $<
-%.html: %.xml
- @(which xmlto > /dev/null 2>&1) || \
- (echo "*** You need to install xmlto ***"; \
- exit 1)
- $(call cmd,db2html)
-
-mandocs: $(MANFILES)
-
-htmldocs: $(HTMLFILES)
-
-clean-files := $(MANFILES) $(HTMLFILES)
-
-# we don't support other %docs targets right now
-%docs:
- @true
diff --git a/Documentation/kdbus/kdbus.bus.xml b/Documentation/kdbus/kdbus.bus.xml
deleted file mode 100644
index 83f1198bc..000000000
--- a/Documentation/kdbus/kdbus.bus.xml
+++ /dev/null
@@ -1,344 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.bus">
-
- <refentryinfo>
- <title>kdbus.bus</title>
- <productname>kdbus.bus</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.bus</refname>
- <refpurpose>kdbus bus</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- A bus is a resource that is shared between connections in order to
- transmit messages (see
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>).
- Each bus is independent, and operations on the bus will not have any
- effect on other buses. A bus is a management entity that controls the
- addresses of its connections, their policies and message transactions
- performed via this bus.
- </para>
- <para>
- Each bus is bound to the mount instance it was created on. It has a
- custom name that is unique across all buses of a domain. In
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- a bus is presented as a directory. No operations can be performed on
- the bus itself; instead you need to perform the operations on an endpoint
- associated with the bus. Endpoints are accessible as files underneath the
- bus directory. A default endpoint called <constant>bus</constant> is
- provided on each bus.
- </para>
- <para>
- Bus names may be chosen freely except for one restriction: the name must
- be prefixed with the numeric effective UID of the creator and a dash. This
- is required to avoid namespace clashes between different users. When
- creating a bus, the name that is passed in must be properly formatted, or
- the kernel will refuse creation of the bus. Example:
- <literal>1047-foobar</literal> is an acceptable name for a bus
- registered by a user with UID 1047. However,
- <literal>1024-foobar</literal> is not, and neither is
- <literal>foobar</literal>. The UID must be provided in the
- user-namespace of the bus owner.
- </para>
- <para>
- To create a new bus, you need to open the control file of a domain and
- employ the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl. The control
- file descriptor that was used to issue
- <constant>KDBUS_CMD_BUS_MAKE</constant> must not previously have been
- used for any other control-ioctl and must be kept open for the entire
- life-time of the created bus. Closing it will immediately cleanup the
- entire bus and all its associated resources and endpoints. Every control
- file descriptor can only be used to create a single new bus; from that
- point on, it is not used for any further communication until the final
- <citerefentry>
- <refentrytitle>close</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- .
- </para>
- <para>
- Each bus will generate a random, 128-bit UUID upon creation. This UUID
- will be returned to creators of connections through
- <varname>kdbus_cmd_hello.id128</varname> and can be used to uniquely
- identify buses, even across different machines or containers. The UUID
- will have its variant bits set to <literal>DCE</literal>, and denote
- version 4 (random). For more details on UUIDs, see <ulink
- url="https://en.wikipedia.org/wiki/Universally_unique_identifier">
- the Wikipedia article on UUIDs</ulink>.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Creating buses</title>
- <para>
- To create a new bus, the <constant>KDBUS_CMD_BUS_MAKE</constant>
- command is used. It takes a <type>struct kdbus_cmd</type> argument.
- </para>
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>The flags for creation.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term>
- <listitem>
- <para>Make the bus file group-accessible.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term>
- <listitem>
- <para>Make the bus file world-accessible.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following items (see
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>)
- are expected for <constant>KDBUS_CMD_BUS_MAKE</constant>.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term>
- <listitem>
- <para>
- Contains a null-terminated string that identifies the
- bus. The name must be unique across the kdbus domain and
- must start with the effective UID of the caller, followed by
- a '<literal>-</literal>' (dash). This item is mandatory.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term>
- <listitem>
- <para>
- Bus-wide bloom parameters passed in a
- <type>struct kdbus_bloom_parameter</type>. These settings are
- copied back to new connections verbatim. This item is
- mandatory. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for a more detailed description of this item.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term>
- <listitem>
- <para>
- An optional item that contains a set of attach flags that are
- returned to connections when they query the bus creator
- metadata. If not set, no metadata is returned.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_BUS_MAKE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EBADMSG</constant></term>
- <listitem><para>
- A mandatory item is missing.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The flags supplied in the <constant>struct kdbus_cmd</constant>
- are invalid or the supplied name does not start with the current
- UID and a '<literal>-</literal>' (dash).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EEXIST</constant></term>
- <listitem><para>
- A bus of that name already exists.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ESHUTDOWN</constant></term>
- <listitem><para>
- The kdbus mount instance for the bus was already shut down.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMFILE</constant></term>
- <listitem><para>
- The maximum number of buses for the current user is exhausted.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.connection.xml b/Documentation/kdbus/kdbus.connection.xml
deleted file mode 100644
index 4bb5f30f3..000000000
--- a/Documentation/kdbus/kdbus.connection.xml
+++ /dev/null
@@ -1,1244 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.connection">
-
- <refentryinfo>
- <title>kdbus.connection</title>
- <productname>kdbus.connection</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.connection</refname>
- <refpurpose>kdbus connection</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Connections are identified by their <emphasis>connection ID</emphasis>,
- internally implemented as a <type>uint64_t</type> counter.
- The IDs of every newly created bus start at <constant>1</constant>, and
- every new connection will increment the counter by <constant>1</constant>.
- The IDs are not reused.
- </para>
- <para>
- In higher level tools, the user visible representation of a connection is
- defined by the D-Bus protocol specification as
- <constant>":1.&lt;ID&gt;"</constant>.
- </para>
- <para>
- Messages with a specific <type>uint64_t</type> destination ID are
- directly delivered to the connection with the corresponding ID. Signal
- messages (see
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>)
- may be addressed to the special destination ID
- <constant>KDBUS_DST_ID_BROADCAST</constant> (~0ULL) and will then
- potentially be delivered to all currently active connections on the bus.
- However, in order to receive any signal messages, clients must subscribe
- to them by installing a match (see
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>).
- </para>
- <para>
- Messages synthesized and sent directly by the kernel will carry the
- special source ID <constant>KDBUS_SRC_ID_KERNEL</constant> (0).
- </para>
- <para>
- In addition to the unique <type>uint64_t</type> connection ID,
- established connections can request the ownership of
- <emphasis>well-known names</emphasis>, under which they can be found and
- addressed by other bus clients. A well-known name is associated with one
- and only one connection at a time. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- on name acquisition, the name registry, and the validity of names.
- </para>
- <para>
- Messages can specify the special destination ID
- <constant>KDBUS_DST_ID_NAME</constant> (0) and carry a well-known name
- in the message data. Such a message is delivered to the destination
- connection which owns that well-known name.
- </para>
-
- <programlisting><![CDATA[
- +-------------------------------------------------------------------------+
- | +---------------+ +---------------------------+ |
- | | Connection | | Message | -----------------+ |
- | | :1.22 | --> | src: 22 | | |
- | | | | dst: 25 | | |
- | | | | | | |
- | | | | | | |
- | | | +---------------------------+ | |
- | | | | |
- | | | <--------------------------------------+ | |
- | +---------------+ | | |
- | | | |
- | +---------------+ +---------------------------+ | | |
- | | Connection | | Message | -----+ | |
- | | :1.25 | --> | src: 25 | | |
- | | | | dst: 0xffffffffffffffff | -------------+ | |
- | | | | (KDBUS_DST_ID_BROADCAST) | | | |
- | | | | | ---------+ | | |
- | | | +---------------------------+ | | | |
- | | | | | | |
- | | | <--------------------------------------------------+ |
- | +---------------+ | | |
- | | | |
- | +---------------+ +---------------------------+ | | |
- | | Connection | | Message | --+ | | |
- | | :1.55 | --> | src: 55 | | | | |
- | | | | dst: 0 / org.foo.bar | | | | |
- | | | | | | | | |
- | | | | | | | | |
- | | | +---------------------------+ | | | |
- | | | | | | |
- | | | <------------------------------------------+ | |
- | +---------------+ | | |
- | | | |
- | +---------------+ | | |
- | | Connection | | | |
- | | :1.81 | | | |
- | | org.foo.bar | | | |
- | | | | | |
- | | | | | |
- | | | <-----------------------------------+ | |
- | | | | |
- | | | <----------------------------------------------+ |
- | +---------------+ |
- +-------------------------------------------------------------------------+
- ]]></programlisting>
- </refsect1>
-
- <refsect1>
- <title>Privileged connections</title>
- <para>
- A connection is considered <emphasis>privileged</emphasis> if the user
- it was created by is the same that created the bus, or if the creating
- task had <constant>CAP_IPC_OWNER</constant> set when it called
- <constant>KDBUS_CMD_HELLO</constant> (see below).
- </para>
- <para>
- Privileged connections have permission to employ certain restricted
- functions and commands, which are explained below and in other kdbus
- man-pages.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Activator and policy holder connection</title>
- <para>
- An <emphasis>activator</emphasis> connection is a placeholder for a
- <emphasis>well-known name</emphasis>. Messages sent to such a connection
- can be used to start an implementer connection, which will then get all
- the messages from the activator copied over. An activator connection
- cannot be used to send any message.
- </para>
- <para>
- A <emphasis>policy holder</emphasis> connection only installs a policy
- for one or more names. These policy entries are kept active as long as
- the connection is alive, and are removed once it terminates. Such a
- policy connection type can be used to deploy restrictions for names that
- are not yet active on the bus. A policy holder connection cannot be used
- to send any message.
- </para>
- <para>
- The creation of activator or policy holder connections is restricted to
- privileged users on the bus (see above).
- </para>
- </refsect1>
-
- <refsect1>
- <title>Monitor connections</title>
- <para>
- Monitors are eavesdropping connections that receive all the traffic on the
- bus, but is invisible to other connections. Such connections have all
- properties of any other, regular connection, except for the following
- details:
- </para>
-
- <itemizedlist>
- <listitem><para>
- They will get every message sent over the bus, both unicasts and
- broadcasts.
- </para></listitem>
-
- <listitem><para>
- Installing matches for signal messages is neither necessary
- nor allowed.
- </para></listitem>
-
- <listitem><para>
- They cannot send messages or be directly addressed as receiver.
- </para></listitem>
-
- <listitem><para>
- They cannot own well-known names. Therefore, they also can't operate as
- activators.
- </para></listitem>
-
- <listitem><para>
- Their creation and destruction will not cause
- <constant>KDBUS_ITEM_ID_{ADD,REMOVE}</constant> (see
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>).
- </para></listitem>
-
- <listitem><para>
- They are not listed with their unique name in name registry dumps
- (see <constant>KDBUS_CMD_NAME_LIST</constant> in
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>), so other connections cannot detect the presence of
- a monitor.
- </para></listitem>
- </itemizedlist>
- <para>
- The creation of monitor connections is restricted to privileged users on
- the bus (see above).
- </para>
- </refsect1>
-
- <refsect1>
- <title>Creating connections</title>
- <para>
- A connection to a bus is created by opening an endpoint file (see
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>)
- of a bus and becoming an active client with the
- <constant>KDBUS_CMD_HELLO</constant> ioctl. Every connection has a unique
- identifier on the bus and can address messages to every other connection
- on the same bus by using the peer's connection ID as the destination.
- </para>
- <para>
- The <constant>KDBUS_CMD_HELLO</constant> ioctl takes a <type>struct
- kdbus_cmd_hello</type> as argument.
- </para>
-
- <programlisting>
-struct kdbus_cmd_hello {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 attach_flags_send;
- __u64 attach_flags_recv;
- __u64 bus_flags;
- __u64 id;
- __u64 pool_size;
- __u64 offset;
- __u8 id128[16];
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem>
- <para>Flags to apply to this connection</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_HELLO_ACCEPT_FD</constant></term>
- <listitem>
- <para>
- When this flag is set, the connection can be sent file
- descriptors as message payload of unicast messages. If it's
- not set, an attempt to send file descriptors will result in
- <constant>-ECOMM</constant> on the sender's side.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_HELLO_ACTIVATOR</constant></term>
- <listitem>
- <para>
- Make this connection an activator (see above). With this bit
- set, an item of type <constant>KDBUS_ITEM_NAME</constant> has
- to be attached. This item describes the well-known name this
- connection should be an activator for.
- A connection can not be an activator and a policy holder at
- the same time time, so this bit is not allowed together with
- <constant>KDBUS_HELLO_POLICY_HOLDER</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_HELLO_POLICY_HOLDER</constant></term>
- <listitem>
- <para>
- Make this connection a policy holder (see above). With this
- bit set, an item of type <constant>KDBUS_ITEM_NAME</constant>
- has to be attached. This item describes the well-known name
- this connection should hold a policy for.
- A connection can not be an activator and a policy holder at
- the same time time, so this bit is not allowed together with
- <constant>KDBUS_HELLO_ACTIVATOR</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_HELLO_MONITOR</constant></term>
- <listitem>
- <para>
- Make this connection a monitor connection (see above).
- </para>
- <para>
- This flag can only be set by privileged bus connections. See
- below for more information.
- A connection can not be monitor and an activator or a policy
- holder at the same time time, so this bit is not allowed
- together with <constant>KDBUS_HELLO_ACTIVATOR</constant> or
- <constant>KDBUS_HELLO_POLICY_HOLDER</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>attach_flags_send</varname></term>
- <listitem><para>
- Set the bits for metadata this connection permits to be sent to the
- receiving peer. Only metadata items that are both allowed to be sent
- by the sender and that are requested by the receiver will be attached
- to the message.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>attach_flags_recv</varname></term>
- <listitem><para>
- Request the attachment of metadata for each message received by this
- connection. See
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for information about metadata, and
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- regarding items in general.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>bus_flags</varname></term>
- <listitem><para>
- Upon successful completion of the ioctl, this member will contain the
- flags of the bus it connected to.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- Upon successful completion of the command, this member will contain
- the numerical ID of the new connection.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>pool_size</varname></term>
- <listitem><para>
- The size of the communication pool, in bytes. The pool can be
- accessed by calling
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- on the file descriptor that was used to issue the
- <constant>KDBUS_CMD_HELLO</constant> ioctl.
- The pool size of a connection must be greater than
- <constant>0</constant> and a multiple of
- <constant>PAGE_SIZE</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>offset</varname></term>
- <listitem><para>
- The kernel will return the offset in the pool where returned details
- will be stored. See below.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id128</varname></term>
- <listitem><para>
- Upon successful completion of the ioctl, this member will contain the
- <emphasis>128-bit UUID</emphasis> of the connected bus.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Variable list of items containing optional additional information.
- The following items are currently expected/valid:
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term>
- <listitem>
- <para>
- Contains a string that describes this connection, so it can
- be identified later.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term>
- <listitem>
- <para>
- For activators and policy holders only, combinations of
- these two items describe policy access entries. See
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further details.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CREDS</constant></term>
- <term><constant>KDBUS_ITEM_PIDS</constant></term>
- <term><constant>KDBUS_ITEM_SECLABEL</constant></term>
- <listitem>
- <para>
- Privileged bus users may submit these types in order to
- create connections with faked credentials. This information
- will be returned when peer information is queried by
- <constant>KDBUS_CMD_CONN_INFO</constant>. See below for more
- information on retrieving information on connections.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- At the offset returned in the <varname>offset</varname> field of
- <type>struct kdbus_cmd_hello</type>, the kernel will store items
- of the following types:
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term>
- <listitem>
- <para>
- Bloom filter parameter as defined by the bus creator.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The offset in the pool has to be freed with the
- <constant>KDBUS_CMD_FREE</constant> ioctl. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further information.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Retrieving information on a connection</title>
- <para>
- The <constant>KDBUS_CMD_CONN_INFO</constant> ioctl can be used to
- retrieve credentials and properties of the initial creator of a
- connection. This ioctl uses the following struct.
- </para>
-
- <programlisting>
-struct kdbus_cmd_info {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 id;
- __u64 attach_flags;
- __u64 offset;
- __u64 info_size;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Currently, no flags are supported.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will return <errorcode>0</errorcode>,
- and the <varname>flags</varname> field is set to
- <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- The numerical ID of the connection for which information is to be
- retrieved. If set to a non-zero value, the
- <constant>KDBUS_ITEM_OWNED_NAME</constant> item is ignored.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>attach_flags</varname></term>
- <listitem><para>
- Specifies which metadata items should be attached to the answer. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>offset</varname></term>
- <listitem><para>
- When the ioctl returns, this field will contain the offset of the
- connection information inside the caller's pool. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further information.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>info_size</varname></term>
- <listitem><para>
- The kernel will return the size of the returned information, so
- applications can optionally
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- specific parts of the pool. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further information.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following items are expected for
- <constant>KDBUS_CMD_CONN_INFO</constant>.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term>
- <listitem>
- <para>
- Contains the well-known name of the connection to look up as.
- This item is mandatory if the <varname>id</varname> field is
- set to 0.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- When the ioctl returns, the following struct will be stored in the
- caller's pool at <varname>offset</varname>. The fields in this struct
- are described below.
- </para>
-
- <programlisting>
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- The connection's unique ID.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- The connection's flags as specified when it was created.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Depending on the <varname>flags</varname> field in
- <type>struct kdbus_cmd_info</type>, items of types
- <constant>KDBUS_ITEM_OWNED_NAME</constant> and
- <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant> may follow here.
- <constant>KDBUS_ITEM_NEGOTIATE</constant> is also allowed.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Once the caller is finished with parsing the return buffer, it needs to
- employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in
- order to free the buffer part. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further information.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Getting information about a connection's bus creator</title>
- <para>
- The <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> ioctl takes the same
- struct as <constant>KDBUS_CMD_CONN_INFO</constant>, but is used to
- retrieve information about the creator of the bus the connection is
- attached to. The metadata returned by this call is collected during the
- creation of the bus and is never altered afterwards, so it provides
- pristine information on the task that created the bus, at the moment when
- it did so.
- </para>
- <para>
- In response to this call, a slice in the connection's pool is allocated
- and filled with an object of type <type>struct kdbus_info</type>,
- pointed to by the ioctl's <varname>offset</varname> field.
- </para>
-
- <programlisting>
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- The bus ID.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- The bus flags as specified when it was created.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Metadata information is stored in items here. The item list
- contains a <constant>KDBUS_ITEM_MAKE_NAME</constant> item that
- indicates the bus name of the calling connection.
- <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed to probe
- for known item types.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Once the caller is finished with parsing the return buffer, it needs to
- employ the <constant>KDBUS_CMD_FREE</constant> command for the offset, in
- order to free the buffer part. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further information.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Updating connection details</title>
- <para>
- Some of a connection's details can be updated with the
- <constant>KDBUS_CMD_CONN_UPDATE</constant> ioctl, using the file
- descriptor that was used to create the connection. The update command
- uses the following struct.
- </para>
-
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Currently, no flags are supported.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will return <errorcode>0</errorcode>,
- and the <varname>flags</varname> field is set to
- <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Items to describe the connection details to be updated. The
- following item types are supported.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term>
- <listitem>
- <para>
- Supply a new set of metadata items that this connection
- permits to be sent along with messages.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term>
- <listitem>
- <para>
- Supply a new set of metadata items that this connection
- requests to be attached to each message.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term>
- <listitem>
- <para>
- Policy holder connections may supply a new set of policy
- information with these items. For other connection types,
- <constant>EOPNOTSUPP</constant> is returned in
- <varname>errno</varname>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Termination of connections</title>
- <para>
- A connection can be terminated by simply calling
- <citerefentry>
- <refentrytitle>close</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- on its file descriptor. All pending incoming messages will be discarded,
- and the memory allocated by the pool will be freed.
- </para>
-
- <para>
- An alternative way of closing down a connection is via the
- <constant>KDBUS_CMD_BYEBYE</constant> ioctl. This ioctl will succeed only
- if the message queue of the connection is empty at the time of closing;
- otherwise, the ioctl will fail with <varname>errno</varname> set to
- <constant>EBUSY</constant>. When this ioctl returns
- successfully, the connection has been terminated and won't accept any new
- messages from remote peers. This way, a connection can be terminated
- race-free, without losing any messages. The ioctl takes an argument of
- type <type>struct kdbus_cmd</type>.
- </para>
-
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Currently, no flags are supported.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will fail with
- <varname>errno</varname> set to <constant>EPROTO</constant>, and
- the <varname>flags</varname> field is set to <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following item types are supported.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_HELLO</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EFAULT</constant></term>
- <listitem><para>
- The supplied pool size was 0 or not a multiple of the page size.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The flags supplied in <type>struct kdbus_cmd_hello</type>
- are invalid.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- An illegal combination of
- <constant>KDBUS_HELLO_MONITOR</constant>,
- <constant>KDBUS_HELLO_ACTIVATOR</constant> and
- <constant>KDBUS_HELLO_POLICY_HOLDER</constant> was passed in
- <varname>flags</varname>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- An invalid set of items was supplied.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ECONNREFUSED</constant></term>
- <listitem><para>
- The attach_flags_send field did not satisfy the requirements of
- the bus.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EPERM</constant></term>
- <listitem><para>
- A <constant>KDBUS_ITEM_CREDS</constant> items was supplied, but the
- current user is not privileged.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ESHUTDOWN</constant></term>
- <listitem><para>
- The bus you were trying to connect to has already been shut down.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMFILE</constant></term>
- <listitem><para>
- The maximum number of connections on the bus has been reached.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EOPNOTSUPP</constant></term>
- <listitem><para>
- The endpoint does not support the connection flags supplied in
- <type>struct kdbus_cmd_hello</type>.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_BYEBYE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EALREADY</constant></term>
- <listitem><para>
- The connection has already been shut down.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EBUSY</constant></term>
- <listitem><para>
- There are still messages queued up in the connection's pool.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_CONN_INFO</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Invalid flags, or neither an ID nor a name was provided, or the
- name is invalid.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ESRCH</constant></term>
- <listitem><para>
- Connection lookup by name failed.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ENXIO</constant></term>
- <listitem><para>
- No connection with the provided connection ID found.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_CONN_UPDATE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal flags or items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Wildcards submitted in policy entries, or illegal sequence
- of policy items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EOPNOTSUPP</constant></term>
- <listitem><para>
- Operation not supported by connection.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>E2BIG</constant></term>
- <listitem><para>
- Too many policy items attached.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.endpoint.xml b/Documentation/kdbus/kdbus.endpoint.xml
deleted file mode 100644
index 6632485f3..000000000
--- a/Documentation/kdbus/kdbus.endpoint.xml
+++ /dev/null
@@ -1,429 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.endpoint">
-
- <refentryinfo>
- <title>kdbus.endpoint</title>
- <productname>kdbus.endpoint</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.endpoint</refname>
- <refpurpose>kdbus endpoint</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- Endpoints are entry points to a bus (see
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>).
- By default, each bus has a default
- endpoint called 'bus'. The bus owner has the ability to create custom
- endpoints with specific names, permissions, and policy databases
- (see below). An endpoint is presented as file underneath the directory
- of the parent bus.
- </para>
- <para>
- To create a custom endpoint, open the default endpoint
- (<literal>bus</literal>) and use the
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> ioctl with
- <type>struct kdbus_cmd</type>. Custom endpoints always have a policy
- database that, by default, forbids any operation. You have to explicitly
- install policy entries to allow any operation on this endpoint.
- </para>
- <para>
- Once <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> succeeded, the new
- endpoint will appear in the filesystem
- (<citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>), and the used file descriptor will manage the
- newly created endpoint resource. It cannot be used to manage further
- resources and must be kept open as long as the endpoint is needed. The
- endpoint will be terminated as soon as the file descriptor is closed.
- </para>
- <para>
- Endpoint names may be chosen freely except for one restriction: the name
- must be prefixed with the numeric effective UID of the creator and a dash.
- This is required to avoid namespace clashes between different users. When
- creating an endpoint, the name that is passed in must be properly
- formatted or the kernel will refuse creation of the endpoint. Example:
- <literal>1047-my-endpoint</literal> is an acceptable name for an
- endpoint registered by a user with UID 1047. However,
- <literal>1024-my-endpoint</literal> is not, and neither is
- <literal>my-endpoint</literal>. The UID must be provided in the
- user-namespace of the bus.
- </para>
- <para>
- To create connections to a bus, use <constant>KDBUS_CMD_HELLO</constant>
- on a file descriptor returned by <function>open()</function> on an
- endpoint node. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further details.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Creating custom endpoints</title>
- <para>
- To create a new endpoint, the
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> command is used. Along with
- the endpoint's name, which will be used to expose the endpoint in the
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>,
- the command also optionally takes items to set up the endpoint's
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> takes a
- <type>struct kdbus_cmd</type> argument.
- </para>
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>The flags for creation.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_MAKE_ACCESS_GROUP</constant></term>
- <listitem>
- <para>Make the endpoint file group-accessible.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_MAKE_ACCESS_WORLD</constant></term>
- <listitem>
- <para>Make the endpoint file world-accessible.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following items are expected for
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term>
- <listitem>
- <para>Contains a string to identify the endpoint name.</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term>
- <listitem>
- <para>
- These items are used to set the policy attached to the
- endpoint. For more details on bus and endpoint policies, see
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <varname>EINVAL</varname>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Updating endpoints</title>
- <para>
- To update an existing endpoint, the
- <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> command is used on the file
- descriptor that was used to create the endpoint, using
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. The only relevant detail of
- the endpoint that can be updated is the policy. When the command is
- employed, the policy of the endpoint is <emphasis>replaced</emphasis>
- atomically with the new set of rules.
- The command takes a <type>struct kdbus_cmd</type> argument.
- </para>
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Unused for this command.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will return <errorcode>0</errorcode>,
- and the <varname>flags</varname> field is set to
- <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following items are expected for
- <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant>.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term>
- <listitem>
- <para>
- These items are used to set the policy attached to the
- endpoint. For more details on bus and endpoint policies, see
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- Existing policy is atomically replaced with the new rules
- provided.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> may fail with the
- following errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The flags supplied in the <type>struct kdbus_cmd</type>
- are invalid.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and
- <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EEXIST</constant></term>
- <listitem><para>
- An endpoint of that name already exists.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EPERM</constant></term>
- <listitem><para>
- The calling user is not privileged. See
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for information about privileged users.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> may fail with the
- following errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The flags supplied in <type>struct kdbus_cmd</type>
- are invalid.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal combination of <constant>KDBUS_ITEM_NAME</constant> and
- <constant>KDBUS_ITEM_POLICY_ACCESS</constant> was provided.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.fs.xml b/Documentation/kdbus/kdbus.fs.xml
deleted file mode 100644
index 8c2a90e10..000000000
--- a/Documentation/kdbus/kdbus.fs.xml
+++ /dev/null
@@ -1,124 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus_fs">
-
- <refentryinfo>
- <title>kdbus.fs</title>
- <productname>kdbus.fs</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.fs</refname>
- <refpurpose>kdbus file system</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>File-system Layout</title>
-
- <para>
- The <emphasis>kdbusfs</emphasis> pseudo filesystem provides access to
- kdbus entities, such as <emphasis>buses</emphasis> and
- <emphasis>endpoints</emphasis>. Each time the filesystem is mounted,
- a new, isolated kdbus instance is created, which is independent from the
- other instances.
- </para>
- <para>
- The system-wide standard mount point for <emphasis>kdbusfs</emphasis> is
- <constant>/sys/fs/kdbus</constant>.
- </para>
-
- <para>
- Buses are represented as directories in the file system layout, whereas
- endpoints are exposed as files inside these directories. At the top-level,
- a <emphasis>control</emphasis> node is present, which can be opened to
- create new buses via the <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl.
- Each <emphasis>bus</emphasis> shows a default endpoint called
- <varname>bus</varname>, which can be opened to either create a connection
- with the <constant>KDBUS_CMD_HELLO</constant> ioctl, or to create new
- custom endpoints for the bus with
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry> and
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
-
- <para>Following, you can see an example layout of the
- <emphasis>kdbusfs</emphasis> filesystem:</para>
-
-<programlisting>
- /sys/fs/kdbus/ ; mount-point
- |-- 0-system ; bus directory
- | |-- bus ; default endpoint
- | `-- 1017-custom ; custom endpoint
- |-- 1000-user ; bus directory
- | |-- bus ; default endpoint
- | |-- 1000-service-A ; custom endpoint
- | `-- 1000-service-B ; custom endpoint
- `-- control ; control file
-</programlisting>
- </refsect1>
-
- <refsect1>
- <title>Mounting instances</title>
- <para>
- In order to get a new and separate kdbus environment, a new instance
- of <emphasis>kdbusfs</emphasis> can be mounted like this:
- </para>
-<programlisting>
- # mount -t kdbusfs kdbusfs /tmp/new_kdbus/
-</programlisting>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>mount</refentrytitle>
- <manvolnum>8</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.item.xml b/Documentation/kdbus/kdbus.item.xml
deleted file mode 100644
index ee09dfa44..000000000
--- a/Documentation/kdbus/kdbus.item.xml
+++ /dev/null
@@ -1,839 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus">
-
- <refentryinfo>
- <title>kdbus.item</title>
- <productname>kdbus item</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.item</refname>
- <refpurpose>kdbus item structure, layout and usage</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- To flexibly augment transport structures, data blobs of type
- <type>struct kdbus_item</type> can be attached to the structs passed
- into the ioctls. Some ioctls make items of certain types mandatory,
- others are optional. Items that are unsupported by ioctls they are
- attached to will cause the ioctl to fail with <varname>errno</varname>
- set to <constant>EINVAL</constant>.
- Items are also used for information stored in a connection's
- <emphasis>pool</emphasis>, such as received messages, name lists or
- requested connection or bus owner information. Depending on the type of
- an item, its total size is either fixed or variable.
- </para>
-
- <refsect2>
- <title>Chaining items</title>
- <para>
- Whenever items are used as part of the kdbus kernel API, they are
- embedded in structs that are embedded inside structs that themselves
- include a size field containing the overall size of the structure.
- This allows multiple items to be chained up, and an item iterator
- (see below) is capable of detecting the end of an item chain.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Alignment</title>
- <para>
- The kernel expects all items to be aligned to 8-byte boundaries.
- Unaligned items will cause the ioctl they are used with to fail
- with <varname>errno</varname> set to <constant>EINVAL</constant>.
- An item that has an unaligned size itself hence needs to be padded
- if it is followed by another item.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Iterating items</title>
- <para>
- A simple iterator would iterate over the items until the items have
- reached the embedding structure's overall size. An example
- implementation is shown below.
- </para>
-
- <programlisting><![CDATA[
-#define KDBUS_ALIGN8(val) (((val) + 7) & ~7)
-
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
-
-#define KDBUS_ITEM_FOREACH(item, head, first) \
- for ((item) = (head)->first; \
- ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
- ((uint8_t *)(item) >= (uint8_t *)(head)); \
- (item) = KDBUS_ITEM_NEXT(item))
- ]]></programlisting>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>Item layout</title>
- <para>
- A <type>struct kdbus_item</type> consists of a
- <varname>size</varname> field, describing its overall size, and a
- <varname>type</varname> field, both 64 bit wide. They are followed by
- a union to store information that is specific to the item's type.
- The struct layout is shown below.
- </para>
-
- <programlisting>
-struct kdbus_item {
- __u64 size;
- __u64 type;
- /* item payload - see below */
- union {
- __u8 data[0];
- __u32 data32[0];
- __u64 data64[0];
- char str[0];
-
- __u64 id;
- struct kdbus_vec vec;
- struct kdbus_creds creds;
- struct kdbus_pids pids;
- struct kdbus_audit audit;
- struct kdbus_caps caps;
- struct kdbus_timestamp timestamp;
- struct kdbus_name name;
- struct kdbus_bloom_parameter bloom_parameter;
- struct kdbus_bloom_filter bloom_filter;
- struct kdbus_memfd memfd;
- int fds[0];
- struct kdbus_notify_name_change name_change;
- struct kdbus_notify_id_change id_change;
- struct kdbus_policy_access policy_access;
- };
-};
- </programlisting>
-
- <para>
- <type>struct kdbus_item</type> should never be used to allocate
- an item instance, as its size may grow in future releases of the API.
- Instead, it should be manually assembled by storing the
- <varname>size</varname>, <varname>type</varname> and payload to a
- struct of its own.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Item types</title>
-
- <refsect2>
- <title>Negotiation item</title>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item is attached to any ioctl, programs can
- <emphasis>probe</emphasis> the kernel for known item types.
- The item carries an array of <type>uint64_t</type> values in
- <varname>item.data64</varname>, each set to an item type to
- probe. The kernel will reset each member of this array that is
- not recognized as valid item type to <constant>0</constant>.
- This way, users can negotiate kernel features at start-up to
- keep newer userspace compatible with older kernels. This item
- is never attached by the kernel in response to any command.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>Command specific items</title>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term>
- <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term>
- <listitem><para>
- Messages are directly copied by the sending process into the
- receiver's
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- This way, two peers can exchange data by effectively doing a
- single-copy from one process to another; the kernel will not buffer
- the data anywhere else. <constant>KDBUS_ITEM_PAYLOAD_VEC</constant>
- is used when <emphasis>sending</emphasis> message. The item
- references a memory address when the payload data can be found.
- <constant>KDBUS_ITEM_PAYLOAD_OFF</constant> is used when messages
- are <emphasis>received</emphasis>, and the
- <constant>offset</constant> value describes the offset inside the
- receiving connection's
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- where the message payload can be found. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on passing of payload data along with a
- message.
- <programlisting>
-struct kdbus_vec {
- __u64 size;
- union {
- __u64 address;
- __u64 offset;
- };
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term>
- <listitem><para>
- Transports a file descriptor of a <emphasis>memfd</emphasis> in
- <type>struct kdbus_memfd</type> in <varname>item.memfd</varname>.
- The <varname>size</varname> field has to match the actual size of
- the memfd that was specified when it was created. The
- <varname>start</varname> parameter denotes the offset inside the
- memfd at which the referenced payload starts. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on passing of payload data along with a
- message.
- <programlisting>
-struct kdbus_memfd {
- __u64 start;
- __u64 size;
- int fd;
- __u32 __pad;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_FDS</constant></term>
- <listitem><para>
- Contains an array of <emphasis>file descriptors</emphasis>.
- When used with <constant>KDBUS_CMD_SEND</constant>, the values of
- this array must be filled with valid file descriptor numbers.
- When received as item attached to a message, the array will
- contain the numbers of the installed file descriptors, or
- <constant>-1</constant> in case an error occurred.
- In either case, the number of entries in the array is derived from
- the item's total size. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>Items specific to some commands</title>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term>
- <listitem><para>
- Transports a file descriptor that can be used to cancel a
- synchronous <constant>KDBUS_CMD_SEND</constant> operation by
- writing to it. The file descriptor is stored in
- <varname>item.fd[0]</varname>. The item may only contain one
- file descriptor. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on this item and how to use it.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_PARAMETER</constant></term>
- <listitem><para>
- Contains a set of <emphasis>bloom parameters</emphasis> as
- <type>struct kdbus_bloom_parameter</type> in
- <varname>item.bloom_parameter</varname>.
- The item is passed from userspace to kernel during the
- <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl, and returned
- verbatim when <constant>KDBUS_CMD_HELLO</constant> is called.
- The kernel does not use the bloom parameters, but they need to
- be known by each connection on the bus in order to define the
- bloom filter hash details. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on matching and bloom filters.
- <programlisting>
-struct kdbus_bloom_parameter {
- __u64 size;
- __u64 n_hash;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term>
- <listitem><para>
- Carries a <emphasis>bloom filter</emphasis> as
- <type>struct kdbus_bloom_filter</type> in
- <varname>item.bloom_filter</varname>. It is mandatory to send this
- item attached to a <type>struct kdbus_msg</type>, in case the
- message is a signal. This item is never transported from kernel to
- userspace. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on matching and bloom filters.
- <programlisting>
-struct kdbus_bloom_filter {
- __u64 generation;
- __u64 data[0];
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term>
- <listitem><para>
- Transports a <emphasis>bloom mask</emphasis> as binary data blob
- stored in <varname>item.data</varname>. This item is used to
- describe a match into a connection's match database. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on matching and bloom filters.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_DST_NAME</constant></term>
- <listitem><para>
- Contains a <emphasis>well-known name</emphasis> to send a
- message to, as null-terminated string in
- <varname>item.str</varname>. This item is used with
- <constant>KDBUS_CMD_SEND</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on how to send a message.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_MAKE_NAME</constant></term>
- <listitem><para>
- Contains a <emphasis>bus name</emphasis> or
- <emphasis>endpoint name</emphasis>, stored as null-terminated
- string in <varname>item.str</varname>. This item is sent from
- userspace to kernel when buses or endpoints are created, and
- returned back to userspace when the bus creator information is
- queried. See
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant></term>
- <term><constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant></term>
- <listitem><para>
- Contains a set of <emphasis>attach flags</emphasis> at
- <emphasis>send</emphasis> or <emphasis>receive</emphasis> time. See
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>,
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry> and
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on attach flags.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ID</constant></term>
- <listitem><para>
- Transports a connection's <emphasis>numerical ID</emphasis> of
- a connection as <type>uint64_t</type> value in
- <varname>item.id</varname>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <listitem><para>
- Transports a name associated with the
- <emphasis>name registry</emphasis> as null-terminated string as
- <type>struct kdbus_name</type> in
- <varname>item.name</varname>. The <varname>flags</varname>
- contains the flags of the name. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on how to access the name registry of a bus.
- <programlisting>
-struct kdbus_name {
- __u64 flags;
- char name[0];
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>Items attached by the kernel as metadata</title>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_TIMESTAMP</constant></term>
- <listitem><para>
- Contains both the <emphasis>monotonic</emphasis> and the
- <emphasis>realtime</emphasis> timestamp, taken when the message
- was processed on the kernel side.
- Stored as <type>struct kdbus_timestamp</type> in
- <varname>item.timestamp</varname>.
- <programlisting>
-struct kdbus_timestamp {
- __u64 seqnum;
- __u64 monotonic_ns;
- __u64 realtime_ns;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CREDS</constant></term>
- <listitem><para>
- Contains a set of <emphasis>user</emphasis> and
- <emphasis>group</emphasis> information as 32-bit values, in the
- usual four flavors: real, effective, saved and filesystem related.
- Stored as <type>struct kdbus_creds</type> in
- <varname>item.creds</varname>.
- <programlisting>
-struct kdbus_creds {
- __u32 uid;
- __u32 euid;
- __u32 suid;
- __u32 fsuid;
- __u32 gid;
- __u32 egid;
- __u32 sgid;
- __u32 fsgid;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_PIDS</constant></term>
- <listitem><para>
- Contains the <emphasis>PID</emphasis>, <emphasis>TID</emphasis>
- and <emphasis>parent PID (PPID)</emphasis> of a remote peer.
- Stored as <type>struct kdbus_pids</type> in
- <varname>item.pids</varname>.
- <programlisting>
-struct kdbus_pids {
- __u64 pid;
- __u64 tid;
- __u64 ppid;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_AUXGROUPS</constant></term>
- <listitem><para>
- Contains the <emphasis>auxiliary (supplementary) groups</emphasis>
- a remote peer is a member of, stored as array of
- <type>uint32_t</type> values in <varname>item.data32</varname>.
- The array length can be determined by looking at the item's total
- size, subtracting the size of the header and dividing the
- remainder by <constant>sizeof(uint32_t)</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_OWNED_NAME</constant></term>
- <listitem><para>
- Contains a <emphasis>well-known name</emphasis> currently owned
- by a connection. The name is stored as null-terminated string in
- <varname>item.str</varname>. Its length can also be derived from
- the item's total size.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_TID_COMM</constant> [*]</term>
- <listitem><para>
- Contains the <emphasis>comm</emphasis> string of a task's
- <emphasis>TID</emphasis> (thread ID), stored as null-terminated
- string in <varname>item.str</varname>. Its length can also be
- derived from the item's total size. Receivers of this item should
- not use its contents for any kind of security measures. See below.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_PID_COMM</constant> [*]</term>
- <listitem><para>
- Contains the <emphasis>comm</emphasis> string of a task's
- <emphasis>PID</emphasis> (process ID), stored as null-terminated
- string in <varname>item.str</varname>. Its length can also be
- derived from the item's total size. Receivers of this item should
- not use its contents for any kind of security measures. See below.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_EXE</constant> [*]</term>
- <listitem><para>
- Contains the <emphasis>path to the executable</emphasis> of a task,
- stored as null-terminated string in <varname>item.str</varname>. Its
- length can also be derived from the item's total size. Receivers of
- this item should not use its contents for any kind of security
- measures. See below.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CMDLINE</constant> [*]</term>
- <listitem><para>
- Contains the <emphasis>command line arguments</emphasis> of a
- task, stored as an <emphasis>array</emphasis> of null-terminated
- strings in <varname>item.str</varname>. The total length of all
- strings in the array can be derived from the item's total size.
- Receivers of this item should not use its contents for any kind
- of security measures. See below.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CGROUP</constant></term>
- <listitem><para>
- Contains the <emphasis>cgroup path</emphasis> of a task, stored
- as null-terminated string in <varname>item.str</varname>. Its
- length can also be derived from the item's total size.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CAPS</constant></term>
- <listitem><para>
- Contains sets of <emphasis>capabilities</emphasis>, stored as
- <type>struct kdbus_caps</type> in <varname>item.caps</varname>.
- As the item size may increase in the future, programs should be
- written in a way that it takes
- <varname>item.caps.last_cap</varname> into account, and derive
- the number of sets and rows from the item size and the reported
- number of valid capability bits.
- <programlisting>
-struct kdbus_caps {
- __u32 last_cap;
- __u32 caps[0];
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_SECLABEL</constant></term>
- <listitem><para>
- Contains the <emphasis>LSM label</emphasis> of a task, stored as
- null-terminated string in <varname>item.str</varname>. Its length
- can also be derived from the item's total size.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_AUDIT</constant></term>
- <listitem><para>
- Contains the audit <emphasis>sessionid</emphasis> and
- <emphasis>loginuid</emphasis> of a task, stored as
- <type>struct kdbus_audit</type> in
- <varname>item.audit</varname>.
- <programlisting>
-struct kdbus_audit {
- __u32 sessionid;
- __u32 loginuid;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_CONN_DESCRIPTION</constant></term>
- <listitem><para>
- Contains the <emphasis>connection description</emphasis>, as set
- by <constant>KDBUS_CMD_HELLO</constant> or
- <constant>KDBUS_CMD_CONN_UPDATE</constant>, stored as
- null-terminated string in <varname>item.str</varname>. Its length
- can also be derived from the item's total size.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- All metadata is automatically translated into the
- <emphasis>namespaces</emphasis> of the task that receives them. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para>
-
- <para>
- [*] Note that the content stored in metadata items of type
- <constant>KDBUS_ITEM_TID_COMM</constant>,
- <constant>KDBUS_ITEM_PID_COMM</constant>,
- <constant>KDBUS_ITEM_EXE</constant> and
- <constant>KDBUS_ITEM_CMDLINE</constant>
- can easily be tampered by the sending tasks. Therefore, they should
- <emphasis>not</emphasis> be used for any sort of security relevant
- assumptions. The only reason they are transmitted is to let
- receivers know about details that were set when metadata was
- collected, even though the task they were collected from is not
- active any longer when the items are received.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Items used for policy entries, matches and notifications</title>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_POLICY_ACCESS</constant></term>
- <listitem><para>
- This item describes a <emphasis>policy access</emphasis> entry to
- access the policy database of a
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry> or
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- Please refer to
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on the policy database and how to access it.
- <programlisting>
-struct kdbus_policy_access {
- __u64 type;
- __u64 access;
- __u64 id;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ID_ADD</constant></term>
- <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term>
- <listitem><para>
- This item is sent as attachment to a
- <emphasis>kernel notification</emphasis> and indicates that a
- new connection was created on the bus, or that a connection was
- disconnected, respectively. It stores a
- <type>struct kdbus_notify_id_change</type> in
- <varname>item.id_change</varname>.
- The <varname>id</varname> field contains the numeric ID of the
- connection that was added or removed, and <varname>flags</varname>
- is set to the connection flags, as passed by
- <constant>KDBUS_CMD_HELLO</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on matches and notification messages.
- <programlisting>
-struct kdbus_notify_id_change {
- __u64 id;
- __u64 flags;
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME_ADD</constant></term>
- <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term>
- <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term>
- <listitem><para>
- This item is sent as attachment to a
- <emphasis>kernel notification</emphasis> and indicates that a
- <emphasis>well-known name</emphasis> appeared, disappeared or
- transferred to another owner on the bus. It stores a
- <type>struct kdbus_notify_name_change</type> in
- <varname>item.name_change</varname>.
- <varname>old_id</varname> describes the former owner of the name
- and is set to <constant>0</constant> values in case of
- <constant>KDBUS_ITEM_NAME_ADD</constant>.
- <varname>new_id</varname> describes the new owner of the name and
- is set to <constant>0</constant> values in case of
- <constant>KDBUS_ITEM_NAME_REMOVE</constant>.
- The <varname>name</varname> field contains the well-known name the
- notification is about, as null-terminated string. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on matches and notification messages.
- <programlisting>
-struct kdbus_notify_name_change {
- struct kdbus_notify_id_change old_id;
- struct kdbus_notify_id_change new_id;
- char name[0];
-};
- </programlisting>
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_REPLY_TIMEOUT</constant></term>
- <listitem><para>
- This item is sent as attachment to a
- <emphasis>kernel notification</emphasis>. It informs the receiver
- that an expected reply to a message was not received in time.
- The remote peer ID and the message cookie are stored in the message
- header. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information about messages, timeouts and notifications.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_REPLY_DEAD</constant></term>
- <listitem><para>
- This item is sent as attachment to a
- <emphasis>kernel notification</emphasis>. It informs the receiver
- that a remote connection a reply is expected from was disconnected
- before that reply was sent. The remote peer ID and the message
- cookie are stored in the message header. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information about messages, timeouts and notifications.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>memfd_create</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-
-</refentry>
diff --git a/Documentation/kdbus/kdbus.match.xml b/Documentation/kdbus/kdbus.match.xml
deleted file mode 100644
index ae38e04ab..000000000
--- a/Documentation/kdbus/kdbus.match.xml
+++ /dev/null
@@ -1,555 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.match">
-
- <refentryinfo>
- <title>kdbus.match</title>
- <productname>kdbus.match</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.match</refname>
- <refpurpose>kdbus match</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- kdbus connections can install matches in order to subscribe to signal
- messages sent on the bus. Such signal messages can be either directed
- to a single connection (by setting a specific connection ID in
- <varname>struct kdbus_msg.dst_id</varname> or by sending it to a
- well-known name), or to potentially <emphasis>all</emphasis> currently
- active connections on the bus (by setting
- <varname>struct kdbus_msg.dst_id</varname> to
- <constant>KDBUS_DST_ID_BROADCAST</constant>).
- A signal message always has the <constant>KDBUS_MSG_SIGNAL</constant>
- bit set in the <varname>flags</varname> bitfield.
- Also, signal messages can originate from either the kernel (called
- <emphasis>notifications</emphasis>), or from other bus connections.
- In either case, a bus connection needs to have a suitable
- <emphasis>match</emphasis> installed in order to receive any signal
- message. Without any rules installed in the connection, no signal message
- will be received.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Matches for signal messages from other connections</title>
- <para>
- Matches for messages from other connections (not kernel notifications)
- are implemented as bloom filters (see below). The sender adds certain
- properties of the message as elements to a bloom filter bit field, and
- sends that along with the signal message.
-
- The receiving connection adds the message properties it is interested in
- as elements to a bloom mask bit field, and uploads the mask as match rule,
- possibly along with some other rules to further limit the match.
-
- The kernel will match the signal message's bloom filter against the
- connection's bloom mask (simply by &amp;-ing it), and will decide whether
- the message should be delivered to a connection.
- </para>
- <para>
- The kernel has no notion of any specific properties of the signal message,
- all it sees are the bit fields of the bloom filter and the mask to match
- against. The use of bloom filters allows simple and efficient matching,
- without exposing any message properties or internals to the kernel side.
- Clients need to deal with the fact that they might receive signal messages
- which they did not subscribe to, as the bloom filter might allow
- false-positives to pass the filter.
-
- To allow the future extension of the set of elements in the bloom filter,
- the filter specifies a <emphasis>generation</emphasis> number. A later
- generation must always contain all elements of the set of the previous
- generation, but can add new elements to the set. The match rules mask can
- carry an array with all previous generations of masks individually stored.
- When the filter and mask are matched by the kernel, the mask with the
- closest matching generation is selected as the index into the mask array.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Bloom filters</title>
- <para>
- Bloom filters allow checking whether a given word is present in a
- dictionary. This allows connections to set up a mask for information it
- is interested in, and will be delivered signal messages that have a
- matching filter.
-
- For general information, see
- <ulink url="https://en.wikipedia.org/wiki/Bloom_filter">the Wikipedia
- article on bloom filters</ulink>.
- </para>
- <para>
- The size of the bloom filter is defined per bus when it is created, in
- <varname>kdbus_bloom_parameter.size</varname>. All bloom filters attached
- to signal messages on the bus must match this size, and all bloom filter
- matches uploaded by connections must also match the size, or a multiple
- thereof (see below).
-
- The calculation of the mask has to be done in userspace applications. The
- kernel just checks the bitmasks to decide whether or not to let the
- message pass. All bits in the mask must match the filter in and bit-wise
- <emphasis>AND</emphasis> logic, but the mask may have more bits set than
- the filter. Consequently, false positive matches are expected to happen,
- and programs must deal with that fact by checking the contents of the
- payload again at receive time.
- </para>
- <para>
- Masks are entities that are always passed to the kernel as part of a
- match (with an item of type <constant>KDBUS_ITEM_BLOOM_MASK</constant>),
- and filters can be attached to signals, with an item of type
- <constant>KDBUS_ITEM_BLOOM_FILTER</constant>. For a filter to match, all
- its bits have to be set in the match mask as well.
- </para>
- <para>
- For example, consider a bus that has a bloom size of 8 bytes, and the
- following mask/filter combinations:
- </para>
- <programlisting><![CDATA[
- filter 0x0101010101010101
- mask 0x0101010101010101
- -> matches
-
- filter 0x0303030303030303
- mask 0x0101010101010101
- -> doesn't match
-
- filter 0x0101010101010101
- mask 0x0303030303030303
- -> matches
- ]]></programlisting>
-
- <para>
- Hence, in order to catch all messages, a mask filled with
- <constant>0xff</constant> bytes can be installed as a wildcard match rule.
- </para>
-
- <refsect2>
- <title>Generations</title>
-
- <para>
- Uploaded matches may contain multiple masks, which have to be as large
- as the bloom filter size defined by the bus. Each block of a mask is
- called a <emphasis>generation</emphasis>, starting at index 0.
-
- At match time, when a signal is about to be delivered, a bloom mask
- generation is passed, which denotes which of the bloom masks the filter
- should be matched against. This allows programs to provide backward
- compatible masks at upload time, while older clients can still match
- against older versions of filters.
- </para>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>Matches for kernel notifications</title>
- <para>
- To receive kernel generated notifications (see
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>),
- a connection must install match rules that are different from
- the bloom filter matches described in the section above. They can be
- filtered by the connection ID that caused the notification to be sent, by
- one of the names it currently owns, or by the type of the notification
- (ID/name add/remove/change).
- </para>
- </refsect1>
-
- <refsect1>
- <title>Adding a match</title>
- <para>
- To add a match, the <constant>KDBUS_CMD_MATCH_ADD</constant> ioctl is
- used, which takes a <type>struct kdbus_cmd_match</type> as an argument
- described below.
-
- Note that each of the items attached to this command will internally
- create one match <emphasis>rule</emphasis>, and the collection of them,
- which is submitted as one block via the ioctl, is called a
- <emphasis>match</emphasis>. To allow a message to pass, all rules of a
- match have to be satisfied. Hence, adding more items to the command will
- only narrow the possibility of a match to effectively let the message
- pass, and will decrease the chance that the connection's process will be
- woken up needlessly.
-
- Multiple matches can be installed per connection. As long as one of it has
- a set of rules which allows the message to pass, this one will be
- decisive.
- </para>
-
- <programlisting>
-struct kdbus_cmd_match {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 cookie;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>Flags to control the behavior of the ioctl.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_MATCH_REPLACE</constant></term>
- <listitem>
- <para>Make the endpoint file group-accessible</para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>cookie</varname></term>
- <listitem><para>
- A cookie which identifies the match, so it can be referred to when
- removing it.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Items to define the actual rules of the matches. The following item
- types are expected. Each item will create one new match rule.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_MASK</constant></term>
- <listitem>
- <para>
- An item that carries the bloom filter mask to match against
- in its data field. The payload size must match the bloom
- filter size that was specified when the bus was created.
- See the "Bloom filters" section above for more information on
- bloom filters.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME</constant></term>
- <listitem>
- <para>
- When used as part of kernel notifications, this item specifies
- a name that is acquired, lost or that changed its owner (see
- below). When used as part of a match for user-generated signal
- messages, it specifies a name that the sending connection must
- own at the time of sending the signal.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ID</constant></term>
- <listitem>
- <para>
- Specify a sender connection's ID that will match this rule.
- For kernel notifications, this specifies the ID of a
- connection that was added to or removed from the bus.
- For used-generated signals, it specifies the ID of the
- connection that sent the signal message.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NAME_ADD</constant></term>
- <term><constant>KDBUS_ITEM_NAME_REMOVE</constant></term>
- <term><constant>KDBUS_ITEM_NAME_CHANGE</constant></term>
- <listitem>
- <para>
- These items request delivery of kernel notifications that
- describe a name acquisition, loss, or change. The details
- are stored in the item's
- <varname>kdbus_notify_name_change</varname> member.
- All information specified must be matched in order to make
- the message pass. Use
- <constant>KDBUS_MATCH_ID_ANY</constant> to
- match against any unique connection ID.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_ID_ADD</constant></term>
- <term><constant>KDBUS_ITEM_ID_REMOVE</constant></term>
- <listitem>
- <para>
- These items request delivery of kernel notifications that are
- generated when a connection is created or terminated.
- <type>struct kdbus_notify_id_change</type> is used to
- store the actual match information. This item can be used to
- monitor one particular connection ID, or, when the ID field
- is set to <constant>KDBUS_MATCH_ID_ANY</constant>,
- all of them.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_NEGOTIATE</constant></term>
- <listitem><para>
- With this item, programs can <emphasis>probe</emphasis> the
- kernel for known item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Refer to
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on message types.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Removing a match</title>
- <para>
- Matches can be removed with the
- <constant>KDBUS_CMD_MATCH_REMOVE</constant> ioctl, which takes
- <type>struct kdbus_cmd_match</type> as argument, but its fields
- usage slightly differs compared to that of
- <constant>KDBUS_CMD_MATCH_ADD</constant>.
- </para>
-
- <programlisting>
-struct kdbus_cmd_match {
- __u64 size;
- __u64 cookie;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>cookie</varname></term>
- <listitem><para>
- The cookie of the match, as it was passed when the match was added.
- All matches that have this cookie will be removed.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- No flags are supported for this use case.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will fail with
- <errorcode>-1</errorcode>, <varname>errno</varname> is set to
- <constant>EPROTO</constant>, and the <varname>flags</varname> field
- is set to <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- No items are supported for this use case, but
- <constant>KDBUS_ITEM_NEGOTIATE</constant> is allowed nevertheless.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_MATCH_ADD</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal flags or items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EDOM</constant></term>
- <listitem><para>
- Illegal bloom filter size.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMFILE</constant></term>
- <listitem><para>
- Too many matches for this connection.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_MATCH_REMOVE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal flags.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EBADSLT</constant></term>
- <listitem><para>
- A match entry with the given cookie could not be found.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.message.xml b/Documentation/kdbus/kdbus.message.xml
deleted file mode 100644
index 0115d9d50..000000000
--- a/Documentation/kdbus/kdbus.message.xml
+++ /dev/null
@@ -1,1276 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.message">
-
- <refentryinfo>
- <title>kdbus.message</title>
- <productname>kdbus.message</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.message</refname>
- <refpurpose>kdbus message</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- A kdbus message is used to exchange information between two connections
- on a bus, or to transport notifications from the kernel to one or many
- connections. This document describes the layout of messages, how payload
- is added to them and how they are sent and received.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Message layout</title>
-
- <para>The layout of a message is shown below.</para>
-
- <programlisting>
- +-------------------------------------------------------------------------+
- | Message |
- | +---------------------------------------------------------------------+ |
- | | Header | |
- | | size: overall message size, including the data records | |
- | | destination: connection ID of the receiver | |
- | | source: connection ID of the sender (set by kernel) | |
- | | payload_type: "DBusDBus" textual identifier stored as uint64_t | |
- | +---------------------------------------------------------------------+ |
- | +---------------------------------------------------------------------+ |
- | | Data Record | |
- | | size: overall record size (without padding) | |
- | | type: type of data | |
- | | data: reference to data (address or file descriptor) | |
- | +---------------------------------------------------------------------+ |
- | +---------------------------------------------------------------------+ |
- | | padding bytes to the next 8 byte alignment | |
- | +---------------------------------------------------------------------+ |
- | +---------------------------------------------------------------------+ |
- | | Data Record | |
- | | size: overall record size (without padding) | |
- | | ... | |
- | +---------------------------------------------------------------------+ |
- | +---------------------------------------------------------------------+ |
- | | padding bytes to the next 8 byte alignment | |
- | +---------------------------------------------------------------------+ |
- | +---------------------------------------------------------------------+ |
- | | Data Record | |
- | | size: overall record size | |
- | | ... | |
- | +---------------------------------------------------------------------+ |
- | ... further data records ... |
- +-------------------------------------------------------------------------+
- </programlisting>
- </refsect1>
-
- <refsect1>
- <title>Message payload</title>
-
- <para>
- When connecting to the bus, receivers request a memory pool of a given
- size, large enough to carry all backlog of data enqueued for the
- connection. The pool is internally backed by a shared memory file which
- can be <function>mmap()</function>ed by the receiver. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para>
-
- <para>
- Message payload must be described in items attached to a message when
- it is sent. A receiver can access the payload by looking at the items
- that are attached to a message in its pool. The following items are used.
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term>
- <listitem>
- <para>
- This item references a piece of memory on the sender side which is
- directly copied into the receiver's pool. This way, two peers can
- exchange data by effectively doing a single-copy from one process
- to another; the kernel will not buffer the data anywhere else.
- This item is never found in a message received by a connection.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_OFF</constant></term>
- <listitem>
- <para>
- This item is attached to messages on the receiving side and points
- to a memory area inside the receiver's pool. The
- <varname>offset</varname> variable in the item denotes the memory
- location relative to the message itself.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term>
- <listitem>
- <para>
- Messages can reference <emphasis>memfd</emphasis> files which
- contain the data. memfd files are tmpfs-backed files that allow
- sealing of the content of the file, which prevents all writable
- access to the file content.
- </para>
- <para>
- Only memfds that have
- <constant>(F_SEAL_SHRINK|F_SEAL_GROW|F_SEAL_WRITE|F_SEAL_SEAL)
- </constant>
- set are accepted as payload data, which enforces reliable passing of
- data. The receiver can assume that neither the sender nor anyone
- else can alter the content after the message is sent. If those
- seals are not set on the memfd, the ioctl will fail with
- <errorcode>-1</errorcode>, and <varname>errno</varname> will be
- set to <constant>ETXTBUSY</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_FDS</constant></term>
- <listitem>
- <para>
- Messages can transport regular file descriptors via
- <constant>KDBUS_ITEM_FDS</constant>. This item carries an array
- of <type>int</type> values in <varname>item.fd</varname>. The
- maximum number of file descriptors in the item is
- <constant>253</constant>, and only one item of this type is
- accepted per message. All passed values must be valid file
- descriptors; the open count of each file descriptors is increased
- by installing it to the receiver's task. This item can only be
- used for directed messages, not for broadcasts, and only to
- remote peers that have opted-in for receiving file descriptors
- at connection time (<constant>KDBUS_HELLO_ACCEPT_FD</constant>).
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The sender must not make any assumptions on the type in which data is
- received by the remote peer. The kernel is free to re-pack multiple
- <constant>KDBUS_ITEM_PAYLOAD_VEC</constant> and
- <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> payloads. For instance, the
- kernel may decide to merge multiple <constant>VECs</constant> into a
- single <constant>VEC</constant>, inline <constant>MEMFD</constant>
- payloads into memory, or merge all passed <constant>VECs</constant> into a
- single <constant>MEMFD</constant>. However, the kernel preserves the order
- of passed data. This means that the order of all <constant>VEC</constant>
- and <constant>MEMFD</constant> items is not changed in respect to each
- other. In other words: All passed <constant>VEC</constant> and
- <constant>MEMFD</constant> data payloads are treated as a single stream
- of data that may be received by the remote peer in a different set of
- chunks than it was sent as.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Sending messages</title>
-
- <para>
- Messages are passed to the kernel with the
- <constant>KDBUS_CMD_SEND</constant> ioctl. Depending on the destination
- address of the message, the kernel delivers the message to the specific
- destination connection, or to some subset of all connections on the same
- bus. Sending messages across buses is not possible. Messages are always
- queued in the memory pool of the destination connection (see above).
- </para>
-
- <para>
- The <constant>KDBUS_CMD_SEND</constant> ioctl uses a
- <type>struct kdbus_cmd_send</type> to describe the message
- transfer.
- </para>
- <programlisting>
-struct kdbus_cmd_send {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 msg_address;
- struct kdbus_msg_info reply;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>Flags for message delivery</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_SEND_SYNC_REPLY</constant></term>
- <listitem>
- <para>
- By default, all calls to kdbus are considered asynchronous,
- non-blocking. However, as there are many use cases that need
- to wait for a remote peer to answer a method call, there's a
- way to send a message and wait for a reply in a synchronous
- fashion. This is what the
- <constant>KDBUS_SEND_SYNC_REPLY</constant> controls. The
- <constant>KDBUS_CMD_SEND</constant> ioctl will block until the
- reply has arrived, the timeout limit is reached, in case the
- remote connection was shut down, or if interrupted by a signal
- before any reply; see
- <citerefentry>
- <refentrytitle>signal</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
-
- The offset of the reply message in the sender's pool is stored
- in <varname>reply</varname> when the ioctl has returned without
- error. Hence, there is no need for another
- <constant>KDBUS_CMD_RECV</constant> ioctl or anything else to
- receive the reply.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Request a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will fail with
- <errorcode>-1</errorcode>, <varname>errno</varname>
- is set to <constant>EPROTO</constant>.
- Once the ioctl returned, the <varname>flags</varname>
- field will have all bits set that the kernel recognizes as
- valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>msg_address</varname></term>
- <listitem><para>
- In this field, users have to provide a pointer to a message
- (<type>struct kdbus_msg</type>) to send. See below for a
- detailed description.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>reply</varname></term>
- <listitem><para>
- Only used for synchronous replies. See description of
- <type>struct kdbus_cmd_recv</type> for more details.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- The following items are currently recognized.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_CANCEL_FD</constant></term>
- <listitem>
- <para>
- When this optional item is passed in, and the call is
- executed as SYNC call, the passed in file descriptor can be
- used as alternative cancellation point. The kernel will call
- <citerefentry>
- <refentrytitle>poll</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- on this file descriptor, and once it reports any incoming
- bytes, the blocking send operation will be canceled; the
- blocking, synchronous ioctl call will return
- <errorcode>-1</errorcode>, and <varname>errno</varname> will
- be set to <errorname>ECANCELED</errorname>.
- Any type of file descriptor on which
- <citerefentry>
- <refentrytitle>poll</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- can be called on can be used as payload to this item; for
- example, an eventfd can be used for this purpose, see
- <citerefentry>
- <refentrytitle>eventfd</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>.
- For asynchronous message sending, this item is allowed but
- ignored.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The message referenced by the <varname>msg_address</varname> above has
- the following layout.
- </para>
-
- <programlisting>
-struct kdbus_msg {
- __u64 size;
- __u64 flags;
- __s64 priority;
- __u64 dst_id;
- __u64 src_id;
- __u64 payload_type;
- __u64 cookie;
- __u64 timeout_ns;
- __u64 cookie_reply;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>Flags to describe message details.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_MSG_EXPECT_REPLY</constant></term>
- <listitem>
- <para>
- Expect a reply to this message from the remote peer. With
- this bit set, the timeout_ns field must be set to a non-zero
- number of nanoseconds in which the receiving peer is expected
- to reply. If such a reply is not received in time, the sender
- will be notified with a timeout message (see below). The
- value must be an absolute value, in nanoseconds and based on
- <constant>CLOCK_MONOTONIC</constant>.
- </para><para>
- For a message to be accepted as reply, it must be a direct
- message to the original sender (not a broadcast and not a
- signal message), and its
- <varname>kdbus_msg.cookie_reply</varname> must match the
- previous message's <varname>kdbus_msg.cookie</varname>.
- </para><para>
- Expected replies also temporarily open the policy of the
- sending connection, so the other peer is allowed to respond
- within the given time window.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_MSG_NO_AUTO_START</constant></term>
- <listitem>
- <para>
- By default, when a message is sent to an activator
- connection, the activator is notified and will start an
- implementer. This flag inhibits that behavior. With this bit
- set, and the remote being an activator, the ioctl will fail
- with <varname>errno</varname> set to
- <constant>EADDRNOTAVAIL</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>priority</varname></term>
- <listitem><para>
- The priority of this message. Receiving messages (see below) may
- optionally be constrained to messages of a minimal priority. This
- allows for use cases where timing critical data is interleaved with
- control data on the same connection. If unused, the priority field
- should be set to <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>dst_id</varname></term>
- <listitem><para>
- The numeric ID of the destination connection, or
- <constant>KDBUS_DST_ID_BROADCAST</constant>
- (~0ULL) to address every peer on the bus, or
- <constant>KDBUS_DST_ID_NAME</constant> (0) to look
- it up dynamically from the bus' name registry.
- In the latter case, an item of type
- <constant>KDBUS_ITEM_DST_NAME</constant> is mandatory.
- Also see
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- .
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>src_id</varname></term>
- <listitem><para>
- Upon return of the ioctl, this member will contain the sending
- connection's numerical ID. Should be 0 at send time.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>payload_type</varname></term>
- <listitem><para>
- Type of the payload in the actual data records. Currently, only
- <constant>KDBUS_PAYLOAD_DBUS</constant> is accepted as input value
- of this field. When receiving messages that are generated by the
- kernel (notifications), this field will contain
- <constant>KDBUS_PAYLOAD_KERNEL</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>cookie</varname></term>
- <listitem><para>
- Cookie of this message, for later recognition. Also, when replying
- to a message (see above), the <varname>cookie_reply</varname>
- field must match this value.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>timeout_ns</varname></term>
- <listitem><para>
- If the message sent requires a reply from the remote peer (see above),
- this field contains the timeout in absolute nanoseconds based on
- <constant>CLOCK_MONOTONIC</constant>. Also see
- <citerefentry>
- <refentrytitle>clock_gettime</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>cookie_reply</varname></term>
- <listitem><para>
- If the message sent is a reply to another message, this field must
- match the cookie of the formerly received message.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- A dynamically sized list of items to contain additional information.
- The following items are expected/valid:
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ITEM_PAYLOAD_VEC</constant></term>
- <term><constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant></term>
- <term><constant>KDBUS_ITEM_FDS</constant></term>
- <listitem>
- <para>
- Actual data records containing the payload. See section
- "Message payload".
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_BLOOM_FILTER</constant></term>
- <listitem>
- <para>
- Bloom filter for matches (see below).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ITEM_DST_NAME</constant></term>
- <listitem>
- <para>
- Well-known name to send this message to. Required if
- <varname>dst_id</varname> is set to
- <constant>KDBUS_DST_ID_NAME</constant>.
- If a connection holding the given name can't be found,
- the ioctl will fail with <varname>errno</varname> set to
- <constant>ESRCH</constant> is returned.
- </para>
- <para>
- For messages to a unique name (ID), this item is optional. If
- present, the kernel will make sure the name owner matches the
- given unique name. This allows programs to tie the message
- sending to the condition that a name is currently owned by a
- certain unique name.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The message will be augmented by the requested metadata items when
- queued into the receiver's pool. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on metadata.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Receiving messages</title>
-
- <para>
- Messages are received by the client with the
- <constant>KDBUS_CMD_RECV</constant> ioctl. The endpoint file of the bus
- supports <function>poll()/epoll()/select()</function>; when new messages
- are available on the connection's file descriptor,
- <constant>POLLIN</constant> is reported. For compatibility reasons,
- <constant>POLLOUT</constant> is always reported as well. Note, however,
- that the latter does not guarantee that a message can in fact be sent, as
- this depends on how many pending messages the receiver has in its pool.
- </para>
-
- <para>
- With the <constant>KDBUS_CMD_RECV</constant> ioctl, a
- <type>struct kdbus_cmd_recv</type> is used.
- </para>
-
- <programlisting>
-struct kdbus_cmd_recv {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __s64 priority;
- __u64 dropped_msgs;
- struct kdbus_msg_info msg;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>Flags to control the receive command.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_RECV_PEEK</constant></term>
- <listitem>
- <para>
- Just return the location of the next message. Do not install
- file descriptors or anything else. This is usually used to
- determine the sender of the next queued message.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_RECV_DROP</constant></term>
- <listitem>
- <para>
- Drop the next message without doing anything else with it,
- and free the pool slice. This a short-cut for
- <constant>KDBUS_RECV_PEEK</constant> and
- <constant>KDBUS_CMD_FREE</constant>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_RECV_USE_PRIORITY</constant></term>
- <listitem>
- <para>
- Dequeue the messages ordered by their priority, and filtering
- them with the priority field (see below).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Request a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will fail with
- <errorcode>-1</errorcode>, <varname>errno</varname>
- is set to <constant>EPROTO</constant>.
- Once the ioctl returned, the <varname>flags</varname>
- field will have all bits set that the kernel recognizes as
- valid for this command.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. If the <varname>dropped_msgs</varname>
- field is non-zero, <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant>
- is set. If a file descriptor could not be installed, the
- <constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant> flag is set.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>priority</varname></term>
- <listitem><para>
- With <constant>KDBUS_RECV_USE_PRIORITY</constant> set in
- <varname>flags</varname>, messages will be dequeued ordered by their
- priority, starting with the highest value. Also, messages will be
- filtered by the value given in this field, so the returned message
- will at least have the requested priority. If no such message is
- waiting in the queue, the ioctl will fail, and
- <varname>errno</varname> will be set to <constant>EAGAIN</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>dropped_msgs</varname></term>
- <listitem><para>
- Whenever a message with <constant>KDBUS_MSG_SIGNAL</constant> is sent
- but cannot be queued on a peer (e.g., as it contains FDs but the peer
- does not support FDs, or there is no space left in the peer's pool)
- the 'dropped_msgs' counter of the peer is incremented. On the next
- RECV ioctl, the 'dropped_msgs' field is copied into the ioctl struct
- and cleared on the peer. If it was non-zero, the
- <constant>KDBUS_RECV_RETURN_DROPPED_MSGS</constant> flag will be set
- in <varname>return_flags</varname>. Note that this will only happen
- if the ioctl succeeded or failed with <constant>EAGAIN</constant>. In
- other error cases, the 'dropped_msgs' field of the peer is left
- untouched.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>msg</varname></term>
- <listitem><para>
- Embedded struct containing information on the received message when
- this command succeeded (see below).
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem><para>
- Items to specify further details for the receive command.
- Currently unused, and all items will be rejected with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Both <type>struct kdbus_cmd_recv</type> and
- <type>struct kdbus_cmd_send</type> embed
- <type>struct kdbus_msg_info</type>.
- For the <constant>KDBUS_CMD_SEND</constant> ioctl, it is used to catch
- synchronous replies, if one was requested, and is unused otherwise.
- </para>
-
- <programlisting>
-struct kdbus_msg_info {
- __u64 offset;
- __u64 msg_size;
- __u64 return_flags;
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>offset</varname></term>
- <listitem><para>
- Upon return of the ioctl, this field contains the offset in the
- receiver's memory pool. The memory must be freed with
- <constant>KDBUS_CMD_FREE</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further details.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>msg_size</varname></term>
- <listitem><para>
- Upon successful return of the ioctl, this field contains the size of
- the allocated slice at offset <varname>offset</varname>.
- It is the combination of the size of the stored
- <type>struct kdbus_msg</type> object plus all appended VECs.
- You can use it in combination with <varname>offset</varname> to map
- a single message, instead of mapping the entire pool. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for further details.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem>
- <para>
- Kernel-provided return flags. Currently, the following flags are
- defined.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_RECV_RETURN_INCOMPLETE_FDS</constant></term>
- <listitem>
- <para>
- The message contained memfds or file descriptors, and the
- kernel failed to install one or more of them at receive time.
- Most probably that happened because the maximum number of
- file descriptors for the receiver's task were exceeded.
- In such cases, the message is still delivered, so this is not
- a fatal condition. File descriptors numbers inside the
- <constant>KDBUS_ITEM_FDS</constant> item or memfd files
- referenced by <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant>
- items which could not be installed will be set to
- <constant>-1</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Unless <constant>KDBUS_RECV_DROP</constant> was passed, the
- <varname>offset</varname> field contains the location of the new message
- inside the receiver's pool after the <constant>KDBUS_CMD_RECV</constant>
- ioctl was employed. The message is stored as <type>struct kdbus_msg</type>
- at this offset, and can be interpreted with the semantics described above.
- </para>
- <para>
- Also, if the connection allowed for file descriptor to be passed
- (<constant>KDBUS_HELLO_ACCEPT_FD</constant>), and if the message contained
- any, they will be installed into the receiving process when the
- <constant>KDBUS_CMD_RECV</constant> ioctl is called.
- <emphasis>memfds</emphasis> may always be part of the message payload.
- The receiving task is obliged to close all file descriptors appropriately
- once no longer needed. If <constant>KDBUS_RECV_PEEK</constant> is set, no
- file descriptors are installed. This allows for peeking at a message,
- looking at its metadata only and dropping it via
- <constant>KDBUS_RECV_DROP</constant>, without installing any of the file
- descriptors into the receiving process.
- </para>
- <para>
- The caller is obliged to call the <constant>KDBUS_CMD_FREE</constant>
- ioctl with the returned offset when the memory is no longer needed.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Notifications</title>
- <para>
- A kernel notification is a regular kdbus message with the following
- details.
- </para>
-
- <itemizedlist>
- <listitem><para>
- kdbus_msg.src_id == <constant>KDBUS_SRC_ID_KERNEL</constant>
- </para></listitem>
- <listitem><para>
- kdbus_msg.dst_id == <constant>KDBUS_DST_ID_BROADCAST</constant>
- </para></listitem>
- <listitem><para>
- kdbus_msg.payload_type == <constant>KDBUS_PAYLOAD_KERNEL</constant>
- </para></listitem>
- <listitem><para>
- Has exactly one of the items attached that are described below.
- </para></listitem>
- <listitem><para>
- Always has a timestamp item (<constant>KDBUS_ITEM_TIMESTAMP</constant>)
- attached.
- </para></listitem>
- </itemizedlist>
-
- <para>
- The kernel will notify its users of the following events.
- </para>
-
- <itemizedlist>
- <listitem><para>
- When connection <emphasis>A</emphasis> is terminated while connection
- <emphasis>B</emphasis> is waiting for a reply from it, connection
- <emphasis>B</emphasis> is notified with a message with an item of
- type <constant>KDBUS_ITEM_REPLY_DEAD</constant>.
- </para></listitem>
-
- <listitem><para>
- When connection <emphasis>A</emphasis> does not receive a reply from
- connection <emphasis>B</emphasis> within the specified timeout window,
- connection <emphasis>A</emphasis> will receive a message with an
- item of type <constant>KDBUS_ITEM_REPLY_TIMEOUT</constant>.
- </para></listitem>
-
- <listitem><para>
- When an ordinary connection (not a monitor) is created on or removed
- from a bus, messages with an item of type
- <constant>KDBUS_ITEM_ID_ADD</constant> or
- <constant>KDBUS_ITEM_ID_REMOVE</constant>, respectively, are delivered
- to all bus members that match these messages through their match
- database. Eavesdroppers (monitor connections) do not cause such
- notifications to be sent. They are invisible on the bus.
- </para></listitem>
-
- <listitem><para>
- When a connection gains or loses ownership of a name, messages with an
- item of type <constant>KDBUS_ITEM_NAME_ADD</constant>,
- <constant>KDBUS_ITEM_NAME_REMOVE</constant> or
- <constant>KDBUS_ITEM_NAME_CHANGE</constant> are delivered to all bus
- members that match these messages through their match database.
- </para></listitem>
- </itemizedlist>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_SEND</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EOPNOTSUPP</constant></term>
- <listitem><para>
- The connection is not an ordinary connection, or the passed
- file descriptors in <constant>KDBUS_ITEM_FDS</constant> item are
- either kdbus handles or unix domain sockets. Both are currently
- unsupported.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The submitted payload type is
- <constant>KDBUS_PAYLOAD_KERNEL</constant>,
- <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set without timeout
- or cookie values, <constant>KDBUS_SEND_SYNC_REPLY</constant> was
- set without <constant>KDBUS_MSG_EXPECT_REPLY</constant>, an invalid
- item was supplied, <constant>src_id</constant> was non-zero and was
- different from the current connection's ID, a supplied memfd had a
- size of 0, or a string was not properly null-terminated.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ENOTUNIQ</constant></term>
- <listitem><para>
- The supplied destination is
- <constant>KDBUS_DST_ID_BROADCAST</constant> and either
- file descriptors were passed, or
- <constant>KDBUS_MSG_EXPECT_REPLY</constant> was set,
- or a timeout was given.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>E2BIG</constant></term>
- <listitem><para>
- Too many items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMSGSIZE</constant></term>
- <listitem><para>
- The size of the message header and items or the payload vector
- is excessive.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EEXIST</constant></term>
- <listitem><para>
- Multiple <constant>KDBUS_ITEM_FDS</constant>,
- <constant>KDBUS_ITEM_BLOOM_FILTER</constant> or
- <constant>KDBUS_ITEM_DST_NAME</constant> items were supplied.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EBADF</constant></term>
- <listitem><para>
- The supplied <constant>KDBUS_ITEM_FDS</constant> or
- <constant>KDBUS_ITEM_PAYLOAD_MEMFD</constant> items
- contained an illegal file descriptor.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMEDIUMTYPE</constant></term>
- <listitem><para>
- The supplied memfd is not a sealed kdbus memfd.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EMFILE</constant></term>
- <listitem><para>
- Too many file descriptors inside a
- <constant>KDBUS_ITEM_FDS</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EBADMSG</constant></term>
- <listitem><para>
- An item had illegal size, both a <constant>dst_id</constant> and a
- <constant>KDBUS_ITEM_DST_NAME</constant> was given, or both a name
- and a bloom filter was given.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ETXTBSY</constant></term>
- <listitem><para>
- The supplied kdbus memfd file cannot be sealed or the seal
- was removed, because it is shared with other processes or
- still mapped with
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ECOMM</constant></term>
- <listitem><para>
- A peer does not accept the file descriptors addressed to it.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EFAULT</constant></term>
- <listitem><para>
- The supplied bloom filter size was not 64-bit aligned, or supplied
- memory could not be accessed by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EDOM</constant></term>
- <listitem><para>
- The supplied bloom filter size did not match the bloom filter
- size of the bus.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EDESTADDRREQ</constant></term>
- <listitem><para>
- <constant>dst_id</constant> was set to
- <constant>KDBUS_DST_ID_NAME</constant>, but no
- <constant>KDBUS_ITEM_DST_NAME</constant> was attached.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ESRCH</constant></term>
- <listitem><para>
- The name to look up was not found in the name registry.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EADDRNOTAVAIL</constant></term>
- <listitem><para>
- <constant>KDBUS_MSG_NO_AUTO_START</constant> was given but the
- destination connection is an activator.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ENXIO</constant></term>
- <listitem><para>
- The passed numeric destination connection ID couldn't be found,
- or is not connected.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ECONNRESET</constant></term>
- <listitem><para>
- The destination connection is no longer active.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ETIMEDOUT</constant></term>
- <listitem><para>
- Timeout while synchronously waiting for a reply.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINTR</constant></term>
- <listitem><para>
- Interrupted system call while synchronously waiting for a reply.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EPIPE</constant></term>
- <listitem><para>
- When sending a message, a synchronous reply from the receiving
- connection was expected but the connection died before answering.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ENOBUFS</constant></term>
- <listitem><para>
- Too many pending messages on the receiver side.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EREMCHG</constant></term>
- <listitem><para>
- Both a well-known name and a unique name (ID) was given, but
- the name is not currently owned by that connection.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EXFULL</constant></term>
- <listitem><para>
- The memory pool of the receiver is full.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EREMOTEIO</constant></term>
- <listitem><para>
- While synchronously waiting for a reply, the remote peer
- failed with an I/O error.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_RECV</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EOPNOTSUPP</constant></term>
- <listitem><para>
- The connection is not an ordinary connection, or the passed
- file descriptors are either kdbus handles or unix domain
- sockets. Both are currently unsupported.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Invalid flags or offset.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EAGAIN</constant></term>
- <listitem><para>
- No message found in the queue.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>clock_gettime</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>ioctl</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>poll</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>select</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>epoll</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>eventfd</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>memfd_create</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.name.xml b/Documentation/kdbus/kdbus.name.xml
deleted file mode 100644
index 3f5f6a6c5..000000000
--- a/Documentation/kdbus/kdbus.name.xml
+++ /dev/null
@@ -1,711 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.name">
-
- <refentryinfo>
- <title>kdbus.name</title>
- <productname>kdbus.name</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.name</refname>
- <refpurpose>kdbus.name</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
- <para>
- Each
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- instantiates a name registry to resolve well-known names into unique
- connection IDs for message delivery. The registry will be queried when a
- message is sent with <varname>kdbus_msg.dst_id</varname> set to
- <constant>KDBUS_DST_ID_NAME</constant>, or when a registry dump is
- requested with <constant>KDBUS_CMD_NAME_LIST</constant>.
- </para>
-
- <para>
- All of the below is subject to policy rules for <emphasis>SEE</emphasis>
- and <emphasis>OWN</emphasis> permissions. See
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Name validity</title>
- <para>
- A name has to comply with the following rules in order to be considered
- valid.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- The name has two or more elements separated by a
- '<literal>.</literal>' (period) character.
- </para>
- </listitem>
- <listitem>
- <para>
- All elements must contain at least one character.
- </para>
- </listitem>
- <listitem>
- <para>
- Each element must only contain the ASCII characters
- <literal>[A-Z][a-z][0-9]_</literal> and must not begin with a
- digit.
- </para>
- </listitem>
- <listitem>
- <para>
- The name must contain at least one '<literal>.</literal>' (period)
- character (and thus at least two elements).
- </para>
- </listitem>
- <listitem>
- <para>
- The name must not begin with a '<literal>.</literal>' (period)
- character.
- </para>
- </listitem>
- <listitem>
- <para>
- The name must not exceed <constant>255</constant> characters in
- length.
- </para>
- </listitem>
- </itemizedlist>
- </refsect1>
-
- <refsect1>
- <title>Acquiring a name</title>
- <para>
- To acquire a name, a client uses the
- <constant>KDBUS_CMD_NAME_ACQUIRE</constant> ioctl with
- <type>struct kdbus_cmd</type> as argument.
- </para>
-
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>Flags to control details in the name acquisition.</para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_NAME_REPLACE_EXISTING</constant></term>
- <listitem>
- <para>
- Acquiring a name that is already present usually fails,
- unless this flag is set in the call, and
- <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> (see below)
- was set when the current owner of the name acquired it, or
- if the current owner is an activator connection (see
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term>
- <listitem>
- <para>
- Allow other connections to take over this name. When this
- happens, the former owner of the connection will be notified
- of the name loss.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_NAME_QUEUE</constant></term>
- <listitem>
- <para>
- A name that is already acquired by a connection can not be
- acquired again (unless the
- <constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant> flag was
- set during acquisition; see above).
- However, a connection can put itself in a queue of
- connections waiting for the name to be released. Once that
- happens, the first connection in that queue becomes the new
- owner and is notified accordingly.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Request a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will fail with
- <errorcode>-1</errorcode>, and <varname>errno</varname>
- is set to <constant>EPROTO</constant>.
- Once the ioctl returned, the <varname>flags</varname>
- field will have all bits set that the kernel recognizes as
- valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem>
- <para>
- Flags returned by the kernel. Currently, the following may be
- returned by the kernel.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_NAME_IN_QUEUE</constant></term>
- <listitem>
- <para>
- The name was not acquired yet, but the connection was
- placed in the queue of peers waiting for the name.
- This can only happen if <constant>KDBUS_NAME_QUEUE</constant>
- was set in the <varname>flags</varname> member (see above).
- The connection will receive a name owner change notification
- once the current owner has given up the name and its
- ownership was transferred.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Items to submit the name. Currently, one item of type
- <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and
- the contained string must be a valid bus name.
- <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for
- valid item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for a detailed description of how this item is used.
- </para>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <errorname>>EINVAL</errorname>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Releasing a name</title>
- <para>
- A connection may release a name explicitly with the
- <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl. If the connection was
- an implementer of an activatable name, its pending messages are moved
- back to the activator. If there are any connections queued up as waiters
- for the name, the first one in the queue (the oldest entry) will become
- the new owner. The same happens implicitly for all names once a
- connection terminates. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on connections.
- </para>
- <para>
- The <constant>KDBUS_CMD_NAME_RELEASE</constant> ioctl uses the same data
- structure as the acquisition call
- (<constant>KDBUS_CMD_NAME_ACQUIRE</constant>),
- but with slightly different field usage.
- </para>
-
- <programlisting>
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Flags to the command. Currently unused.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will return <errorcode>0</errorcode>,
- and the <varname>flags</varname> field is set to
- <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Items to submit the name. Currently, one item of type
- <constant>KDBUS_ITEM_NAME</constant> is expected and allowed, and
- the contained string must be a valid bus name.
- <constant>KDBUS_ITEM_NEGOTIATE</constant> may be used to probe for
- valid item types. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for a detailed description of how this item is used.
- </para>
- <para>
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Dumping the name registry</title>
- <para>
- A connection may request a complete or filtered dump of currently active
- bus names with the <constant>KDBUS_CMD_LIST</constant> ioctl, which
- takes a <type>struct kdbus_cmd_list</type> as argument.
- </para>
-
- <programlisting>
-struct kdbus_cmd_list {
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem>
- <para>
- Any combination of flags to specify which names should be dumped.
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_LIST_UNIQUE</constant></term>
- <listitem>
- <para>
- List the unique (numeric) IDs of the connection, whether it
- owns a name or not.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_LIST_NAMES</constant></term>
- <listitem>
- <para>
- List well-known names stored in the database which are
- actively owned by a real connection (not an activator).
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_LIST_ACTIVATORS</constant></term>
- <listitem>
- <para>
- List names that are owned by an activator.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_LIST_QUEUED</constant></term>
- <listitem>
- <para>
- List connections that are not yet owning a name but are
- waiting for it to become available.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Request a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will fail with
- <errorcode>-1</errorcode>, and <varname>errno</varname>
- is set to <constant>EPROTO</constant>.
- Once the ioctl returned, the <varname>flags</varname>
- field will have all bits set that the kernel recognizes as
- valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>offset</varname></term>
- <listitem><para>
- When the ioctl returns successfully, the offset to the name registry
- dump inside the connection's pool will be stored in this field.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The returned list of names is stored in a <type>struct kdbus_list</type>
- that in turn contains an array of type <type>struct kdbus_info</type>,
- The array-size in bytes is given as <varname>list_size</varname>.
- The fields inside <type>struct kdbus_info</type> is described next.
- </para>
-
- <programlisting>
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- The owning connection's unique ID.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- The flags of the owning connection.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem>
- <para>
- Items containing the actual name. Currently, one item of type
- <constant>KDBUS_ITEM_OWNED_NAME</constant> will be attached,
- including the name's flags. In that item, the flags field of the
- name may carry the following bits:
- </para>
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_NAME_ALLOW_REPLACEMENT</constant></term>
- <listitem>
- <para>
- Other connections are allowed to take over this name from the
- connection that owns it.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_NAME_IN_QUEUE</constant></term>
- <listitem>
- <para>
- When retrieving a list of currently acquired names in the
- registry, this flag indicates whether the connection
- actually owns the name or is currently waiting for it to
- become available.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_NAME_ACTIVATOR</constant></term>
- <listitem>
- <para>
- An activator connection owns a name as a placeholder for an
- implementer, which is started on demand by programs as soon
- as the first message arrives. There's some more information
- on this topic in
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- .
- </para>
- <para>
- In contrast to
- <constant>KDBUS_NAME_REPLACE_EXISTING</constant>,
- when a name is taken over from an activator connection, all
- the messages that have been queued in the activator
- connection will be moved over to the new owner. The activator
- connection will still be tracked for the name and will take
- control again if the implementer connection terminates.
- </para>
- <para>
- This flag can not be used when acquiring a name, but is
- implicitly set through <constant>KDBUS_CMD_HELLO</constant>
- with <constant>KDBUS_HELLO_ACTIVATOR</constant> set in
- <varname>kdbus_cmd_hello.conn_flags</varname>.
- </para>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_FLAG_NEGOTIATE</constant></term>
- <listitem>
- <para>
- Requests a set of valid flags for this ioctl. When this bit is
- set, no action is taken; the ioctl will return
- <errorcode>0</errorcode>, and the <varname>flags</varname>
- field will have all bits set that are valid for this command.
- The <constant>KDBUS_FLAG_NEGOTIATE</constant> bit will be
- cleared by the operation.
- </para>
- </listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- The returned buffer must be freed with the
- <constant>KDBUS_CMD_FREE</constant> ioctl when the user is finished with
- it. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_NAME_ACQUIRE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Illegal command flags, illegal name provided, or an activator
- tried to acquire a second name.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EPERM</constant></term>
- <listitem><para>
- Policy prohibited name ownership.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EALREADY</constant></term>
- <listitem><para>
- Connection already owns that name.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EEXIST</constant></term>
- <listitem><para>
- The name already exists and can not be taken over.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>E2BIG</constant></term>
- <listitem><para>
- The maximum number of well-known names per connection is exhausted.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_NAME_RELEASE</constant>
- may fail with the following errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Invalid command flags, or invalid name provided.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ESRCH</constant></term>
- <listitem><para>
- Name is not found in the registry.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EADDRINUSE</constant></term>
- <listitem><para>
- Name is owned by a different connection and can't be released.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_LIST</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Invalid command flags
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>ENOBUFS</constant></term>
- <listitem><para>
- No available memory in the connection's pool.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.policy.xml b/Documentation/kdbus/kdbus.policy.xml
deleted file mode 100644
index 673241638..000000000
--- a/Documentation/kdbus/kdbus.policy.xml
+++ /dev/null
@@ -1,406 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.policy">
-
- <refentryinfo>
- <title>kdbus.policy</title>
- <productname>kdbus.policy</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.policy</refname>
- <refpurpose>kdbus policy</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
-
- <para>
- A kdbus policy restricts the possibilities of connections to own, see and
- talk to well-known names. A policy can be associated with a bus (through a
- policy holder connection) or a custom endpoint. kdbus stores its policy
- information in a database that can be accessed through the following
- ioctl commands:
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_CMD_HELLO</constant></term>
- <listitem><para>
- When creating, or updating, a policy holder connection. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></term>
- <term><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></term>
- <listitem><para>
- When creating, or updating, a bus custom endpoint. See
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- In all cases, the name and policy access information is stored in items
- of type <constant>KDBUS_ITEM_NAME</constant> and
- <constant>KDBUS_ITEM_POLICY_ACCESS</constant>. For this transport, the
- following rules apply.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- An item of type <constant>KDBUS_ITEM_NAME</constant> must be followed
- by at least one <constant>KDBUS_ITEM_POLICY_ACCESS</constant> item.
- </para>
- </listitem>
-
- <listitem>
- <para>
- An item of type <constant>KDBUS_ITEM_NAME</constant> can be followed
- by an arbitrary number of
- <constant>KDBUS_ITEM_POLICY_ACCESS</constant> items.
- </para>
- </listitem>
-
- <listitem>
- <para>
- An arbitrary number of groups of names and access levels can be given.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Names passed in items of type <constant>KDBUS_ITEM_NAME</constant> must
- comply to the rules of valid kdbus.name. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information.
-
- The payload of an item of type
- <constant>KDBUS_ITEM_POLICY_ACCESS</constant> is defined by the following
- struct. For more information on the layout of items, please refer to
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para>
-
- <programlisting>
-struct kdbus_policy_access {
- __u64 type;
- __u64 access;
- __u64 id;
-};
- </programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>type</varname></term>
- <listitem>
- <para>
- One of the following.
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_POLICY_ACCESS_USER</constant></term>
- <listitem><para>
- Grant access to a user with the UID stored in the
- <varname>id</varname> field.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_POLICY_ACCESS_GROUP</constant></term>
- <listitem><para>
- Grant access to a user with the GID stored in the
- <varname>id</varname> field.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_POLICY_ACCESS_WORLD</constant></term>
- <listitem><para>
- Grant access to everyone. The <varname>id</varname> field
- is ignored.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>access</varname></term>
- <listitem>
- <para>
- The access to grant. One of the following.
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_POLICY_SEE</constant></term>
- <listitem><para>
- Allow the name to be seen.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_POLICY_TALK</constant></term>
- <listitem><para>
- Allow the name to be talked to.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_POLICY_OWN</constant></term>
- <listitem><para>
- Allow the name to be owned.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>id</varname></term>
- <listitem><para>
- For <constant>KDBUS_POLICY_ACCESS_USER</constant>, stores the UID.
- For <constant>KDBUS_POLICY_ACCESS_GROUP</constant>, stores the GID.
- </para></listitem>
- </varlistentry>
-
- </variablelist>
-
- <para>
- All endpoints of buses have an empty policy database by default.
- Therefore, unless policy rules are added, all operations will also be
- denied by default. Also see
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Wildcard names</title>
- <para>
- Policy holder connections may upload names that contain the wildcard
- suffix (<literal>".*"</literal>). Such a policy entry is effective for
- every well-known name that extends the provided name by exactly one more
- level.
-
- For example, the name <literal>foo.bar.*</literal> matches both
- <literal>"foo.bar.baz"</literal> and
- <literal>"foo.bar.bazbaz"</literal> are, but not
- <literal>"foo.bar.baz.baz"</literal>.
-
- This allows connections to take control over multiple names that the
- policy holder doesn't need to know about when uploading the policy.
-
- Such wildcard entries are not allowed for custom endpoints.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Privileged connections</title>
- <para>
- The policy database is overruled when action is taken by a privileged
- connection. Please refer to
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information on what makes a connection privileged.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Examples</title>
- <para>
- For instance, a set of policy rules may look like this:
- </para>
-
- <programlisting>
-KDBUS_ITEM_NAME: str='org.foo.bar'
-KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=1000
-KDBUS_ITEM_POLICY_ACCESS: type=USER, access=TALK, ID=1001
-KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=SEE
-
-KDBUS_ITEM_NAME: str='org.blah.baz'
-KDBUS_ITEM_POLICY_ACCESS: type=USER, access=OWN, ID=0
-KDBUS_ITEM_POLICY_ACCESS: type=WORLD, access=TALK
- </programlisting>
-
- <para>
- That means that 'org.foo.bar' may only be owned by UID 1000, but every
- user on the bus is allowed to see the name. However, only UID 1001 may
- actually send a message to the connection and receive a reply from it.
-
- The second rule allows 'org.blah.baz' to be owned by UID 0 only, but
- every user may talk to it.
- </para>
- </refsect1>
-
- <refsect1>
- <title>TALK access and multiple well-known names per connection</title>
- <para>
- Note that TALK access is checked against all names of a connection. For
- example, if a connection owns both <constant>'org.foo.bar'</constant> and
- <constant>'org.blah.baz'</constant>, and the policy database allows
- <constant>'org.blah.baz'</constant> to be talked to by WORLD, then this
- permission is also granted to <constant>'org.foo.bar'</constant>. That
- might sound illogical, but after all, we allow messages to be directed to
- either the ID or a well-known name, and policy is applied to the
- connection, not the name. In other words, the effective TALK policy for a
- connection is the most permissive of all names the connection owns.
-
- For broadcast messages, the receiver needs TALK permissions to the sender
- to receive the broadcast.
- </para>
- <para>
- Both the endpoint and the bus policy databases are consulted to allow
- name registry listing, owning a well-known name and message delivery.
- If either one fails, the operation is failed with
- <varname>errno</varname> set to <constant>EPERM</constant>.
-
- For best practices, connections that own names with a restricted TALK
- access should not install matches. This avoids cases where the sent
- message may pass the bloom filter due to false-positives and may also
- satisfy the policy rules.
-
- Also see
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Implicit policies</title>
- <para>
- Depending on the type of the endpoint, a set of implicit rules that
- override installed policies might be enforced.
-
- On default endpoints, the following set is enforced and checked before
- any user-supplied policy is checked.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Privileged connections always override any installed policy. Those
- connections could easily install their own policies, so there is no
- reason to enforce installed policies.
- </para>
- </listitem>
- <listitem>
- <para>
- Connections can always talk to connections of the same user. This
- includes broadcast messages.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Custom endpoints have stricter policies. The following rules apply:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- Policy rules are always enforced, even if the connection is a
- privileged connection.
- </para>
- </listitem>
- <listitem>
- <para>
- Policy rules are always enforced for <constant>TALK</constant> access,
- even if both ends are running under the same user. This includes
- broadcast messages.
- </para>
- </listitem>
- <listitem>
- <para>
- To restrict the set of names that can be seen, endpoint policies can
- install <constant>SEE</constant> policies.
- </para>
- </listitem>
- </itemizedlist>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.pool.xml b/Documentation/kdbus/kdbus.pool.xml
deleted file mode 100644
index a9e16f196..000000000
--- a/Documentation/kdbus/kdbus.pool.xml
+++ /dev/null
@@ -1,326 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus.pool">
-
- <refentryinfo>
- <title>kdbus.pool</title>
- <productname>kdbus.pool</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus.pool</refname>
- <refpurpose>kdbus pool</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Description</title>
- <para>
- A pool for data received from the kernel is installed for every
- <emphasis>connection</emphasis> of the <emphasis>bus</emphasis>, and
- is sized according to the information stored in the
- <varname>pool_size</varname> member of <type>struct kdbus_cmd_hello</type>
- when <constant>KDBUS_CMD_HELLO</constant> is employed. Internally, the
- pool is segmented into <emphasis>slices</emphasis>, each referenced by its
- <emphasis>offset</emphasis> in the pool, expressed in <type>bytes</type>.
- See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more information about <constant>KDBUS_CMD_HELLO</constant>.
- </para>
-
- <para>
- The pool is written to by the kernel when one of the following
- <emphasis>ioctls</emphasis> is issued:
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_CMD_HELLO</constant></term>
- <listitem><para>
- ... to receive details about the bus the connection was made to
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>KDBUS_CMD_RECV</constant></term>
- <listitem><para>
- ... to receive a message
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>KDBUS_CMD_LIST</constant></term>
- <listitem><para>
- ... to dump the name registry
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>KDBUS_CMD_CONN_INFO</constant></term>
- <listitem><para>
- ... to retrieve information on a connection
- </para></listitem>
- </varlistentry>
- <varlistentry>
- <term><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></term>
- <listitem><para>
- ... to retrieve information about a connection's bus creator
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- </para>
- <para>
- The <varname>offset</varname> fields returned by either one of the
- aforementioned ioctls describe offsets inside the pool. In order to make
- the slice available for subsequent calls,
- <constant>KDBUS_CMD_FREE</constant> has to be called on that offset
- (see below). Otherwise, the pool will fill up, and the connection won't
- be able to receive any more information through its pool.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Pool slice allocation</title>
- <para>
- Pool slices are allocated by the kernel in order to report information
- back to a task, such as messages, returned name list etc.
- Allocation of pool slices cannot be initiated by userspace. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for examples of commands that use the <emphasis>pool</emphasis> to
- return data.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Accessing the pool memory</title>
- <para>
- Memory in the pool is read-only for userspace and may only be written
- to by the kernel. To read from the pool memory, the caller is expected to
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- the buffer into its task, like this:
- </para>
- <programlisting>
-uint8_t *buf = mmap(NULL, size, PROT_READ, MAP_SHARED, conn_fd, 0);
- </programlisting>
-
- <para>
- In order to map the entire pool, the <varname>size</varname> parameter in
- the example above should be set to the value of the
- <varname>pool_size</varname> member of
- <type>struct kdbus_cmd_hello</type> when
- <constant>KDBUS_CMD_HELLO</constant> was employed to create the
- connection (see above).
- </para>
-
- <para>
- The <emphasis>file descriptor</emphasis> used to map the memory must be
- the one that was used to create the <emphasis>connection</emphasis>.
- In other words, the one that was used to call
- <constant>KDBUS_CMD_HELLO</constant>. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
-
- <para>
- Alternatively, instead of mapping the entire pool buffer, only parts
- of it can be mapped. Every kdbus command that returns an
- <emphasis>offset</emphasis> (see above) also reports a
- <emphasis>size</emphasis> along with it, so programs can be written
- in a way that it only maps portions of the pool to access a specific
- <emphasis>slice</emphasis>.
- </para>
-
- <para>
- When access to the pool memory is no longer needed, programs should
- call <function>munmap()</function> on the pointer returned by
- <function>mmap()</function>.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Freeing pool slices</title>
- <para>
- The <constant>KDBUS_CMD_FREE</constant> ioctl is used to free a slice
- inside the pool, describing an offset that was returned in an
- <varname>offset</varname> field of another ioctl struct.
- The <constant>KDBUS_CMD_FREE</constant> command takes a
- <type>struct kdbus_cmd_free</type> as argument.
- </para>
-
-<programlisting>
-struct kdbus_cmd_free {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- struct kdbus_item items[0];
-};
-</programlisting>
-
- <para>The fields in this struct are described below.</para>
-
- <variablelist>
- <varlistentry>
- <term><varname>size</varname></term>
- <listitem><para>
- The overall size of the struct, including its items.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>flags</varname></term>
- <listitem><para>
- Currently unused.
- <constant>KDBUS_FLAG_NEGOTIATE</constant> is accepted to probe for
- valid flags. If set, the ioctl will return <errorcode>0</errorcode>,
- and the <varname>flags</varname> field is set to
- <constant>0</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>return_flags</varname></term>
- <listitem><para>
- Flags returned by the kernel. Currently unused and always set to
- <constant>0</constant> by the kernel.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>offset</varname></term>
- <listitem><para>
- The offset to free, as returned by other ioctls that allocated
- memory for returned information.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><varname>items</varname></term>
- <listitem><para>
- Items to specify further details for the receive command.
- Currently unused.
- Unrecognized items are rejected, and the ioctl will fail with
- <varname>errno</varname> set to <constant>EINVAL</constant>.
- All items except for
- <constant>KDBUS_ITEM_NEGOTIATE</constant> (see
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- ) will be rejected.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect1>
-
- <refsect1>
- <title>Return value</title>
- <para>
- On success, all mentioned ioctl commands return <errorcode>0</errorcode>;
- on error, <errorcode>-1</errorcode> is returned, and
- <varname>errno</varname> is set to indicate the error.
- If the issued ioctl is illegal for the file descriptor used,
- <varname>errno</varname> will be set to <constant>ENOTTY</constant>.
- </para>
-
- <refsect2>
- <title>
- <constant>KDBUS_CMD_FREE</constant> may fail with the following
- errors
- </title>
-
- <variablelist>
- <varlistentry>
- <term><constant>ENXIO</constant></term>
- <listitem><para>
- No pool slice found at given offset.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- Invalid flags provided.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>EINVAL</constant></term>
- <listitem><para>
- The offset is valid, but the user is not allowed to free the slice.
- This happens, for example, if the offset was retrieved with
- <constant>KDBUS_RECV_PEEK</constant>.
- </para></listitem>
- </varlistentry>
- </variablelist>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>munmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- </simplelist>
- </refsect1>
-</refentry>
diff --git a/Documentation/kdbus/kdbus.xml b/Documentation/kdbus/kdbus.xml
deleted file mode 100644
index d8e7400df..000000000
--- a/Documentation/kdbus/kdbus.xml
+++ /dev/null
@@ -1,1012 +0,0 @@
-<?xml version='1.0'?> <!--*-nxml-*-->
-<!DOCTYPE refentry PUBLIC "-//OASIS//DTD DocBook XML V4.2//EN"
- "http://www.oasis-open.org/docbook/xml/4.2/docbookx.dtd">
-
-<refentry id="kdbus">
-
- <refentryinfo>
- <title>kdbus</title>
- <productname>kdbus</productname>
- </refentryinfo>
-
- <refmeta>
- <refentrytitle>kdbus</refentrytitle>
- <manvolnum>7</manvolnum>
- </refmeta>
-
- <refnamediv>
- <refname>kdbus</refname>
- <refpurpose>Kernel Message Bus</refpurpose>
- </refnamediv>
-
- <refsect1>
- <title>Synopsis</title>
- <para>
- kdbus is an inter-process communication bus system controlled by the
- kernel. It provides user-space with an API to create buses and send
- unicast and multicast messages to one, or many, peers connected to the
- same bus. It does not enforce any layout on the transmitted data, but
- only provides the transport layer used for message interchange between
- peers.
- </para>
- <para>
- This set of man-pages gives a comprehensive overview of the kernel-level
- API, with all ioctl commands, associated structs and bit masks. However,
- most people will not use this API level directly, but rather let one of
- the high-level abstraction libraries help them integrate D-Bus
- functionality into their applications.
- </para>
- </refsect1>
-
- <refsect1>
- <title>Description</title>
- <para>
- kdbus provides a pseudo filesystem called <emphasis>kdbusfs</emphasis>,
- which is usually mounted on <filename>/sys/fs/kdbus</filename>. Bus
- primitives can be accessed as files and sub-directories underneath this
- mount-point. Any advanced operations are done via
- <function>ioctl()</function> on files created by
- <emphasis>kdbusfs</emphasis>. Multiple mount-points of
- <emphasis>kdbusfs</emphasis> are independent of each other. This allows
- namespacing of kdbus by mounting a new instance of
- <emphasis>kdbusfs</emphasis> in a new mount-namespace. kdbus calls these
- mount instances domains and each bus belongs to exactly one domain.
- </para>
-
- <para>
- kdbus was designed as a transport layer for D-Bus, but is in no way
- limited, nor controlled by the D-Bus protocol specification. The D-Bus
- protocol is one possible application layer on top of kdbus.
- </para>
-
- <para>
- For the general D-Bus protocol specification, its payload format, its
- marshaling, and its communication semantics, please refer to the
- <ulink url="http://dbus.freedesktop.org/doc/dbus-specification.html">
- D-Bus specification</ulink>.
- </para>
-
- </refsect1>
-
- <refsect1>
- <title>Terminology</title>
-
- <refsect2>
- <title>Domain</title>
- <para>
- A domain is a <emphasis>kdbusfs</emphasis> mount-point containing all
- the bus primitives. Each domain is independent, and separate domains
- do not affect each other.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Bus</title>
- <para>
- A bus is a named object inside a domain. Clients exchange messages
- over a bus. Multiple buses themselves have no connection to each other;
- messages can only be exchanged on the same bus. The default endpoint of
- a bus, to which clients establish connections, is the "bus" file
- /sys/fs/kdbus/&lt;bus name&gt;/bus.
- Common operating system setups create one "system bus" per system,
- and one "user bus" for every logged-in user. Applications or services
- may create their own private buses. The kernel driver does not
- distinguish between different bus types, they are all handled the same
- way. See
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Endpoint</title>
- <para>
- An endpoint provides a file to talk to a bus. Opening an endpoint
- creates a new connection to the bus to which the endpoint belongs. All
- endpoints have unique names and are accessible as files underneath the
- directory of a bus, e.g., /sys/fs/kdbus/&lt;bus&gt;/&lt;endpoint&gt;
- Every bus has a default endpoint called "bus".
- A bus can optionally offer additional endpoints with custom names
- to provide restricted access to the bus. Custom endpoints carry
- additional policy which can be used to create sandboxes with
- locked-down, limited, filtered access to a bus. See
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Connection</title>
- <para>
- A connection to a bus is created by opening an endpoint file of a
- bus. Every ordinary client connection has a unique identifier on the
- bus and can address messages to every other connection on the same
- bus by using the peer's connection ID as the destination. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Pool</title>
- <para>
- Each connection allocates a piece of shmem-backed memory that is
- used to receive messages and answers to ioctl commands from the kernel.
- It is never used to send anything to the kernel. In order to access that
- memory, an application must mmap() it into its address space. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Well-known Name</title>
- <para>
- A connection can, in addition to its implicit unique connection ID,
- request the ownership of a textual well-known name. Well-known names are
- noted in reverse-domain notation, such as com.example.service1. A
- connection that offers a service on a bus is usually reached by its
- well-known name. An analogy of connection ID and well-known name is an
- IP address and a DNS name associated with that address. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Message</title>
- <para>
- Connections can exchange messages with other connections by addressing
- the peers with their connection ID or well-known name. A message
- consists of a message header with information on how to route the
- message, and the message payload, which is a logical byte stream of
- arbitrary size. Messages can carry additional file descriptors to be
- passed from one connection to another, just like passing file
- descriptors over UNIX domain sockets. Every connection can specify which
- set of metadata the kernel should attach to the message when it is
- delivered to the receiving connection. Metadata contains information
- like: system time stamps, UID, GID, TID, proc-starttime, well-known
- names, process comm, process exe, process argv, cgroup, capabilities,
- seclabel, audit session, loginuid and the connection's human-readable
- name. See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Item</title>
- <para>
- The API of kdbus implements the notion of items, submitted through and
- returned by most ioctls, and stored inside data structures in the
- connection's pool. See
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Broadcast, signal, filter, match</title>
- <para>
- Signals are messages that a receiver opts in for by installing a blob of
- bytes, called a 'match'. Signal messages must always carry a
- counter-part blob, called a 'filter', and signals are only delivered to
- peers which have a match that white-lists the message's filter. Senders
- of signal messages can use either a single connection ID as receiver,
- or the special connection ID
- <constant>KDBUS_DST_ID_BROADCAST</constant> to potentially send it to
- all connections of a bus, following the logic described above. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- and
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Policy</title>
- <para>
- A policy is a set of rules that define which connections can see, talk
- to, or register a well-known name on the bus. A policy is attached to
- buses and custom endpoints, and modified by policy holder connections or
- owners of custom endpoints. See
- <citerefentry>
- <refentrytitle>kdbus.policy</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Privileged bus users</title>
- <para>
- A user connecting to the bus is considered privileged if it is either
- the creator of the bus, or if it has the CAP_IPC_OWNER capability flag
- set. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>Bus Layout</title>
-
- <para>
- A <emphasis>bus</emphasis> provides and defines an environment that peers
- can connect to for message interchange. A bus is created via the kdbus
- control interface and can be modified by the bus creator. It applies the
- policy that control all bus operations. The bus creator itself does not
- participate as a peer. To establish a peer
- <emphasis>connection</emphasis>, you have to open one of the
- <emphasis>endpoints</emphasis> of a bus. Each bus provides a default
- endpoint, but further endpoints can be created on-demand. Endpoints are
- used to apply additional policies for all connections on this endpoint.
- Thus, they provide additional filters to further restrict access of
- specific connections to the bus.
- </para>
-
- <para>
- Following, you can see an example bus layout:
- </para>
-
- <programlisting><![CDATA[
- Bus Creator
- |
- |
- +-----+
- | Bus |
- +-----+
- |
- __________________/ \__________________
- / \
- | |
- +----------+ +----------+
- | Endpoint | | Endpoint |
- +----------+ +----------+
- _________/|\_________ _________/|\_________
- / | \ / | \
- | | | | | |
- | | | | | |
- Connection Connection Connection Connection Connection Connection
- ]]></programlisting>
-
- </refsect1>
-
- <refsect1>
- <title>Data structures and interconnections</title>
- <programlisting><![CDATA[
- +--------------------------------------------------------------------------+
- | Domain (Mount Point) |
- | /sys/fs/kdbus/control |
- | +----------------------------------------------------------------------+ |
- | | Bus (System Bus) | |
- | | /sys/fs/kdbus/0-system/ | |
- | | +-------------------------------+ +--------------------------------+ | |
- | | | Endpoint | | Endpoint | | |
- | | | /sys/fs/kdbus/0-system/bus | | /sys/fs/kdbus/0-system/ep.app | | |
- | | +-------------------------------+ +--------------------------------+ | |
- | | +--------------+ +--------------+ +--------------+ +---------------+ | |
- | | | Connection | | Connection | | Connection | | Connection | | |
- | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | |
- | | +--------------+ +--------------+ +--------------+ +---------------+ | |
- | +----------------------------------------------------------------------+ |
- | |
- | +----------------------------------------------------------------------+ |
- | | Bus (User Bus for UID 2702) | |
- | | /sys/fs/kdbus/2702-user/ | |
- | | +-------------------------------+ +--------------------------------+ | |
- | | | Endpoint | | Endpoint | | |
- | | | /sys/fs/kdbus/2702-user/bus | | /sys/fs/kdbus/2702-user/ep.app | | |
- | | +-------------------------------+ +--------------------------------+ | |
- | | +--------------+ +--------------+ +--------------+ +---------------+ | |
- | | | Connection | | Connection | | Connection | | Connection | | |
- | | | :1.22 | | :1.25 | | :1.55 | | :1.81 | | |
- | | +--------------+ +--------------+ +--------------------------------+ | |
- | +----------------------------------------------------------------------+ |
- +--------------------------------------------------------------------------+
- ]]></programlisting>
- </refsect1>
-
- <refsect1>
- <title>Metadata</title>
-
- <refsect2>
- <title>When metadata is collected</title>
- <para>
- kdbus records data about the system in certain situations. Such metadata
- can refer to the currently active process (creds, PIDs, current user
- groups, process names and its executable path, cgroup membership,
- capabilities, security label and audit information), connection
- information (description string, currently owned names) and time stamps.
- </para>
- <para>
- Metadata is collected at the following times.
- </para>
-
- <itemizedlist>
- <listitem><para>
- When a bus is created (<constant>KDBUS_CMD_MAKE</constant>),
- information about the calling task is collected. This data is returned
- by the kernel via the <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant>
- call.
- </para></listitem>
-
- <listitem>
- <para>
- When a connection is created (<constant>KDBUS_CMD_HELLO</constant>),
- information about the calling task is collected. Alternatively, a
- privileged connection may provide 'faked' information about
- credentials, PIDs and security labels which will be stored instead.
- This data is returned by the kernel as information on a connection
- (<constant>KDBUS_CMD_CONN_INFO</constant>). Only metadata that a
- connection allowed to be sent (by setting its bit in
- <varname>attach_flags_send</varname>) will be exported in this way.
- </para>
- </listitem>
-
- <listitem>
- <para>
- When a message is sent (<constant>KDBUS_CMD_SEND</constant>),
- information about the sending task and the sending connection is
- collected. This metadata will be attached to the message when it
- arrives in the receiver's pool. If the connection sending the
- message installed faked credentials (see
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>),
- the message will not be augmented by any information about the
- currently sending task. Note that only metadata that was requested
- by the receiving connection will be collected and attached to
- messages.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Which metadata items are actually delivered depends on the following
- sets and masks:
- </para>
-
- <itemizedlist>
- <listitem><para>
- (a) the system-wide kmod creds mask
- (module parameter <varname>attach_flags_mask</varname>)
- </para></listitem>
-
- <listitem><para>
- (b) the per-connection send creds mask, set by the connecting client
- </para></listitem>
-
- <listitem><para>
- (c) the per-connection receive creds mask, set by the connecting
- client
- </para></listitem>
-
- <listitem><para>
- (d) the per-bus minimal creds mask, set by the bus creator
- </para></listitem>
-
- <listitem><para>
- (e) the per-bus owner creds mask, set by the bus creator
- </para></listitem>
-
- <listitem><para>
- (f) the mask specified when querying creds of a bus peer
- </para></listitem>
-
- <listitem><para>
- (g) the mask specified when querying creds of a bus owner
- </para></listitem>
- </itemizedlist>
-
- <para>
- With the following rules:
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- [1] The creds attached to messages are determined as
- <constant>a &amp; b &amp; c</constant>.
- </para>
- </listitem>
-
- <listitem>
- <para>
- [2] When connecting to a bus (<constant>KDBUS_CMD_HELLO</constant>),
- and <constant>~b &amp; d != 0</constant>, the call will fail with,
- <errorcode>-1</errorcode>, and <varname>errno</varname> is set to
- <constant>ECONNREFUSED</constant>.
- </para>
- </listitem>
-
- <listitem>
- <para>
- [3] When querying creds of a bus peer, the creds returned are
- <constant>a &amp; b &amp; f</constant>.
- </para>
- </listitem>
-
- <listitem>
- <para>
- [4] When querying creds of a bus owner, the creds returned are
- <constant>a &amp; e &amp; g</constant>.
- </para>
- </listitem>
- </itemizedlist>
-
- <para>
- Hence, programs might not always get all requested metadata items that
- it requested. Code must be written so that it can cope with this fact.
- </para>
- </refsect2>
-
- <refsect2>
- <title>Benefits and heads-up</title>
- <para>
- Attaching metadata to messages has two major benefits.
-
- <itemizedlist>
- <listitem>
- <para>
- Metadata attached to messages is gathered at the moment when the
- other side calls <constant>KDBUS_CMD_SEND</constant>, or,
- respectively, then the kernel notification is generated. There is
- no need for the receiving peer to retrieve information about the
- task in a second step. This closes a race gap that would otherwise
- be inherent.
- </para>
- </listitem>
- <listitem>
- <para>
- As metadata is delivered along with messages in the same data
- blob, no extra calls to kernel functions etc. are needed to gather
- them.
- </para>
- </listitem>
- </itemizedlist>
-
- Note, however, that collecting metadata does come at a price for
- performance, so developers should carefully assess which metadata to
- really opt-in for. For best practice, data that is not needed as part
- of a message should not be requested by the connection in the first
- place (see <varname>attach_flags_recv</varname> in
- <constant>KDBUS_CMD_HELLO</constant>).
- </para>
- </refsect2>
-
- <refsect2>
- <title>Attach flags for metadata items</title>
- <para>
- To let the kernel know which metadata information to attach as items
- to the aforementioned commands, it uses a bitmask. In those, the
- following <emphasis>attach flags</emphasis> are currently supported.
- Both the <varname>attach_flags_recv</varname> and
- <varname>attach_flags_send</varname> fields of
- <type>struct kdbus_cmd_hello</type>, as well as the payload of the
- <constant>KDBUS_ITEM_ATTACH_FLAGS_SEND</constant> and
- <constant>KDBUS_ITEM_ATTACH_FLAGS_RECV</constant> items follow this
- scheme.
- </para>
-
- <variablelist>
- <varlistentry>
- <term><constant>KDBUS_ATTACH_TIMESTAMP</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_TIMESTAMP</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_CREDS</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_CREDS</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_PIDS</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_PIDS</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_AUXGROUPS</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_AUXGROUPS</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_NAMES</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_OWNED_NAME</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_TID_COMM</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_TID_COMM</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_PID_COMM</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_PID_COMM</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_EXE</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_EXE</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_CMDLINE</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_CMDLINE</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_CGROUP</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_CGROUP</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_CAPS</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_CAPS</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_SECLABEL</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_SECLABEL</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_AUDIT</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_AUDIT</constant>.
- </para></listitem>
- </varlistentry>
-
- <varlistentry>
- <term><constant>KDBUS_ATTACH_CONN_DESCRIPTION</constant></term>
- <listitem><para>
- Requests the attachment of an item of type
- <constant>KDBUS_ITEM_CONN_DESCRIPTION</constant>.
- </para></listitem>
- </varlistentry>
- </variablelist>
-
- <para>
- Please refer to
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for detailed information about the layout and payload of items and
- what metadata should be used to.
- </para>
- </refsect2>
- </refsect1>
-
- <refsect1>
- <title>The ioctl interface</title>
-
- <para>
- As stated in the 'synopsis' section above, application developers are
- strongly encouraged to use kdbus through one of the high-level D-Bus
- abstraction libraries, rather than using the low-level API directly.
- </para>
-
- <para>
- kdbus on the kernel level exposes its functions exclusively through
- <citerefentry>
- <refentrytitle>ioctl</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>,
- employed on file descriptors returned by
- <citerefentry>
- <refentrytitle>open</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- on pseudo files exposed by
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para>
- <para>
- Following is a list of all the ioctls, along with the command structs
- they must be used with.
- </para>
-
- <informaltable frame="none">
- <tgroup cols="3" colsep="1">
- <thead>
- <row>
- <entry>ioctl signature</entry>
- <entry>command</entry>
- <entry>transported struct</entry>
- </row>
- </thead>
- <tbody>
- <row>
- <entry><constant>0x40189500</constant></entry>
- <entry><constant>KDBUS_CMD_BUS_MAKE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x40189510</constant></entry>
- <entry><constant>KDBUS_CMD_ENDPOINT_MAKE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0xc0609580</constant></entry>
- <entry><constant>KDBUS_CMD_HELLO</constant></entry>
- <entry><type>struct kdbus_cmd_hello *</type></entry>
- </row><row>
- <entry><constant>0x40189582</constant></entry>
- <entry><constant>KDBUS_CMD_BYEBYE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x40389590</constant></entry>
- <entry><constant>KDBUS_CMD_SEND</constant></entry>
- <entry><type>struct kdbus_cmd_send *</type></entry>
- </row><row>
- <entry><constant>0x80409591</constant></entry>
- <entry><constant>KDBUS_CMD_RECV</constant></entry>
- <entry><type>struct kdbus_cmd_recv *</type></entry>
- </row><row>
- <entry><constant>0x40209583</constant></entry>
- <entry><constant>KDBUS_CMD_FREE</constant></entry>
- <entry><type>struct kdbus_cmd_free *</type></entry>
- </row><row>
- <entry><constant>0x401895a0</constant></entry>
- <entry><constant>KDBUS_CMD_NAME_ACQUIRE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x401895a1</constant></entry>
- <entry><constant>KDBUS_CMD_NAME_RELEASE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x80289586</constant></entry>
- <entry><constant>KDBUS_CMD_LIST</constant></entry>
- <entry><type>struct kdbus_cmd_list *</type></entry>
- </row><row>
- <entry><constant>0x80309584</constant></entry>
- <entry><constant>KDBUS_CMD_CONN_INFO</constant></entry>
- <entry><type>struct kdbus_cmd_info *</type></entry>
- </row><row>
- <entry><constant>0x40209551</constant></entry>
- <entry><constant>KDBUS_CMD_UPDATE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x80309585</constant></entry>
- <entry><constant>KDBUS_CMD_BUS_CREATOR_INFO</constant></entry>
- <entry><type>struct kdbus_cmd_info *</type></entry>
- </row><row>
- <entry><constant>0x40189511</constant></entry>
- <entry><constant>KDBUS_CMD_ENDPOINT_UPDATE</constant></entry>
- <entry><type>struct kdbus_cmd *</type></entry>
- </row><row>
- <entry><constant>0x402095b0</constant></entry>
- <entry><constant>KDBUS_CMD_MATCH_ADD</constant></entry>
- <entry><type>struct kdbus_cmd_match *</type></entry>
- </row><row>
- <entry><constant>0x402095b1</constant></entry>
- <entry><constant>KDBUS_CMD_MATCH_REMOVE</constant></entry>
- <entry><type>struct kdbus_cmd_match *</type></entry>
- </row>
- </tbody>
- </tgroup>
- </informaltable>
-
- <para>
- Depending on the type of <emphasis>kdbusfs</emphasis> node that was
- opened and what ioctls have been executed on a file descriptor before,
- a different sub-set of ioctl commands is allowed.
- </para>
-
- <itemizedlist>
- <listitem>
- <para>
- On a file descriptor resulting from opening a
- <emphasis>control node</emphasis>, only the
- <constant>KDBUS_CMD_BUS_MAKE</constant> ioctl may be executed.
- </para>
- </listitem>
- <listitem>
- <para>
- On a file descriptor resulting from opening a
- <emphasis>bus endpoint node</emphasis>, only the
- <constant>KDBUS_CMD_ENDPOINT_MAKE</constant> and
- <constant>KDBUS_CMD_HELLO</constant> ioctls may be executed.
- </para>
- </listitem>
- <listitem>
- <para>
- A file descriptor that was used to create a bus
- (via <constant>KDBUS_CMD_BUS_MAKE</constant>) is called a
- <emphasis>bus owner</emphasis> file descriptor. The bus will be
- active as long as the file descriptor is kept open.
- A bus owner file descriptor can not be used to
- employ any further ioctls. As soon as
- <citerefentry>
- <refentrytitle>close</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- is called on it, the bus will be shut down, along will all associated
- endpoints and connections. See
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </listitem>
- <listitem>
- <para>
- A file descriptor that was used to create an endpoint
- (via <constant>KDBUS_CMD_ENDPOINT_MAKE</constant>) is called an
- <emphasis>endpoint owner</emphasis> file descriptor. The endpoint
- will be active as long as the file descriptor is kept open.
- An endpoint owner file descriptor can only be used
- to update details of an endpoint through the
- <constant>KDBUS_CMD_ENDPOINT_UPDATE</constant> ioctl. As soon as
- <citerefentry>
- <refentrytitle>close</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- is called on it, the endpoint will be removed from the bus, and all
- connections that are connected to the bus through it are shut down.
- See
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- for more details.
- </para>
- </listitem>
- <listitem>
- <para>
- A file descriptor that was used to create a connection
- (via <constant>KDBUS_CMD_HELLO</constant>) is called a
- <emphasis>connection owner</emphasis> file descriptor. The connection
- will be active as long as the file descriptor is kept open.
- A connection owner file descriptor may be used to
- issue any of the following ioctls.
- </para>
-
- <itemizedlist>
- <listitem><para>
- <constant>KDBUS_CMD_UPDATE</constant> to tweak details of the
- connection. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_BYEBYE</constant> to shut down a connection
- without losing messages. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_FREE</constant> to free a slice of memory in
- the pool. See
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_CONN_INFO</constant> to retrieve information
- on other connections on the bus. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_BUS_CREATOR_INFO</constant> to retrieve
- information on the bus creator. See
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_LIST</constant> to retrieve a list of
- currently active well-known names and unique IDs on the bus. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_SEND</constant> and
- <constant>KDBUS_CMD_RECV</constant> to send or receive a message.
- See
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_NAME_ACQUIRE</constant> and
- <constant>KDBUS_CMD_NAME_RELEASE</constant> to acquire or release
- a well-known name on the bus. See
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
-
- <listitem><para>
- <constant>KDBUS_CMD_MATCH_ADD</constant> and
- <constant>KDBUS_CMD_MATCH_REMOVE</constant> to add or remove
- a match for signal messages. See
- <citerefentry>
- <refentrytitle>kdbus.match</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>.
- </para></listitem>
- </itemizedlist>
- </listitem>
- </itemizedlist>
-
- <para>
- These ioctls, along with the structs they transport, are explained in
- detail in the other documents linked to in the "See Also" section below.
- </para>
- </refsect1>
-
- <refsect1>
- <title>See Also</title>
- <simplelist type="inline">
- <member>
- <citerefentry>
- <refentrytitle>kdbus.bus</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.connection</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.endpoint</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.fs</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.item</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.message</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.name</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>kdbus.pool</refentrytitle>
- <manvolnum>7</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>ioctl</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>mmap</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>open</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <citerefentry>
- <refentrytitle>close</refentrytitle>
- <manvolnum>2</manvolnum>
- </citerefentry>
- </member>
- <member>
- <ulink url="http://freedesktop.org/wiki/Software/dbus">D-Bus</ulink>
- </member>
- </simplelist>
- </refsect1>
-
-</refentry>
diff --git a/Documentation/kdbus/stylesheet.xsl b/Documentation/kdbus/stylesheet.xsl
deleted file mode 100644
index 52565eac7..000000000
--- a/Documentation/kdbus/stylesheet.xsl
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<stylesheet xmlns="http://www.w3.org/1999/XSL/Transform" version="1.0">
- <param name="chunk.quietly">1</param>
- <param name="funcsynopsis.style">ansi</param>
- <param name="funcsynopsis.tabular.threshold">80</param>
- <param name="callout.graphics">0</param>
- <param name="paper.type">A4</param>
- <param name="generate.section.toc.level">2</param>
- <param name="use.id.as.filename">1</param>
- <param name="citerefentry.link">1</param>
- <strip-space elements="*"/>
- <template name="generate.citerefentry.link">
- <value-of select="refentrytitle"/>
- <text>.html</text>
- </template>
-</stylesheet>
diff --git a/MAINTAINERS b/MAINTAINERS
index 84af0bd68..e1a9511fc 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -6003,19 +6003,6 @@ S: Maintained
F: Documentation/kbuild/kconfig-language.txt
F: scripts/kconfig/
-KDBUS
-M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-M: Daniel Mack <daniel@zonque.org>
-M: David Herrmann <dh.herrmann@googlemail.com>
-M: Djalal Harouni <tixxdz@opendz.org>
-L: linux-kernel@vger.kernel.org
-S: Maintained
-F: ipc/kdbus/*
-F: samples/kdbus/*
-F: Documentation/kdbus/*
-F: include/uapi/linux/kdbus.h
-F: tools/testing/selftests/kdbus/
-
KDUMP
M: Vivek Goyal <vgoyal@redhat.com>
M: Haren Myneni <hbabu@us.ibm.com>
diff --git a/Makefile b/Makefile
index a288afa13..d9c43553b 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
VERSION = 4
PATCHLEVEL = 4
-SUBLEVEL = 1
+SUBLEVEL = 2
EXTRAVERSION = -gnu
NAME = Blurry Fish Butt
@@ -1346,7 +1346,6 @@ $(help-board-dirs): help-%:
%docs: scripts_basic FORCE
$(Q)$(MAKE) $(build)=scripts build_docproc build_check-lc_ctype
$(Q)$(MAKE) $(build)=Documentation/DocBook $@
- $(Q)$(MAKE) $(build)=Documentation/kdbus $@
else # KBUILD_EXTMOD
diff --git a/arch/parisc/include/asm/hugetlb.h b/arch/parisc/include/asm/hugetlb.h
index 7d56a9ccb..a65d88871 100644
--- a/arch/parisc/include/asm/hugetlb.h
+++ b/arch/parisc/include/asm/hugetlb.h
@@ -54,24 +54,12 @@ static inline pte_t huge_pte_wrprotect(pte_t pte)
return pte_wrprotect(pte);
}
-static inline void huge_ptep_set_wrprotect(struct mm_struct *mm,
- unsigned long addr, pte_t *ptep)
-{
- pte_t old_pte = *ptep;
- set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
-}
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep);
-static inline int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
unsigned long addr, pte_t *ptep,
- pte_t pte, int dirty)
-{
- int changed = !pte_same(*ptep, pte);
- if (changed) {
- set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
- flush_tlb_page(vma, addr);
- }
- return changed;
-}
+ pte_t pte, int dirty);
static inline pte_t huge_ptep_get(pte_t *ptep)
{
diff --git a/arch/parisc/include/uapi/asm/siginfo.h b/arch/parisc/include/uapi/asm/siginfo.h
index d7034728f..1c75565d9 100644
--- a/arch/parisc/include/uapi/asm/siginfo.h
+++ b/arch/parisc/include/uapi/asm/siginfo.h
@@ -1,6 +1,10 @@
#ifndef _PARISC_SIGINFO_H
#define _PARISC_SIGINFO_H
+#if defined(__LP64__)
+#define __ARCH_SI_PREAMBLE_SIZE (4 * sizeof(int))
+#endif
+
#include <asm-generic/siginfo.h>
#undef NSIGTRAP
diff --git a/arch/parisc/mm/hugetlbpage.c b/arch/parisc/mm/hugetlbpage.c
index f6fdc77a7..54ba39262 100644
--- a/arch/parisc/mm/hugetlbpage.c
+++ b/arch/parisc/mm/hugetlbpage.c
@@ -105,15 +105,13 @@ static inline void purge_tlb_entries_huge(struct mm_struct *mm, unsigned long ad
addr |= _HUGE_PAGE_SIZE_ENCODING_DEFAULT;
for (i = 0; i < (1 << (HPAGE_SHIFT-REAL_HPAGE_SHIFT)); i++) {
- mtsp(mm->context, 1);
- pdtlb(addr);
- if (unlikely(split_tlb))
- pitlb(addr);
+ purge_tlb_entries(mm, addr);
addr += (1UL << REAL_HPAGE_SHIFT);
}
}
-void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+/* __set_huge_pte_at() must be called holding the pa_tlb_lock. */
+static void __set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
pte_t *ptep, pte_t entry)
{
unsigned long addr_start;
@@ -123,14 +121,9 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
addr_start = addr;
for (i = 0; i < (1 << HUGETLB_PAGE_ORDER); i++) {
- /* Directly write pte entry. We could call set_pte_at(mm, addr, ptep, entry)
- * instead, but then we get double locking on pa_tlb_lock. */
- *ptep = entry;
+ set_pte(ptep, entry);
ptep++;
- /* Drop the PAGE_SIZE/non-huge tlb entry */
- purge_tlb_entries(mm, addr);
-
addr += PAGE_SIZE;
pte_val(entry) += PAGE_SIZE;
}
@@ -138,18 +131,61 @@ void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
purge_tlb_entries_huge(mm, addr_start);
}
+void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+ pte_t *ptep, pte_t entry)
+{
+ unsigned long flags;
+
+ purge_tlb_start(flags);
+ __set_huge_pte_at(mm, addr, ptep, entry);
+ purge_tlb_end(flags);
+}
+
pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
pte_t *ptep)
{
+ unsigned long flags;
pte_t entry;
+ purge_tlb_start(flags);
entry = *ptep;
- set_huge_pte_at(mm, addr, ptep, __pte(0));
+ __set_huge_pte_at(mm, addr, ptep, __pte(0));
+ purge_tlb_end(flags);
return entry;
}
+
+void huge_ptep_set_wrprotect(struct mm_struct *mm,
+ unsigned long addr, pte_t *ptep)
+{
+ unsigned long flags;
+ pte_t old_pte;
+
+ purge_tlb_start(flags);
+ old_pte = *ptep;
+ __set_huge_pte_at(mm, addr, ptep, pte_wrprotect(old_pte));
+ purge_tlb_end(flags);
+}
+
+int huge_ptep_set_access_flags(struct vm_area_struct *vma,
+ unsigned long addr, pte_t *ptep,
+ pte_t pte, int dirty)
+{
+ unsigned long flags;
+ int changed;
+
+ purge_tlb_start(flags);
+ changed = !pte_same(*ptep, pte);
+ if (changed) {
+ __set_huge_pte_at(vma->vm_mm, addr, ptep, pte);
+ }
+ purge_tlb_end(flags);
+ return changed;
+}
+
+
int pmd_huge(pmd_t pmd)
{
return 0;
diff --git a/arch/x86/crypto/chacha20-ssse3-x86_64.S b/arch/x86/crypto/chacha20-ssse3-x86_64.S
index 712b13047..3a33124e9 100644
--- a/arch/x86/crypto/chacha20-ssse3-x86_64.S
+++ b/arch/x86/crypto/chacha20-ssse3-x86_64.S
@@ -157,7 +157,9 @@ ENTRY(chacha20_4block_xor_ssse3)
# done with the slightly better performing SSSE3 byte shuffling,
# 7/12-bit word rotation uses traditional shift+OR.
- sub $0x40,%rsp
+ mov %rsp,%r11
+ sub $0x80,%rsp
+ and $~63,%rsp
# x0..15[0-3] = s0..3[0..3]
movq 0x00(%rdi),%xmm1
@@ -620,6 +622,6 @@ ENTRY(chacha20_4block_xor_ssse3)
pxor %xmm1,%xmm15
movdqu %xmm15,0xf0(%rsi)
- add $0x40,%rsp
+ mov %r11,%rsp
ret
ENDPROC(chacha20_4block_xor_ssse3)
diff --git a/block/blk-merge.c b/block/blk-merge.c
index e01405a3e..b966db8f3 100644
--- a/block/blk-merge.c
+++ b/block/blk-merge.c
@@ -68,6 +68,18 @@ static struct bio *blk_bio_write_same_split(struct request_queue *q,
return bio_split(bio, q->limits.max_write_same_sectors, GFP_NOIO, bs);
}
+static inline unsigned get_max_io_size(struct request_queue *q,
+ struct bio *bio)
+{
+ unsigned sectors = blk_max_size_offset(q, bio->bi_iter.bi_sector);
+ unsigned mask = queue_logical_block_size(q) - 1;
+
+ /* aligned to logical block size */
+ sectors &= ~(mask >> 9);
+
+ return sectors;
+}
+
static struct bio *blk_bio_segment_split(struct request_queue *q,
struct bio *bio,
struct bio_set *bs,
@@ -79,11 +91,9 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
unsigned front_seg_size = bio->bi_seg_front_size;
bool do_split = true;
struct bio *new = NULL;
+ const unsigned max_sectors = get_max_io_size(q, bio);
bio_for_each_segment(bv, bio, iter) {
- if (sectors + (bv.bv_len >> 9) > queue_max_sectors(q))
- goto split;
-
/*
* If the queue doesn't support SG gaps and adding this
* offset would create a gap, disallow it.
@@ -91,6 +101,21 @@ static struct bio *blk_bio_segment_split(struct request_queue *q,
if (bvprvp && bvec_gap_to_prev(q, bvprvp, bv.bv_offset))
goto split;
+ if (sectors + (bv.bv_len >> 9) > max_sectors) {
+ /*
+ * Consider this a new segment if we're splitting in
+ * the middle of this vector.
+ */
+ if (nsegs < queue_max_segments(q) &&
+ sectors < max_sectors) {
+ nsegs++;
+ sectors = max_sectors;
+ }
+ if (sectors)
+ goto split;
+ /* Make this single bvec as the 1st segment */
+ }
+
if (bvprvp && blk_queue_cluster(q)) {
if (seg_size + bv.bv_len > queue_max_segment_size(q))
goto new_segment;
diff --git a/crypto/af_alg.c b/crypto/af_alg.c
index a8e7aa3e2..f5e18c2a4 100644
--- a/crypto/af_alg.c
+++ b/crypto/af_alg.c
@@ -76,6 +76,8 @@ int af_alg_register_type(const struct af_alg_type *type)
goto unlock;
type->ops->owner = THIS_MODULE;
+ if (type->ops_nokey)
+ type->ops_nokey->owner = THIS_MODULE;
node->type = type;
list_add(&node->list, &alg_types);
err = 0;
@@ -125,6 +127,26 @@ int af_alg_release(struct socket *sock)
}
EXPORT_SYMBOL_GPL(af_alg_release);
+void af_alg_release_parent(struct sock *sk)
+{
+ struct alg_sock *ask = alg_sk(sk);
+ unsigned int nokey = ask->nokey_refcnt;
+ bool last = nokey && !ask->refcnt;
+
+ sk = ask->parent;
+ ask = alg_sk(sk);
+
+ lock_sock(sk);
+ ask->nokey_refcnt -= nokey;
+ if (!last)
+ last = !--ask->refcnt;
+ release_sock(sk);
+
+ if (last)
+ sock_put(sk);
+}
+EXPORT_SYMBOL_GPL(af_alg_release_parent);
+
static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
{
const u32 forbidden = CRYPTO_ALG_INTERNAL;
@@ -133,6 +155,7 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
struct sockaddr_alg *sa = (void *)uaddr;
const struct af_alg_type *type;
void *private;
+ int err;
if (sock->state == SS_CONNECTED)
return -EINVAL;
@@ -160,16 +183,22 @@ static int alg_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
return PTR_ERR(private);
}
+ err = -EBUSY;
lock_sock(sk);
+ if (ask->refcnt | ask->nokey_refcnt)
+ goto unlock;
swap(ask->type, type);
swap(ask->private, private);
+ err = 0;
+
+unlock:
release_sock(sk);
alg_do_release(type, private);
- return 0;
+ return err;
}
static int alg_setkey(struct sock *sk, char __user *ukey,
@@ -202,11 +231,15 @@ static int alg_setsockopt(struct socket *sock, int level, int optname,
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
const struct af_alg_type *type;
- int err = -ENOPROTOOPT;
+ int err = -EBUSY;
lock_sock(sk);
+ if (ask->refcnt)
+ goto unlock;
+
type = ask->type;
+ err = -ENOPROTOOPT;
if (level != SOL_ALG || !type)
goto unlock;
@@ -238,6 +271,7 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
struct alg_sock *ask = alg_sk(sk);
const struct af_alg_type *type;
struct sock *sk2;
+ unsigned int nokey;
int err;
lock_sock(sk);
@@ -257,20 +291,29 @@ int af_alg_accept(struct sock *sk, struct socket *newsock)
security_sk_clone(sk, sk2);
err = type->accept(ask->private, sk2);
- if (err) {
- sk_free(sk2);
+
+ nokey = err == -ENOKEY;
+ if (nokey && type->accept_nokey)
+ err = type->accept_nokey(ask->private, sk2);
+
+ if (err)
goto unlock;
- }
sk2->sk_family = PF_ALG;
- sock_hold(sk);
+ if (nokey || !ask->refcnt++)
+ sock_hold(sk);
+ ask->nokey_refcnt += nokey;
alg_sk(sk2)->parent = sk;
alg_sk(sk2)->type = type;
+ alg_sk(sk2)->nokey_refcnt = nokey;
newsock->ops = type->ops;
newsock->state = SS_CONNECTED;
+ if (nokey)
+ newsock->ops = type->ops_nokey;
+
err = 0;
unlock:
diff --git a/crypto/ahash.c b/crypto/ahash.c
index 9c1dc8d61..d19b52324 100644
--- a/crypto/ahash.c
+++ b/crypto/ahash.c
@@ -451,6 +451,7 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
struct ahash_alg *alg = crypto_ahash_alg(hash);
hash->setkey = ahash_nosetkey;
+ hash->has_setkey = false;
hash->export = ahash_no_export;
hash->import = ahash_no_import;
@@ -463,8 +464,10 @@ static int crypto_ahash_init_tfm(struct crypto_tfm *tfm)
hash->finup = alg->finup ?: ahash_def_finup;
hash->digest = alg->digest;
- if (alg->setkey)
+ if (alg->setkey) {
hash->setkey = alg->setkey;
+ hash->has_setkey = true;
+ }
if (alg->export)
hash->export = alg->export;
if (alg->import)
diff --git a/crypto/algif_hash.c b/crypto/algif_hash.c
index b4c24fe3d..68a5ceaa0 100644
--- a/crypto/algif_hash.c
+++ b/crypto/algif_hash.c
@@ -34,6 +34,11 @@ struct hash_ctx {
struct ahash_request req;
};
+struct algif_hash_tfm {
+ struct crypto_ahash *hash;
+ bool has_key;
+};
+
static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
size_t ignored)
{
@@ -49,7 +54,8 @@ static int hash_sendmsg(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
if (!ctx->more) {
- err = crypto_ahash_init(&ctx->req);
+ err = af_alg_wait_for_completion(crypto_ahash_init(&ctx->req),
+ &ctx->completion);
if (err)
goto unlock;
}
@@ -120,6 +126,7 @@ static ssize_t hash_sendpage(struct socket *sock, struct page *page,
} else {
if (!ctx->more) {
err = crypto_ahash_init(&ctx->req);
+ err = af_alg_wait_for_completion(err, &ctx->completion);
if (err)
goto unlock;
}
@@ -235,19 +242,151 @@ static struct proto_ops algif_hash_ops = {
.accept = hash_accept,
};
+static int hash_check_key(struct socket *sock)
+{
+ int err = 0;
+ struct sock *psk;
+ struct alg_sock *pask;
+ struct algif_hash_tfm *tfm;
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+
+ lock_sock(sk);
+ if (ask->refcnt)
+ goto unlock_child;
+
+ psk = ask->parent;
+ pask = alg_sk(ask->parent);
+ tfm = pask->private;
+
+ err = -ENOKEY;
+ lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+ if (!tfm->has_key)
+ goto unlock;
+
+ if (!pask->refcnt++)
+ sock_hold(psk);
+
+ ask->refcnt = 1;
+ sock_put(psk);
+
+ err = 0;
+
+unlock:
+ release_sock(psk);
+unlock_child:
+ release_sock(sk);
+
+ return err;
+}
+
+static int hash_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+ size_t size)
+{
+ int err;
+
+ err = hash_check_key(sock);
+ if (err)
+ return err;
+
+ return hash_sendmsg(sock, msg, size);
+}
+
+static ssize_t hash_sendpage_nokey(struct socket *sock, struct page *page,
+ int offset, size_t size, int flags)
+{
+ int err;
+
+ err = hash_check_key(sock);
+ if (err)
+ return err;
+
+ return hash_sendpage(sock, page, offset, size, flags);
+}
+
+static int hash_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+ size_t ignored, int flags)
+{
+ int err;
+
+ err = hash_check_key(sock);
+ if (err)
+ return err;
+
+ return hash_recvmsg(sock, msg, ignored, flags);
+}
+
+static int hash_accept_nokey(struct socket *sock, struct socket *newsock,
+ int flags)
+{
+ int err;
+
+ err = hash_check_key(sock);
+ if (err)
+ return err;
+
+ return hash_accept(sock, newsock, flags);
+}
+
+static struct proto_ops algif_hash_ops_nokey = {
+ .family = PF_ALG,
+
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .getname = sock_no_getname,
+ .ioctl = sock_no_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .getsockopt = sock_no_getsockopt,
+ .mmap = sock_no_mmap,
+ .bind = sock_no_bind,
+ .setsockopt = sock_no_setsockopt,
+ .poll = sock_no_poll,
+
+ .release = af_alg_release,
+ .sendmsg = hash_sendmsg_nokey,
+ .sendpage = hash_sendpage_nokey,
+ .recvmsg = hash_recvmsg_nokey,
+ .accept = hash_accept_nokey,
+};
+
static void *hash_bind(const char *name, u32 type, u32 mask)
{
- return crypto_alloc_ahash(name, type, mask);
+ struct algif_hash_tfm *tfm;
+ struct crypto_ahash *hash;
+
+ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+ if (!tfm)
+ return ERR_PTR(-ENOMEM);
+
+ hash = crypto_alloc_ahash(name, type, mask);
+ if (IS_ERR(hash)) {
+ kfree(tfm);
+ return ERR_CAST(hash);
+ }
+
+ tfm->hash = hash;
+
+ return tfm;
}
static void hash_release(void *private)
{
- crypto_free_ahash(private);
+ struct algif_hash_tfm *tfm = private;
+
+ crypto_free_ahash(tfm->hash);
+ kfree(tfm);
}
static int hash_setkey(void *private, const u8 *key, unsigned int keylen)
{
- return crypto_ahash_setkey(private, key, keylen);
+ struct algif_hash_tfm *tfm = private;
+ int err;
+
+ err = crypto_ahash_setkey(tfm->hash, key, keylen);
+ tfm->has_key = !err;
+
+ return err;
}
static void hash_sock_destruct(struct sock *sk)
@@ -261,12 +400,14 @@ static void hash_sock_destruct(struct sock *sk)
af_alg_release_parent(sk);
}
-static int hash_accept_parent(void *private, struct sock *sk)
+static int hash_accept_parent_nokey(void *private, struct sock *sk)
{
struct hash_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
- unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(private);
- unsigned ds = crypto_ahash_digestsize(private);
+ struct algif_hash_tfm *tfm = private;
+ struct crypto_ahash *hash = tfm->hash;
+ unsigned len = sizeof(*ctx) + crypto_ahash_reqsize(hash);
+ unsigned ds = crypto_ahash_digestsize(hash);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
@@ -286,7 +427,7 @@ static int hash_accept_parent(void *private, struct sock *sk)
ask->private = ctx;
- ahash_request_set_tfm(&ctx->req, private);
+ ahash_request_set_tfm(&ctx->req, hash);
ahash_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
af_alg_complete, &ctx->completion);
@@ -295,12 +436,24 @@ static int hash_accept_parent(void *private, struct sock *sk)
return 0;
}
+static int hash_accept_parent(void *private, struct sock *sk)
+{
+ struct algif_hash_tfm *tfm = private;
+
+ if (!tfm->has_key && crypto_ahash_has_setkey(tfm->hash))
+ return -ENOKEY;
+
+ return hash_accept_parent_nokey(private, sk);
+}
+
static const struct af_alg_type algif_type_hash = {
.bind = hash_bind,
.release = hash_release,
.setkey = hash_setkey,
.accept = hash_accept_parent,
+ .accept_nokey = hash_accept_parent_nokey,
.ops = &algif_hash_ops,
+ .ops_nokey = &algif_hash_ops_nokey,
.name = "hash",
.owner = THIS_MODULE
};
diff --git a/crypto/algif_skcipher.c b/crypto/algif_skcipher.c
index 634b4d1ab..f5e9f9310 100644
--- a/crypto/algif_skcipher.c
+++ b/crypto/algif_skcipher.c
@@ -31,6 +31,11 @@ struct skcipher_sg_list {
struct scatterlist sg[0];
};
+struct skcipher_tfm {
+ struct crypto_skcipher *skcipher;
+ bool has_key;
+};
+
struct skcipher_ctx {
struct list_head tsgl;
struct af_alg_sgl rsgl;
@@ -60,18 +65,10 @@ struct skcipher_async_req {
struct skcipher_async_rsgl first_sgl;
struct list_head list;
struct scatterlist *tsg;
- char iv[];
+ atomic_t *inflight;
+ struct skcipher_request req;
};
-#define GET_SREQ(areq, ctx) (struct skcipher_async_req *)((char *)areq + \
- crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req)))
-
-#define GET_REQ_SIZE(ctx) \
- crypto_skcipher_reqsize(crypto_skcipher_reqtfm(&ctx->req))
-
-#define GET_IV_SIZE(ctx) \
- crypto_skcipher_ivsize(crypto_skcipher_reqtfm(&ctx->req))
-
#define MAX_SGL_ENTS ((4096 - sizeof(struct skcipher_sg_list)) / \
sizeof(struct scatterlist) - 1)
@@ -97,15 +94,12 @@ static void skcipher_free_async_sgls(struct skcipher_async_req *sreq)
static void skcipher_async_cb(struct crypto_async_request *req, int err)
{
- struct sock *sk = req->data;
- struct alg_sock *ask = alg_sk(sk);
- struct skcipher_ctx *ctx = ask->private;
- struct skcipher_async_req *sreq = GET_SREQ(req, ctx);
+ struct skcipher_async_req *sreq = req->data;
struct kiocb *iocb = sreq->iocb;
- atomic_dec(&ctx->inflight);
+ atomic_dec(sreq->inflight);
skcipher_free_async_sgls(sreq);
- kfree(req);
+ kzfree(sreq);
iocb->ki_complete(iocb, err, err);
}
@@ -301,8 +295,11 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
+ struct sock *psk = ask->parent;
+ struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
- struct crypto_skcipher *tfm = crypto_skcipher_reqtfm(&ctx->req);
+ struct skcipher_tfm *skc = pask->private;
+ struct crypto_skcipher *tfm = skc->skcipher;
unsigned ivsize = crypto_skcipher_ivsize(tfm);
struct skcipher_sg_list *sgl;
struct af_alg_control con = {};
@@ -387,7 +384,8 @@ static int skcipher_sendmsg(struct socket *sock, struct msghdr *msg,
sgl = list_entry(ctx->tsgl.prev, struct skcipher_sg_list, list);
sg = sgl->sg;
- sg_unmark_end(sg + sgl->cur);
+ if (sgl->cur)
+ sg_unmark_end(sg + sgl->cur - 1);
do {
i = sgl->cur;
plen = min_t(int, len, PAGE_SIZE);
@@ -503,37 +501,43 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
+ struct sock *psk = ask->parent;
+ struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
+ struct skcipher_tfm *skc = pask->private;
+ struct crypto_skcipher *tfm = skc->skcipher;
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
struct skcipher_async_req *sreq;
struct skcipher_request *req;
struct skcipher_async_rsgl *last_rsgl = NULL;
- unsigned int txbufs = 0, len = 0, tx_nents = skcipher_all_sg_nents(ctx);
- unsigned int reqlen = sizeof(struct skcipher_async_req) +
- GET_REQ_SIZE(ctx) + GET_IV_SIZE(ctx);
+ unsigned int txbufs = 0, len = 0, tx_nents;
+ unsigned int reqsize = crypto_skcipher_reqsize(tfm);
+ unsigned int ivsize = crypto_skcipher_ivsize(tfm);
int err = -ENOMEM;
bool mark = false;
+ char *iv;
- lock_sock(sk);
- req = kmalloc(reqlen, GFP_KERNEL);
- if (unlikely(!req))
- goto unlock;
+ sreq = kzalloc(sizeof(*sreq) + reqsize + ivsize, GFP_KERNEL);
+ if (unlikely(!sreq))
+ goto out;
- sreq = GET_SREQ(req, ctx);
+ req = &sreq->req;
+ iv = (char *)(req + 1) + reqsize;
sreq->iocb = msg->msg_iocb;
- memset(&sreq->first_sgl, '\0', sizeof(struct skcipher_async_rsgl));
INIT_LIST_HEAD(&sreq->list);
+ sreq->inflight = &ctx->inflight;
+
+ lock_sock(sk);
+ tx_nents = skcipher_all_sg_nents(ctx);
sreq->tsg = kcalloc(tx_nents, sizeof(*sg), GFP_KERNEL);
- if (unlikely(!sreq->tsg)) {
- kfree(req);
+ if (unlikely(!sreq->tsg))
goto unlock;
- }
sg_init_table(sreq->tsg, tx_nents);
- memcpy(sreq->iv, ctx->iv, GET_IV_SIZE(ctx));
- skcipher_request_set_tfm(req, crypto_skcipher_reqtfm(&ctx->req));
- skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_BACKLOG,
- skcipher_async_cb, sk);
+ memcpy(iv, ctx->iv, ivsize);
+ skcipher_request_set_tfm(req, tfm);
+ skcipher_request_set_callback(req, CRYPTO_TFM_REQ_MAY_SLEEP,
+ skcipher_async_cb, sreq);
while (iov_iter_count(&msg->msg_iter)) {
struct skcipher_async_rsgl *rsgl;
@@ -609,20 +613,22 @@ static int skcipher_recvmsg_async(struct socket *sock, struct msghdr *msg,
sg_mark_end(sreq->tsg + txbufs - 1);
skcipher_request_set_crypt(req, sreq->tsg, sreq->first_sgl.sgl.sg,
- len, sreq->iv);
+ len, iv);
err = ctx->enc ? crypto_skcipher_encrypt(req) :
crypto_skcipher_decrypt(req);
if (err == -EINPROGRESS) {
atomic_inc(&ctx->inflight);
err = -EIOCBQUEUED;
+ sreq = NULL;
goto unlock;
}
free:
skcipher_free_async_sgls(sreq);
- kfree(req);
unlock:
skcipher_wmem_wakeup(sk);
release_sock(sk);
+ kzfree(sreq);
+out:
return err;
}
@@ -631,9 +637,12 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
{
struct sock *sk = sock->sk;
struct alg_sock *ask = alg_sk(sk);
+ struct sock *psk = ask->parent;
+ struct alg_sock *pask = alg_sk(psk);
struct skcipher_ctx *ctx = ask->private;
- unsigned bs = crypto_skcipher_blocksize(crypto_skcipher_reqtfm(
- &ctx->req));
+ struct skcipher_tfm *skc = pask->private;
+ struct crypto_skcipher *tfm = skc->skcipher;
+ unsigned bs = crypto_skcipher_blocksize(tfm);
struct skcipher_sg_list *sgl;
struct scatterlist *sg;
int err = -EAGAIN;
@@ -642,13 +651,6 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
lock_sock(sk);
while (msg_data_left(msg)) {
- sgl = list_first_entry(&ctx->tsgl,
- struct skcipher_sg_list, list);
- sg = sgl->sg;
-
- while (!sg->length)
- sg++;
-
if (!ctx->used) {
err = skcipher_wait_for_data(sk, flags);
if (err)
@@ -669,6 +671,13 @@ static int skcipher_recvmsg_sync(struct socket *sock, struct msghdr *msg,
if (!used)
goto free;
+ sgl = list_first_entry(&ctx->tsgl,
+ struct skcipher_sg_list, list);
+ sg = sgl->sg;
+
+ while (!sg->length)
+ sg++;
+
skcipher_request_set_crypt(&ctx->req, sg, ctx->rsgl.sg, used,
ctx->iv);
@@ -748,19 +757,139 @@ static struct proto_ops algif_skcipher_ops = {
.poll = skcipher_poll,
};
+static int skcipher_check_key(struct socket *sock)
+{
+ int err = 0;
+ struct sock *psk;
+ struct alg_sock *pask;
+ struct skcipher_tfm *tfm;
+ struct sock *sk = sock->sk;
+ struct alg_sock *ask = alg_sk(sk);
+
+ lock_sock(sk);
+ if (ask->refcnt)
+ goto unlock_child;
+
+ psk = ask->parent;
+ pask = alg_sk(ask->parent);
+ tfm = pask->private;
+
+ err = -ENOKEY;
+ lock_sock_nested(psk, SINGLE_DEPTH_NESTING);
+ if (!tfm->has_key)
+ goto unlock;
+
+ if (!pask->refcnt++)
+ sock_hold(psk);
+
+ ask->refcnt = 1;
+ sock_put(psk);
+
+ err = 0;
+
+unlock:
+ release_sock(psk);
+unlock_child:
+ release_sock(sk);
+
+ return err;
+}
+
+static int skcipher_sendmsg_nokey(struct socket *sock, struct msghdr *msg,
+ size_t size)
+{
+ int err;
+
+ err = skcipher_check_key(sock);
+ if (err)
+ return err;
+
+ return skcipher_sendmsg(sock, msg, size);
+}
+
+static ssize_t skcipher_sendpage_nokey(struct socket *sock, struct page *page,
+ int offset, size_t size, int flags)
+{
+ int err;
+
+ err = skcipher_check_key(sock);
+ if (err)
+ return err;
+
+ return skcipher_sendpage(sock, page, offset, size, flags);
+}
+
+static int skcipher_recvmsg_nokey(struct socket *sock, struct msghdr *msg,
+ size_t ignored, int flags)
+{
+ int err;
+
+ err = skcipher_check_key(sock);
+ if (err)
+ return err;
+
+ return skcipher_recvmsg(sock, msg, ignored, flags);
+}
+
+static struct proto_ops algif_skcipher_ops_nokey = {
+ .family = PF_ALG,
+
+ .connect = sock_no_connect,
+ .socketpair = sock_no_socketpair,
+ .getname = sock_no_getname,
+ .ioctl = sock_no_ioctl,
+ .listen = sock_no_listen,
+ .shutdown = sock_no_shutdown,
+ .getsockopt = sock_no_getsockopt,
+ .mmap = sock_no_mmap,
+ .bind = sock_no_bind,
+ .accept = sock_no_accept,
+ .setsockopt = sock_no_setsockopt,
+
+ .release = af_alg_release,
+ .sendmsg = skcipher_sendmsg_nokey,
+ .sendpage = skcipher_sendpage_nokey,
+ .recvmsg = skcipher_recvmsg_nokey,
+ .poll = skcipher_poll,
+};
+
static void *skcipher_bind(const char *name, u32 type, u32 mask)
{
- return crypto_alloc_skcipher(name, type, mask);
+ struct skcipher_tfm *tfm;
+ struct crypto_skcipher *skcipher;
+
+ tfm = kzalloc(sizeof(*tfm), GFP_KERNEL);
+ if (!tfm)
+ return ERR_PTR(-ENOMEM);
+
+ skcipher = crypto_alloc_skcipher(name, type, mask);
+ if (IS_ERR(skcipher)) {
+ kfree(tfm);
+ return ERR_CAST(skcipher);
+ }
+
+ tfm->skcipher = skcipher;
+
+ return tfm;
}
static void skcipher_release(void *private)
{
- crypto_free_skcipher(private);
+ struct skcipher_tfm *tfm = private;
+
+ crypto_free_skcipher(tfm->skcipher);
+ kfree(tfm);
}
static int skcipher_setkey(void *private, const u8 *key, unsigned int keylen)
{
- return crypto_skcipher_setkey(private, key, keylen);
+ struct skcipher_tfm *tfm = private;
+ int err;
+
+ err = crypto_skcipher_setkey(tfm->skcipher, key, keylen);
+ tfm->has_key = !err;
+
+ return err;
}
static void skcipher_wait(struct sock *sk)
@@ -788,24 +917,26 @@ static void skcipher_sock_destruct(struct sock *sk)
af_alg_release_parent(sk);
}
-static int skcipher_accept_parent(void *private, struct sock *sk)
+static int skcipher_accept_parent_nokey(void *private, struct sock *sk)
{
struct skcipher_ctx *ctx;
struct alg_sock *ask = alg_sk(sk);
- unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(private);
+ struct skcipher_tfm *tfm = private;
+ struct crypto_skcipher *skcipher = tfm->skcipher;
+ unsigned int len = sizeof(*ctx) + crypto_skcipher_reqsize(skcipher);
ctx = sock_kmalloc(sk, len, GFP_KERNEL);
if (!ctx)
return -ENOMEM;
- ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(private),
+ ctx->iv = sock_kmalloc(sk, crypto_skcipher_ivsize(skcipher),
GFP_KERNEL);
if (!ctx->iv) {
sock_kfree_s(sk, ctx, len);
return -ENOMEM;
}
- memset(ctx->iv, 0, crypto_skcipher_ivsize(private));
+ memset(ctx->iv, 0, crypto_skcipher_ivsize(skcipher));
INIT_LIST_HEAD(&ctx->tsgl);
ctx->len = len;
@@ -818,8 +949,9 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
ask->private = ctx;
- skcipher_request_set_tfm(&ctx->req, private);
- skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_BACKLOG,
+ skcipher_request_set_tfm(&ctx->req, skcipher);
+ skcipher_request_set_callback(&ctx->req, CRYPTO_TFM_REQ_MAY_SLEEP |
+ CRYPTO_TFM_REQ_MAY_BACKLOG,
af_alg_complete, &ctx->completion);
sk->sk_destruct = skcipher_sock_destruct;
@@ -827,12 +959,24 @@ static int skcipher_accept_parent(void *private, struct sock *sk)
return 0;
}
+static int skcipher_accept_parent(void *private, struct sock *sk)
+{
+ struct skcipher_tfm *tfm = private;
+
+ if (!tfm->has_key && crypto_skcipher_has_setkey(tfm->skcipher))
+ return -ENOKEY;
+
+ return skcipher_accept_parent_nokey(private, sk);
+}
+
static const struct af_alg_type algif_type_skcipher = {
.bind = skcipher_bind,
.release = skcipher_release,
.setkey = skcipher_setkey,
.accept = skcipher_accept_parent,
+ .accept_nokey = skcipher_accept_parent_nokey,
.ops = &algif_skcipher_ops,
+ .ops_nokey = &algif_skcipher_ops_nokey,
.name = "skcipher",
.owner = THIS_MODULE
};
diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c
index 06f1b60f0..4c0a0e271 100644
--- a/crypto/crc32c_generic.c
+++ b/crypto/crc32c_generic.c
@@ -172,4 +172,3 @@ MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations wrapper for lib/crc32c");
MODULE_LICENSE("GPL");
MODULE_ALIAS_CRYPTO("crc32c");
MODULE_ALIAS_CRYPTO("crc32c-generic");
-MODULE_SOFTDEP("pre: crc32c");
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 237f3795c..43fe85f20 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -499,6 +499,7 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
if (link->dump == NULL)
return -EINVAL;
+ down_read(&crypto_alg_sem);
list_for_each_entry(alg, &crypto_alg_list, cra_list)
dump_alloc += CRYPTO_REPORT_MAXSIZE;
@@ -508,8 +509,11 @@ static int crypto_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
.done = link->done,
.min_dump_alloc = dump_alloc,
};
- return netlink_dump_start(crypto_nlsk, skb, nlh, &c);
+ err = netlink_dump_start(crypto_nlsk, skb, nlh, &c);
}
+ up_read(&crypto_alg_sem);
+
+ return err;
}
err = nlmsg_parse(nlh, crypto_msg_min[type], attrs, CRYPTOCFGA_MAX,
diff --git a/crypto/shash.c b/crypto/shash.c
index ecb1e3d39..359754591 100644
--- a/crypto/shash.c
+++ b/crypto/shash.c
@@ -354,9 +354,10 @@ int crypto_init_shash_ops_async(struct crypto_tfm *tfm)
crt->final = shash_async_final;
crt->finup = shash_async_finup;
crt->digest = shash_async_digest;
+ crt->setkey = shash_async_setkey;
+
+ crt->has_setkey = alg->setkey != shash_no_setkey;
- if (alg->setkey)
- crt->setkey = shash_async_setkey;
if (alg->export)
crt->export = shash_async_export;
if (alg->import)
diff --git a/crypto/skcipher.c b/crypto/skcipher.c
index 7591928be..d199c0b17 100644
--- a/crypto/skcipher.c
+++ b/crypto/skcipher.c
@@ -118,6 +118,7 @@ static int crypto_init_skcipher_ops_blkcipher(struct crypto_tfm *tfm)
skcipher->decrypt = skcipher_decrypt_blkcipher;
skcipher->ivsize = crypto_blkcipher_ivsize(blkcipher);
+ skcipher->has_setkey = calg->cra_blkcipher.max_keysize;
return 0;
}
@@ -210,6 +211,7 @@ static int crypto_init_skcipher_ops_ablkcipher(struct crypto_tfm *tfm)
skcipher->ivsize = crypto_ablkcipher_ivsize(ablkcipher);
skcipher->reqsize = crypto_ablkcipher_reqsize(ablkcipher) +
sizeof(struct ablkcipher_request);
+ skcipher->has_setkey = calg->cra_ablkcipher.max_keysize;
return 0;
}
diff --git a/drivers/ata/ahci.c b/drivers/ata/ahci.c
index f1917908e..f8c0afb80 100644
--- a/drivers/ata/ahci.c
+++ b/drivers/ata/ahci.c
@@ -264,6 +264,26 @@ static const struct pci_device_id ahci_pci_tbl[] = {
{ PCI_VDEVICE(INTEL, 0x3b2b), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2c), board_ahci }, /* PCH RAID */
{ PCI_VDEVICE(INTEL, 0x3b2f), board_ahci }, /* PCH AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b0), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b1), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b2), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b3), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b4), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b5), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b6), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19b7), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19bE), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19bF), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c0), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c1), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c2), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c3), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c4), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c5), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c6), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19c7), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19cE), board_ahci }, /* DNV AHCI */
+ { PCI_VDEVICE(INTEL, 0x19cF), board_ahci }, /* DNV AHCI */
{ PCI_VDEVICE(INTEL, 0x1c02), board_ahci }, /* CPT AHCI */
{ PCI_VDEVICE(INTEL, 0x1c03), board_ahci }, /* CPT AHCI */
{ PCI_VDEVICE(INTEL, 0x1c04), board_ahci }, /* CPT RAID */
diff --git a/drivers/ata/libahci.c b/drivers/ata/libahci.c
index 89254bb3e..27a06e0cd 100644
--- a/drivers/ata/libahci.c
+++ b/drivers/ata/libahci.c
@@ -495,8 +495,8 @@ void ahci_save_initial_config(struct device *dev, struct ahci_host_priv *hpriv)
}
}
- /* fabricate port_map from cap.nr_ports */
- if (!port_map) {
+ /* fabricate port_map from cap.nr_ports for < AHCI 1.3 */
+ if (!port_map && vers < 0x10300) {
port_map = (1 << ahci_nr_ports(cap)) - 1;
dev_warn(dev, "forcing PORTS_IMPL to 0x%x\n", port_map);
diff --git a/drivers/block/zram/zcomp.c b/drivers/block/zram/zcomp.c
index 5cb13ca3a..c53617752 100644
--- a/drivers/block/zram/zcomp.c
+++ b/drivers/block/zram/zcomp.c
@@ -76,7 +76,7 @@ static void zcomp_strm_free(struct zcomp *comp, struct zcomp_strm *zstrm)
*/
static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
{
- struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_KERNEL);
+ struct zcomp_strm *zstrm = kmalloc(sizeof(*zstrm), GFP_NOIO);
if (!zstrm)
return NULL;
@@ -85,7 +85,7 @@ static struct zcomp_strm *zcomp_strm_alloc(struct zcomp *comp)
* allocate 2 pages. 1 for compressed data, plus 1 extra for the
* case when compressed size is larger than the original one
*/
- zstrm->buffer = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO, 1);
+ zstrm->buffer = (void *)__get_free_pages(GFP_NOIO | __GFP_ZERO, 1);
if (!zstrm->private || !zstrm->buffer) {
zcomp_strm_free(comp, zstrm);
zstrm = NULL;
diff --git a/drivers/block/zram/zcomp_lz4.c b/drivers/block/zram/zcomp_lz4.c
index f2afb7e98..dd6083124 100644
--- a/drivers/block/zram/zcomp_lz4.c
+++ b/drivers/block/zram/zcomp_lz4.c
@@ -10,17 +10,36 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/lz4.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include "zcomp_lz4.h"
static void *zcomp_lz4_create(void)
{
- return kzalloc(LZ4_MEM_COMPRESS, GFP_KERNEL);
+ void *ret;
+
+ /*
+ * This function can be called in swapout/fs write path
+ * so we can't use GFP_FS|IO. And it assumes we already
+ * have at least one stream in zram initialization so we
+ * don't do best effort to allocate more stream in here.
+ * A default stream will work well without further multiple
+ * streams. That's why we use NORETRY | NOWARN.
+ */
+ ret = kzalloc(LZ4_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
+ __GFP_NOWARN);
+ if (!ret)
+ ret = __vmalloc(LZ4_MEM_COMPRESS,
+ GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
+ __GFP_ZERO | __GFP_HIGHMEM,
+ PAGE_KERNEL);
+ return ret;
}
static void zcomp_lz4_destroy(void *private)
{
- kfree(private);
+ kvfree(private);
}
static int zcomp_lz4_compress(const unsigned char *src, unsigned char *dst,
diff --git a/drivers/block/zram/zcomp_lzo.c b/drivers/block/zram/zcomp_lzo.c
index da1bc47d5..edc549920 100644
--- a/drivers/block/zram/zcomp_lzo.c
+++ b/drivers/block/zram/zcomp_lzo.c
@@ -10,17 +10,36 @@
#include <linux/kernel.h>
#include <linux/slab.h>
#include <linux/lzo.h>
+#include <linux/vmalloc.h>
+#include <linux/mm.h>
#include "zcomp_lzo.h"
static void *lzo_create(void)
{
- return kzalloc(LZO1X_MEM_COMPRESS, GFP_KERNEL);
+ void *ret;
+
+ /*
+ * This function can be called in swapout/fs write path
+ * so we can't use GFP_FS|IO. And it assumes we already
+ * have at least one stream in zram initialization so we
+ * don't do best effort to allocate more stream in here.
+ * A default stream will work well without further multiple
+ * streams. That's why we use NORETRY | NOWARN.
+ */
+ ret = kzalloc(LZO1X_MEM_COMPRESS, GFP_NOIO | __GFP_NORETRY |
+ __GFP_NOWARN);
+ if (!ret)
+ ret = __vmalloc(LZO1X_MEM_COMPRESS,
+ GFP_NOIO | __GFP_NORETRY | __GFP_NOWARN |
+ __GFP_ZERO | __GFP_HIGHMEM,
+ PAGE_KERNEL);
+ return ret;
}
static void lzo_destroy(void *private)
{
- kfree(private);
+ kvfree(private);
}
static int lzo_compress(const unsigned char *src, unsigned char *dst,
diff --git a/drivers/block/zram/zram_drv.c b/drivers/block/zram/zram_drv.c
index 47915d736..370c2f760 100644
--- a/drivers/block/zram/zram_drv.c
+++ b/drivers/block/zram/zram_drv.c
@@ -1325,7 +1325,6 @@ static int zram_remove(struct zram *zram)
pr_info("Removed device: %s\n", zram->disk->disk_name);
- idr_remove(&zram_index_idr, zram->disk->first_minor);
blk_cleanup_queue(zram->disk->queue);
del_gendisk(zram->disk);
put_disk(zram->disk);
@@ -1367,10 +1366,12 @@ static ssize_t hot_remove_store(struct class *class,
mutex_lock(&zram_index_mutex);
zram = idr_find(&zram_index_idr, dev_id);
- if (zram)
+ if (zram) {
ret = zram_remove(zram);
- else
+ idr_remove(&zram_index_idr, dev_id);
+ } else {
ret = -ENODEV;
+ }
mutex_unlock(&zram_index_mutex);
return ret ? ret : count;
diff --git a/drivers/crypto/atmel-sha.c b/drivers/crypto/atmel-sha.c
index 660d8c065..3178f84d2 100644
--- a/drivers/crypto/atmel-sha.c
+++ b/drivers/crypto/atmel-sha.c
@@ -783,7 +783,7 @@ static void atmel_sha_finish_req(struct ahash_request *req, int err)
dd->flags &= ~(SHA_FLAGS_BUSY | SHA_FLAGS_FINAL | SHA_FLAGS_CPU |
SHA_FLAGS_DMA_READY | SHA_FLAGS_OUTPUT_READY);
- clk_disable_unprepare(dd->iclk);
+ clk_disable(dd->iclk);
if (req->base.complete)
req->base.complete(&req->base, err);
@@ -796,7 +796,7 @@ static int atmel_sha_hw_init(struct atmel_sha_dev *dd)
{
int err;
- err = clk_prepare_enable(dd->iclk);
+ err = clk_enable(dd->iclk);
if (err)
return err;
@@ -823,7 +823,7 @@ static void atmel_sha_hw_version_init(struct atmel_sha_dev *dd)
dev_info(dd->dev,
"version: 0x%x\n", dd->hw_version);
- clk_disable_unprepare(dd->iclk);
+ clk_disable(dd->iclk);
}
static int atmel_sha_handle_queue(struct atmel_sha_dev *dd,
@@ -1411,6 +1411,10 @@ static int atmel_sha_probe(struct platform_device *pdev)
goto res_err;
}
+ err = clk_prepare(sha_dd->iclk);
+ if (err)
+ goto res_err;
+
atmel_sha_hw_version_init(sha_dd);
atmel_sha_get_cap(sha_dd);
@@ -1422,12 +1426,12 @@ static int atmel_sha_probe(struct platform_device *pdev)
if (IS_ERR(pdata)) {
dev_err(&pdev->dev, "platform data not available\n");
err = PTR_ERR(pdata);
- goto res_err;
+ goto iclk_unprepare;
}
}
if (!pdata->dma_slave) {
err = -ENXIO;
- goto res_err;
+ goto iclk_unprepare;
}
err = atmel_sha_dma_init(sha_dd, pdata);
if (err)
@@ -1458,6 +1462,8 @@ err_algs:
if (sha_dd->caps.has_dma)
atmel_sha_dma_cleanup(sha_dd);
err_sha_dma:
+iclk_unprepare:
+ clk_unprepare(sha_dd->iclk);
res_err:
tasklet_kill(&sha_dd->done_task);
sha_dd_err:
@@ -1484,12 +1490,7 @@ static int atmel_sha_remove(struct platform_device *pdev)
if (sha_dd->caps.has_dma)
atmel_sha_dma_cleanup(sha_dd);
- iounmap(sha_dd->io_base);
-
- clk_put(sha_dd->iclk);
-
- if (sha_dd->irq >= 0)
- free_irq(sha_dd->irq, sha_dd);
+ clk_unprepare(sha_dd->iclk);
return 0;
}
diff --git a/drivers/crypto/caam/ctrl.c b/drivers/crypto/caam/ctrl.c
index 8abb4bc54..69d4a1326 100644
--- a/drivers/crypto/caam/ctrl.c
+++ b/drivers/crypto/caam/ctrl.c
@@ -534,8 +534,8 @@ static int caam_probe(struct platform_device *pdev)
* long pointers in master configuration register
*/
clrsetbits_32(&ctrl->mcr, MCFGR_AWCACHE_MASK, MCFGR_AWCACHE_CACH |
- MCFGR_WDENABLE | (sizeof(dma_addr_t) == sizeof(u64) ?
- MCFGR_LONG_PTR : 0));
+ MCFGR_AWCACHE_BUFF | MCFGR_WDENABLE |
+ (sizeof(dma_addr_t) == sizeof(u64) ? MCFGR_LONG_PTR : 0));
/*
* Read the Compile Time paramters and SCFGR to determine
diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index 0643e3366..c0656e7f3 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -306,7 +306,7 @@ static int mv_cesa_dev_dma_init(struct mv_cesa_dev *cesa)
return -ENOMEM;
dma->padding_pool = dmam_pool_create("cesa_padding", dev, 72, 1, 0);
- if (!dma->cache_pool)
+ if (!dma->padding_pool)
return -ENOMEM;
cesa->dma = dma;
diff --git a/drivers/crypto/sunxi-ss/sun4i-ss-core.c b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
index eab6fe227..107cd2a41 100644
--- a/drivers/crypto/sunxi-ss/sun4i-ss-core.c
+++ b/drivers/crypto/sunxi-ss/sun4i-ss-core.c
@@ -39,6 +39,7 @@ static struct sun4i_ss_alg_template ss_algs[] = {
.import = sun4i_hash_import_md5,
.halg = {
.digestsize = MD5_DIGEST_SIZE,
+ .statesize = sizeof(struct md5_state),
.base = {
.cra_name = "md5",
.cra_driver_name = "md5-sun4i-ss",
@@ -66,6 +67,7 @@ static struct sun4i_ss_alg_template ss_algs[] = {
.import = sun4i_hash_import_sha1,
.halg = {
.digestsize = SHA1_DIGEST_SIZE,
+ .statesize = sizeof(struct sha1_state),
.base = {
.cra_name = "sha1",
.cra_driver_name = "sha1-sun4i-ss",
diff --git a/drivers/hid/hid-multitouch.c b/drivers/hid/hid-multitouch.c
index 3d664d013..2b8ff18d3 100644
--- a/drivers/hid/hid-multitouch.c
+++ b/drivers/hid/hid-multitouch.c
@@ -357,8 +357,19 @@ static void mt_feature_mapping(struct hid_device *hdev,
break;
}
- td->inputmode = field->report->id;
- td->inputmode_index = usage->usage_index;
+ if (td->inputmode < 0) {
+ td->inputmode = field->report->id;
+ td->inputmode_index = usage->usage_index;
+ } else {
+ /*
+ * Some elan panels wrongly declare 2 input mode
+ * features, and silently ignore when we set the
+ * value in the second field. Skip the second feature
+ * and hope for the best.
+ */
+ dev_info(&hdev->dev,
+ "Ignoring the extra HID_DG_INPUTMODE\n");
+ }
break;
case HID_DG_CONTACTMAX:
diff --git a/drivers/hid/usbhid/hid-core.c b/drivers/hid/usbhid/hid-core.c
index 36712e9f5..5dd426fee 100644
--- a/drivers/hid/usbhid/hid-core.c
+++ b/drivers/hid/usbhid/hid-core.c
@@ -477,8 +477,6 @@ static void hid_ctrl(struct urb *urb)
struct usbhid_device *usbhid = hid->driver_data;
int unplug = 0, status = urb->status;
- spin_lock(&usbhid->lock);
-
switch (status) {
case 0: /* success */
if (usbhid->ctrl[usbhid->ctrltail].dir == USB_DIR_IN)
@@ -498,6 +496,8 @@ static void hid_ctrl(struct urb *urb)
hid_warn(urb->dev, "ctrl urb status %d received\n", status);
}
+ spin_lock(&usbhid->lock);
+
if (unplug) {
usbhid->ctrltail = usbhid->ctrlhead;
} else {
diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 7df977776..dad768caa 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -405,17 +405,18 @@ static void __arm_lpae_free_pgtable(struct arm_lpae_io_pgtable *data, int lvl,
arm_lpae_iopte *start, *end;
unsigned long table_size;
- /* Only leaf entries at the last level */
- if (lvl == ARM_LPAE_MAX_LEVELS - 1)
- return;
-
if (lvl == ARM_LPAE_START_LVL(data))
table_size = data->pgd_size;
else
table_size = 1UL << data->pg_shift;
start = ptep;
- end = (void *)ptep + table_size;
+
+ /* Only leaf entries at the last level */
+ if (lvl == ARM_LPAE_MAX_LEVELS - 1)
+ end = ptep;
+ else
+ end = (void *)ptep + table_size;
while (ptep != end) {
arm_lpae_iopte pte = *ptep++;
diff --git a/drivers/md/md.c b/drivers/md/md.c
index 61aacab42..b1e1f6b95 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -2017,28 +2017,32 @@ int md_integrity_register(struct mddev *mddev)
}
EXPORT_SYMBOL(md_integrity_register);
-/* Disable data integrity if non-capable/non-matching disk is being added */
-void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
+/*
+ * Attempt to add an rdev, but only if it is consistent with the current
+ * integrity profile
+ */
+int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev)
{
struct blk_integrity *bi_rdev;
struct blk_integrity *bi_mddev;
+ char name[BDEVNAME_SIZE];
if (!mddev->gendisk)
- return;
+ return 0;
bi_rdev = bdev_get_integrity(rdev->bdev);
bi_mddev = blk_get_integrity(mddev->gendisk);
if (!bi_mddev) /* nothing to do */
- return;
- if (rdev->raid_disk < 0) /* skip spares */
- return;
- if (bi_rdev && blk_integrity_compare(mddev->gendisk,
- rdev->bdev->bd_disk) >= 0)
- return;
- WARN_ON_ONCE(!mddev->suspended);
- printk(KERN_NOTICE "disabling data integrity on %s\n", mdname(mddev));
- blk_integrity_unregister(mddev->gendisk);
+ return 0;
+
+ if (blk_integrity_compare(mddev->gendisk, rdev->bdev->bd_disk) != 0) {
+ printk(KERN_NOTICE "%s: incompatible integrity profile for %s\n",
+ mdname(mddev), bdevname(rdev->bdev, name));
+ return -ENXIO;
+ }
+
+ return 0;
}
EXPORT_SYMBOL(md_integrity_add_rdev);
diff --git a/drivers/md/md.h b/drivers/md/md.h
index ca0b643fe..dfa57b415 100644
--- a/drivers/md/md.h
+++ b/drivers/md/md.h
@@ -657,7 +657,7 @@ extern void md_wait_for_blocked_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern void md_set_array_sectors(struct mddev *mddev, sector_t array_sectors);
extern int md_check_no_bitmap(struct mddev *mddev);
extern int md_integrity_register(struct mddev *mddev);
-extern void md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
+extern int md_integrity_add_rdev(struct md_rdev *rdev, struct mddev *mddev);
extern int strict_strtoul_scaled(const char *cp, unsigned long *res, int scale);
extern void mddev_init(struct mddev *mddev);
diff --git a/drivers/md/multipath.c b/drivers/md/multipath.c
index 7331a80d8..0a72ab6e6 100644
--- a/drivers/md/multipath.c
+++ b/drivers/md/multipath.c
@@ -257,6 +257,9 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
disk_stack_limits(mddev->gendisk, rdev->bdev,
rdev->data_offset << 9);
+ err = md_integrity_add_rdev(rdev, mddev);
+ if (err)
+ break;
spin_lock_irq(&conf->device_lock);
mddev->degraded--;
rdev->raid_disk = path;
@@ -264,9 +267,6 @@ static int multipath_add_disk(struct mddev *mddev, struct md_rdev *rdev)
spin_unlock_irq(&conf->device_lock);
rcu_assign_pointer(p->rdev, rdev);
err = 0;
- mddev_suspend(mddev);
- md_integrity_add_rdev(rdev, mddev);
- mddev_resume(mddev);
break;
}
diff --git a/drivers/md/raid1.c b/drivers/md/raid1.c
index e2169ff6e..c4b913409 100644
--- a/drivers/md/raid1.c
+++ b/drivers/md/raid1.c
@@ -1589,6 +1589,9 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (mddev->recovery_disabled == conf->recovery_disabled)
return -EBUSY;
+ if (md_integrity_add_rdev(rdev, mddev))
+ return -ENXIO;
+
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
@@ -1632,9 +1635,6 @@ static int raid1_add_disk(struct mddev *mddev, struct md_rdev *rdev)
break;
}
}
- mddev_suspend(mddev);
- md_integrity_add_rdev(rdev, mddev);
- mddev_resume(mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
print_conf(conf);
diff --git a/drivers/md/raid10.c b/drivers/md/raid10.c
index 84e597e1c..ce959b4ae 100644
--- a/drivers/md/raid10.c
+++ b/drivers/md/raid10.c
@@ -1698,6 +1698,9 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
if (rdev->saved_raid_disk < 0 && !_enough(conf, 1, -1))
return -EINVAL;
+ if (md_integrity_add_rdev(rdev, mddev))
+ return -ENXIO;
+
if (rdev->raid_disk >= 0)
first = last = rdev->raid_disk;
@@ -1739,9 +1742,6 @@ static int raid10_add_disk(struct mddev *mddev, struct md_rdev *rdev)
rcu_assign_pointer(p->rdev, rdev);
break;
}
- mddev_suspend(mddev);
- md_integrity_add_rdev(rdev, mddev);
- mddev_resume(mddev);
if (mddev->queue && blk_queue_discard(bdev_get_queue(rdev->bdev)))
queue_flag_set_unlocked(QUEUE_FLAG_DISCARD, mddev->queue);
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 728d2cc8a..175a76114 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -478,7 +478,6 @@ static const struct i2c_device_id ir_kbd_id[] = {
{ "ir_rx_z8f0811_hdpvr", 0 },
{ }
};
-MODULE_DEVICE_TABLE(i2c, ir_kbd_id);
static struct i2c_driver ir_kbd_driver = {
.driver = {
diff --git a/drivers/media/pci/saa7134/saa7134-alsa.c b/drivers/media/pci/saa7134/saa7134-alsa.c
index 1d2c310ce..94f816244 100644
--- a/drivers/media/pci/saa7134/saa7134-alsa.c
+++ b/drivers/media/pci/saa7134/saa7134-alsa.c
@@ -1211,6 +1211,8 @@ static int alsa_device_init(struct saa7134_dev *dev)
static int alsa_device_exit(struct saa7134_dev *dev)
{
+ if (!snd_saa7134_cards[dev->nr])
+ return 1;
snd_card_free(snd_saa7134_cards[dev->nr]);
snd_saa7134_cards[dev->nr] = NULL;
@@ -1260,7 +1262,8 @@ static void saa7134_alsa_exit(void)
int idx;
for (idx = 0; idx < SNDRV_CARDS; idx++) {
- snd_card_free(snd_saa7134_cards[idx]);
+ if (snd_saa7134_cards[idx])
+ snd_card_free(snd_saa7134_cards[idx]);
}
saa7134_dmasound_init = NULL;
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index ece544efc..3ff583f16 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -3995,6 +3995,9 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
return ret;
}
+ if (!mtd->name && mtd->dev.parent)
+ mtd->name = dev_name(mtd->dev.parent);
+
/* Set the default functions */
nand_set_defaults(chip, chip->options & NAND_BUSWIDTH_16);
diff --git a/drivers/net/wireless/realtek/rtlwifi/regd.c b/drivers/net/wireless/realtek/rtlwifi/regd.c
index a62bf0a65..5be34118e 100644
--- a/drivers/net/wireless/realtek/rtlwifi/regd.c
+++ b/drivers/net/wireless/realtek/rtlwifi/regd.c
@@ -351,7 +351,6 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select(
case COUNTRY_CODE_SPAIN:
case COUNTRY_CODE_FRANCE:
case COUNTRY_CODE_ISRAEL:
- case COUNTRY_CODE_WORLD_WIDE_13:
return &rtl_regdom_12_13;
case COUNTRY_CODE_MKK:
case COUNTRY_CODE_MKK1:
@@ -360,6 +359,7 @@ static const struct ieee80211_regdomain *_rtl_regdomain_select(
return &rtl_regdom_14_60_64;
case COUNTRY_CODE_GLOBAL_DOMAIN:
return &rtl_regdom_14;
+ case COUNTRY_CODE_WORLD_WIDE_13:
case COUNTRY_CODE_WORLD_WIDE_13_5G_ALL:
return &rtl_regdom_12_13_5g_all;
default:
diff --git a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
index 2f9cf34a7..d83100479 100644
--- a/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
+++ b/drivers/net/wireless/realtek/rtlwifi/rtl8821ae/sw.c
@@ -95,8 +95,6 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
rtl8821ae_bt_reg_init(hw);
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
- rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -168,12 +166,15 @@ int rtl8821ae_init_sw_vars(struct ieee80211_hw *hw)
rtlpriv->psc.swctrl_lps = rtlpriv->cfg->mod_params->swctrl_lps;
rtlpriv->psc.fwctrl_lps = rtlpriv->cfg->mod_params->fwctrl_lps;
rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
- rtlpci->msi_support = rtlpriv->cfg->mod_params->int_clear;
+ rtlpci->int_clear = rtlpriv->cfg->mod_params->int_clear;
+ rtlpriv->cfg->mod_params->sw_crypto =
+ rtlpriv->cfg->mod_params->sw_crypto;
+ rtlpriv->cfg->mod_params->disable_watchdog =
+ rtlpriv->cfg->mod_params->disable_watchdog;
if (rtlpriv->cfg->mod_params->disable_watchdog)
pr_info("watchdog disabled\n");
rtlpriv->psc.reg_fwctrl_lps = 3;
rtlpriv->psc.reg_max_lps_awakeintvl = 5;
- rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
/* for ASPM, you can close aspm through
* set const_support_pciaspm = 0
diff --git a/drivers/net/wireless/ti/wlcore/io.h b/drivers/net/wireless/ti/wlcore/io.h
index 0305729d0..10cf37476 100644
--- a/drivers/net/wireless/ti/wlcore/io.h
+++ b/drivers/net/wireless/ti/wlcore/io.h
@@ -207,19 +207,23 @@ static inline int __must_check wlcore_write_reg(struct wl1271 *wl, int reg,
static inline void wl1271_power_off(struct wl1271 *wl)
{
- int ret;
+ int ret = 0;
if (!test_bit(WL1271_FLAG_GPIO_POWER, &wl->flags))
return;
- ret = wl->if_ops->power(wl->dev, false);
+ if (wl->if_ops->power)
+ ret = wl->if_ops->power(wl->dev, false);
if (!ret)
clear_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
}
static inline int wl1271_power_on(struct wl1271 *wl)
{
- int ret = wl->if_ops->power(wl->dev, true);
+ int ret = 0;
+
+ if (wl->if_ops->power)
+ ret = wl->if_ops->power(wl->dev, true);
if (ret == 0)
set_bit(WL1271_FLAG_GPIO_POWER, &wl->flags);
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 236b41090..44f059f7f 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -73,7 +73,10 @@
*/
#define SPI_AGGR_BUFFER_SIZE (4 * PAGE_SIZE)
-#define WSPI_MAX_NUM_OF_CHUNKS (SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE)
+/* Maximum number of SPI write chunks */
+#define WSPI_MAX_NUM_OF_CHUNKS \
+ ((SPI_AGGR_BUFFER_SIZE / WSPI_MAX_CHUNK_SIZE) + 1)
+
struct wl12xx_spi_glue {
struct device *dev;
@@ -268,9 +271,10 @@ static int __must_check wl12xx_spi_raw_write(struct device *child, int addr,
void *buf, size_t len, bool fixed)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
- struct spi_transfer t[2 * (WSPI_MAX_NUM_OF_CHUNKS + 1)];
+ /* SPI write buffers - 2 for each chunk */
+ struct spi_transfer t[2 * WSPI_MAX_NUM_OF_CHUNKS];
struct spi_message m;
- u32 commands[WSPI_MAX_NUM_OF_CHUNKS];
+ u32 commands[WSPI_MAX_NUM_OF_CHUNKS]; /* 1 command per chunk */
u32 *cmd;
u32 chunk_len;
int i;
diff --git a/drivers/pci/bus.c b/drivers/pci/bus.c
index d3346d239..89b3befc7 100644
--- a/drivers/pci/bus.c
+++ b/drivers/pci/bus.c
@@ -140,6 +140,8 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
type_mask |= IORESOURCE_TYPE_BITS;
pci_bus_for_each_resource(bus, r, i) {
+ resource_size_t min_used = min;
+
if (!r)
continue;
@@ -163,12 +165,12 @@ static int pci_bus_alloc_from_region(struct pci_bus *bus, struct resource *res,
* overrides "min".
*/
if (avail.start)
- min = avail.start;
+ min_used = avail.start;
max = avail.end;
/* Ok, try it out.. */
- ret = allocate_resource(r, res, size, min, max,
+ ret = allocate_resource(r, res, size, min_used, max,
align, alignf, alignf_data);
if (ret == 0)
return 0;
diff --git a/drivers/pci/host/pci-dra7xx.c b/drivers/pci/host/pci-dra7xx.c
index 8c3688046..923607bda 100644
--- a/drivers/pci/host/pci-dra7xx.c
+++ b/drivers/pci/host/pci-dra7xx.c
@@ -302,7 +302,8 @@ static int __init dra7xx_add_pcie_port(struct dra7xx_pcie *dra7xx,
}
ret = devm_request_irq(&pdev->dev, pp->irq,
- dra7xx_pcie_msi_irq_handler, IRQF_SHARED,
+ dra7xx_pcie_msi_irq_handler,
+ IRQF_SHARED | IRQF_NO_THREAD,
"dra7-pcie-msi", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request irq\n");
diff --git a/drivers/pci/host/pci-exynos.c b/drivers/pci/host/pci-exynos.c
index 01095e116..d997d22d4 100644
--- a/drivers/pci/host/pci-exynos.c
+++ b/drivers/pci/host/pci-exynos.c
@@ -522,7 +522,8 @@ static int __init exynos_add_pcie_port(struct pcie_port *pp,
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
exynos_pcie_msi_irq_handler,
- IRQF_SHARED, "exynos-pcie", pp);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ "exynos-pcie", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request msi irq\n");
return ret;
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index 22e822412..9ce7cd148 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -537,7 +537,8 @@ static int __init imx6_add_pcie_port(struct pcie_port *pp,
ret = devm_request_irq(&pdev->dev, pp->msi_irq,
imx6_pcie_msi_handler,
- IRQF_SHARED, "mx6-pcie-msi", pp);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ "mx6-pcie-msi", pp);
if (ret) {
dev_err(&pdev->dev, "failed to request MSI irq\n");
return ret;
diff --git a/drivers/pci/host/pci-tegra.c b/drivers/pci/host/pci-tegra.c
index 3018ae52e..30323114c 100644
--- a/drivers/pci/host/pci-tegra.c
+++ b/drivers/pci/host/pci-tegra.c
@@ -1288,7 +1288,7 @@ static int tegra_pcie_enable_msi(struct tegra_pcie *pcie)
msi->irq = err;
- err = request_irq(msi->irq, tegra_pcie_msi_irq, 0,
+ err = request_irq(msi->irq, tegra_pcie_msi_irq, IRQF_NO_THREAD,
tegra_msi_irq_chip.name, pcie);
if (err < 0) {
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
diff --git a/drivers/pci/host/pcie-rcar.c b/drivers/pci/host/pcie-rcar.c
index f4fa6c537..414c33686 100644
--- a/drivers/pci/host/pcie-rcar.c
+++ b/drivers/pci/host/pcie-rcar.c
@@ -720,14 +720,16 @@ static int rcar_pcie_enable_msi(struct rcar_pcie *pcie)
/* Two irqs are for MSI, but they are also used for non-MSI irqs */
err = devm_request_irq(&pdev->dev, msi->irq1, rcar_pcie_msi_irq,
- IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ rcar_msi_irq_chip.name, pcie);
if (err < 0) {
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
goto err;
}
err = devm_request_irq(&pdev->dev, msi->irq2, rcar_pcie_msi_irq,
- IRQF_SHARED, rcar_msi_irq_chip.name, pcie);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ rcar_msi_irq_chip.name, pcie);
if (err < 0) {
dev_err(&pdev->dev, "failed to request IRQ: %d\n", err);
goto err;
diff --git a/drivers/pci/host/pcie-spear13xx.c b/drivers/pci/host/pcie-spear13xx.c
index b95b7563c..a6cd8233e 100644
--- a/drivers/pci/host/pcie-spear13xx.c
+++ b/drivers/pci/host/pcie-spear13xx.c
@@ -279,7 +279,8 @@ static int spear13xx_add_pcie_port(struct pcie_port *pp,
return -ENODEV;
}
ret = devm_request_irq(dev, pp->irq, spear13xx_pcie_irq_handler,
- IRQF_SHARED, "spear1340-pcie", pp);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ "spear1340-pcie", pp);
if (ret) {
dev_err(dev, "failed to request irq %d\n", pp->irq);
return ret;
diff --git a/drivers/pci/host/pcie-xilinx.c b/drivers/pci/host/pcie-xilinx.c
index 3c7a0d580..4cfa46360 100644
--- a/drivers/pci/host/pcie-xilinx.c
+++ b/drivers/pci/host/pcie-xilinx.c
@@ -781,7 +781,8 @@ static int xilinx_pcie_parse_dt(struct xilinx_pcie_port *port)
port->irq = irq_of_parse_and_map(node, 0);
err = devm_request_irq(dev, port->irq, xilinx_pcie_intr_handler,
- IRQF_SHARED, "xilinx-pcie", port);
+ IRQF_SHARED | IRQF_NO_THREAD,
+ "xilinx-pcie", port);
if (err) {
dev_err(dev, "unable to request irq %d\n", port->irq);
return err;
diff --git a/drivers/tty/n_tty.c b/drivers/tty/n_tty.c
index e49c2bce5..cf000b331 100644
--- a/drivers/tty/n_tty.c
+++ b/drivers/tty/n_tty.c
@@ -258,16 +258,13 @@ static void n_tty_check_throttle(struct tty_struct *tty)
static void n_tty_check_unthrottle(struct tty_struct *tty)
{
- if (tty->driver->type == TTY_DRIVER_TYPE_PTY &&
- tty->link->ldisc->ops->write_wakeup == n_tty_write_wakeup) {
+ if (tty->driver->type == TTY_DRIVER_TYPE_PTY) {
if (chars_in_buffer(tty) > TTY_THRESHOLD_UNTHROTTLE)
return;
if (!tty->count)
return;
n_tty_kick_worker(tty);
- n_tty_write_wakeup(tty->link);
- if (waitqueue_active(&tty->link->write_wait))
- wake_up_interruptible_poll(&tty->link->write_wait, POLLOUT);
+ tty_wakeup(tty->link);
return;
}
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index bcc8e1e8b..7cef54334 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -1462,13 +1462,13 @@ static int tty_reopen(struct tty_struct *tty)
{
struct tty_driver *driver = tty->driver;
- if (!tty->count)
- return -EIO;
-
if (driver->type == TTY_DRIVER_TYPE_PTY &&
driver->subtype == PTY_TYPE_MASTER)
return -EIO;
+ if (!tty->count)
+ return -EAGAIN;
+
if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
return -EBUSY;
@@ -2069,7 +2069,12 @@ retry_open:
if (tty) {
mutex_unlock(&tty_mutex);
- tty_lock(tty);
+ retval = tty_lock_interruptible(tty);
+ if (retval) {
+ if (retval == -EINTR)
+ retval = -ERESTARTSYS;
+ goto err_unref;
+ }
/* safe to drop the kref from tty_driver_lookup_tty() */
tty_kref_put(tty);
retval = tty_reopen(tty);
@@ -2087,7 +2092,11 @@ retry_open:
if (IS_ERR(tty)) {
retval = PTR_ERR(tty);
- goto err_file;
+ if (retval != -EAGAIN || signal_pending(current))
+ goto err_file;
+ tty_free_file(filp);
+ schedule();
+ goto retry_open;
}
tty_add_file(tty, filp);
@@ -2156,6 +2165,7 @@ retry_open:
return 0;
err_unlock:
mutex_unlock(&tty_mutex);
+err_unref:
/* after locks to avoid deadlock */
if (!IS_ERR_OR_NULL(driver))
tty_driver_kref_put(driver);
@@ -2653,6 +2663,28 @@ static int tiocsetd(struct tty_struct *tty, int __user *p)
}
/**
+ * tiocgetd - get line discipline
+ * @tty: tty device
+ * @p: pointer to user data
+ *
+ * Retrieves the line discipline id directly from the ldisc.
+ *
+ * Locking: waits for ldisc reference (in case the line discipline
+ * is changing or the tty is being hungup)
+ */
+
+static int tiocgetd(struct tty_struct *tty, int __user *p)
+{
+ struct tty_ldisc *ld;
+ int ret;
+
+ ld = tty_ldisc_ref_wait(tty);
+ ret = put_user(ld->ops->num, p);
+ tty_ldisc_deref(ld);
+ return ret;
+}
+
+/**
* send_break - performed time break
* @tty: device to break on
* @duration: timeout in mS
@@ -2878,7 +2910,7 @@ long tty_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
case TIOCGSID:
return tiocgsid(tty, real_tty, p);
case TIOCGETD:
- return put_user(tty->ldisc->ops->num, (int __user *)p);
+ return tiocgetd(tty, p);
case TIOCSETD:
return tiocsetd(tty, p);
case TIOCVHANGUP:
diff --git a/drivers/tty/tty_mutex.c b/drivers/tty/tty_mutex.c
index 0efcf713b..d09293bc0 100644
--- a/drivers/tty/tty_mutex.c
+++ b/drivers/tty/tty_mutex.c
@@ -22,6 +22,14 @@ void __lockfunc tty_lock(struct tty_struct *tty)
}
EXPORT_SYMBOL(tty_lock);
+int tty_lock_interruptible(struct tty_struct *tty)
+{
+ if (WARN(tty->magic != TTY_MAGIC, "L Bad %p\n", tty))
+ return -EIO;
+ tty_kref_get(tty);
+ return mutex_lock_interruptible(&tty->legacy_mutex);
+}
+
void __lockfunc tty_unlock(struct tty_struct *tty)
{
if (tty->magic != TTY_MAGIC) {
diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c
index 26ca4f910..e4c70dce3 100644
--- a/drivers/usb/class/cdc-acm.c
+++ b/drivers/usb/class/cdc-acm.c
@@ -428,7 +428,8 @@ static void acm_read_bulk_callback(struct urb *urb)
set_bit(rb->index, &acm->read_urbs_free);
dev_dbg(&acm->data->dev, "%s - non-zero urb status: %d\n",
__func__, status);
- return;
+ if ((status != -ENOENT) || (urb->actual_length == 0))
+ return;
}
usb_mark_last_busy(acm->dev);
@@ -1404,6 +1405,8 @@ made_compressed_probe:
usb_sndbulkpipe(usb_dev, epwrite->bEndpointAddress),
NULL, acm->writesize, acm_write_bulk, snd);
snd->urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ if (quirks & SEND_ZERO_PACKET)
+ snd->urb->transfer_flags |= URB_ZERO_PACKET;
snd->instance = acm;
}
@@ -1861,6 +1864,10 @@ static const struct usb_device_id acm_ids[] = {
{ USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
USB_CDC_ACM_PROTO_AT_CDMA) },
+ { USB_DEVICE(0x1519, 0x0452), /* Intel 7260 modem */
+ .driver_info = SEND_ZERO_PACKET,
+ },
+
{ }
};
diff --git a/drivers/usb/class/cdc-acm.h b/drivers/usb/class/cdc-acm.h
index dd9af38e7..ccfaba9ab 100644
--- a/drivers/usb/class/cdc-acm.h
+++ b/drivers/usb/class/cdc-acm.h
@@ -134,3 +134,4 @@ struct acm {
#define IGNORE_DEVICE BIT(5)
#define QUIRK_CONTROL_LINE_STATE BIT(6)
#define CLEAR_HALT_CONDITIONS BIT(7)
+#define SEND_ZERO_PACKET BIT(8)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index 868343678..1560f3f3e 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -5386,7 +5386,6 @@ static int usb_reset_and_verify_device(struct usb_device *udev)
}
bos = udev->bos;
- udev->bos = NULL;
for (i = 0; i < SET_CONFIG_TRIES; ++i) {
@@ -5479,8 +5478,11 @@ done:
usb_set_usb2_hardware_lpm(udev, 1);
usb_unlocked_enable_lpm(udev);
usb_enable_ltm(udev);
- usb_release_bos_descriptor(udev);
- udev->bos = bos;
+ /* release the new BOS descriptor allocated by hub_port_init() */
+ if (udev->bos != bos) {
+ usb_release_bos_descriptor(udev);
+ udev->bos = bos;
+ }
return 0;
re_enumerate:
diff --git a/drivers/usb/host/xhci-pci.c b/drivers/usb/host/xhci-pci.c
index c62109091..c2d65206e 100644
--- a/drivers/usb/host/xhci-pci.c
+++ b/drivers/usb/host/xhci-pci.c
@@ -28,7 +28,9 @@
#include "xhci.h"
#include "xhci-trace.h"
-#define PORT2_SSIC_CONFIG_REG2 0x883c
+#define SSIC_PORT_NUM 2
+#define SSIC_PORT_CFG2 0x880c
+#define SSIC_PORT_CFG2_OFFSET 0x30
#define PROG_DONE (1 << 30)
#define SSIC_PORT_UNUSED (1 << 31)
@@ -45,6 +47,7 @@
#define PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI 0x22b5
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI 0xa12f
#define PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI 0x9d2f
+#define PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI 0x0aa8
static const char hcd_name[] = "xhci_hcd";
@@ -152,7 +155,8 @@ static void xhci_pci_quirks(struct device *dev, struct xhci_hcd *xhci)
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
(pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_LP_XHCI ||
pdev->device == PCI_DEVICE_ID_INTEL_SUNRISEPOINT_H_XHCI ||
- pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI)) {
+ pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI ||
+ pdev->device == PCI_DEVICE_ID_INTEL_BROXTON_M_XHCI)) {
xhci->quirks |= XHCI_PME_STUCK_QUIRK;
}
if (pdev->vendor == PCI_VENDOR_ID_ETRON &&
@@ -322,28 +326,36 @@ static void xhci_pme_quirk(struct usb_hcd *hcd, bool suspend)
struct pci_dev *pdev = to_pci_dev(hcd->self.controller);
u32 val;
void __iomem *reg;
+ int i;
if (pdev->vendor == PCI_VENDOR_ID_INTEL &&
pdev->device == PCI_DEVICE_ID_INTEL_CHERRYVIEW_XHCI) {
- reg = (void __iomem *) xhci->cap_regs + PORT2_SSIC_CONFIG_REG2;
-
- /* Notify SSIC that SSIC profile programming is not done */
- val = readl(reg) & ~PROG_DONE;
- writel(val, reg);
-
- /* Mark SSIC port as unused(suspend) or used(resume) */
- val = readl(reg);
- if (suspend)
- val |= SSIC_PORT_UNUSED;
- else
- val &= ~SSIC_PORT_UNUSED;
- writel(val, reg);
-
- /* Notify SSIC that SSIC profile programming is done */
- val = readl(reg) | PROG_DONE;
- writel(val, reg);
- readl(reg);
+ for (i = 0; i < SSIC_PORT_NUM; i++) {
+ reg = (void __iomem *) xhci->cap_regs +
+ SSIC_PORT_CFG2 +
+ i * SSIC_PORT_CFG2_OFFSET;
+
+ /*
+ * Notify SSIC that SSIC profile programming
+ * is not done.
+ */
+ val = readl(reg) & ~PROG_DONE;
+ writel(val, reg);
+
+ /* Mark SSIC port as unused(suspend) or used(resume) */
+ val = readl(reg);
+ if (suspend)
+ val |= SSIC_PORT_UNUSED;
+ else
+ val &= ~SSIC_PORT_UNUSED;
+ writel(val, reg);
+
+ /* Notify SSIC that SSIC profile programming is done */
+ val = readl(reg) | PROG_DONE;
+ writel(val, reg);
+ readl(reg);
+ }
}
reg = (void __iomem *) xhci->cap_regs + 0x80a4;
diff --git a/drivers/usb/phy/phy-msm-usb.c b/drivers/usb/phy/phy-msm-usb.c
index 0d19a6d61..970a30e15 100644
--- a/drivers/usb/phy/phy-msm-usb.c
+++ b/drivers/usb/phy/phy-msm-usb.c
@@ -1599,6 +1599,8 @@ static int msm_otg_read_dt(struct platform_device *pdev, struct msm_otg *motg)
&motg->id.nb);
if (ret < 0) {
dev_err(&pdev->dev, "register ID notifier failed\n");
+ extcon_unregister_notifier(motg->vbus.extcon,
+ EXTCON_USB, &motg->vbus.nb);
return ret;
}
@@ -1660,15 +1662,6 @@ static int msm_otg_probe(struct platform_device *pdev)
if (!motg)
return -ENOMEM;
- pdata = dev_get_platdata(&pdev->dev);
- if (!pdata) {
- if (!np)
- return -ENXIO;
- ret = msm_otg_read_dt(pdev, motg);
- if (ret)
- return ret;
- }
-
motg->phy.otg = devm_kzalloc(&pdev->dev, sizeof(struct usb_otg),
GFP_KERNEL);
if (!motg->phy.otg)
@@ -1710,6 +1703,15 @@ static int msm_otg_probe(struct platform_device *pdev)
if (!motg->regs)
return -ENOMEM;
+ pdata = dev_get_platdata(&pdev->dev);
+ if (!pdata) {
+ if (!np)
+ return -ENXIO;
+ ret = msm_otg_read_dt(pdev, motg);
+ if (ret)
+ return ret;
+ }
+
/*
* NOTE: The PHYs can be multiplexed between the chipidea controller
* and the dwc3 controller, using a single bit. It is important that
@@ -1717,8 +1719,10 @@ static int msm_otg_probe(struct platform_device *pdev)
*/
if (motg->phy_number) {
phy_select = devm_ioremap_nocache(&pdev->dev, USB2_PHY_SEL, 4);
- if (!phy_select)
- return -ENOMEM;
+ if (!phy_select) {
+ ret = -ENOMEM;
+ goto unregister_extcon;
+ }
/* Enable second PHY with the OTG port */
writel(0x1, phy_select);
}
@@ -1728,7 +1732,8 @@ static int msm_otg_probe(struct platform_device *pdev)
motg->irq = platform_get_irq(pdev, 0);
if (motg->irq < 0) {
dev_err(&pdev->dev, "platform_get_irq failed\n");
- return motg->irq;
+ ret = motg->irq;
+ goto unregister_extcon;
}
regs[0].supply = "vddcx";
@@ -1737,7 +1742,7 @@ static int msm_otg_probe(struct platform_device *pdev)
ret = devm_regulator_bulk_get(motg->phy.dev, ARRAY_SIZE(regs), regs);
if (ret)
- return ret;
+ goto unregister_extcon;
motg->vddcx = regs[0].consumer;
motg->v3p3 = regs[1].consumer;
@@ -1834,6 +1839,12 @@ disable_clks:
clk_disable_unprepare(motg->clk);
if (!IS_ERR(motg->core_clk))
clk_disable_unprepare(motg->core_clk);
+unregister_extcon:
+ extcon_unregister_notifier(motg->id.extcon,
+ EXTCON_USB_HOST, &motg->id.nb);
+ extcon_unregister_notifier(motg->vbus.extcon,
+ EXTCON_USB, &motg->vbus.nb);
+
return ret;
}
diff --git a/drivers/usb/serial/cp210x.c b/drivers/usb/serial/cp210x.c
index 59b2126b2..1dd991908 100644
--- a/drivers/usb/serial/cp210x.c
+++ b/drivers/usb/serial/cp210x.c
@@ -98,6 +98,7 @@ static const struct usb_device_id id_table[] = {
{ USB_DEVICE(0x10C4, 0x81AC) }, /* MSD Dash Hawk */
{ USB_DEVICE(0x10C4, 0x81AD) }, /* INSYS USB Modem */
{ USB_DEVICE(0x10C4, 0x81C8) }, /* Lipowsky Industrie Elektronik GmbH, Baby-JTAG */
+ { USB_DEVICE(0x10C4, 0x81D7) }, /* IAI Corp. RCB-CV-USB USB to RS485 Adaptor */
{ USB_DEVICE(0x10C4, 0x81E2) }, /* Lipowsky Industrie Elektronik GmbH, Baby-LIN */
{ USB_DEVICE(0x10C4, 0x81E7) }, /* Aerocomm Radio */
{ USB_DEVICE(0x10C4, 0x81E8) }, /* Zephyr Bioharness */
diff --git a/drivers/usb/serial/ftdi_sio.c b/drivers/usb/serial/ftdi_sio.c
index a5a0376bb..8c660ae40 100644
--- a/drivers/usb/serial/ftdi_sio.c
+++ b/drivers/usb/serial/ftdi_sio.c
@@ -824,6 +824,7 @@ static const struct usb_device_id id_table_combined[] = {
{ USB_DEVICE(FTDI_VID, FTDI_TURTELIZER_PID),
.driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
{ USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_USB60F) },
+ { USB_DEVICE(RATOC_VENDOR_ID, RATOC_PRODUCT_ID_SCU18) },
{ USB_DEVICE(FTDI_VID, FTDI_REU_TINY_PID) },
/* Papouch devices based on FTDI chip */
diff --git a/drivers/usb/serial/ftdi_sio_ids.h b/drivers/usb/serial/ftdi_sio_ids.h
index 67c6d4469..a84df2513 100644
--- a/drivers/usb/serial/ftdi_sio_ids.h
+++ b/drivers/usb/serial/ftdi_sio_ids.h
@@ -615,6 +615,7 @@
*/
#define RATOC_VENDOR_ID 0x0584
#define RATOC_PRODUCT_ID_USB60F 0xb020
+#define RATOC_PRODUCT_ID_SCU18 0xb03a
/*
* Infineon Technologies
diff --git a/drivers/usb/serial/option.c b/drivers/usb/serial/option.c
index f2280606b..db86e512e 100644
--- a/drivers/usb/serial/option.c
+++ b/drivers/usb/serial/option.c
@@ -268,6 +268,8 @@ static void option_instat_callback(struct urb *urb);
#define TELIT_PRODUCT_CC864_SINGLE 0x1006
#define TELIT_PRODUCT_DE910_DUAL 0x1010
#define TELIT_PRODUCT_UE910_V2 0x1012
+#define TELIT_PRODUCT_LE922_USBCFG0 0x1042
+#define TELIT_PRODUCT_LE922_USBCFG3 0x1043
#define TELIT_PRODUCT_LE920 0x1200
#define TELIT_PRODUCT_LE910 0x1201
@@ -615,6 +617,16 @@ static const struct option_blacklist_info telit_le920_blacklist = {
.reserved = BIT(1) | BIT(5),
};
+static const struct option_blacklist_info telit_le922_blacklist_usbcfg0 = {
+ .sendsetup = BIT(2),
+ .reserved = BIT(0) | BIT(1) | BIT(3),
+};
+
+static const struct option_blacklist_info telit_le922_blacklist_usbcfg3 = {
+ .sendsetup = BIT(0),
+ .reserved = BIT(1) | BIT(2) | BIT(3),
+};
+
static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_COLT) },
{ USB_DEVICE(OPTION_VENDOR_ID, OPTION_PRODUCT_RICOLA) },
@@ -1160,6 +1172,10 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_CC864_SINGLE) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_DE910_DUAL) },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_UE910_V2) },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG0),
+ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg0 },
+ { USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE922_USBCFG3),
+ .driver_info = (kernel_ulong_t)&telit_le922_blacklist_usbcfg3 },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE910),
.driver_info = (kernel_ulong_t)&telit_le910_blacklist },
{ USB_DEVICE(TELIT_VENDOR_ID, TELIT_PRODUCT_LE920),
@@ -1679,7 +1695,7 @@ static const struct usb_device_id option_ids[] = {
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_EU3_P) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PH8),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
- { USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX) },
+ { USB_DEVICE_INTERFACE_CLASS(CINTERION_VENDOR_ID, CINTERION_PRODUCT_AHXX, 0xff) },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_PLXX),
.driver_info = (kernel_ulong_t)&net_intf4_blacklist },
{ USB_DEVICE(CINTERION_VENDOR_ID, CINTERION_PRODUCT_HC28_MDM) },
diff --git a/drivers/usb/serial/visor.c b/drivers/usb/serial/visor.c
index 60afb39eb..337a0be89 100644
--- a/drivers/usb/serial/visor.c
+++ b/drivers/usb/serial/visor.c
@@ -544,6 +544,11 @@ static int treo_attach(struct usb_serial *serial)
(serial->num_interrupt_in == 0))
return 0;
+ if (serial->num_bulk_in < 2 || serial->num_interrupt_in < 2) {
+ dev_err(&serial->interface->dev, "missing endpoints\n");
+ return -ENODEV;
+ }
+
/*
* It appears that Treos and Kyoceras want to use the
* 1st bulk in endpoint to communicate with the 2nd bulk out endpoint,
@@ -597,8 +602,10 @@ static int clie_5_attach(struct usb_serial *serial)
*/
/* some sanity check */
- if (serial->num_ports < 2)
- return -1;
+ if (serial->num_bulk_out < 2) {
+ dev_err(&serial->interface->dev, "missing bulk out endpoints\n");
+ return -ENODEV;
+ }
/* port 0 now uses the modified endpoint Address */
port = serial->port[0];
diff --git a/fs/aufs/aufs.h b/fs/aufs/aufs.h
index 75290bdbb..49f43b433 100644
--- a/fs/aufs/aufs.h
+++ b/fs/aufs/aufs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/branch.c b/fs/aufs/branch.c
index f49142260..1ab5e1f2d 100644
--- a/fs/aufs/branch.c
+++ b/fs/aufs/branch.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/branch.h b/fs/aufs/branch.h
index 7b9e7c9cd..4c52ae166 100644
--- a/fs/aufs/branch.h
+++ b/fs/aufs/branch.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/cpup.c b/fs/aufs/cpup.c
index cd322746c..a34648874 100644
--- a/fs/aufs/cpup.c
+++ b/fs/aufs/cpup.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
@@ -8,6 +8,7 @@
#include <linux/fs_stack.h>
#include <linux/mm.h>
+#include <linux/task_work.h>
#include "aufs.h"
void au_cpup_attr_flags(struct inode *dst, unsigned int iflags)
@@ -380,6 +381,7 @@ static int au_cp_regular(struct au_cp_generic *cpg)
}
};
struct super_block *sb;
+ struct task_struct *tsk = current;
/* bsrc branch can be ro/rw. */
sb = cpg->dentry->d_sb;
@@ -397,7 +399,21 @@ static int au_cp_regular(struct au_cp_generic *cpg)
IMustLock(d_inode(file[SRC].dentry));
err = au_copy_file(file[DST].file, file[SRC].file, cpg->len);
- fput(file[DST].file);
+ /* i wonder if we had O_NO_DELAY_FPUT flag */
+ if (tsk->flags & PF_KTHREAD)
+ __fput_sync(file[DST].file);
+ else {
+ WARN(1, "%pD\nPlease report this warning to aufs-users ML",
+ file[DST].file);
+ fput(file[DST].file);
+ /*
+ * too bad.
+ * we have to call both since we don't know which place the file
+ * was added to.
+ */
+ task_work_run();
+ flush_delayed_fput();
+ }
au_sbr_put(sb, file[DST].bindex);
out_src:
diff --git a/fs/aufs/cpup.h b/fs/aufs/cpup.h
index 3355f0880..ccba2c427 100644
--- a/fs/aufs/cpup.h
+++ b/fs/aufs/cpup.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dbgaufs.c b/fs/aufs/dbgaufs.c
index c7c612c28..0aefb5ed8 100644
--- a/fs/aufs/dbgaufs.c
+++ b/fs/aufs/dbgaufs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dbgaufs.h b/fs/aufs/dbgaufs.h
index efa9a4db9..81f272e42 100644
--- a/fs/aufs/dbgaufs.h
+++ b/fs/aufs/dbgaufs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dcsub.c b/fs/aufs/dcsub.c
index f9d9d526c..e72accebb 100644
--- a/fs/aufs/dcsub.c
+++ b/fs/aufs/dcsub.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dcsub.h b/fs/aufs/dcsub.h
index 2aa87acc3..5d2cf661d 100644
--- a/fs/aufs/dcsub.h
+++ b/fs/aufs/dcsub.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/debug.c b/fs/aufs/debug.c
index 42053aa7f..4529831a9 100644
--- a/fs/aufs/debug.c
+++ b/fs/aufs/debug.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/debug.h b/fs/aufs/debug.h
index 0a2e7e7b0..0567f31d0 100644
--- a/fs/aufs/debug.h
+++ b/fs/aufs/debug.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dentry.c b/fs/aufs/dentry.c
index aad25be88..e47a7e6c4 100644
--- a/fs/aufs/dentry.c
+++ b/fs/aufs/dentry.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dentry.h b/fs/aufs/dentry.h
index 522522179..c794adf59 100644
--- a/fs/aufs/dentry.h
+++ b/fs/aufs/dentry.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dinfo.c b/fs/aufs/dinfo.c
index 25b971bc6..ad6d045c4 100644
--- a/fs/aufs/dinfo.c
+++ b/fs/aufs/dinfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dir.c b/fs/aufs/dir.c
index ccdcebeb3..8a619062a 100644
--- a/fs/aufs/dir.c
+++ b/fs/aufs/dir.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dir.h b/fs/aufs/dir.h
index 803a0f1a5..b0a79d722 100644
--- a/fs/aufs/dir.h
+++ b/fs/aufs/dir.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dynop.c b/fs/aufs/dynop.c
index 1f1283814..53a8b55d8 100644
--- a/fs/aufs/dynop.c
+++ b/fs/aufs/dynop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 Junjiro R. Okajima
+ * Copyright (C) 2010-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/dynop.h b/fs/aufs/dynop.h
index 6d739c124..8680bfc53 100644
--- a/fs/aufs/dynop.h
+++ b/fs/aufs/dynop.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 Junjiro R. Okajima
+ * Copyright (C) 2010-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/export.c b/fs/aufs/export.c
index 3026f39a7..4ce7732b7 100644
--- a/fs/aufs/export.c
+++ b/fs/aufs/export.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/f_op.c b/fs/aufs/f_op.c
index 91c2ce78a..c1be75cb0 100644
--- a/fs/aufs/f_op.c
+++ b/fs/aufs/f_op.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/fhsm.c b/fs/aufs/fhsm.c
index 47106cbe9..db079d6ee 100644
--- a/fs/aufs/fhsm.c
+++ b/fs/aufs/fhsm.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2015 Junjiro R. Okajima
+ * Copyright (C) 2011-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/file.c b/fs/aufs/file.c
index 72316b122..6b8a66b4a 100644
--- a/fs/aufs/file.c
+++ b/fs/aufs/file.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/file.h b/fs/aufs/file.h
index 488473e31..27d802487 100644
--- a/fs/aufs/file.h
+++ b/fs/aufs/file.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/finfo.c b/fs/aufs/finfo.c
index e709205b5..b5eb55dfb 100644
--- a/fs/aufs/finfo.c
+++ b/fs/aufs/finfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/fstype.h b/fs/aufs/fstype.h
index 6196c606b..e429a8b17 100644
--- a/fs/aufs/fstype.h
+++ b/fs/aufs/fstype.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
@@ -240,6 +240,7 @@ static inline int au_test_hfsplus(struct super_block *sb __maybe_unused)
static inline int au_test_fs_unsuppoted(struct super_block *sb)
{
return
+ au_test_fuse(sb) || /* for a security reason, temporarily */
#ifndef CONFIG_AUFS_BR_RAMFS
au_test_ramfs(sb) ||
#endif
diff --git a/fs/aufs/hfsnotify.c b/fs/aufs/hfsnotify.c
index 5c370196f..c0a1a63a9 100644
--- a/fs/aufs/hfsnotify.c
+++ b/fs/aufs/hfsnotify.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/hfsplus.c b/fs/aufs/hfsplus.c
index 34c1f1abf..145c6ac2f 100644
--- a/fs/aufs/hfsplus.c
+++ b/fs/aufs/hfsplus.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 Junjiro R. Okajima
+ * Copyright (C) 2010-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/hnotify.c b/fs/aufs/hnotify.c
index 3943dc4b4..3e0a4f67d 100644
--- a/fs/aufs/hnotify.c
+++ b/fs/aufs/hnotify.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/i_op.c b/fs/aufs/i_op.c
index daad67aa1..1c634bab9 100644
--- a/fs/aufs/i_op.c
+++ b/fs/aufs/i_op.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/i_op_add.c b/fs/aufs/i_op_add.c
index 0c3530e55..3fc355859 100644
--- a/fs/aufs/i_op_add.c
+++ b/fs/aufs/i_op_add.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/i_op_del.c b/fs/aufs/i_op_del.c
index 3cd4c7b19..68741aadb 100644
--- a/fs/aufs/i_op_del.c
+++ b/fs/aufs/i_op_del.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/i_op_ren.c b/fs/aufs/i_op_ren.c
index fd815fdbc..c880144b5 100644
--- a/fs/aufs/i_op_ren.c
+++ b/fs/aufs/i_op_ren.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/iinfo.c b/fs/aufs/iinfo.c
index c604f6987..67ef672a0 100644
--- a/fs/aufs/iinfo.c
+++ b/fs/aufs/iinfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/inode.c b/fs/aufs/inode.c
index cedc53420..5a87727ba 100644
--- a/fs/aufs/inode.c
+++ b/fs/aufs/inode.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/inode.h b/fs/aufs/inode.h
index c3e26940f..534b9e814 100644
--- a/fs/aufs/inode.h
+++ b/fs/aufs/inode.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/ioctl.c b/fs/aufs/ioctl.c
index 87e3ddc88..6528fb911 100644
--- a/fs/aufs/ioctl.c
+++ b/fs/aufs/ioctl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/loop.c b/fs/aufs/loop.c
index f324758e9..5711e7a2f 100644
--- a/fs/aufs/loop.c
+++ b/fs/aufs/loop.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/loop.h b/fs/aufs/loop.h
index 6d9864dff..48bf070e8 100644
--- a/fs/aufs/loop.h
+++ b/fs/aufs/loop.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/module.c b/fs/aufs/module.c
index 3268e62e4..ec12f2e66 100644
--- a/fs/aufs/module.c
+++ b/fs/aufs/module.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/module.h b/fs/aufs/module.h
index adee827fa..b129ad4b6 100644
--- a/fs/aufs/module.h
+++ b/fs/aufs/module.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/mvdown.c b/fs/aufs/mvdown.c
index 53e0f6af9..1f2224f6d 100644
--- a/fs/aufs/mvdown.c
+++ b/fs/aufs/mvdown.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2015 Junjiro R. Okajima
+ * Copyright (C) 2011-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/opts.c b/fs/aufs/opts.c
index f79d15e32..5c39817f3 100644
--- a/fs/aufs/opts.c
+++ b/fs/aufs/opts.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/opts.h b/fs/aufs/opts.h
index 3899e9240..0d6c2e1c7 100644
--- a/fs/aufs/opts.h
+++ b/fs/aufs/opts.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/plink.c b/fs/aufs/plink.c
index af2246c09..6fdab1e0e 100644
--- a/fs/aufs/plink.c
+++ b/fs/aufs/plink.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/poll.c b/fs/aufs/poll.c
index c324fc727..dd2baf5dc 100644
--- a/fs/aufs/poll.c
+++ b/fs/aufs/poll.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/posix_acl.c b/fs/aufs/posix_acl.c
index d9ce95724..1c19e629b 100644
--- a/fs/aufs/posix_acl.c
+++ b/fs/aufs/posix_acl.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2015 Junjiro R. Okajima
+ * Copyright (C) 2014-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/procfs.c b/fs/aufs/procfs.c
index ead2a0052..2c8893edf 100644
--- a/fs/aufs/procfs.c
+++ b/fs/aufs/procfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2015 Junjiro R. Okajima
+ * Copyright (C) 2010-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/rdu.c b/fs/aufs/rdu.c
index f11d9bbbd..a9e9e9893 100644
--- a/fs/aufs/rdu.c
+++ b/fs/aufs/rdu.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/rwsem.h b/fs/aufs/rwsem.h
index 171ee0c18..ef50c2ccb 100644
--- a/fs/aufs/rwsem.h
+++ b/fs/aufs/rwsem.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/sbinfo.c b/fs/aufs/sbinfo.c
index 8f2ec5573..e3c58f643 100644
--- a/fs/aufs/sbinfo.c
+++ b/fs/aufs/sbinfo.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/spl.h b/fs/aufs/spl.h
index a66d39e9e..f9b528826 100644
--- a/fs/aufs/spl.h
+++ b/fs/aufs/spl.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/super.c b/fs/aufs/super.c
index 98cfd64dd..b41d78913 100644
--- a/fs/aufs/super.c
+++ b/fs/aufs/super.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/super.h b/fs/aufs/super.h
index d15172962..2761df917 100644
--- a/fs/aufs/super.h
+++ b/fs/aufs/super.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/sysaufs.c b/fs/aufs/sysaufs.c
index 29ac6faa6..8ec10fb31 100644
--- a/fs/aufs/sysaufs.c
+++ b/fs/aufs/sysaufs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/sysaufs.h b/fs/aufs/sysaufs.h
index feb78fd86..1f799835e 100644
--- a/fs/aufs/sysaufs.h
+++ b/fs/aufs/sysaufs.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/sysfs.c b/fs/aufs/sysfs.c
index ec8df8f6c..ed42f53d0 100644
--- a/fs/aufs/sysfs.c
+++ b/fs/aufs/sysfs.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/sysrq.c b/fs/aufs/sysrq.c
index 3a0182b90..7921ed716 100644
--- a/fs/aufs/sysrq.c
+++ b/fs/aufs/sysrq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/vdir.c b/fs/aufs/vdir.c
index db81f49dd..f64cc2b7a 100644
--- a/fs/aufs/vdir.c
+++ b/fs/aufs/vdir.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/vfsub.c b/fs/aufs/vfsub.c
index da0df5a38..f072c59c0 100644
--- a/fs/aufs/vfsub.c
+++ b/fs/aufs/vfsub.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/vfsub.h b/fs/aufs/vfsub.h
index 4218da12e..a7d8a1cf9 100644
--- a/fs/aufs/vfsub.h
+++ b/fs/aufs/vfsub.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/wbr_policy.c b/fs/aufs/wbr_policy.c
index 53a01fb06..c822b428d 100644
--- a/fs/aufs/wbr_policy.c
+++ b/fs/aufs/wbr_policy.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/whout.c b/fs/aufs/whout.c
index 05ba0857b..04eb9af2b 100644
--- a/fs/aufs/whout.c
+++ b/fs/aufs/whout.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/whout.h b/fs/aufs/whout.h
index b39acea2c..4077dd19e 100644
--- a/fs/aufs/whout.h
+++ b/fs/aufs/whout.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/wkq.c b/fs/aufs/wkq.c
index 08870ec06..0f1500e93 100644
--- a/fs/aufs/wkq.c
+++ b/fs/aufs/wkq.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/wkq.h b/fs/aufs/wkq.h
index 8f01343d8..f6c9b9902 100644
--- a/fs/aufs/wkq.h
+++ b/fs/aufs/wkq.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/xattr.c b/fs/aufs/xattr.c
index c1695b329..f592e05ea 100644
--- a/fs/aufs/xattr.c
+++ b/fs/aufs/xattr.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014-2015 Junjiro R. Okajima
+ * Copyright (C) 2014-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/aufs/xino.c b/fs/aufs/xino.c
index 61df836cd..994258e3f 100644
--- a/fs/aufs/xino.c
+++ b/fs/aufs/xino.c
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
/*
diff --git a/fs/ext4/crypto_key.c b/fs/ext4/crypto_key.c
index c5882b36e..9a16d1e75 100644
--- a/fs/ext4/crypto_key.c
+++ b/fs/ext4/crypto_key.c
@@ -213,9 +213,11 @@ retry:
res = -ENOKEY;
goto out;
}
+ down_read(&keyring_key->sem);
ukp = user_key_payload(keyring_key);
if (ukp->datalen != sizeof(struct ext4_encryption_key)) {
res = -EINVAL;
+ up_read(&keyring_key->sem);
goto out;
}
master_key = (struct ext4_encryption_key *)ukp->data;
@@ -226,10 +228,12 @@ retry:
"ext4: key size incorrect: %d\n",
master_key->size);
res = -ENOKEY;
+ up_read(&keyring_key->sem);
goto out;
}
res = ext4_derive_key_aes(ctx.nonce, master_key->raw,
raw_key);
+ up_read(&keyring_key->sem);
if (res)
goto out;
got_key:
diff --git a/fs/file_table.c b/fs/file_table.c
index df66450fb..38e046adc 100644
--- a/fs/file_table.c
+++ b/fs/file_table.c
@@ -259,6 +259,7 @@ void flush_delayed_fput(void)
{
delayed_fput(NULL);
}
+EXPORT_SYMBOL(flush_delayed_fput);
static DECLARE_DELAYED_WORK(delayed_fput_work, delayed_fput);
@@ -301,6 +302,7 @@ void __fput_sync(struct file *file)
}
EXPORT_SYMBOL(fput);
+EXPORT_SYMBOL(__fput_sync);
void put_filp(struct file *file)
{
diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c
index 89818036f..343b0f1f1 100644
--- a/fs/nfs/nfs4proc.c
+++ b/fs/nfs/nfs4proc.c
@@ -8054,7 +8054,6 @@ static void nfs4_layoutreturn_release(void *calldata)
pnfs_set_layout_stateid(lo, &lrp->res.stateid, true);
pnfs_mark_matching_lsegs_invalid(lo, &freeme, &lrp->args.range);
pnfs_clear_layoutreturn_waitbit(lo);
- lo->plh_block_lgets--;
spin_unlock(&lo->plh_inode->i_lock);
pnfs_free_lseg_list(&freeme);
pnfs_put_layout_hdr(lrp->args.layout);
diff --git a/fs/ocfs2/dlm/dlmmaster.c b/fs/ocfs2/dlm/dlmmaster.c
index 84f2f8079..4e2162b35 100644
--- a/fs/ocfs2/dlm/dlmmaster.c
+++ b/fs/ocfs2/dlm/dlmmaster.c
@@ -2519,6 +2519,11 @@ static int dlm_migrate_lockres(struct dlm_ctxt *dlm,
spin_lock(&dlm->master_lock);
ret = dlm_add_migration_mle(dlm, res, mle, &oldmle, name,
namelen, target, dlm->node_num);
+ /* get an extra reference on the mle.
+ * otherwise the assert_master from the new
+ * master will destroy this.
+ */
+ dlm_get_mle_inuse(mle);
spin_unlock(&dlm->master_lock);
spin_unlock(&dlm->spinlock);
@@ -2554,6 +2559,7 @@ fail:
if (mle_added) {
dlm_mle_detach_hb_events(dlm, mle);
dlm_put_mle(mle);
+ dlm_put_mle_inuse(mle);
} else if (mle) {
kmem_cache_free(dlm_mle_cache, mle);
mle = NULL;
@@ -2571,17 +2577,6 @@ fail:
* ensure that all assert_master work is flushed. */
flush_workqueue(dlm->dlm_worker);
- /* get an extra reference on the mle.
- * otherwise the assert_master from the new
- * master will destroy this.
- * also, make sure that all callers of dlm_get_mle
- * take both dlm->spinlock and dlm->master_lock */
- spin_lock(&dlm->spinlock);
- spin_lock(&dlm->master_lock);
- dlm_get_mle_inuse(mle);
- spin_unlock(&dlm->master_lock);
- spin_unlock(&dlm->spinlock);
-
/* notify new node and send all lock state */
/* call send_one_lockres with migration flag.
* this serves as notice to the target node that a
@@ -3312,6 +3307,15 @@ top:
mle->new_master != dead_node)
continue;
+ if (mle->new_master == dead_node && mle->inuse) {
+ mlog(ML_NOTICE, "%s: target %u died during "
+ "migration from %u, the MLE is "
+ "still keep used, ignore it!\n",
+ dlm->name, dead_node,
+ mle->master);
+ continue;
+ }
+
/* If we have reached this point, this mle needs to be
* removed from the list and freed. */
dlm_clean_migration_mle(dlm, mle);
diff --git a/fs/ocfs2/dlm/dlmrecovery.c b/fs/ocfs2/dlm/dlmrecovery.c
index 9e4f862d2..42f0cae93 100644
--- a/fs/ocfs2/dlm/dlmrecovery.c
+++ b/fs/ocfs2/dlm/dlmrecovery.c
@@ -2360,6 +2360,8 @@ static void dlm_do_local_recovery_cleanup(struct dlm_ctxt *dlm, u8 dead_node)
break;
}
}
+ dlm_lockres_clear_refmap_bit(dlm, res,
+ dead_node);
spin_unlock(&res->spinlock);
continue;
}
diff --git a/fs/ocfs2/dlmglue.c b/fs/ocfs2/dlmglue.c
index 20276e340..b002acf50 100644
--- a/fs/ocfs2/dlmglue.c
+++ b/fs/ocfs2/dlmglue.c
@@ -1390,6 +1390,7 @@ static int __ocfs2_cluster_lock(struct ocfs2_super *osb,
unsigned int gen;
int noqueue_attempted = 0;
int dlm_locked = 0;
+ int kick_dc = 0;
if (!(lockres->l_flags & OCFS2_LOCK_INITIALIZED)) {
mlog_errno(-EINVAL);
@@ -1524,7 +1525,12 @@ update_holders:
unlock:
lockres_clear_flags(lockres, OCFS2_LOCK_UPCONVERT_FINISHING);
+ /* ocfs2_unblock_lock reques on seeing OCFS2_LOCK_UPCONVERT_FINISHING */
+ kick_dc = (lockres->l_flags & OCFS2_LOCK_BLOCKED);
+
spin_unlock_irqrestore(&lockres->l_lock, flags);
+ if (kick_dc)
+ ocfs2_wake_downconvert_thread(osb);
out:
/*
* This is helping work around a lock inversion between the page lock
diff --git a/include/crypto/hash.h b/include/crypto/hash.h
index 3d69c93d5..6361892ea 100644
--- a/include/crypto/hash.h
+++ b/include/crypto/hash.h
@@ -204,6 +204,7 @@ struct crypto_ahash {
unsigned int keylen);
unsigned int reqsize;
+ bool has_setkey;
struct crypto_tfm base;
};
@@ -375,6 +376,11 @@ static inline void *ahash_request_ctx(struct ahash_request *req)
int crypto_ahash_setkey(struct crypto_ahash *tfm, const u8 *key,
unsigned int keylen);
+static inline bool crypto_ahash_has_setkey(struct crypto_ahash *tfm)
+{
+ return tfm->has_setkey;
+}
+
/**
* crypto_ahash_finup() - update and finalize message digest
* @req: reference to the ahash_request handle that holds all information
diff --git a/include/crypto/if_alg.h b/include/crypto/if_alg.h
index 018afb264..a2bfd7843 100644
--- a/include/crypto/if_alg.h
+++ b/include/crypto/if_alg.h
@@ -30,6 +30,9 @@ struct alg_sock {
struct sock *parent;
+ unsigned int refcnt;
+ unsigned int nokey_refcnt;
+
const struct af_alg_type *type;
void *private;
};
@@ -50,9 +53,11 @@ struct af_alg_type {
void (*release)(void *private);
int (*setkey)(void *private, const u8 *key, unsigned int keylen);
int (*accept)(void *private, struct sock *sk);
+ int (*accept_nokey)(void *private, struct sock *sk);
int (*setauthsize)(void *private, unsigned int authsize);
struct proto_ops *ops;
+ struct proto_ops *ops_nokey;
struct module *owner;
char name[14];
};
@@ -67,6 +72,7 @@ int af_alg_register_type(const struct af_alg_type *type);
int af_alg_unregister_type(const struct af_alg_type *type);
int af_alg_release(struct socket *sock);
+void af_alg_release_parent(struct sock *sk);
int af_alg_accept(struct sock *sk, struct socket *newsock);
int af_alg_make_sg(struct af_alg_sgl *sgl, struct iov_iter *iter, int len);
@@ -83,11 +89,6 @@ static inline struct alg_sock *alg_sk(struct sock *sk)
return (struct alg_sock *)sk;
}
-static inline void af_alg_release_parent(struct sock *sk)
-{
- sock_put(alg_sk(sk)->parent);
-}
-
static inline void af_alg_init_completion(struct af_alg_completion *completion)
{
init_completion(&completion->completion);
diff --git a/include/crypto/skcipher.h b/include/crypto/skcipher.h
index d8dd41fb0..fd8742a40 100644
--- a/include/crypto/skcipher.h
+++ b/include/crypto/skcipher.h
@@ -61,6 +61,8 @@ struct crypto_skcipher {
unsigned int ivsize;
unsigned int reqsize;
+ bool has_setkey;
+
struct crypto_tfm base;
};
@@ -305,6 +307,11 @@ static inline int crypto_skcipher_setkey(struct crypto_skcipher *tfm,
return tfm->setkey(tfm, key, keylen);
}
+static inline bool crypto_skcipher_has_setkey(struct crypto_skcipher *tfm)
+{
+ return tfm->has_setkey;
+}
+
/**
* crypto_skcipher_reqtfm() - obtain cipher handle from request
* @req: skcipher_request out of which the cipher handle is to be obtained
diff --git a/include/linux/console.h b/include/linux/console.h
index ec3a76bfa..3a61cf71b 100644
--- a/include/linux/console.h
+++ b/include/linux/console.h
@@ -150,6 +150,7 @@ extern int console_trylock(void);
extern void console_unlock(void);
extern void console_conditional_schedule(void);
extern void console_unblank(void);
+extern void console_flush_on_panic(void);
extern struct tty_driver *console_device(int *);
extern void console_stop(struct console *);
extern void console_start(struct console *);
diff --git a/include/linux/hrtimer.h b/include/linux/hrtimer.h
index 76dd4f0da..2ead22dd7 100644
--- a/include/linux/hrtimer.h
+++ b/include/linux/hrtimer.h
@@ -87,7 +87,8 @@ enum hrtimer_restart {
* @function: timer expiry callback function
* @base: pointer to the timer base (per cpu and per clock)
* @state: state information (See bit values above)
- * @start_pid: timer statistics field to store the pid of the task which
+ * @is_rel: Set if the timer was armed relative
+ * @start_pid: timer statistics field to store the pid of the task which
* started the timer
* @start_site: timer statistics field to store the site where the timer
* was started
@@ -101,7 +102,8 @@ struct hrtimer {
ktime_t _softexpires;
enum hrtimer_restart (*function)(struct hrtimer *);
struct hrtimer_clock_base *base;
- unsigned long state;
+ u8 state;
+ u8 is_rel;
#ifdef CONFIG_TIMER_STATS
int start_pid;
void *start_site;
@@ -321,6 +323,27 @@ static inline void clock_was_set_delayed(void) { }
#endif
+static inline ktime_t
+__hrtimer_expires_remaining_adjusted(const struct hrtimer *timer, ktime_t now)
+{
+ ktime_t rem = ktime_sub(timer->node.expires, now);
+
+ /*
+ * Adjust relative timers for the extra we added in
+ * hrtimer_start_range_ns() to prevent short timeouts.
+ */
+ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && timer->is_rel)
+ rem.tv64 -= hrtimer_resolution;
+ return rem;
+}
+
+static inline ktime_t
+hrtimer_expires_remaining_adjusted(const struct hrtimer *timer)
+{
+ return __hrtimer_expires_remaining_adjusted(timer,
+ timer->base->get_time());
+}
+
extern void clock_was_set(void);
#ifdef CONFIG_TIMERFD
extern void timerfd_clock_was_set(void);
@@ -390,7 +413,12 @@ static inline void hrtimer_restart(struct hrtimer *timer)
}
/* Query timers: */
-extern ktime_t hrtimer_get_remaining(const struct hrtimer *timer);
+extern ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust);
+
+static inline ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+{
+ return __hrtimer_get_remaining(timer, false);
+}
extern u64 hrtimer_get_next_event(void);
diff --git a/include/linux/tty.h b/include/linux/tty.h
index 5e31f1b99..6b6e811f4 100644
--- a/include/linux/tty.h
+++ b/include/linux/tty.h
@@ -654,6 +654,7 @@ extern long vt_compat_ioctl(struct tty_struct *tty,
/* tty_mutex.c */
/* functions for preparation of BKL removal */
extern void __lockfunc tty_lock(struct tty_struct *tty);
+extern int tty_lock_interruptible(struct tty_struct *tty);
extern void __lockfunc tty_unlock(struct tty_struct *tty);
extern void __lockfunc tty_lock_slave(struct tty_struct *tty);
extern void __lockfunc tty_unlock_slave(struct tty_struct *tty);
diff --git a/include/sound/rawmidi.h b/include/sound/rawmidi.h
index f6cbef78d..3b91ad5d5 100644
--- a/include/sound/rawmidi.h
+++ b/include/sound/rawmidi.h
@@ -167,6 +167,10 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count);
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count);
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream,
+ int count);
/* main midi functions */
diff --git a/include/uapi/linux/Kbuild b/include/uapi/linux/Kbuild
index b3132cb19..d736c11b6 100644
--- a/include/uapi/linux/Kbuild
+++ b/include/uapi/linux/Kbuild
@@ -219,7 +219,6 @@ header-y += ixjuser.h
header-y += jffs2.h
header-y += joystick.h
header-y += kcmp.h
-header-y += kdbus.h
header-y += kdev_t.h
header-y += kd.h
header-y += kernelcapi.h
diff --git a/include/uapi/linux/aufs_type.h b/include/uapi/linux/aufs_type.h
index 54fad75e8..5fd2da85e 100644
--- a/include/uapi/linux/aufs_type.h
+++ b/include/uapi/linux/aufs_type.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2005-2015 Junjiro R. Okajima
+ * Copyright (C) 2005-2016 Junjiro R. Okajima
*/
#ifndef __AUFS_TYPE_H__
diff --git a/include/uapi/linux/kdbus.h b/include/uapi/linux/kdbus.h
deleted file mode 100644
index 4fc44cb1d..000000000
--- a/include/uapi/linux/kdbus.h
+++ /dev/null
@@ -1,984 +0,0 @@
-/*
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef _UAPI_KDBUS_H_
-#define _UAPI_KDBUS_H_
-
-#include <linux/ioctl.h>
-#include <linux/types.h>
-
-#define KDBUS_IOCTL_MAGIC 0x95
-#define KDBUS_SRC_ID_KERNEL (0)
-#define KDBUS_DST_ID_NAME (0)
-#define KDBUS_MATCH_ID_ANY (~0ULL)
-#define KDBUS_DST_ID_BROADCAST (~0ULL)
-#define KDBUS_FLAG_NEGOTIATE (1ULL << 63)
-
-/**
- * struct kdbus_notify_id_change - name registry change message
- * @id: New or former owner of the name
- * @flags: flags field from KDBUS_HELLO_*
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- */
-struct kdbus_notify_id_change {
- __u64 id;
- __u64 flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_notify_name_change - name registry change message
- * @old_id: ID and flags of former owner of a name
- * @new_id: ID and flags of new owner of a name
- * @name: Well-known name
- *
- * Sent from kernel to userspace when the owner or activator of
- * a well-known name changes.
- *
- * Attached to:
- * KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- */
-struct kdbus_notify_name_change {
- struct kdbus_notify_id_change old_id;
- struct kdbus_notify_id_change new_id;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_creds - process credentials
- * @uid: User ID
- * @euid: Effective UID
- * @suid: Saved UID
- * @fsuid: Filesystem UID
- * @gid: Group ID
- * @egid: Effective GID
- * @sgid: Saved GID
- * @fsgid: Filesystem GID
- *
- * Attached to:
- * KDBUS_ITEM_CREDS
- */
-struct kdbus_creds {
- __u64 uid;
- __u64 euid;
- __u64 suid;
- __u64 fsuid;
- __u64 gid;
- __u64 egid;
- __u64 sgid;
- __u64 fsgid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_pids - process identifiers
- * @pid: Process ID
- * @tid: Thread ID
- * @ppid: Parent process ID
- *
- * The PID and TID of a process.
- *
- * Attached to:
- * KDBUS_ITEM_PIDS
- */
-struct kdbus_pids {
- __u64 pid;
- __u64 tid;
- __u64 ppid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_caps - process capabilities
- * @last_cap: Highest currently known capability bit
- * @caps: Variable number of 32-bit capabilities flags
- *
- * Contains a variable number of 32-bit capabilities flags.
- *
- * Attached to:
- * KDBUS_ITEM_CAPS
- */
-struct kdbus_caps {
- __u32 last_cap;
- __u32 caps[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_audit - audit information
- * @sessionid: The audit session ID
- * @loginuid: The audit login uid
- *
- * Attached to:
- * KDBUS_ITEM_AUDIT
- */
-struct kdbus_audit {
- __u32 sessionid;
- __u32 loginuid;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_timestamp
- * @seqnum: Global per-domain message sequence number
- * @monotonic_ns: Monotonic timestamp, in nanoseconds
- * @realtime_ns: Realtime timestamp, in nanoseconds
- *
- * Attached to:
- * KDBUS_ITEM_TIMESTAMP
- */
-struct kdbus_timestamp {
- __u64 seqnum;
- __u64 monotonic_ns;
- __u64 realtime_ns;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_vec - I/O vector for kdbus payload items
- * @size: The size of the vector
- * @address: Memory address of data buffer
- * @offset: Offset in the in-message payload memory,
- * relative to the message head
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_VEC, KDBUS_ITEM_PAYLOAD_OFF
- */
-struct kdbus_vec {
- __u64 size;
- union {
- __u64 address;
- __u64 offset;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_parameter - bus-wide bloom parameters
- * @size: Size of the bit field in bytes (m / 8)
- * @n_hash: Number of hash functions used (k)
- */
-struct kdbus_bloom_parameter {
- __u64 size;
- __u64 n_hash;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_bloom_filter - bloom filter containing n elements
- * @generation: Generation of the element set in the filter
- * @data: Bit field, multiple of 8 bytes
- */
-struct kdbus_bloom_filter {
- __u64 generation;
- __u64 data[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_memfd - a kdbus memfd
- * @start: The offset into the memfd where the segment starts
- * @size: The size of the memfd segment
- * @fd: The file descriptor number
- * @__pad: Padding to ensure proper alignment and size
- *
- * Attached to:
- * KDBUS_ITEM_PAYLOAD_MEMFD
- */
-struct kdbus_memfd {
- __u64 start;
- __u64 size;
- int fd;
- __u32 __pad;
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_name - a registered well-known name with its flags
- * @flags: Flags from KDBUS_NAME_*
- * @name: Well-known name
- *
- * Attached to:
- * KDBUS_ITEM_OWNED_NAME
- */
-struct kdbus_name {
- __u64 flags;
- char name[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_policy_access_type - permissions of a policy record
- * @_KDBUS_POLICY_ACCESS_NULL: Uninitialized/invalid
- * @KDBUS_POLICY_ACCESS_USER: Grant access to a uid
- * @KDBUS_POLICY_ACCESS_GROUP: Grant access to gid
- * @KDBUS_POLICY_ACCESS_WORLD: World-accessible
- */
-enum kdbus_policy_access_type {
- _KDBUS_POLICY_ACCESS_NULL,
- KDBUS_POLICY_ACCESS_USER,
- KDBUS_POLICY_ACCESS_GROUP,
- KDBUS_POLICY_ACCESS_WORLD,
-};
-
-/**
- * enum kdbus_policy_access_flags - mode flags
- * @KDBUS_POLICY_OWN: Allow to own a well-known name
- * Implies KDBUS_POLICY_TALK and KDBUS_POLICY_SEE
- * @KDBUS_POLICY_TALK: Allow communication to a well-known name
- * Implies KDBUS_POLICY_SEE
- * @KDBUS_POLICY_SEE: Allow to see a well-known name
- */
-enum kdbus_policy_type {
- KDBUS_POLICY_SEE = 0,
- KDBUS_POLICY_TALK,
- KDBUS_POLICY_OWN,
-};
-
-/**
- * struct kdbus_policy_access - policy access item
- * @type: One of KDBUS_POLICY_ACCESS_* types
- * @access: Access to grant
- * @id: For KDBUS_POLICY_ACCESS_USER, the uid
- * For KDBUS_POLICY_ACCESS_GROUP, the gid
- */
-struct kdbus_policy_access {
- __u64 type; /* USER, GROUP, WORLD */
- __u64 access; /* OWN, TALK, SEE */
- __u64 id; /* uid, gid, 0 */
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_attach_flags - flags for metadata attachments
- * @KDBUS_ATTACH_TIMESTAMP: Timestamp
- * @KDBUS_ATTACH_CREDS: Credentials
- * @KDBUS_ATTACH_PIDS: PIDs
- * @KDBUS_ATTACH_AUXGROUPS: Auxiliary groups
- * @KDBUS_ATTACH_NAMES: Well-known names
- * @KDBUS_ATTACH_TID_COMM: The "comm" process identifier of the TID
- * @KDBUS_ATTACH_PID_COMM: The "comm" process identifier of the PID
- * @KDBUS_ATTACH_EXE: The path of the executable
- * @KDBUS_ATTACH_CMDLINE: The process command line
- * @KDBUS_ATTACH_CGROUP: The croup membership
- * @KDBUS_ATTACH_CAPS: The process capabilities
- * @KDBUS_ATTACH_SECLABEL: The security label
- * @KDBUS_ATTACH_AUDIT: The audit IDs
- * @KDBUS_ATTACH_CONN_DESCRIPTION: The human-readable connection name
- * @_KDBUS_ATTACH_ALL: All of the above
- * @_KDBUS_ATTACH_ANY: Wildcard match to enable any kind of
- * metatdata.
- */
-enum kdbus_attach_flags {
- KDBUS_ATTACH_TIMESTAMP = 1ULL << 0,
- KDBUS_ATTACH_CREDS = 1ULL << 1,
- KDBUS_ATTACH_PIDS = 1ULL << 2,
- KDBUS_ATTACH_AUXGROUPS = 1ULL << 3,
- KDBUS_ATTACH_NAMES = 1ULL << 4,
- KDBUS_ATTACH_TID_COMM = 1ULL << 5,
- KDBUS_ATTACH_PID_COMM = 1ULL << 6,
- KDBUS_ATTACH_EXE = 1ULL << 7,
- KDBUS_ATTACH_CMDLINE = 1ULL << 8,
- KDBUS_ATTACH_CGROUP = 1ULL << 9,
- KDBUS_ATTACH_CAPS = 1ULL << 10,
- KDBUS_ATTACH_SECLABEL = 1ULL << 11,
- KDBUS_ATTACH_AUDIT = 1ULL << 12,
- KDBUS_ATTACH_CONN_DESCRIPTION = 1ULL << 13,
- _KDBUS_ATTACH_ALL = (1ULL << 14) - 1,
- _KDBUS_ATTACH_ANY = ~0ULL
-};
-
-/**
- * enum kdbus_item_type - item types to chain data in a list
- * @_KDBUS_ITEM_NULL: Uninitialized/invalid
- * @_KDBUS_ITEM_USER_BASE: Start of user items
- * @KDBUS_ITEM_NEGOTIATE: Negotiate supported items
- * @KDBUS_ITEM_PAYLOAD_VEC: Vector to data
- * @KDBUS_ITEM_PAYLOAD_OFF: Data at returned offset to message head
- * @KDBUS_ITEM_PAYLOAD_MEMFD: Data as sealed memfd
- * @KDBUS_ITEM_FDS: Attached file descriptors
- * @KDBUS_ITEM_CANCEL_FD: FD used to cancel a synchronous
- * operation by writing to it from
- * userspace
- * @KDBUS_ITEM_BLOOM_PARAMETER: Bus-wide bloom parameters, used with
- * KDBUS_CMD_BUS_MAKE, carries a
- * struct kdbus_bloom_parameter
- * @KDBUS_ITEM_BLOOM_FILTER: Bloom filter carried with a message,
- * used to match against a bloom mask of a
- * connection, carries a struct
- * kdbus_bloom_filter
- * @KDBUS_ITEM_BLOOM_MASK: Bloom mask used to match against a
- * message'sbloom filter
- * @KDBUS_ITEM_DST_NAME: Destination's well-known name
- * @KDBUS_ITEM_MAKE_NAME: Name of domain, bus, endpoint
- * @KDBUS_ITEM_ATTACH_FLAGS_SEND: Attach-flags, used for updating which
- * metadata a connection opts in to send
- * @KDBUS_ITEM_ATTACH_FLAGS_RECV: Attach-flags, used for updating which
- * metadata a connection requests to
- * receive for each reeceived message
- * @KDBUS_ITEM_ID: Connection ID
- * @KDBUS_ITEM_NAME: Well-know name with flags
- * @_KDBUS_ITEM_ATTACH_BASE: Start of metadata attach items
- * @KDBUS_ITEM_TIMESTAMP: Timestamp
- * @KDBUS_ITEM_CREDS: Process credentials
- * @KDBUS_ITEM_PIDS: Process identifiers
- * @KDBUS_ITEM_AUXGROUPS: Auxiliary process groups
- * @KDBUS_ITEM_OWNED_NAME: A name owned by the associated
- * connection
- * @KDBUS_ITEM_TID_COMM: Thread ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_PID_COMM: Process ID "comm" identifier
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_EXE: The path of the executable
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CMDLINE: The process command line
- * (Don't trust this, see below.)
- * @KDBUS_ITEM_CGROUP: The croup membership
- * @KDBUS_ITEM_CAPS: The process capabilities
- * @KDBUS_ITEM_SECLABEL: The security label
- * @KDBUS_ITEM_AUDIT: The audit IDs
- * @KDBUS_ITEM_CONN_DESCRIPTION: The connection's human-readable name
- * (debugging)
- * @_KDBUS_ITEM_POLICY_BASE: Start of policy items
- * @KDBUS_ITEM_POLICY_ACCESS: Policy access block
- * @_KDBUS_ITEM_KERNEL_BASE: Start of kernel-generated message items
- * @KDBUS_ITEM_NAME_ADD: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_REMOVE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_NAME_CHANGE: Notification in kdbus_notify_name_change
- * @KDBUS_ITEM_ID_ADD: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_ID_REMOVE: Notification in kdbus_notify_id_change
- * @KDBUS_ITEM_REPLY_TIMEOUT: Timeout has been reached
- * @KDBUS_ITEM_REPLY_DEAD: Destination died
- *
- * N.B: The process and thread COMM fields, as well as the CMDLINE and
- * EXE fields may be altered by unprivileged processes und should
- * hence *not* used for security decisions. Peers should make use of
- * these items only for informational purposes, such as generating log
- * records.
- */
-enum kdbus_item_type {
- _KDBUS_ITEM_NULL,
- _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_NEGOTIATE = _KDBUS_ITEM_USER_BASE,
- KDBUS_ITEM_PAYLOAD_VEC,
- KDBUS_ITEM_PAYLOAD_OFF,
- KDBUS_ITEM_PAYLOAD_MEMFD,
- KDBUS_ITEM_FDS,
- KDBUS_ITEM_CANCEL_FD,
- KDBUS_ITEM_BLOOM_PARAMETER,
- KDBUS_ITEM_BLOOM_FILTER,
- KDBUS_ITEM_BLOOM_MASK,
- KDBUS_ITEM_DST_NAME,
- KDBUS_ITEM_MAKE_NAME,
- KDBUS_ITEM_ATTACH_FLAGS_SEND,
- KDBUS_ITEM_ATTACH_FLAGS_RECV,
- KDBUS_ITEM_ID,
- KDBUS_ITEM_NAME,
- KDBUS_ITEM_DST_ID,
-
- /* keep these item types in sync with KDBUS_ATTACH_* flags */
- _KDBUS_ITEM_ATTACH_BASE = 0x1000,
- KDBUS_ITEM_TIMESTAMP = _KDBUS_ITEM_ATTACH_BASE,
- KDBUS_ITEM_CREDS,
- KDBUS_ITEM_PIDS,
- KDBUS_ITEM_AUXGROUPS,
- KDBUS_ITEM_OWNED_NAME,
- KDBUS_ITEM_TID_COMM,
- KDBUS_ITEM_PID_COMM,
- KDBUS_ITEM_EXE,
- KDBUS_ITEM_CMDLINE,
- KDBUS_ITEM_CGROUP,
- KDBUS_ITEM_CAPS,
- KDBUS_ITEM_SECLABEL,
- KDBUS_ITEM_AUDIT,
- KDBUS_ITEM_CONN_DESCRIPTION,
-
- _KDBUS_ITEM_POLICY_BASE = 0x2000,
- KDBUS_ITEM_POLICY_ACCESS = _KDBUS_ITEM_POLICY_BASE,
-
- _KDBUS_ITEM_KERNEL_BASE = 0x8000,
- KDBUS_ITEM_NAME_ADD = _KDBUS_ITEM_KERNEL_BASE,
- KDBUS_ITEM_NAME_REMOVE,
- KDBUS_ITEM_NAME_CHANGE,
- KDBUS_ITEM_ID_ADD,
- KDBUS_ITEM_ID_REMOVE,
- KDBUS_ITEM_REPLY_TIMEOUT,
- KDBUS_ITEM_REPLY_DEAD,
-};
-
-/**
- * struct kdbus_item - chain of data blocks
- * @size: Overall data record size
- * @type: Kdbus_item type of data
- * @data: Generic bytes
- * @data32: Generic 32 bit array
- * @data64: Generic 64 bit array
- * @str: Generic string
- * @id: Connection ID
- * @vec: KDBUS_ITEM_PAYLOAD_VEC
- * @creds: KDBUS_ITEM_CREDS
- * @audit: KDBUS_ITEM_AUDIT
- * @timestamp: KDBUS_ITEM_TIMESTAMP
- * @name: KDBUS_ITEM_NAME
- * @bloom_parameter: KDBUS_ITEM_BLOOM_PARAMETER
- * @bloom_filter: KDBUS_ITEM_BLOOM_FILTER
- * @memfd: KDBUS_ITEM_PAYLOAD_MEMFD
- * @name_change: KDBUS_ITEM_NAME_ADD
- * KDBUS_ITEM_NAME_REMOVE
- * KDBUS_ITEM_NAME_CHANGE
- * @id_change: KDBUS_ITEM_ID_ADD
- * KDBUS_ITEM_ID_REMOVE
- * @policy: KDBUS_ITEM_POLICY_ACCESS
- */
-struct kdbus_item {
- __u64 size;
- __u64 type;
- union {
- __u8 data[0];
- __u32 data32[0];
- __u64 data64[0];
- char str[0];
-
- __u64 id;
- struct kdbus_vec vec;
- struct kdbus_creds creds;
- struct kdbus_pids pids;
- struct kdbus_audit audit;
- struct kdbus_caps caps;
- struct kdbus_timestamp timestamp;
- struct kdbus_name name;
- struct kdbus_bloom_parameter bloom_parameter;
- struct kdbus_bloom_filter bloom_filter;
- struct kdbus_memfd memfd;
- int fds[0];
- struct kdbus_notify_name_change name_change;
- struct kdbus_notify_id_change id_change;
- struct kdbus_policy_access policy_access;
- };
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_msg_flags - type of message
- * @KDBUS_MSG_EXPECT_REPLY: Expect a reply message, used for
- * method calls. The userspace-supplied
- * cookie identifies the message and the
- * respective reply carries the cookie
- * in cookie_reply
- * @KDBUS_MSG_NO_AUTO_START: Do not start a service if the addressed
- * name is not currently active. This flag is
- * not looked at by the kernel but only
- * serves as hint for userspace implementations.
- * @KDBUS_MSG_SIGNAL: Treat this message as signal
- */
-enum kdbus_msg_flags {
- KDBUS_MSG_EXPECT_REPLY = 1ULL << 0,
- KDBUS_MSG_NO_AUTO_START = 1ULL << 1,
- KDBUS_MSG_SIGNAL = 1ULL << 2,
-};
-
-/**
- * enum kdbus_payload_type - type of payload carried by message
- * @KDBUS_PAYLOAD_KERNEL: Kernel-generated simple message
- * @KDBUS_PAYLOAD_DBUS: D-Bus marshalling "DBusDBus"
- *
- * Any payload-type is accepted. Common types will get added here once
- * established.
- */
-enum kdbus_payload_type {
- KDBUS_PAYLOAD_KERNEL,
- KDBUS_PAYLOAD_DBUS = 0x4442757344427573ULL,
-};
-
-/**
- * struct kdbus_msg - the representation of a kdbus message
- * @size: Total size of the message
- * @flags: Message flags (KDBUS_MSG_*), userspace → kernel
- * @priority: Message queue priority value
- * @dst_id: 64-bit ID of the destination connection
- * @src_id: 64-bit ID of the source connection
- * @payload_type: Payload type (KDBUS_PAYLOAD_*)
- * @cookie: Userspace-supplied cookie, for the connection
- * to identify its messages
- * @timeout_ns: The time to wait for a message reply from the peer.
- * If there is no reply, and the send command is
- * executed asynchronously, a kernel-generated message
- * with an attached KDBUS_ITEM_REPLY_TIMEOUT item
- * is sent to @src_id. For synchronously executed send
- * command, the value denotes the maximum time the call
- * blocks to wait for a reply. The timeout is expected in
- * nanoseconds and as absolute CLOCK_MONOTONIC value.
- * @cookie_reply: A reply to the requesting message with the same
- * cookie. The requesting connection can match its
- * request and the reply with this value
- * @items: A list of kdbus_items containing the message payload
- */
-struct kdbus_msg {
- __u64 size;
- __u64 flags;
- __s64 priority;
- __u64 dst_id;
- __u64 src_id;
- __u64 payload_type;
- __u64 cookie;
- union {
- __u64 timeout_ns;
- __u64 cookie_reply;
- };
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_msg_info - returned message container
- * @offset: Offset of kdbus_msg slice in pool
- * @msg_size: Copy of the kdbus_msg.size field
- * @return_flags: Command return flags, kernel → userspace
- */
-struct kdbus_msg_info {
- __u64 offset;
- __u64 msg_size;
- __u64 return_flags;
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_send_flags - flags for sending messages
- * @KDBUS_SEND_SYNC_REPLY: Wait for destination connection to
- * reply to this message. The
- * KDBUS_CMD_SEND ioctl() will block
- * until the reply is received, and
- * reply in struct kdbus_cmd_send will
- * yield the offset in the sender's pool
- * where the reply can be found.
- * This flag is only valid if
- * @KDBUS_MSG_EXPECT_REPLY is set as well.
- */
-enum kdbus_send_flags {
- KDBUS_SEND_SYNC_REPLY = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_send - send message
- * @size: Overall size of this structure
- * @flags: Flags to change send behavior (KDBUS_SEND_*)
- * @return_flags: Command return flags, kernel → userspace
- * @msg_address: Storage address of the kdbus_msg to send
- * @reply: Storage for message reply if KDBUS_SEND_SYNC_REPLY
- * was given
- * @items: Additional items for this command
- */
-struct kdbus_cmd_send {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 msg_address;
- struct kdbus_msg_info reply;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_recv_flags - flags for de-queuing messages
- * @KDBUS_RECV_PEEK: Return the next queued message without
- * actually de-queuing it, and without installing
- * any file descriptors or other resources. It is
- * usually used to determine the activating
- * connection of a bus name.
- * @KDBUS_RECV_DROP: Drop and free the next queued message and all
- * its resources without actually receiving it.
- * @KDBUS_RECV_USE_PRIORITY: Only de-queue messages with the specified or
- * higher priority (lowest values); if not set,
- * the priority value is ignored.
- */
-enum kdbus_recv_flags {
- KDBUS_RECV_PEEK = 1ULL << 0,
- KDBUS_RECV_DROP = 1ULL << 1,
- KDBUS_RECV_USE_PRIORITY = 1ULL << 2,
-};
-
-/**
- * enum kdbus_recv_return_flags - return flags for message receive commands
- * @KDBUS_RECV_RETURN_INCOMPLETE_FDS: One or more file descriptors could not
- * be installed. These descriptors in
- * KDBUS_ITEM_FDS will carry the value -1.
- * @KDBUS_RECV_RETURN_DROPPED_MSGS: There have been dropped messages since
- * the last time a message was received.
- * The 'dropped_msgs' counter contains the
- * number of messages dropped pool
- * overflows or other missed broadcasts.
- */
-enum kdbus_recv_return_flags {
- KDBUS_RECV_RETURN_INCOMPLETE_FDS = 1ULL << 0,
- KDBUS_RECV_RETURN_DROPPED_MSGS = 1ULL << 1,
-};
-
-/**
- * struct kdbus_cmd_recv - struct to de-queue a buffered message
- * @size: Overall size of this object
- * @flags: KDBUS_RECV_* flags, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @priority: Minimum priority of the messages to de-queue. Lowest
- * values have the highest priority.
- * @dropped_msgs: In case there were any dropped messages since the last
- * time a message was received, this will be set to the
- * number of lost messages and
- * KDBUS_RECV_RETURN_DROPPED_MSGS will be set in
- * 'return_flags'. This can only happen if the ioctl
- * returns 0 or EAGAIN.
- * @msg: Return storage for received message.
- * @items: Additional items for this command.
- *
- * This struct is used with the KDBUS_CMD_RECV ioctl.
- */
-struct kdbus_cmd_recv {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __s64 priority;
- __u64 dropped_msgs;
- struct kdbus_msg_info msg;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_free - struct to free a slice of memory in the pool
- * @size: Overall size of this structure
- * @flags: Flags for the free command, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @offset: The offset of the memory slice, as returned by other
- * ioctls
- * @items: Additional items to modify the behavior
- *
- * This struct is used with the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_cmd_free {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_hello_flags - flags for struct kdbus_cmd_hello
- * @KDBUS_HELLO_ACCEPT_FD: The connection allows the reception of
- * any passed file descriptors
- * @KDBUS_HELLO_ACTIVATOR: Special-purpose connection which registers
- * a well-know name for a process to be started
- * when traffic arrives
- * @KDBUS_HELLO_POLICY_HOLDER: Special-purpose connection which registers
- * policy entries for a name. The provided name
- * is not activated and not registered with the
- * name database, it only allows unprivileged
- * connections to acquire a name, talk or discover
- * a service
- * @KDBUS_HELLO_MONITOR: Special-purpose connection to monitor
- * bus traffic
- */
-enum kdbus_hello_flags {
- KDBUS_HELLO_ACCEPT_FD = 1ULL << 0,
- KDBUS_HELLO_ACTIVATOR = 1ULL << 1,
- KDBUS_HELLO_POLICY_HOLDER = 1ULL << 2,
- KDBUS_HELLO_MONITOR = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_hello - struct to say hello to kdbus
- * @size: The total size of the structure
- * @flags: Connection flags (KDBUS_HELLO_*), userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @attach_flags_send: Mask of metadata to attach to each message sent
- * off by this connection (KDBUS_ATTACH_*)
- * @attach_flags_recv: Mask of metadata to attach to each message receieved
- * by the new connection (KDBUS_ATTACH_*)
- * @bus_flags: The flags field copied verbatim from the original
- * KDBUS_CMD_BUS_MAKE ioctl. It's intended to be useful
- * to do negotiation of features of the payload that is
- * transferred (kernel → userspace)
- * @id: The ID of this connection (kernel → userspace)
- * @pool_size: Size of the connection's buffer where the received
- * messages are placed
- * @offset: Pool offset where items are returned to report
- * additional information about the bus and the newly
- * created connection.
- * @items_size: Size of buffer returned in the pool slice at @offset.
- * @id128: Unique 128-bit ID of the bus (kernel → userspace)
- * @items: A list of items
- *
- * This struct is used with the KDBUS_CMD_HELLO ioctl.
- */
-struct kdbus_cmd_hello {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 attach_flags_send;
- __u64 attach_flags_recv;
- __u64 bus_flags;
- __u64 id;
- __u64 pool_size;
- __u64 offset;
- __u64 items_size;
- __u8 id128[16];
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_info - connection information
- * @size: total size of the struct
- * @id: 64bit object ID
- * @flags: object creation flags
- * @items: list of items
- *
- * Note that the user is responsible for freeing the allocated memory with
- * the KDBUS_CMD_FREE ioctl.
- */
-struct kdbus_info {
- __u64 size;
- __u64 id;
- __u64 flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_list_flags - what to include into the returned list
- * @KDBUS_LIST_UNIQUE: active connections
- * @KDBUS_LIST_ACTIVATORS: activator connections
- * @KDBUS_LIST_NAMES: known well-known names
- * @KDBUS_LIST_QUEUED: queued-up names
- */
-enum kdbus_list_flags {
- KDBUS_LIST_UNIQUE = 1ULL << 0,
- KDBUS_LIST_NAMES = 1ULL << 1,
- KDBUS_LIST_ACTIVATORS = 1ULL << 2,
- KDBUS_LIST_QUEUED = 1ULL << 3,
-};
-
-/**
- * struct kdbus_cmd_list - list connections
- * @size: overall size of this object
- * @flags: flags for the query (KDBUS_LIST_*), userspace → kernel
- * @return_flags: command return flags, kernel → userspace
- * @offset: Offset in the caller's pool buffer where an array of
- * kdbus_info objects is stored.
- * The user must use KDBUS_CMD_FREE to free the
- * allocated memory.
- * @list_size: size of returned list in bytes
- * @items: Items for the command. Reserved for future use.
- *
- * This structure is used with the KDBUS_CMD_LIST ioctl.
- */
-struct kdbus_cmd_list {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 offset;
- __u64 list_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * struct kdbus_cmd_info - struct used for KDBUS_CMD_CONN_INFO ioctl
- * @size: The total size of the struct
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @id: The 64-bit ID of the connection. If set to zero, passing
- * @name is required. kdbus will look up the name to
- * determine the ID in this case.
- * @attach_flags: Set of attach flags to specify the set of information
- * to receive, userspace → kernel
- * @offset: Returned offset in the caller's pool buffer where the
- * kdbus_info struct result is stored. The user must
- * use KDBUS_CMD_FREE to free the allocated memory.
- * @info_size: Output buffer to report size of data at @offset.
- * @items: The optional item list, containing the
- * well-known name to look up as a KDBUS_ITEM_NAME.
- * Only needed in case @id is zero.
- *
- * On success, the KDBUS_CMD_CONN_INFO ioctl will return 0 and @offset will
- * tell the user the offset in the connection pool buffer at which to find the
- * result in a struct kdbus_info.
- */
-struct kdbus_cmd_info {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 id;
- __u64 attach_flags;
- __u64 offset;
- __u64 info_size;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_cmd_match_flags - flags to control the KDBUS_CMD_MATCH_ADD ioctl
- * @KDBUS_MATCH_REPLACE: If entries with the supplied cookie already
- * exists, remove them before installing the new
- * matches.
- */
-enum kdbus_cmd_match_flags {
- KDBUS_MATCH_REPLACE = 1ULL << 0,
-};
-
-/**
- * struct kdbus_cmd_match - struct to add or remove matches
- * @size: The total size of the struct
- * @flags: Flags for match command (KDBUS_MATCH_*),
- * userspace → kernel
- * @return_flags: Command return flags, kernel → userspace
- * @cookie: Userspace supplied cookie. When removing, the cookie
- * identifies the match to remove
- * @items: A list of items for additional information
- *
- * This structure is used with the KDBUS_CMD_MATCH_ADD and
- * KDBUS_CMD_MATCH_REMOVE ioctl.
- */
-struct kdbus_cmd_match {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- __u64 cookie;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * enum kdbus_make_flags - Flags for KDBUS_CMD_{BUS,ENDPOINT}_MAKE
- * @KDBUS_MAKE_ACCESS_GROUP: Make the bus or endpoint node group-accessible
- * @KDBUS_MAKE_ACCESS_WORLD: Make the bus or endpoint node world-accessible
- */
-enum kdbus_make_flags {
- KDBUS_MAKE_ACCESS_GROUP = 1ULL << 0,
- KDBUS_MAKE_ACCESS_WORLD = 1ULL << 1,
-};
-
-/**
- * enum kdbus_name_flags - flags for KDBUS_CMD_NAME_ACQUIRE
- * @KDBUS_NAME_REPLACE_EXISTING: Try to replace name of other connections
- * @KDBUS_NAME_ALLOW_REPLACEMENT: Allow the replacement of the name
- * @KDBUS_NAME_QUEUE: Name should be queued if busy
- * @KDBUS_NAME_IN_QUEUE: Name is queued
- * @KDBUS_NAME_ACTIVATOR: Name is owned by a activator connection
- * @KDBUS_NAME_PRIMARY: Primary owner of the name
- * @KDBUS_NAME_ACQUIRED: Name was acquired/queued _now_
- */
-enum kdbus_name_flags {
- KDBUS_NAME_REPLACE_EXISTING = 1ULL << 0,
- KDBUS_NAME_ALLOW_REPLACEMENT = 1ULL << 1,
- KDBUS_NAME_QUEUE = 1ULL << 2,
- KDBUS_NAME_IN_QUEUE = 1ULL << 3,
- KDBUS_NAME_ACTIVATOR = 1ULL << 4,
- KDBUS_NAME_PRIMARY = 1ULL << 5,
- KDBUS_NAME_ACQUIRED = 1ULL << 6,
-};
-
-/**
- * struct kdbus_cmd - generic ioctl payload
- * @size: Overall size of this structure
- * @flags: Flags for this ioctl, userspace → kernel
- * @return_flags: Ioctl return flags, kernel → userspace
- * @items: Additional items to modify the behavior
- *
- * This is a generic ioctl payload object. It's used by all ioctls that only
- * take flags and items as input.
- */
-struct kdbus_cmd {
- __u64 size;
- __u64 flags;
- __u64 return_flags;
- struct kdbus_item items[0];
-} __attribute__((__aligned__(8)));
-
-/**
- * Ioctl API
- *
- * KDBUS_CMD_BUS_MAKE: After opening the "control" node, this command
- * creates a new bus with the specified
- * name. The bus is immediately shut down and
- * cleaned up when the opened file descriptor is
- * closed.
- *
- * KDBUS_CMD_ENDPOINT_MAKE: Creates a new named special endpoint to talk to
- * the bus. Such endpoints usually carry a more
- * restrictive policy and grant restricted access
- * to specific applications.
- * KDBUS_CMD_ENDPOINT_UPDATE: Update the properties of a custom enpoint. Used
- * to update the policy.
- *
- * KDBUS_CMD_HELLO: By opening the bus node, a connection is
- * created. After a HELLO the opened connection
- * becomes an active peer on the bus.
- * KDBUS_CMD_UPDATE: Update the properties of a connection. Used to
- * update the metadata subscription mask and
- * policy.
- * KDBUS_CMD_BYEBYE: Disconnect a connection. If there are no
- * messages queued up in the connection's pool,
- * the call succeeds, and the handle is rendered
- * unusable. Otherwise, -EBUSY is returned without
- * any further side-effects.
- * KDBUS_CMD_FREE: Release the allocated memory in the receiver's
- * pool.
- * KDBUS_CMD_CONN_INFO: Retrieve credentials and properties of the
- * initial creator of the connection. The data was
- * stored at registration time and does not
- * necessarily represent the connected process or
- * the actual state of the process.
- * KDBUS_CMD_BUS_CREATOR_INFO: Retrieve information of the creator of the bus
- * a connection is attached to.
- *
- * KDBUS_CMD_SEND: Send a message and pass data from userspace to
- * the kernel.
- * KDBUS_CMD_RECV: Receive a message from the kernel which is
- * placed in the receiver's pool.
- *
- * KDBUS_CMD_NAME_ACQUIRE: Request a well-known bus name to associate with
- * the connection. Well-known names are used to
- * address a peer on the bus.
- * KDBUS_CMD_NAME_RELEASE: Release a well-known name the connection
- * currently owns.
- * KDBUS_CMD_LIST: Retrieve the list of all currently registered
- * well-known and unique names.
- *
- * KDBUS_CMD_MATCH_ADD: Install a match which broadcast messages should
- * be delivered to the connection.
- * KDBUS_CMD_MATCH_REMOVE: Remove a current match for broadcast messages.
- */
-enum kdbus_ioctl_type {
- /* bus owner (00-0f) */
- KDBUS_CMD_BUS_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x00,
- struct kdbus_cmd),
-
- /* endpoint owner (10-1f) */
- KDBUS_CMD_ENDPOINT_MAKE = _IOW(KDBUS_IOCTL_MAGIC, 0x10,
- struct kdbus_cmd),
- KDBUS_CMD_ENDPOINT_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x11,
- struct kdbus_cmd),
-
- /* connection owner (80-ff) */
- KDBUS_CMD_HELLO = _IOWR(KDBUS_IOCTL_MAGIC, 0x80,
- struct kdbus_cmd_hello),
- KDBUS_CMD_UPDATE = _IOW(KDBUS_IOCTL_MAGIC, 0x81,
- struct kdbus_cmd),
- KDBUS_CMD_BYEBYE = _IOW(KDBUS_IOCTL_MAGIC, 0x82,
- struct kdbus_cmd),
- KDBUS_CMD_FREE = _IOW(KDBUS_IOCTL_MAGIC, 0x83,
- struct kdbus_cmd_free),
- KDBUS_CMD_CONN_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x84,
- struct kdbus_cmd_info),
- KDBUS_CMD_BUS_CREATOR_INFO = _IOR(KDBUS_IOCTL_MAGIC, 0x85,
- struct kdbus_cmd_info),
- KDBUS_CMD_LIST = _IOR(KDBUS_IOCTL_MAGIC, 0x86,
- struct kdbus_cmd_list),
-
- KDBUS_CMD_SEND = _IOW(KDBUS_IOCTL_MAGIC, 0x90,
- struct kdbus_cmd_send),
- KDBUS_CMD_RECV = _IOR(KDBUS_IOCTL_MAGIC, 0x91,
- struct kdbus_cmd_recv),
-
- KDBUS_CMD_NAME_ACQUIRE = _IOW(KDBUS_IOCTL_MAGIC, 0xa0,
- struct kdbus_cmd),
- KDBUS_CMD_NAME_RELEASE = _IOW(KDBUS_IOCTL_MAGIC, 0xa1,
- struct kdbus_cmd),
-
- KDBUS_CMD_MATCH_ADD = _IOW(KDBUS_IOCTL_MAGIC, 0xb0,
- struct kdbus_cmd_match),
- KDBUS_CMD_MATCH_REMOVE = _IOW(KDBUS_IOCTL_MAGIC, 0xb1,
- struct kdbus_cmd_match),
-};
-
-#endif /* _UAPI_KDBUS_H_ */
diff --git a/include/uapi/linux/magic.h b/include/uapi/linux/magic.h
index 59e1c45b5..accb036bb 100644
--- a/include/uapi/linux/magic.h
+++ b/include/uapi/linux/magic.h
@@ -77,6 +77,4 @@
#define NSFS_MAGIC 0x6e736673
#define BPF_FS_MAGIC 0xcafe4a11
-#define KDBUS_SUPER_MAGIC 0x44427573
-
#endif /* __LINUX_MAGIC_H__ */
diff --git a/init/Kconfig b/init/Kconfig
index f7e8c274a..79f5ac6aa 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -281,19 +281,6 @@ config POSIX_MQUEUE_SYSCTL
depends on SYSCTL
default y
-config KDBUS
- tristate "kdbus interprocess communication"
- depends on TMPFS
- help
- D-Bus is a system for low-latency, low-overhead, easy to use
- interprocess communication (IPC).
-
- See the man-pages and HTML files in Documentation/kdbus/
- that are generated by 'make mandocs' and 'make htmldocs'.
-
- If you have an ordinary machine, select M here. The module
- will be called kdbus.
-
config CROSS_MEMORY_ATTACH
bool "Enable process_vm_readv/writev syscalls"
depends on MMU
diff --git a/ipc/Makefile b/ipc/Makefile
index 68ec4167d..61eeb1624 100644
--- a/ipc/Makefile
+++ b/ipc/Makefile
@@ -9,4 +9,3 @@ obj_mq-$(CONFIG_COMPAT) += compat_mq.o
obj-$(CONFIG_POSIX_MQUEUE) += mqueue.o msgutil.o $(obj_mq-y)
obj-$(CONFIG_IPC_NS) += namespace.o
obj-$(CONFIG_POSIX_MQUEUE_SYSCTL) += mq_sysctl.o
-obj-$(CONFIG_KDBUS) += kdbus/
diff --git a/ipc/kdbus/Makefile b/ipc/kdbus/Makefile
deleted file mode 100644
index 66663a124..000000000
--- a/ipc/kdbus/Makefile
+++ /dev/null
@@ -1,33 +0,0 @@
-#
-# By setting KDBUS_EXT=2, the kdbus module will be built as kdbus2.ko, and
-# KBUILD_MODNAME=kdbus2. This has the effect that all exported objects have
-# different names than usually (kdbus2fs, /sys/fs/kdbus2/) and you can run
-# your test-infrastructure against the kdbus2.ko, while running your system
-# on kdbus.ko.
-#
-# To just build the module, use:
-# make KDBUS_EXT=2 M=ipc/kdbus
-#
-
-kdbus$(KDBUS_EXT)-y := \
- bus.o \
- connection.o \
- endpoint.o \
- fs.o \
- handle.o \
- item.o \
- main.o \
- match.o \
- message.o \
- metadata.o \
- names.o \
- node.o \
- notify.o \
- domain.o \
- policy.o \
- pool.o \
- reply.o \
- queue.o \
- util.o
-
-obj-$(CONFIG_KDBUS) += kdbus$(KDBUS_EXT).o
diff --git a/ipc/kdbus/bus.c b/ipc/kdbus/bus.c
deleted file mode 100644
index e636d3478..000000000
--- a/ipc/kdbus/bus.c
+++ /dev/null
@@ -1,514 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/hashtable.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/random.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "notify.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "policy.h"
-#include "util.h"
-
-static void kdbus_bus_free(struct kdbus_node *node)
-{
- struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node);
-
- WARN_ON(!list_empty(&bus->monitors_list));
- WARN_ON(!hash_empty(bus->conn_hash));
-
- kdbus_notify_free(bus);
-
- kdbus_user_unref(bus->creator);
- kdbus_name_registry_free(bus->name_registry);
- kdbus_domain_unref(bus->domain);
- kdbus_policy_db_clear(&bus->policy_db);
- kdbus_meta_proc_unref(bus->creator_meta);
- kfree(bus);
-}
-
-static void kdbus_bus_release(struct kdbus_node *node, bool was_active)
-{
- struct kdbus_bus *bus = container_of(node, struct kdbus_bus, node);
-
- if (was_active)
- atomic_dec(&bus->creator->buses);
-}
-
-static struct kdbus_bus *kdbus_bus_new(struct kdbus_domain *domain,
- const char *name,
- struct kdbus_bloom_parameter *bloom,
- const u64 *pattach_owner,
- u64 flags, kuid_t uid, kgid_t gid)
-{
- struct kdbus_bus *b;
- u64 attach_owner;
- int ret;
-
- if (bloom->size < 8 || bloom->size > KDBUS_BUS_BLOOM_MAX_SIZE ||
- !KDBUS_IS_ALIGNED8(bloom->size) || bloom->n_hash < 1)
- return ERR_PTR(-EINVAL);
-
- ret = kdbus_sanitize_attach_flags(pattach_owner ? *pattach_owner : 0,
- &attach_owner);
- if (ret < 0)
- return ERR_PTR(ret);
-
- ret = kdbus_verify_uid_prefix(name, domain->user_namespace, uid);
- if (ret < 0)
- return ERR_PTR(ret);
-
- b = kzalloc(sizeof(*b), GFP_KERNEL);
- if (!b)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(&b->node, KDBUS_NODE_BUS);
-
- b->node.free_cb = kdbus_bus_free;
- b->node.release_cb = kdbus_bus_release;
- b->node.uid = uid;
- b->node.gid = gid;
- b->node.mode = S_IRUSR | S_IXUSR;
-
- if (flags & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- b->node.mode |= S_IRGRP | S_IXGRP;
- if (flags & KDBUS_MAKE_ACCESS_WORLD)
- b->node.mode |= S_IROTH | S_IXOTH;
-
- b->id = atomic64_inc_return(&domain->last_id);
- b->bus_flags = flags;
- b->attach_flags_owner = attach_owner;
- generate_random_uuid(b->id128);
- b->bloom = *bloom;
- b->domain = kdbus_domain_ref(domain);
-
- kdbus_policy_db_init(&b->policy_db);
-
- init_rwsem(&b->conn_rwlock);
- hash_init(b->conn_hash);
- INIT_LIST_HEAD(&b->monitors_list);
-
- INIT_LIST_HEAD(&b->notify_list);
- spin_lock_init(&b->notify_lock);
- mutex_init(&b->notify_flush_lock);
-
- ret = kdbus_node_link(&b->node, &domain->node, name);
- if (ret < 0)
- goto exit_unref;
-
- /* cache the metadata/credentials of the creator */
- b->creator_meta = kdbus_meta_proc_new();
- if (IS_ERR(b->creator_meta)) {
- ret = PTR_ERR(b->creator_meta);
- b->creator_meta = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_proc_collect(b->creator_meta,
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_EXE |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_AUDIT);
- if (ret < 0)
- goto exit_unref;
-
- b->name_registry = kdbus_name_registry_new();
- if (IS_ERR(b->name_registry)) {
- ret = PTR_ERR(b->name_registry);
- b->name_registry = NULL;
- goto exit_unref;
- }
-
- /*
- * Bus-limits of the creator are accounted on its real UID, just like
- * all other per-user limits.
- */
- b->creator = kdbus_user_lookup(domain, current_uid());
- if (IS_ERR(b->creator)) {
- ret = PTR_ERR(b->creator);
- b->creator = NULL;
- goto exit_unref;
- }
-
- return b;
-
-exit_unref:
- kdbus_node_drain(&b->node);
- kdbus_node_unref(&b->node);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_bus_ref() - increase the reference counter of a kdbus_bus
- * @bus: The bus to reference
- *
- * Every user of a bus, except for its creator, must add a reference to the
- * kdbus_bus using this function.
- *
- * Return: the bus itself
- */
-struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus)
-{
- if (bus)
- kdbus_node_ref(&bus->node);
- return bus;
-}
-
-/**
- * kdbus_bus_unref() - decrease the reference counter of a kdbus_bus
- * @bus: The bus to unref
- *
- * Release a reference. If the reference count drops to 0, the bus will be
- * freed.
- *
- * Return: NULL
- */
-struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus)
-{
- if (bus)
- kdbus_node_unref(&bus->node);
- return NULL;
-}
-
-/**
- * kdbus_bus_find_conn_by_id() - find a connection with a given id
- * @bus: The bus to look for the connection
- * @id: The 64-bit connection id
- *
- * Looks up a connection with a given id. The returned connection
- * is ref'ed, and needs to be unref'ed by the user. Returns NULL if
- * the connection can't be found.
- */
-struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id)
-{
- struct kdbus_conn *conn, *found = NULL;
-
- down_read(&bus->conn_rwlock);
- hash_for_each_possible(bus->conn_hash, conn, hentry, id)
- if (conn->id == id) {
- found = kdbus_conn_ref(conn);
- break;
- }
- up_read(&bus->conn_rwlock);
-
- return found;
-}
-
-/**
- * kdbus_bus_broadcast() - send a message to all subscribed connections
- * @bus: The bus the connections are connected to
- * @conn_src: The source connection, may be %NULL for kernel notifications
- * @staging: Staging object containing the message to send
- *
- * Send message to all connections that are currently active on the bus.
- * Connections must still have matches installed in order to let the message
- * pass.
- *
- * The caller must hold the name-registry lock of @bus.
- */
-void kdbus_bus_broadcast(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_staging *staging)
-{
- struct kdbus_conn *conn_dst;
- unsigned int i;
- int ret;
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- /*
- * Make sure broadcast are queued on monitors before we send it out to
- * anyone else. Otherwise, connections might react to broadcasts before
- * the monitor gets the broadcast queued. In the worst case, the
- * monitor sees a reaction to the broadcast before the broadcast itself.
- * We don't give ordering guarantees across connections (and monitors
- * can re-construct order via sequence numbers), but we should at least
- * try to avoid re-ordering for monitors.
- */
- kdbus_bus_eavesdrop(bus, conn_src, staging);
-
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, conn_dst, hentry) {
- if (!kdbus_conn_is_ordinary(conn_dst))
- continue;
-
- /*
- * Check if there is a match for the kmsg object in
- * the destination connection match db
- */
- if (!kdbus_match_db_match_msg(conn_dst->match_db, conn_src,
- staging))
- continue;
-
- if (conn_src) {
- /*
- * Anyone can send broadcasts, as they have no
- * destination. But a receiver needs TALK access to
- * the sender in order to receive broadcasts.
- */
- if (!kdbus_conn_policy_talk(conn_dst, NULL, conn_src))
- continue;
- } else {
- /*
- * Check if there is a policy db that prevents the
- * destination connection from receiving this kernel
- * notification
- */
- if (!kdbus_conn_policy_see_notification(conn_dst, NULL,
- staging->msg))
- continue;
- }
-
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging,
- NULL, NULL);
- if (ret < 0)
- kdbus_conn_lost_message(conn_dst);
- }
- up_read(&bus->conn_rwlock);
-}
-
-/**
- * kdbus_bus_eavesdrop() - send a message to all subscribed monitors
- * @bus: The bus the monitors are connected to
- * @conn_src: The source connection, may be %NULL for kernel notifications
- * @staging: Staging object containing the message to send
- *
- * Send message to all monitors that are currently active on the bus. Monitors
- * must still have matches installed in order to let the message pass.
- *
- * The caller must hold the name-registry lock of @bus.
- */
-void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_staging *staging)
-{
- struct kdbus_conn *conn_dst;
- int ret;
-
- /*
- * Monitor connections get all messages; ignore possible errors
- * when sending messages to monitor connections.
- */
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- down_read(&bus->conn_rwlock);
- list_for_each_entry(conn_dst, &bus->monitors_list, monitor_entry) {
- ret = kdbus_conn_entry_insert(conn_src, conn_dst, staging,
- NULL, NULL);
- if (ret < 0)
- kdbus_conn_lost_message(conn_dst);
- }
- up_read(&bus->conn_rwlock);
-}
-
-/**
- * kdbus_cmd_bus_make() - handle KDBUS_CMD_BUS_MAKE
- * @domain: domain to operate on
- * @argp: command payload
- *
- * Return: NULL or newly created bus on success, ERR_PTR on failure.
- */
-struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
- void __user *argp)
-{
- struct kdbus_bus *bus = NULL;
- struct kdbus_cmd *cmd;
- struct kdbus_ep *ep = NULL;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true },
- { .type = KDBUS_ITEM_BLOOM_PARAMETER, .mandatory = true },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MAKE_ACCESS_GROUP |
- KDBUS_MAKE_ACCESS_WORLD,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret < 0)
- return ERR_PTR(ret);
- if (ret > 0)
- return NULL;
-
- bus = kdbus_bus_new(domain,
- argv[1].item->str, &argv[2].item->bloom_parameter,
- argv[3].item ? argv[3].item->data64 : NULL,
- cmd->flags, current_euid(), current_egid());
- if (IS_ERR(bus)) {
- ret = PTR_ERR(bus);
- bus = NULL;
- goto exit;
- }
-
- if (atomic_inc_return(&bus->creator->buses) > KDBUS_USER_MAX_BUSES) {
- atomic_dec(&bus->creator->buses);
- ret = -EMFILE;
- goto exit;
- }
-
- if (!kdbus_node_activate(&bus->node)) {
- atomic_dec(&bus->creator->buses);
- ret = -ESHUTDOWN;
- goto exit;
- }
-
- ep = kdbus_ep_new(bus, "bus", cmd->flags, bus->node.uid, bus->node.gid,
- false);
- if (IS_ERR(ep)) {
- ret = PTR_ERR(ep);
- ep = NULL;
- goto exit;
- }
-
- if (!kdbus_node_activate(&ep->node)) {
- ret = -ESHUTDOWN;
- goto exit;
- }
-
- /*
- * Drop our own reference, effectively causing the endpoint to be
- * deactivated and released when the parent bus is.
- */
- ep = kdbus_ep_unref(ep);
-
-exit:
- ret = kdbus_args_clear(&args, ret);
- if (ret < 0) {
- if (ep) {
- kdbus_node_drain(&ep->node);
- kdbus_ep_unref(ep);
- }
- if (bus) {
- kdbus_node_drain(&bus->node);
- kdbus_bus_unref(bus);
- }
- return ERR_PTR(ret);
- }
- return bus;
-}
-
-/**
- * kdbus_cmd_bus_creator_info() - handle KDBUS_CMD_BUS_CREATOR_INFO
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_info *cmd;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_item *meta_items = NULL;
- struct kdbus_item_header item_hdr;
- struct kdbus_info info = {};
- size_t meta_size, name_len, cnt = 0;
- struct kvec kvec[6];
- u64 attach_flags, size = 0;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags);
- if (ret < 0)
- goto exit;
-
- attach_flags &= bus->attach_flags_owner;
-
- ret = kdbus_meta_emit(bus->creator_meta, NULL, NULL, conn,
- attach_flags, &meta_items, &meta_size);
- if (ret < 0)
- goto exit;
-
- name_len = strlen(bus->node.name) + 1;
- info.id = bus->id;
- info.flags = bus->bus_flags;
- item_hdr.type = KDBUS_ITEM_MAKE_NAME;
- item_hdr.size = KDBUS_ITEM_HEADER_SIZE + name_len;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size);
- kdbus_kvec_set(&kvec[cnt++], &item_hdr, sizeof(item_hdr), &size);
- kdbus_kvec_set(&kvec[cnt++], bus->node.name, name_len, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- if (meta_size > 0) {
- kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- }
-
- info.size = size;
-
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size);
- if (ret < 0)
- goto exit;
-
- kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size);
-
- if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
- kdbus_member_set_user(&cmd->info_size, argp,
- typeof(*cmd), info_size))
- ret = -EFAULT;
-
-exit:
- kdbus_pool_slice_release(slice);
- kfree(meta_items);
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/bus.h b/ipc/kdbus/bus.h
deleted file mode 100644
index 8c2acaed6..000000000
--- a/ipc/kdbus/bus.h
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_BUS_H
-#define __KDBUS_BUS_H
-
-#include <linux/hashtable.h>
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/spinlock.h>
-#include <uapi/linux/kdbus.h>
-
-#include "metadata.h"
-#include "names.h"
-#include "node.h"
-#include "policy.h"
-
-struct kdbus_conn;
-struct kdbus_domain;
-struct kdbus_staging;
-struct kdbus_user;
-
-/**
- * struct kdbus_bus - bus in a domain
- * @node: kdbus_node
- * @id: ID of this bus in the domain
- * @bus_flags: Simple pass-through flags from userspace to userspace
- * @attach_flags_owner: KDBUS_ATTACH_* flags of bus creator that other
- * connections can see or query
- * @id128: Unique random 128 bit ID of this bus
- * @bloom: Bloom parameters
- * @domain: Domain of this bus
- * @creator: Creator of the bus
- * @creator_meta: Meta information about the bus creator
- * @last_message_id: Last used message id
- * @policy_db: Policy database for this bus
- * @name_registry: Name registry of this bus
- * @conn_rwlock: Read/Write lock for all lists of child connections
- * @conn_hash: Map of connection IDs
- * @monitors_list: Connections that monitor this bus
- * @notify_list: List of pending kernel-generated messages
- * @notify_lock: Notification list lock
- * @notify_flush_lock: Notification flushing lock
- */
-struct kdbus_bus {
- struct kdbus_node node;
-
- /* static */
- u64 id;
- u64 bus_flags;
- u64 attach_flags_owner;
- u8 id128[16];
- struct kdbus_bloom_parameter bloom;
- struct kdbus_domain *domain;
- struct kdbus_user *creator;
- struct kdbus_meta_proc *creator_meta;
-
- /* protected by own locks */
- atomic64_t last_message_id;
- struct kdbus_policy_db policy_db;
- struct kdbus_name_registry *name_registry;
-
- /* protected by conn_rwlock */
- struct rw_semaphore conn_rwlock;
- DECLARE_HASHTABLE(conn_hash, 8);
- struct list_head monitors_list;
-
- /* protected by notify_lock */
- struct list_head notify_list;
- spinlock_t notify_lock;
- struct mutex notify_flush_lock;
-};
-
-struct kdbus_bus *kdbus_bus_ref(struct kdbus_bus *bus);
-struct kdbus_bus *kdbus_bus_unref(struct kdbus_bus *bus);
-
-struct kdbus_conn *kdbus_bus_find_conn_by_id(struct kdbus_bus *bus, u64 id);
-void kdbus_bus_broadcast(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_staging *staging);
-void kdbus_bus_eavesdrop(struct kdbus_bus *bus,
- struct kdbus_conn *conn_src,
- struct kdbus_staging *staging);
-
-struct kdbus_bus *kdbus_cmd_bus_make(struct kdbus_domain *domain,
- void __user *argp);
-int kdbus_cmd_bus_creator_info(struct kdbus_conn *conn, void __user *argp);
-
-#endif
diff --git a/ipc/kdbus/connection.c b/ipc/kdbus/connection.c
deleted file mode 100644
index ef63d6533..000000000
--- a/ipc/kdbus/connection.c
+++ /dev/null
@@ -1,2227 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/audit.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/fs_struct.h>
-#include <linux/hashtable.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/math64.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/path.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "match.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "domain.h"
-#include "item.h"
-#include "notify.h"
-#include "policy.h"
-#include "pool.h"
-#include "reply.h"
-#include "util.h"
-#include "queue.h"
-
-#define KDBUS_CONN_ACTIVE_BIAS (INT_MIN + 2)
-#define KDBUS_CONN_ACTIVE_NEW (INT_MIN + 1)
-
-static struct kdbus_conn *kdbus_conn_new(struct kdbus_ep *ep,
- struct file *file,
- struct kdbus_cmd_hello *hello,
- const char *name,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel,
- const char *conn_description)
-{
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- static struct lock_class_key __key;
-#endif
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_bus *bus = ep->bus;
- struct kdbus_conn *conn;
- u64 attach_flags_send;
- u64 attach_flags_recv;
- u64 items_size = 0;
- bool is_policy_holder;
- bool is_activator;
- bool is_monitor;
- bool privileged;
- bool owner;
- struct kvec kvec;
- int ret;
-
- struct {
- u64 size;
- u64 type;
- struct kdbus_bloom_parameter bloom;
- } bloom_item;
-
- privileged = kdbus_ep_is_privileged(ep, file);
- owner = kdbus_ep_is_owner(ep, file);
-
- is_monitor = hello->flags & KDBUS_HELLO_MONITOR;
- is_activator = hello->flags & KDBUS_HELLO_ACTIVATOR;
- is_policy_holder = hello->flags & KDBUS_HELLO_POLICY_HOLDER;
-
- if (!hello->pool_size || !IS_ALIGNED(hello->pool_size, PAGE_SIZE))
- return ERR_PTR(-EINVAL);
- if (is_monitor + is_activator + is_policy_holder > 1)
- return ERR_PTR(-EINVAL);
- if (name && !is_activator && !is_policy_holder)
- return ERR_PTR(-EINVAL);
- if (!name && (is_activator || is_policy_holder))
- return ERR_PTR(-EINVAL);
- if (name && !kdbus_name_is_valid(name, true))
- return ERR_PTR(-EINVAL);
- if (is_monitor && ep->user)
- return ERR_PTR(-EOPNOTSUPP);
- if (!owner && (is_activator || is_policy_holder || is_monitor))
- return ERR_PTR(-EPERM);
- if (!owner && (creds || pids || seclabel))
- return ERR_PTR(-EPERM);
-
- ret = kdbus_sanitize_attach_flags(hello->attach_flags_send,
- &attach_flags_send);
- if (ret < 0)
- return ERR_PTR(ret);
-
- ret = kdbus_sanitize_attach_flags(hello->attach_flags_recv,
- &attach_flags_recv);
- if (ret < 0)
- return ERR_PTR(ret);
-
- conn = kzalloc(sizeof(*conn), GFP_KERNEL);
- if (!conn)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&conn->kref);
- atomic_set(&conn->active, KDBUS_CONN_ACTIVE_NEW);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- lockdep_init_map(&conn->dep_map, "s_active", &__key, 0);
-#endif
- mutex_init(&conn->lock);
- INIT_LIST_HEAD(&conn->names_list);
- INIT_LIST_HEAD(&conn->reply_list);
- atomic_set(&conn->request_count, 0);
- atomic_set(&conn->lost_count, 0);
- INIT_DELAYED_WORK(&conn->work, kdbus_reply_list_scan_work);
- conn->cred = get_cred(file->f_cred);
- conn->pid = get_pid(task_pid(current));
- get_fs_root(current->fs, &conn->root_path);
- init_waitqueue_head(&conn->wait);
- kdbus_queue_init(&conn->queue);
- conn->privileged = privileged;
- conn->owner = owner;
- conn->ep = kdbus_ep_ref(ep);
- conn->id = atomic64_inc_return(&bus->domain->last_id);
- conn->flags = hello->flags;
- atomic64_set(&conn->attach_flags_send, attach_flags_send);
- atomic64_set(&conn->attach_flags_recv, attach_flags_recv);
- INIT_LIST_HEAD(&conn->monitor_entry);
-
- if (conn_description) {
- conn->description = kstrdup(conn_description, GFP_KERNEL);
- if (!conn->description) {
- ret = -ENOMEM;
- goto exit_unref;
- }
- }
-
- conn->pool = kdbus_pool_new(conn->description, hello->pool_size);
- if (IS_ERR(conn->pool)) {
- ret = PTR_ERR(conn->pool);
- conn->pool = NULL;
- goto exit_unref;
- }
-
- conn->match_db = kdbus_match_db_new();
- if (IS_ERR(conn->match_db)) {
- ret = PTR_ERR(conn->match_db);
- conn->match_db = NULL;
- goto exit_unref;
- }
-
- /* return properties of this connection to the caller */
- hello->bus_flags = bus->bus_flags;
- hello->id = conn->id;
-
- BUILD_BUG_ON(sizeof(bus->id128) != sizeof(hello->id128));
- memcpy(hello->id128, bus->id128, sizeof(hello->id128));
-
- /* privileged processes can impersonate somebody else */
- if (creds || pids || seclabel) {
- conn->meta_fake = kdbus_meta_fake_new();
- if (IS_ERR(conn->meta_fake)) {
- ret = PTR_ERR(conn->meta_fake);
- conn->meta_fake = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_fake_collect(conn->meta_fake,
- creds, pids, seclabel);
- if (ret < 0)
- goto exit_unref;
- } else {
- conn->meta_proc = kdbus_meta_proc_new();
- if (IS_ERR(conn->meta_proc)) {
- ret = PTR_ERR(conn->meta_proc);
- conn->meta_proc = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_meta_proc_collect(conn->meta_proc,
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_EXE |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_AUDIT);
- if (ret < 0)
- goto exit_unref;
- }
-
- /*
- * Account the connection against the current user (UID), or for
- * custom endpoints use the anonymous user assigned to the endpoint.
- * Note that limits are always accounted against the real UID, not
- * the effective UID (cred->user always points to the accounting of
- * cred->uid, not cred->euid).
- * In case the caller is privileged, we allow changing the accounting
- * to the faked user.
- */
- if (ep->user) {
- conn->user = kdbus_user_ref(ep->user);
- } else {
- kuid_t uid;
-
- if (conn->meta_fake && uid_valid(conn->meta_fake->uid) &&
- conn->privileged)
- uid = conn->meta_fake->uid;
- else
- uid = conn->cred->uid;
-
- conn->user = kdbus_user_lookup(ep->bus->domain, uid);
- if (IS_ERR(conn->user)) {
- ret = PTR_ERR(conn->user);
- conn->user = NULL;
- goto exit_unref;
- }
- }
-
- if (atomic_inc_return(&conn->user->connections) > KDBUS_USER_MAX_CONN) {
- /* decremented by destructor as conn->user is valid */
- ret = -EMFILE;
- goto exit_unref;
- }
-
- bloom_item.size = sizeof(bloom_item);
- bloom_item.type = KDBUS_ITEM_BLOOM_PARAMETER;
- bloom_item.bloom = bus->bloom;
- kdbus_kvec_set(&kvec, &bloom_item, bloom_item.size, &items_size);
-
- slice = kdbus_pool_slice_alloc(conn->pool, items_size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit_unref;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, &kvec, 1, items_size);
- if (ret < 0)
- goto exit_unref;
-
- kdbus_pool_slice_publish(slice, &hello->offset, &hello->items_size);
- kdbus_pool_slice_release(slice);
-
- return conn;
-
-exit_unref:
- kdbus_pool_slice_release(slice);
- kdbus_conn_unref(conn);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_conn_free(struct kref *kref)
-{
- struct kdbus_conn *conn = container_of(kref, struct kdbus_conn, kref);
-
- WARN_ON(kdbus_conn_active(conn));
- WARN_ON(delayed_work_pending(&conn->work));
- WARN_ON(!list_empty(&conn->queue.msg_list));
- WARN_ON(!list_empty(&conn->names_list));
- WARN_ON(!list_empty(&conn->reply_list));
-
- if (conn->user) {
- atomic_dec(&conn->user->connections);
- kdbus_user_unref(conn->user);
- }
-
- kdbus_meta_fake_free(conn->meta_fake);
- kdbus_meta_proc_unref(conn->meta_proc);
- kdbus_match_db_free(conn->match_db);
- kdbus_pool_free(conn->pool);
- kdbus_ep_unref(conn->ep);
- path_put(&conn->root_path);
- put_pid(conn->pid);
- put_cred(conn->cred);
- kfree(conn->description);
- kfree(conn->quota);
- kfree(conn);
-}
-
-/**
- * kdbus_conn_ref() - take a connection reference
- * @conn: Connection, may be %NULL
- *
- * Return: the connection itself
- */
-struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn)
-{
- if (conn)
- kref_get(&conn->kref);
- return conn;
-}
-
-/**
- * kdbus_conn_unref() - drop a connection reference
- * @conn: Connection (may be NULL)
- *
- * When the last reference is dropped, the connection's internal structure
- * is freed.
- *
- * Return: NULL
- */
-struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn)
-{
- if (conn)
- kref_put(&conn->kref, __kdbus_conn_free);
- return NULL;
-}
-
-/**
- * kdbus_conn_active() - connection is not disconnected
- * @conn: Connection to check
- *
- * Return true if the connection was not disconnected, yet. Note that a
- * connection might be disconnected asynchronously, unless you hold the
- * connection lock. If that's not suitable for you, see kdbus_conn_acquire() to
- * suppress connection shutdown for a short period.
- *
- * Return: true if the connection is still active
- */
-bool kdbus_conn_active(const struct kdbus_conn *conn)
-{
- return atomic_read(&conn->active) >= 0;
-}
-
-/**
- * kdbus_conn_acquire() - acquire an active connection reference
- * @conn: Connection
- *
- * Users can close a connection via KDBUS_BYEBYE (or by destroying the
- * endpoint/bus/...) at any time. Whenever this happens, we should deny any
- * user-visible action on this connection and signal ECONNRESET instead.
- * To avoid testing for connection availability everytime you take the
- * connection-lock, you can acquire a connection for short periods.
- *
- * By calling kdbus_conn_acquire(), you gain an "active reference" to the
- * connection. You must also hold a regular reference at any time! As long as
- * you hold the active-ref, the connection will not be shut down. However, if
- * the connection was shut down, you can never acquire an active-ref again.
- *
- * kdbus_conn_disconnect() disables the connection and then waits for all active
- * references to be dropped. It will also wake up any pending operation.
- * However, you must not sleep for an indefinite period while holding an
- * active-reference. Otherwise, kdbus_conn_disconnect() might stall. If you need
- * to sleep for an indefinite period, either release the reference and try to
- * acquire it again after waking up, or make kdbus_conn_disconnect() wake up
- * your wait-queue.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_conn_acquire(struct kdbus_conn *conn)
-{
- if (!atomic_inc_unless_negative(&conn->active))
- return -ECONNRESET;
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_);
-#endif
-
- return 0;
-}
-
-/**
- * kdbus_conn_release() - release an active connection reference
- * @conn: Connection
- *
- * This releases an active reference that has been acquired via
- * kdbus_conn_acquire(). If the connection was already disabled and this is the
- * last active-ref that is dropped, the disconnect-waiter will be woken up and
- * properly close the connection.
- */
-void kdbus_conn_release(struct kdbus_conn *conn)
-{
- int v;
-
- if (!conn)
- return;
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_release(&conn->dep_map, 1, _RET_IP_);
-#endif
-
- v = atomic_dec_return(&conn->active);
- if (v != KDBUS_CONN_ACTIVE_BIAS)
- return;
-
- wake_up_all(&conn->wait);
-}
-
-static int kdbus_conn_connect(struct kdbus_conn *conn, const char *name)
-{
- struct kdbus_ep *ep = conn->ep;
- struct kdbus_bus *bus = ep->bus;
- int ret;
-
- if (WARN_ON(atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_NEW))
- return -EALREADY;
-
- /* make sure the ep-node is active while we add our connection */
- if (!kdbus_node_acquire(&ep->node))
- return -ESHUTDOWN;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- mutex_lock(&ep->lock);
- down_write(&bus->conn_rwlock);
-
- /* link into monitor list */
- if (kdbus_conn_is_monitor(conn))
- list_add_tail(&conn->monitor_entry, &bus->monitors_list);
-
- /* link into bus and endpoint */
- list_add_tail(&conn->ep_entry, &ep->conn_list);
- hash_add(bus->conn_hash, &conn->hentry, conn->id);
-
- /* enable lookups and acquire active ref */
- atomic_set(&conn->active, 1);
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire_read(&conn->dep_map, 0, 1, _RET_IP_);
-#endif
-
- up_write(&bus->conn_rwlock);
- mutex_unlock(&ep->lock);
-
- kdbus_node_release(&ep->node);
-
- /*
- * Notify subscribers about the new active connection, unless it is
- * a monitor. Monitors are invisible on the bus, can't be addressed
- * directly, and won't cause any notifications.
- */
- if (!kdbus_conn_is_monitor(conn)) {
- ret = kdbus_notify_id_change(bus, KDBUS_ITEM_ID_ADD,
- conn->id, conn->flags);
- if (ret < 0)
- goto exit_disconnect;
- }
-
- if (kdbus_conn_is_activator(conn)) {
- u64 flags = KDBUS_NAME_ACTIVATOR;
-
- if (WARN_ON(!name)) {
- ret = -EINVAL;
- goto exit_disconnect;
- }
-
- ret = kdbus_name_acquire(bus->name_registry, conn, name,
- flags, NULL);
- if (ret < 0)
- goto exit_disconnect;
- }
-
- kdbus_conn_release(conn);
- kdbus_notify_flush(bus);
- return 0;
-
-exit_disconnect:
- kdbus_conn_release(conn);
- kdbus_conn_disconnect(conn, false);
- return ret;
-}
-
-/**
- * kdbus_conn_disconnect() - disconnect a connection
- * @conn: The connection to disconnect
- * @ensure_queue_empty: Flag to indicate if the call should fail in
- * case the connection's message list is not
- * empty
- *
- * If @ensure_msg_list_empty is true, and the connection has pending messages,
- * -EBUSY is returned.
- *
- * Return: 0 on success, negative errno on failure
- */
-int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty)
-{
- struct kdbus_queue_entry *entry, *tmp;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kdbus_reply *r, *r_tmp;
- struct kdbus_conn *c;
- int i, v;
-
- mutex_lock(&conn->lock);
- v = atomic_read(&conn->active);
- if (v == KDBUS_CONN_ACTIVE_NEW) {
- /* was never connected */
- mutex_unlock(&conn->lock);
- return 0;
- }
- if (v < 0) {
- /* already dead */
- mutex_unlock(&conn->lock);
- return -ECONNRESET;
- }
- if (ensure_queue_empty && !list_empty(&conn->queue.msg_list)) {
- /* still busy */
- mutex_unlock(&conn->lock);
- return -EBUSY;
- }
-
- atomic_add(KDBUS_CONN_ACTIVE_BIAS, &conn->active);
- mutex_unlock(&conn->lock);
-
- wake_up_interruptible(&conn->wait);
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- rwsem_acquire(&conn->dep_map, 0, 0, _RET_IP_);
- if (atomic_read(&conn->active) != KDBUS_CONN_ACTIVE_BIAS)
- lock_contended(&conn->dep_map, _RET_IP_);
-#endif
-
- wait_event(conn->wait,
- atomic_read(&conn->active) == KDBUS_CONN_ACTIVE_BIAS);
-
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- lock_acquired(&conn->dep_map, _RET_IP_);
- rwsem_release(&conn->dep_map, 1, _RET_IP_);
-#endif
-
- cancel_delayed_work_sync(&conn->work);
- kdbus_policy_remove_owner(&conn->ep->bus->policy_db, conn);
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- mutex_lock(&conn->ep->lock);
- down_write(&bus->conn_rwlock);
-
- /* remove from bus and endpoint */
- hash_del(&conn->hentry);
- list_del(&conn->monitor_entry);
- list_del(&conn->ep_entry);
-
- up_write(&bus->conn_rwlock);
- mutex_unlock(&conn->ep->lock);
-
- /*
- * Remove all names associated with this connection; this possibly
- * moves queued messages back to the activator connection.
- */
- kdbus_name_release_all(bus->name_registry, conn);
-
- /* if we die while other connections wait for our reply, notify them */
- mutex_lock(&conn->lock);
- list_for_each_entry_safe(entry, tmp, &conn->queue.msg_list, entry) {
- if (entry->reply)
- kdbus_notify_reply_dead(bus,
- entry->reply->reply_dst->id,
- entry->reply->cookie);
- kdbus_queue_entry_free(entry);
- }
-
- list_for_each_entry_safe(r, r_tmp, &conn->reply_list, entry)
- kdbus_reply_unlink(r);
- mutex_unlock(&conn->lock);
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, c, hentry) {
- mutex_lock(&c->lock);
- list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
- if (r->reply_src != conn)
- continue;
-
- if (r->sync)
- kdbus_sync_reply_wakeup(r, -EPIPE);
- else
- /* send a 'connection dead' notification */
- kdbus_notify_reply_dead(bus, c->id, r->cookie);
-
- kdbus_reply_unlink(r);
- }
- mutex_unlock(&c->lock);
- }
- up_read(&bus->conn_rwlock);
-
- if (!kdbus_conn_is_monitor(conn))
- kdbus_notify_id_change(bus, KDBUS_ITEM_ID_REMOVE,
- conn->id, conn->flags);
-
- kdbus_notify_flush(bus);
-
- return 0;
-}
-
-/**
- * kdbus_conn_has_name() - check if a connection owns a name
- * @conn: Connection
- * @name: Well-know name to check for
- *
- * The caller must hold the registry lock of conn->ep->bus.
- *
- * Return: true if the name is currently owned by the connection
- */
-bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name)
-{
- struct kdbus_name_owner *owner;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (!(owner->flags & KDBUS_NAME_IN_QUEUE) &&
- !strcmp(name, owner->name->name))
- return true;
-
- return false;
-}
-
-struct kdbus_quota {
- u32 memory;
- u16 msgs;
- u8 fds;
-};
-
-/**
- * kdbus_conn_quota_inc() - increase quota accounting
- * @c: connection owning the quota tracking
- * @u: user to account for (or NULL for kernel accounting)
- * @memory: size of memory to account for
- * @fds: number of FDs to account for
- *
- * This call manages the quotas on resource @c. That is, it's used if other
- * users want to use the resources of connection @c, which so far only concerns
- * the receive queue of the destination.
- *
- * This increases the quota-accounting for user @u by @memory bytes and @fds
- * file descriptors. If the user has already reached the quota limits, this call
- * will not do any accounting but return a negative error code indicating the
- * failure.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds)
-{
- struct kdbus_quota *quota;
- size_t available, accounted;
- unsigned int id;
-
- /*
- * Pool Layout:
- * 50% of a pool is always owned by the connection. It is reserved for
- * kernel queries, handling received messages and other tasks that are
- * under control of the pool owner. The other 50% of the pool are used
- * as incoming queue.
- * As we optionally support user-space based policies, we need fair
- * allocation schemes. Furthermore, resource utilization should be
- * maximized, so only minimal resources stay reserved. However, we need
- * to adapt to a dynamic number of users, as we cannot know how many
- * users will talk to a connection. Therefore, the current allocation
- * works like this:
- * We limit the number of bytes in a destination's pool per sending
- * user. The space available for a user is 33% of the unused pool space
- * (whereas the space used by the user itself is also treated as
- * 'unused'). This way, we favor users coming first, but keep enough
- * pool space available for any following users. Given that messages are
- * dequeued in FIFO order, this should balance nicely if the number of
- * users grows. At the same time, this algorithm guarantees that the
- * space available to a connection is reduced dynamically, the more
- * concurrent users talk to a connection.
- */
-
- /* per user-accounting is expensive, so we keep state small */
- BUILD_BUG_ON(sizeof(quota->memory) != 4);
- BUILD_BUG_ON(sizeof(quota->msgs) != 2);
- BUILD_BUG_ON(sizeof(quota->fds) != 1);
- BUILD_BUG_ON(KDBUS_CONN_MAX_MSGS > U16_MAX);
- BUILD_BUG_ON(KDBUS_CONN_MAX_FDS_PER_USER > U8_MAX);
-
- id = u ? u->id : KDBUS_USER_KERNEL_ID;
- if (id >= c->n_quota) {
- unsigned int users;
-
- users = max(KDBUS_ALIGN8(id) + 8, id);
- quota = krealloc(c->quota, users * sizeof(*quota),
- GFP_KERNEL | __GFP_ZERO);
- if (!quota)
- return -ENOMEM;
-
- c->n_quota = users;
- c->quota = quota;
- }
-
- quota = &c->quota[id];
- kdbus_pool_accounted(c->pool, &available, &accounted);
-
- /* half the pool is _always_ reserved for the pool owner */
- available /= 2;
-
- /*
- * Pool owner slices are un-accounted slices; they can claim more
- * than 50% of the queue. However, the slices we're dealing with here
- * belong to the incoming queue, hence they are 'accounted' slices
- * to which the 50%-limit applies.
- */
- if (available < accounted)
- return -ENOBUFS;
-
- /* 1/3 of the remaining space (including your own memory) */
- available = (available - accounted + quota->memory) / 3;
-
- if (available < quota->memory ||
- available - quota->memory < memory ||
- quota->memory + memory > U32_MAX)
- return -ENOBUFS;
- if (quota->msgs >= KDBUS_CONN_MAX_MSGS)
- return -ENOBUFS;
- if (quota->fds + fds < quota->fds ||
- quota->fds + fds > KDBUS_CONN_MAX_FDS_PER_USER)
- return -EMFILE;
-
- quota->memory += memory;
- quota->fds += fds;
- ++quota->msgs;
- return 0;
-}
-
-/**
- * kdbus_conn_quota_dec() - decrease quota accounting
- * @c: connection owning the quota tracking
- * @u: user which was accounted for (or NULL for kernel accounting)
- * @memory: size of memory which was accounted for
- * @fds: number of FDs which were accounted for
- *
- * This does the reverse of kdbus_conn_quota_inc(). You have to release any
- * accounted resources that you called kdbus_conn_quota_inc() for. However, you
- * must not call kdbus_conn_quota_dec() if the accounting failed (that is,
- * kdbus_conn_quota_inc() failed).
- */
-void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds)
-{
- struct kdbus_quota *quota;
- unsigned int id;
-
- id = u ? u->id : KDBUS_USER_KERNEL_ID;
- if (WARN_ON(id >= c->n_quota))
- return;
-
- quota = &c->quota[id];
-
- if (!WARN_ON(quota->msgs == 0))
- --quota->msgs;
- if (!WARN_ON(quota->memory < memory))
- quota->memory -= memory;
- if (!WARN_ON(quota->fds < fds))
- quota->fds -= fds;
-}
-
-/**
- * kdbus_conn_lost_message() - handle lost messages
- * @c: connection that lost a message
- *
- * kdbus is reliable. That means, we try hard to never lose messages. However,
- * memory is limited, so we cannot rely on transmissions to never fail.
- * Therefore, we use quota-limits to let callers know if their unicast message
- * cannot be transmitted to a peer. This works fine for unicasts, but for
- * broadcasts we cannot make the caller handle the transmission failure.
- * Instead, we must let the destination know that it couldn't receive a
- * broadcast.
- * As this is an unlikely scenario, we keep it simple. A single lost-counter
- * remembers the number of lost messages since the last call to RECV. The next
- * message retrieval will notify the connection that it lost messages since the
- * last message retrieval and thus should resync its state.
- */
-void kdbus_conn_lost_message(struct kdbus_conn *c)
-{
- if (atomic_inc_return(&c->lost_count) == 1)
- wake_up_interruptible(&c->wait);
-}
-
-/* Callers should take the conn_dst lock */
-static struct kdbus_queue_entry *
-kdbus_conn_entry_make(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging)
-{
- /* The remote connection was disconnected */
- if (!kdbus_conn_active(conn_dst))
- return ERR_PTR(-ECONNRESET);
-
- /*
- * If the connection does not accept file descriptors but the message
- * has some attached, refuse it.
- *
- * If this is a monitor connection, accept the message. In that
- * case, all file descriptors will be set to -1 at receive time.
- */
- if (!kdbus_conn_is_monitor(conn_dst) &&
- !(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
- staging->gaps && staging->gaps->n_fds > 0)
- return ERR_PTR(-ECOMM);
-
- return kdbus_queue_entry_new(conn_src, conn_dst, staging);
-}
-
-/*
- * Synchronously responding to a message, allocate a queue entry
- * and attach it to the reply tracking object.
- * The connection's queue will never get to see it.
- */
-static int kdbus_conn_entry_sync_attach(struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply_wake)
-{
- struct kdbus_queue_entry *entry;
- int remote_ret, ret = 0;
-
- mutex_lock(&reply_wake->reply_dst->lock);
-
- /*
- * If we are still waiting then proceed, allocate a queue
- * entry and attach it to the reply object
- */
- if (reply_wake->waiting) {
- entry = kdbus_conn_entry_make(reply_wake->reply_src, conn_dst,
- staging);
- if (IS_ERR(entry))
- ret = PTR_ERR(entry);
- else
- /* Attach the entry to the reply object */
- reply_wake->queue_entry = entry;
- } else {
- ret = -ECONNRESET;
- }
-
- /*
- * Update the reply object and wake up remote peer only
- * on appropriate return codes
- *
- * * -ECOMM: if the replying connection failed with -ECOMM
- * then wakeup remote peer with -EREMOTEIO
- *
- * We do this to differenciate between -ECOMM errors
- * from the original sender perspective:
- * -ECOMM error during the sync send and
- * -ECOMM error during the sync reply, this last
- * one is rewritten to -EREMOTEIO
- *
- * * Wake up on all other return codes.
- */
- remote_ret = ret;
-
- if (ret == -ECOMM)
- remote_ret = -EREMOTEIO;
-
- kdbus_sync_reply_wakeup(reply_wake, remote_ret);
- kdbus_reply_unlink(reply_wake);
- mutex_unlock(&reply_wake->reply_dst->lock);
-
- return ret;
-}
-
-/**
- * kdbus_conn_entry_insert() - enqueue a message into the receiver's pool
- * @conn_src: The sending connection
- * @conn_dst: The connection to queue into
- * @staging: Message to send
- * @reply: The reply tracker to attach to the queue entry
- * @name: Destination name this msg is sent to, or NULL
- *
- * Return: 0 on success. negative error otherwise.
- */
-int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply,
- const struct kdbus_name_entry *name)
-{
- struct kdbus_queue_entry *entry;
- int ret;
-
- kdbus_conn_lock2(conn_src, conn_dst);
-
- entry = kdbus_conn_entry_make(conn_src, conn_dst, staging);
- if (IS_ERR(entry)) {
- ret = PTR_ERR(entry);
- goto exit_unlock;
- }
-
- if (reply) {
- kdbus_reply_link(reply);
- if (!reply->sync)
- schedule_delayed_work(&conn_src->work, 0);
- }
-
- /*
- * Record the sequence number of the registered name; it will
- * be remembered by the queue, in case messages addressed to a
- * name need to be moved from or to an activator.
- */
- if (name)
- entry->dst_name_id = name->name_id;
-
- kdbus_queue_entry_enqueue(entry, reply);
- wake_up_interruptible(&conn_dst->wait);
-
- ret = 0;
-
-exit_unlock:
- kdbus_conn_unlock2(conn_src, conn_dst);
- return ret;
-}
-
-static int kdbus_conn_wait_reply(struct kdbus_conn *conn_src,
- struct kdbus_cmd_send *cmd_send,
- struct file *ioctl_file,
- struct file *cancel_fd,
- struct kdbus_reply *reply_wait,
- ktime_t expire)
-{
- struct kdbus_queue_entry *entry;
- struct poll_wqueues pwq = {};
- int ret;
-
- if (WARN_ON(!reply_wait))
- return -EIO;
-
- /*
- * Block until the reply arrives. reply_wait is left untouched
- * by the timeout scans that might be conducted for other,
- * asynchronous replies of conn_src.
- */
-
- poll_initwait(&pwq);
- poll_wait(ioctl_file, &conn_src->wait, &pwq.pt);
-
- for (;;) {
- /*
- * Any of the following conditions will stop our synchronously
- * blocking SEND command:
- *
- * a) The origin sender closed its connection
- * b) The remote peer answered, setting reply_wait->waiting = 0
- * c) The cancel FD was written to
- * d) A signal was received
- * e) The specified timeout was reached, and none of the above
- * conditions kicked in.
- */
-
- /*
- * We have already acquired an active reference when
- * entering here, but another thread may call
- * KDBUS_CMD_BYEBYE which does not acquire an active
- * reference, therefore kdbus_conn_disconnect() will
- * not wait for us.
- */
- if (!kdbus_conn_active(conn_src)) {
- ret = -ECONNRESET;
- break;
- }
-
- /*
- * After the replying peer unset the waiting variable
- * it will wake up us.
- */
- if (!reply_wait->waiting) {
- ret = reply_wait->err;
- break;
- }
-
- if (cancel_fd) {
- unsigned int r;
-
- r = cancel_fd->f_op->poll(cancel_fd, &pwq.pt);
- if (r & POLLIN) {
- ret = -ECANCELED;
- break;
- }
- }
-
- if (signal_pending(current)) {
- ret = -EINTR;
- break;
- }
-
- if (!poll_schedule_timeout(&pwq, TASK_INTERRUPTIBLE,
- &expire, 0)) {
- ret = -ETIMEDOUT;
- break;
- }
-
- /*
- * Reset the poll worker func, so the waitqueues are not
- * added to the poll table again. We just reuse what we've
- * collected earlier for further iterations.
- */
- init_poll_funcptr(&pwq.pt, NULL);
- }
-
- poll_freewait(&pwq);
-
- if (ret == -EINTR) {
- /*
- * Interrupted system call. Unref the reply object, and pass
- * the return value down the chain. Mark the reply as
- * interrupted, so the cleanup work can remove it, but do not
- * unlink it from the list. Once the syscall restarts, we'll
- * pick it up and wait on it again.
- */
- mutex_lock(&conn_src->lock);
- reply_wait->interrupted = true;
- schedule_delayed_work(&conn_src->work, 0);
- mutex_unlock(&conn_src->lock);
-
- return -ERESTARTSYS;
- }
-
- mutex_lock(&conn_src->lock);
- reply_wait->waiting = false;
- entry = reply_wait->queue_entry;
- if (entry) {
- ret = kdbus_queue_entry_install(entry,
- &cmd_send->reply.return_flags,
- true);
- kdbus_pool_slice_publish(entry->slice, &cmd_send->reply.offset,
- &cmd_send->reply.msg_size);
- kdbus_queue_entry_free(entry);
- }
- kdbus_reply_unlink(reply_wait);
- mutex_unlock(&conn_src->lock);
-
- return ret;
-}
-
-static int kdbus_pin_dst(struct kdbus_bus *bus,
- struct kdbus_staging *staging,
- struct kdbus_name_entry **out_name,
- struct kdbus_conn **out_dst)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_owner *owner = NULL;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_conn *dst = NULL;
- int ret;
-
- lockdep_assert_held(&bus->name_registry->rwlock);
-
- if (!staging->dst_name) {
- dst = kdbus_bus_find_conn_by_id(bus, msg->dst_id);
- if (!dst)
- return -ENXIO;
-
- if (!kdbus_conn_is_ordinary(dst)) {
- ret = -ENXIO;
- goto error;
- }
- } else {
- name = kdbus_name_lookup_unlocked(bus->name_registry,
- staging->dst_name);
- if (name)
- owner = kdbus_name_get_owner(name);
- if (!owner)
- return -ESRCH;
-
- /*
- * If both a name and a connection ID are given as destination
- * of a message, check that the currently owning connection of
- * the name matches the specified ID.
- * This way, we allow userspace to send the message to a
- * specific connection by ID only if the connection currently
- * owns the given name.
- */
- if (msg->dst_id != KDBUS_DST_ID_NAME &&
- msg->dst_id != owner->conn->id)
- return -EREMCHG;
-
- if ((msg->flags & KDBUS_MSG_NO_AUTO_START) &&
- kdbus_conn_is_activator(owner->conn))
- return -EADDRNOTAVAIL;
-
- dst = kdbus_conn_ref(owner->conn);
- }
-
- *out_name = name;
- *out_dst = dst;
- return 0;
-
-error:
- kdbus_conn_unref(dst);
- return ret;
-}
-
-static int kdbus_conn_reply(struct kdbus_conn *src,
- struct kdbus_staging *staging)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *reply, *wake = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- int ret;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(msg->flags & KDBUS_MSG_EXPECT_REPLY) ||
- WARN_ON(msg->flags & KDBUS_MSG_SIGNAL))
- return -EINVAL;
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- mutex_lock(&dst->lock);
- reply = kdbus_reply_find(src, dst, msg->cookie_reply);
- if (reply) {
- if (reply->sync)
- wake = kdbus_reply_ref(reply);
- kdbus_reply_unlink(reply);
- }
- mutex_unlock(&dst->lock);
-
- if (!reply) {
- ret = -EBADSLT;
- goto exit;
- }
-
- /* send message */
-
- kdbus_bus_eavesdrop(bus, src, staging);
-
- if (wake)
- ret = kdbus_conn_entry_sync_attach(dst, staging, wake);
- else
- ret = kdbus_conn_entry_insert(src, dst, staging, NULL, name);
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_reply_unref(wake);
- kdbus_conn_unref(dst);
- return ret;
-}
-
-static struct kdbus_reply *kdbus_conn_call(struct kdbus_conn *src,
- struct kdbus_staging *staging,
- ktime_t exp)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *wait = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- int ret;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(msg->flags & KDBUS_MSG_SIGNAL) ||
- WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY)))
- return ERR_PTR(-EINVAL);
-
- /* resume previous wait-context, if available */
-
- mutex_lock(&src->lock);
- wait = kdbus_reply_find(NULL, src, msg->cookie);
- if (wait) {
- if (wait->interrupted) {
- kdbus_reply_ref(wait);
- wait->interrupted = false;
- } else {
- wait = NULL;
- }
- }
- mutex_unlock(&src->lock);
-
- if (wait)
- return wait;
-
- if (ktime_compare(ktime_get(), exp) >= 0)
- return ERR_PTR(-ETIMEDOUT);
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- if (!kdbus_conn_policy_talk(src, current_cred(), dst)) {
- ret = -EPERM;
- goto exit;
- }
-
- wait = kdbus_reply_new(dst, src, msg, name, true);
- if (IS_ERR(wait)) {
- ret = PTR_ERR(wait);
- wait = NULL;
- goto exit;
- }
-
- /* send message */
-
- kdbus_bus_eavesdrop(bus, src, staging);
-
- ret = kdbus_conn_entry_insert(src, dst, staging, wait, name);
- if (ret < 0)
- goto exit;
-
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- if (ret < 0) {
- kdbus_reply_unref(wait);
- wait = ERR_PTR(ret);
- }
- kdbus_conn_unref(dst);
- return wait;
-}
-
-static int kdbus_conn_unicast(struct kdbus_conn *src,
- struct kdbus_staging *staging)
-{
- const struct kdbus_msg *msg = staging->msg;
- struct kdbus_name_entry *name = NULL;
- struct kdbus_reply *wait = NULL;
- struct kdbus_conn *dst = NULL;
- struct kdbus_bus *bus = src->ep->bus;
- bool is_signal = (msg->flags & KDBUS_MSG_SIGNAL);
- int ret = 0;
-
- if (WARN_ON(msg->dst_id == KDBUS_DST_ID_BROADCAST) ||
- WARN_ON(!(msg->flags & KDBUS_MSG_EXPECT_REPLY) &&
- msg->cookie_reply != 0))
- return -EINVAL;
-
- /* name-registry must be locked for lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- /* find and pin destination */
-
- ret = kdbus_pin_dst(bus, staging, &name, &dst);
- if (ret < 0)
- goto exit;
-
- if (is_signal) {
- /* like broadcasts we eavesdrop even if the msg is dropped */
- kdbus_bus_eavesdrop(bus, src, staging);
-
- /* drop silently if peer is not interested or not privileged */
- if (!kdbus_match_db_match_msg(dst->match_db, src, staging) ||
- !kdbus_conn_policy_talk(dst, NULL, src))
- goto exit;
- } else if (!kdbus_conn_policy_talk(src, current_cred(), dst)) {
- ret = -EPERM;
- goto exit;
- } else if (msg->flags & KDBUS_MSG_EXPECT_REPLY) {
- wait = kdbus_reply_new(dst, src, msg, name, false);
- if (IS_ERR(wait)) {
- ret = PTR_ERR(wait);
- wait = NULL;
- goto exit;
- }
- }
-
- /* send message */
-
- if (!is_signal)
- kdbus_bus_eavesdrop(bus, src, staging);
-
- ret = kdbus_conn_entry_insert(src, dst, staging, wait, name);
- if (ret < 0 && !is_signal)
- goto exit;
-
- /* signals are treated like broadcasts, recv-errors are ignored */
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_reply_unref(wait);
- kdbus_conn_unref(dst);
- return ret;
-}
-
-/**
- * kdbus_conn_move_messages() - move messages from one connection to another
- * @conn_dst: Connection to copy to
- * @conn_src: Connection to copy from
- * @name_id: Filter for the sequence number of the registered
- * name, 0 means no filtering.
- *
- * Move all messages from one connection to another. This is used when
- * an implementer connection is taking over/giving back a well-known name
- * from/to an activator connection.
- */
-void kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
- struct kdbus_conn *conn_src,
- u64 name_id)
-{
- struct kdbus_queue_entry *e, *e_tmp;
- struct kdbus_reply *r, *r_tmp;
- struct kdbus_bus *bus;
- struct kdbus_conn *c;
- LIST_HEAD(msg_list);
- int i, ret = 0;
-
- if (WARN_ON(conn_src == conn_dst))
- return;
-
- bus = conn_src->ep->bus;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&bus->conn_rwlock);
- hash_for_each(bus->conn_hash, i, c, hentry) {
- if (c == conn_src || c == conn_dst)
- continue;
-
- mutex_lock(&c->lock);
- list_for_each_entry_safe(r, r_tmp, &c->reply_list, entry) {
- if (r->reply_src != conn_src)
- continue;
-
- /* filter messages for a specific name */
- if (name_id > 0 && r->name_id != name_id)
- continue;
-
- kdbus_conn_unref(r->reply_src);
- r->reply_src = kdbus_conn_ref(conn_dst);
- }
- mutex_unlock(&c->lock);
- }
- up_read(&bus->conn_rwlock);
-
- kdbus_conn_lock2(conn_src, conn_dst);
- list_for_each_entry_safe(e, e_tmp, &conn_src->queue.msg_list, entry) {
- /* filter messages for a specific name */
- if (name_id > 0 && e->dst_name_id != name_id)
- continue;
-
- if (!(conn_dst->flags & KDBUS_HELLO_ACCEPT_FD) &&
- e->gaps && e->gaps->n_fds > 0) {
- kdbus_conn_lost_message(conn_dst);
- kdbus_queue_entry_free(e);
- continue;
- }
-
- ret = kdbus_queue_entry_move(e, conn_dst);
- if (ret < 0) {
- kdbus_conn_lost_message(conn_dst);
- kdbus_queue_entry_free(e);
- continue;
- }
- }
- kdbus_conn_unlock2(conn_src, conn_dst);
-
- /* wake up poll() */
- wake_up_interruptible(&conn_dst->wait);
-}
-
-/* query the policy-database for all names of @whom */
-static bool kdbus_conn_policy_query_all(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_policy_db *db,
- struct kdbus_conn *whom,
- unsigned int access)
-{
- struct kdbus_name_owner *owner;
- bool pass = false;
- int res;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- down_read(&db->entries_rwlock);
- mutex_lock(&whom->lock);
-
- list_for_each_entry(owner, &whom->names_list, conn_entry) {
- if (owner->flags & KDBUS_NAME_IN_QUEUE)
- continue;
-
- res = kdbus_policy_query_unlocked(db,
- conn_creds ? : conn->cred,
- owner->name->name,
- kdbus_strhash(owner->name->name));
- if (res >= (int)access) {
- pass = true;
- break;
- }
- }
-
- mutex_unlock(&whom->lock);
- up_read(&db->entries_rwlock);
-
- return pass;
-}
-
-/**
- * kdbus_conn_policy_own_name() - verify a connection can own the given name
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @name: Name
- *
- * This verifies that @conn is allowed to acquire the well-known name @name.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- unsigned int hash = kdbus_strhash(name);
- int res;
-
- if (!conn_creds)
- conn_creds = conn->cred;
-
- if (conn->ep->user) {
- res = kdbus_policy_query(&conn->ep->policy_db, conn_creds,
- name, hash);
- if (res < KDBUS_POLICY_OWN)
- return false;
- }
-
- if (conn->owner)
- return true;
-
- res = kdbus_policy_query(&conn->ep->bus->policy_db, conn_creds,
- name, hash);
- return res >= KDBUS_POLICY_OWN;
-}
-
-/**
- * kdbus_conn_policy_talk() - verify a connection can talk to a given peer
- * @conn: Connection that tries to talk
- * @conn_creds: Credentials of @conn to use for policy check
- * @to: Connection that is talked to
- *
- * This verifies that @conn is allowed to talk to @to.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *to)
-{
- if (!conn_creds)
- conn_creds = conn->cred;
-
- if (conn->ep->user &&
- !kdbus_conn_policy_query_all(conn, conn_creds, &conn->ep->policy_db,
- to, KDBUS_POLICY_TALK))
- return false;
-
- if (conn->owner)
- return true;
- if (uid_eq(conn_creds->euid, to->cred->uid))
- return true;
-
- return kdbus_conn_policy_query_all(conn, conn_creds,
- &conn->ep->bus->policy_db, to,
- KDBUS_POLICY_TALK);
-}
-
-/**
- * kdbus_conn_policy_see_name_unlocked() - verify a connection can see a given
- * name
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @name: Name
- *
- * This verifies that @conn is allowed to see the well-known name @name. Caller
- * must hold policy-lock.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- int res;
-
- /*
- * By default, all names are visible on a bus. SEE policies can only be
- * installed on custom endpoints, where by default no name is visible.
- */
- if (!conn->ep->user)
- return true;
-
- res = kdbus_policy_query_unlocked(&conn->ep->policy_db,
- conn_creds ? : conn->cred,
- name, kdbus_strhash(name));
- return res >= KDBUS_POLICY_SEE;
-}
-
-static bool kdbus_conn_policy_see_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name)
-{
- bool res;
-
- down_read(&conn->ep->policy_db.entries_rwlock);
- res = kdbus_conn_policy_see_name_unlocked(conn, conn_creds, name);
- up_read(&conn->ep->policy_db.entries_rwlock);
-
- return res;
-}
-
-static bool kdbus_conn_policy_see(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *whom)
-{
- /*
- * By default, all names are visible on a bus, so a connection can
- * always see other connections. SEE policies can only be installed on
- * custom endpoints, where by default no name is visible and we hide
- * peers from each other, unless you see at least _one_ name of the
- * peer.
- */
- return !conn->ep->user ||
- kdbus_conn_policy_query_all(conn, conn_creds,
- &conn->ep->policy_db, whom,
- KDBUS_POLICY_SEE);
-}
-
-/**
- * kdbus_conn_policy_see_notification() - verify a connection is allowed to
- * receive a given kernel notification
- * @conn: Connection
- * @conn_creds: Credentials of @conn to use for policy check
- * @msg: Notification message
- *
- * This checks whether @conn is allowed to see the kernel notification.
- *
- * Return: true if allowed, false if not.
- */
-bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const struct kdbus_msg *msg)
-{
- /*
- * Depending on the notification type, broadcasted kernel notifications
- * have to be filtered:
- *
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}: This notification is forwarded
- * to a peer if, and only if, that peer can see the name this
- * notification is for.
- *
- * KDBUS_ITEM_ID_{ADD,REMOVE}: Notifications for ID changes are
- * broadcast to everyone, to allow tracking peers.
- */
-
- switch (msg->items[0].type) {
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- return kdbus_conn_policy_see_name(conn, conn_creds,
- msg->items[0].name_change.name);
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- return true;
-
- default:
- WARN(1, "Invalid type for notification broadcast: %llu\n",
- (unsigned long long)msg->items[0].type);
- return false;
- }
-}
-
-/**
- * kdbus_cmd_hello() - handle KDBUS_CMD_HELLO
- * @ep: Endpoint to operate on
- * @file: File this connection is opened on
- * @argp: Command payload
- *
- * Return: NULL or newly created connection on success, ERR_PTR on failure.
- */
-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
- void __user *argp)
-{
- struct kdbus_cmd_hello *cmd;
- struct kdbus_conn *c = NULL;
- const char *item_name;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME },
- { .type = KDBUS_ITEM_CREDS },
- { .type = KDBUS_ITEM_PIDS },
- { .type = KDBUS_ITEM_SECLABEL },
- { .type = KDBUS_ITEM_CONN_DESCRIPTION },
- { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_HELLO_ACCEPT_FD |
- KDBUS_HELLO_ACTIVATOR |
- KDBUS_HELLO_POLICY_HOLDER |
- KDBUS_HELLO_MONITOR,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret < 0)
- return ERR_PTR(ret);
- if (ret > 0)
- return NULL;
-
- item_name = argv[1].item ? argv[1].item->str : NULL;
-
- c = kdbus_conn_new(ep, file, cmd, item_name,
- argv[2].item ? &argv[2].item->creds : NULL,
- argv[3].item ? &argv[3].item->pids : NULL,
- argv[4].item ? argv[4].item->str : NULL,
- argv[5].item ? argv[5].item->str : NULL);
- if (IS_ERR(c)) {
- ret = PTR_ERR(c);
- c = NULL;
- goto exit;
- }
-
- ret = kdbus_conn_connect(c, item_name);
- if (ret < 0)
- goto exit;
-
- if (kdbus_conn_is_activator(c) || kdbus_conn_is_policy_holder(c)) {
- ret = kdbus_conn_acquire(c);
- if (ret < 0)
- goto exit;
-
- ret = kdbus_policy_set(&c->ep->bus->policy_db, args.items,
- args.items_size, 1,
- kdbus_conn_is_policy_holder(c), c);
- kdbus_conn_release(c);
- if (ret < 0)
- goto exit;
- }
-
- if (copy_to_user(argp, cmd, sizeof(*cmd)))
- ret = -EFAULT;
-
-exit:
- ret = kdbus_args_clear(&args, ret);
- if (ret < 0) {
- if (c) {
- kdbus_conn_disconnect(c, false);
- kdbus_conn_unref(c);
- }
- return ERR_PTR(ret);
- }
- return c;
-}
-
-/**
- * kdbus_cmd_byebye_unlocked() - handle KDBUS_CMD_BYEBYE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * The caller must not hold any active reference to @conn or this will deadlock.
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_conn_disconnect(conn, true);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_conn_info() - handle KDBUS_CMD_CONN_INFO
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_meta_conn *conn_meta = NULL;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_name_entry *entry = NULL;
- struct kdbus_name_owner *owner = NULL;
- struct kdbus_conn *owner_conn = NULL;
- struct kdbus_item *meta_items = NULL;
- struct kdbus_info info = {};
- struct kdbus_cmd_info *cmd;
- struct kdbus_bus *bus = conn->ep->bus;
- struct kvec kvec[3];
- size_t meta_size, cnt = 0;
- const char *name;
- u64 attach_flags, size = 0;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- /* registry must be held throughout lookup *and* collecting data */
- down_read(&bus->name_registry->rwlock);
-
- ret = kdbus_sanitize_attach_flags(cmd->attach_flags, &attach_flags);
- if (ret < 0)
- goto exit;
-
- name = argv[1].item ? argv[1].item->str : NULL;
-
- if (name) {
- entry = kdbus_name_lookup_unlocked(bus->name_registry, name);
- if (entry)
- owner = kdbus_name_get_owner(entry);
- if (!owner ||
- !kdbus_conn_policy_see_name(conn, current_cred(), name) ||
- (cmd->id != 0 && owner->conn->id != cmd->id)) {
- /* pretend a name doesn't exist if you cannot see it */
- ret = -ESRCH;
- goto exit;
- }
-
- owner_conn = kdbus_conn_ref(owner->conn);
- } else if (cmd->id > 0) {
- owner_conn = kdbus_bus_find_conn_by_id(bus, cmd->id);
- if (!owner_conn || !kdbus_conn_policy_see(conn, current_cred(),
- owner_conn)) {
- /* pretend an id doesn't exist if you cannot see it */
- ret = -ENXIO;
- goto exit;
- }
- } else {
- ret = -EINVAL;
- goto exit;
- }
-
- attach_flags &= atomic64_read(&owner_conn->attach_flags_send);
-
- conn_meta = kdbus_meta_conn_new();
- if (IS_ERR(conn_meta)) {
- ret = PTR_ERR(conn_meta);
- conn_meta = NULL;
- goto exit;
- }
-
- ret = kdbus_meta_conn_collect(conn_meta, owner_conn, 0, attach_flags);
- if (ret < 0)
- goto exit;
-
- ret = kdbus_meta_emit(owner_conn->meta_proc, owner_conn->meta_fake,
- conn_meta, conn, attach_flags,
- &meta_items, &meta_size);
- if (ret < 0)
- goto exit;
-
- info.id = owner_conn->id;
- info.flags = owner_conn->flags;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &size);
- if (meta_size > 0) {
- kdbus_kvec_set(&kvec[cnt++], meta_items, meta_size, &size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &size);
- }
-
- info.size = size;
-
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit;
- }
-
- ret = kdbus_pool_slice_copy_kvec(slice, 0, kvec, cnt, size);
- if (ret < 0)
- goto exit;
-
- kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->info_size);
-
- if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
- kdbus_member_set_user(&cmd->info_size, argp,
- typeof(*cmd), info_size)) {
- ret = -EFAULT;
- goto exit;
- }
-
- ret = 0;
-
-exit:
- up_read(&bus->name_registry->rwlock);
- kdbus_pool_slice_release(slice);
- kfree(meta_items);
- kdbus_meta_conn_unref(conn_meta);
- kdbus_conn_unref(owner_conn);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_update() - handle KDBUS_CMD_UPDATE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_item *item_policy;
- u64 *item_attach_send = NULL;
- u64 *item_attach_recv = NULL;
- struct kdbus_cmd *cmd;
- u64 attach_send;
- u64 attach_recv;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_SEND },
- { .type = KDBUS_ITEM_ATTACH_FLAGS_RECV },
- { .type = KDBUS_ITEM_NAME, .multiple = true },
- { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- item_attach_send = argv[1].item ? &argv[1].item->data64[0] : NULL;
- item_attach_recv = argv[2].item ? &argv[2].item->data64[0] : NULL;
- item_policy = argv[3].item ? : argv[4].item;
-
- if (item_attach_send) {
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- ret = kdbus_sanitize_attach_flags(*item_attach_send,
- &attach_send);
- if (ret < 0)
- goto exit;
- }
-
- if (item_attach_recv) {
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- ret = kdbus_sanitize_attach_flags(*item_attach_recv,
- &attach_recv);
- if (ret < 0)
- goto exit;
- }
-
- if (item_policy && !kdbus_conn_is_policy_holder(conn)) {
- ret = -EOPNOTSUPP;
- goto exit;
- }
-
- /* now that we verified the input, update the connection */
-
- if (item_policy) {
- ret = kdbus_policy_set(&conn->ep->bus->policy_db, cmd->items,
- KDBUS_ITEMS_SIZE(cmd, items),
- 1, true, conn);
- if (ret < 0)
- goto exit;
- }
-
- if (item_attach_send)
- atomic64_set(&conn->attach_flags_send, attach_send);
-
- if (item_attach_recv)
- atomic64_set(&conn->attach_flags_recv, attach_recv);
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_send() - handle KDBUS_CMD_SEND
- * @conn: connection to operate on
- * @f: file this command was called on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp)
-{
- struct kdbus_cmd_send *cmd;
- struct kdbus_staging *staging = NULL;
- struct kdbus_msg *msg = NULL;
- struct file *cancel_fd = NULL;
- int ret, ret2;
-
- /* command arguments */
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_CANCEL_FD },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_SEND_SYNC_REPLY,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- /* message arguments */
- struct kdbus_arg msg_argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_PAYLOAD_VEC, .multiple = true },
- { .type = KDBUS_ITEM_PAYLOAD_MEMFD, .multiple = true },
- { .type = KDBUS_ITEM_FDS },
- { .type = KDBUS_ITEM_BLOOM_FILTER },
- { .type = KDBUS_ITEM_DST_NAME },
- };
- struct kdbus_args msg_args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MSG_EXPECT_REPLY |
- KDBUS_MSG_NO_AUTO_START |
- KDBUS_MSG_SIGNAL,
- .argv = msg_argv,
- .argc = ARRAY_SIZE(msg_argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- /* make sure to parse both, @cmd and @msg on negotiation */
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret < 0)
- goto exit;
- else if (ret > 0 && !cmd->msg_address) /* negotiation without msg */
- goto exit;
-
- ret2 = kdbus_args_parse_msg(&msg_args, KDBUS_PTR(cmd->msg_address),
- &msg);
- if (ret2 < 0) { /* cannot parse message */
- ret = ret2;
- goto exit;
- } else if (ret2 > 0 && !ret) { /* msg-negot implies cmd-negot */
- ret = -EINVAL;
- goto exit;
- } else if (ret > 0) { /* negotiation */
- goto exit;
- }
-
- /* here we parsed both, @cmd and @msg, and neither wants negotiation */
-
- cmd->reply.return_flags = 0;
- kdbus_pool_publish_empty(conn->pool, &cmd->reply.offset,
- &cmd->reply.msg_size);
-
- if (argv[1].item) {
- cancel_fd = fget(argv[1].item->fds[0]);
- if (!cancel_fd) {
- ret = -EBADF;
- goto exit;
- }
-
- if (!cancel_fd->f_op->poll) {
- ret = -EINVAL;
- goto exit;
- }
- }
-
- /* patch-in the source of this message */
- if (msg->src_id > 0 && msg->src_id != conn->id) {
- ret = -EINVAL;
- goto exit;
- }
- msg->src_id = conn->id;
-
- staging = kdbus_staging_new_user(conn->ep->bus, cmd, msg);
- if (IS_ERR(staging)) {
- ret = PTR_ERR(staging);
- staging = NULL;
- goto exit;
- }
-
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST) {
- down_read(&conn->ep->bus->name_registry->rwlock);
- kdbus_bus_broadcast(conn->ep->bus, conn, staging);
- up_read(&conn->ep->bus->name_registry->rwlock);
- } else if (cmd->flags & KDBUS_SEND_SYNC_REPLY) {
- struct kdbus_reply *r;
- ktime_t exp;
-
- exp = ns_to_ktime(msg->timeout_ns);
- r = kdbus_conn_call(conn, staging, exp);
- if (IS_ERR(r)) {
- ret = PTR_ERR(r);
- goto exit;
- }
-
- ret = kdbus_conn_wait_reply(conn, cmd, f, cancel_fd, r, exp);
- kdbus_reply_unref(r);
- if (ret < 0)
- goto exit;
- } else if ((msg->flags & KDBUS_MSG_EXPECT_REPLY) ||
- msg->cookie_reply == 0) {
- ret = kdbus_conn_unicast(conn, staging);
- if (ret < 0)
- goto exit;
- } else {
- ret = kdbus_conn_reply(conn, staging);
- if (ret < 0)
- goto exit;
- }
-
- if (kdbus_member_set_user(&cmd->reply, argp, typeof(*cmd), reply))
- ret = -EFAULT;
-
-exit:
- if (cancel_fd)
- fput(cancel_fd);
- kdbus_staging_free(staging);
- ret = kdbus_args_clear(&msg_args, ret);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_recv() - handle KDBUS_CMD_RECV
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_queue_entry *entry;
- struct kdbus_cmd_recv *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_RECV_PEEK |
- KDBUS_RECV_DROP |
- KDBUS_RECV_USE_PRIORITY,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- cmd->dropped_msgs = 0;
- cmd->msg.return_flags = 0;
- kdbus_pool_publish_empty(conn->pool, &cmd->msg.offset,
- &cmd->msg.msg_size);
-
- /* DROP+priority is not realiably, so prevent it */
- if ((cmd->flags & KDBUS_RECV_DROP) &&
- (cmd->flags & KDBUS_RECV_USE_PRIORITY)) {
- ret = -EINVAL;
- goto exit;
- }
-
- mutex_lock(&conn->lock);
-
- entry = kdbus_queue_peek(&conn->queue, cmd->priority,
- cmd->flags & KDBUS_RECV_USE_PRIORITY);
- if (!entry) {
- mutex_unlock(&conn->lock);
- ret = -EAGAIN;
- } else if (cmd->flags & KDBUS_RECV_DROP) {
- struct kdbus_reply *reply = kdbus_reply_ref(entry->reply);
-
- kdbus_queue_entry_free(entry);
-
- mutex_unlock(&conn->lock);
-
- if (reply) {
- mutex_lock(&reply->reply_dst->lock);
- if (!list_empty(&reply->entry)) {
- kdbus_reply_unlink(reply);
- if (reply->sync)
- kdbus_sync_reply_wakeup(reply, -EPIPE);
- else
- kdbus_notify_reply_dead(conn->ep->bus,
- reply->reply_dst->id,
- reply->cookie);
- }
- mutex_unlock(&reply->reply_dst->lock);
- kdbus_notify_flush(conn->ep->bus);
- }
-
- kdbus_reply_unref(reply);
- } else {
- bool install_fds;
-
- /*
- * PEEK just returns the location of the next message. Do not
- * install FDs nor memfds nor anything else. The only
- * information of interest should be the message header and
- * metadata. Any FD numbers in the payload is undefined for
- * PEEK'ed messages.
- * Also make sure to never install fds into a connection that
- * has refused to receive any. Ordinary connections will not get
- * messages with FDs queued (the receiver will get -ECOMM), but
- * eavesdroppers might.
- */
- install_fds = (conn->flags & KDBUS_HELLO_ACCEPT_FD) &&
- !(cmd->flags & KDBUS_RECV_PEEK);
-
- ret = kdbus_queue_entry_install(entry,
- &cmd->msg.return_flags,
- install_fds);
- if (ret < 0) {
- mutex_unlock(&conn->lock);
- goto exit;
- }
-
- kdbus_pool_slice_publish(entry->slice, &cmd->msg.offset,
- &cmd->msg.msg_size);
-
- if (!(cmd->flags & KDBUS_RECV_PEEK))
- kdbus_queue_entry_free(entry);
-
- mutex_unlock(&conn->lock);
- }
-
- cmd->dropped_msgs = atomic_xchg(&conn->lost_count, 0);
- if (cmd->dropped_msgs > 0)
- cmd->return_flags |= KDBUS_RECV_RETURN_DROPPED_MSGS;
-
- if (kdbus_member_set_user(&cmd->msg, argp, typeof(*cmd), msg) ||
- kdbus_member_set_user(&cmd->dropped_msgs, argp, typeof(*cmd),
- dropped_msgs))
- ret = -EFAULT;
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_free() - handle KDBUS_CMD_FREE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_free *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn) &&
- !kdbus_conn_is_monitor(conn) &&
- !kdbus_conn_is_activator(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_pool_release_offset(conn->pool, cmd->offset);
-
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/connection.h b/ipc/kdbus/connection.h
deleted file mode 100644
index 1ad082014..000000000
--- a/ipc/kdbus/connection.h
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_CONNECTION_H
-#define __KDBUS_CONNECTION_H
-
-#include <linux/atomic.h>
-#include <linux/kref.h>
-#include <linux/lockdep.h>
-#include <linux/path.h>
-
-#include "limits.h"
-#include "metadata.h"
-#include "pool.h"
-#include "queue.h"
-#include "util.h"
-
-#define KDBUS_HELLO_SPECIAL_CONN (KDBUS_HELLO_ACTIVATOR | \
- KDBUS_HELLO_POLICY_HOLDER | \
- KDBUS_HELLO_MONITOR)
-
-struct kdbus_name_entry;
-struct kdbus_quota;
-struct kdbus_staging;
-
-/**
- * struct kdbus_conn - connection to a bus
- * @kref: Reference count
- * @active: Active references to the connection
- * @id: Connection ID
- * @flags: KDBUS_HELLO_* flags
- * @attach_flags_send: KDBUS_ATTACH_* flags for sending
- * @attach_flags_recv: KDBUS_ATTACH_* flags for receiving
- * @description: Human-readable connection description, used for
- * debugging. This field is only set when the
- * connection is created.
- * @ep: The endpoint this connection belongs to
- * @lock: Connection data lock
- * @hentry: Entry in ID <-> connection map
- * @ep_entry: Entry in endpoint
- * @monitor_entry: Entry in monitor, if the connection is a monitor
- * @reply_list: List of connections this connection should
- * reply to
- * @work: Delayed work to handle timeouts
- * activator for
- * @match_db: Subscription filter to broadcast messages
- * @meta_proc: Process metadata of connection creator, or NULL
- * @meta_fake: Faked metadata, or NULL
- * @pool: The user's buffer to receive messages
- * @user: Owner of the connection
- * @cred: The credentials of the connection at creation time
- * @pid: Pid at creation time
- * @root_path: Root path at creation time
- * @request_count: Number of pending requests issued by this
- * connection that are waiting for replies from
- * other peers
- * @lost_count: Number of lost broadcast messages
- * @wait: Wake up this endpoint
- * @queue: The message queue associated with this connection
- * @quota: Array of per-user quota indexed by user->id
- * @n_quota: Number of elements in quota array
- * @names_list: List of well-known names
- * @name_count: Number of owned well-known names
- * @privileged: Whether this connection is privileged on the domain
- * @owner: Owned by the same user as the bus owner
- */
-struct kdbus_conn {
- struct kref kref;
- atomic_t active;
-#ifdef CONFIG_DEBUG_LOCK_ALLOC
- struct lockdep_map dep_map;
-#endif
- u64 id;
- u64 flags;
- atomic64_t attach_flags_send;
- atomic64_t attach_flags_recv;
- const char *description;
- struct kdbus_ep *ep;
- struct mutex lock;
- struct hlist_node hentry;
- struct list_head ep_entry;
- struct list_head monitor_entry;
- struct list_head reply_list;
- struct delayed_work work;
- struct kdbus_match_db *match_db;
- struct kdbus_meta_proc *meta_proc;
- struct kdbus_meta_fake *meta_fake;
- struct kdbus_pool *pool;
- struct kdbus_user *user;
- const struct cred *cred;
- struct pid *pid;
- struct path root_path;
- atomic_t request_count;
- atomic_t lost_count;
- wait_queue_head_t wait;
- struct kdbus_queue queue;
-
- struct kdbus_quota *quota;
- unsigned int n_quota;
-
- /* protected by registry->rwlock */
- struct list_head names_list;
- unsigned int name_count;
-
- bool privileged:1;
- bool owner:1;
-};
-
-struct kdbus_conn *kdbus_conn_ref(struct kdbus_conn *conn);
-struct kdbus_conn *kdbus_conn_unref(struct kdbus_conn *conn);
-bool kdbus_conn_active(const struct kdbus_conn *conn);
-int kdbus_conn_acquire(struct kdbus_conn *conn);
-void kdbus_conn_release(struct kdbus_conn *conn);
-int kdbus_conn_disconnect(struct kdbus_conn *conn, bool ensure_queue_empty);
-bool kdbus_conn_has_name(struct kdbus_conn *conn, const char *name);
-int kdbus_conn_quota_inc(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds);
-void kdbus_conn_quota_dec(struct kdbus_conn *c, struct kdbus_user *u,
- size_t memory, size_t fds);
-void kdbus_conn_lost_message(struct kdbus_conn *c);
-int kdbus_conn_entry_insert(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst,
- struct kdbus_staging *staging,
- struct kdbus_reply *reply,
- const struct kdbus_name_entry *name);
-void kdbus_conn_move_messages(struct kdbus_conn *conn_dst,
- struct kdbus_conn *conn_src,
- u64 name_id);
-
-/* policy */
-bool kdbus_conn_policy_own_name(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- const char *name);
-bool kdbus_conn_policy_talk(struct kdbus_conn *conn,
- const struct cred *conn_creds,
- struct kdbus_conn *to);
-bool kdbus_conn_policy_see_name_unlocked(struct kdbus_conn *conn,
- const struct cred *curr_creds,
- const char *name);
-bool kdbus_conn_policy_see_notification(struct kdbus_conn *conn,
- const struct cred *curr_creds,
- const struct kdbus_msg *msg);
-
-/* command dispatcher */
-struct kdbus_conn *kdbus_cmd_hello(struct kdbus_ep *ep, struct file *file,
- void __user *argp);
-int kdbus_cmd_byebye_unlocked(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_conn_info(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_update(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_send(struct kdbus_conn *conn, struct file *f, void __user *argp);
-int kdbus_cmd_recv(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_free(struct kdbus_conn *conn, void __user *argp);
-
-/**
- * kdbus_conn_is_ordinary() - Check if connection is ordinary
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is an ordinary connection
- */
-static inline int kdbus_conn_is_ordinary(const struct kdbus_conn *conn)
-{
- return !(conn->flags & KDBUS_HELLO_SPECIAL_CONN);
-}
-
-/**
- * kdbus_conn_is_activator() - Check if connection is an activator
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is an activator
- */
-static inline int kdbus_conn_is_activator(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_ACTIVATOR;
-}
-
-/**
- * kdbus_conn_is_policy_holder() - Check if connection is a policy holder
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is a policy holder
- */
-static inline int kdbus_conn_is_policy_holder(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_POLICY_HOLDER;
-}
-
-/**
- * kdbus_conn_is_monitor() - Check if connection is a monitor
- * @conn: The connection to check
- *
- * Return: Non-zero if the connection is a monitor
- */
-static inline int kdbus_conn_is_monitor(const struct kdbus_conn *conn)
-{
- return conn->flags & KDBUS_HELLO_MONITOR;
-}
-
-/**
- * kdbus_conn_lock2() - Lock two connections
- * @a: connection A to lock or NULL
- * @b: connection B to lock or NULL
- *
- * Lock two connections at once. As we need to have a stable locking order, we
- * always lock the connection with lower memory address first.
- */
-static inline void kdbus_conn_lock2(struct kdbus_conn *a, struct kdbus_conn *b)
-{
- if (a < b) {
- if (a)
- mutex_lock(&a->lock);
- if (b && b != a)
- mutex_lock_nested(&b->lock, !!a);
- } else {
- if (b)
- mutex_lock(&b->lock);
- if (a && a != b)
- mutex_lock_nested(&a->lock, !!b);
- }
-}
-
-/**
- * kdbus_conn_unlock2() - Unlock two connections
- * @a: connection A to unlock or NULL
- * @b: connection B to unlock or NULL
- *
- * Unlock two connections at once. See kdbus_conn_lock2().
- */
-static inline void kdbus_conn_unlock2(struct kdbus_conn *a,
- struct kdbus_conn *b)
-{
- if (a)
- mutex_unlock(&a->lock);
- if (b && b != a)
- mutex_unlock(&b->lock);
-}
-
-/**
- * kdbus_conn_assert_active() - lockdep assert on active lock
- * @conn: connection that shall be active
- *
- * This verifies via lockdep that the caller holds an active reference to the
- * given connection.
- */
-static inline void kdbus_conn_assert_active(struct kdbus_conn *conn)
-{
- lockdep_assert_held(conn);
-}
-
-#endif
diff --git a/ipc/kdbus/domain.c b/ipc/kdbus/domain.c
deleted file mode 100644
index 5d52d009d..000000000
--- a/ipc/kdbus/domain.c
+++ /dev/null
@@ -1,296 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "bus.h"
-#include "domain.h"
-#include "handle.h"
-#include "item.h"
-#include "limits.h"
-#include "util.h"
-
-static void kdbus_domain_control_free(struct kdbus_node *node)
-{
- kfree(node);
-}
-
-static struct kdbus_node *kdbus_domain_control_new(struct kdbus_domain *domain,
- unsigned int access)
-{
- struct kdbus_node *node;
- int ret;
-
- node = kzalloc(sizeof(*node), GFP_KERNEL);
- if (!node)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(node, KDBUS_NODE_CONTROL);
-
- node->free_cb = kdbus_domain_control_free;
- node->mode = domain->node.mode;
- node->mode = S_IRUSR | S_IWUSR;
- if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- node->mode |= S_IRGRP | S_IWGRP;
- if (access & KDBUS_MAKE_ACCESS_WORLD)
- node->mode |= S_IROTH | S_IWOTH;
-
- ret = kdbus_node_link(node, &domain->node, "control");
- if (ret < 0)
- goto exit_free;
-
- return node;
-
-exit_free:
- kdbus_node_drain(node);
- kdbus_node_unref(node);
- return ERR_PTR(ret);
-}
-
-static void kdbus_domain_free(struct kdbus_node *node)
-{
- struct kdbus_domain *domain =
- container_of(node, struct kdbus_domain, node);
-
- put_user_ns(domain->user_namespace);
- ida_destroy(&domain->user_ida);
- idr_destroy(&domain->user_idr);
- kfree(domain);
-}
-
-/**
- * kdbus_domain_new() - create a new domain
- * @access: The access mode for this node (KDBUS_MAKE_ACCESS_*)
- *
- * Return: a new kdbus_domain on success, ERR_PTR on failure
- */
-struct kdbus_domain *kdbus_domain_new(unsigned int access)
-{
- struct kdbus_domain *d;
- int ret;
-
- d = kzalloc(sizeof(*d), GFP_KERNEL);
- if (!d)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(&d->node, KDBUS_NODE_DOMAIN);
-
- d->node.free_cb = kdbus_domain_free;
- d->node.mode = S_IRUSR | S_IXUSR;
- if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- d->node.mode |= S_IRGRP | S_IXGRP;
- if (access & KDBUS_MAKE_ACCESS_WORLD)
- d->node.mode |= S_IROTH | S_IXOTH;
-
- mutex_init(&d->lock);
- idr_init(&d->user_idr);
- ida_init(&d->user_ida);
-
- /* Pin user namespace so we can guarantee domain-unique bus * names. */
- d->user_namespace = get_user_ns(current_user_ns());
-
- ret = kdbus_node_link(&d->node, NULL, NULL);
- if (ret < 0)
- goto exit_unref;
-
- return d;
-
-exit_unref:
- kdbus_node_drain(&d->node);
- kdbus_node_unref(&d->node);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_domain_ref() - take a domain reference
- * @domain: Domain
- *
- * Return: the domain itself
- */
-struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain)
-{
- if (domain)
- kdbus_node_ref(&domain->node);
- return domain;
-}
-
-/**
- * kdbus_domain_unref() - drop a domain reference
- * @domain: Domain
- *
- * When the last reference is dropped, the domain internal structure
- * is freed.
- *
- * Return: NULL
- */
-struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain)
-{
- if (domain)
- kdbus_node_unref(&domain->node);
- return NULL;
-}
-
-/**
- * kdbus_domain_populate() - populate static domain nodes
- * @domain: domain to populate
- * @access: KDBUS_MAKE_ACCESS_* access restrictions for new nodes
- *
- * Allocate and activate static sub-nodes of the given domain. This will fail if
- * you call it on a non-active node or if the domain was already populated.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access)
-{
- struct kdbus_node *control;
-
- /*
- * Create a control-node for this domain. We drop our own reference
- * immediately, effectively causing the node to be deactivated and
- * released when the parent domain is.
- */
- control = kdbus_domain_control_new(domain, access);
- if (IS_ERR(control))
- return PTR_ERR(control);
-
- kdbus_node_activate(control);
- kdbus_node_unref(control);
- return 0;
-}
-
-/**
- * kdbus_user_lookup() - lookup a kdbus_user object
- * @domain: domain of the user
- * @uid: uid of the user; INVALID_UID for an anon user
- *
- * Lookup the kdbus user accounting object for the given domain. If INVALID_UID
- * is passed, a new anonymous user is created which is private to the caller.
- *
- * Return: The user object is returned, ERR_PTR on failure.
- */
-struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid)
-{
- struct kdbus_user *u = NULL, *old = NULL;
- int ret;
-
- mutex_lock(&domain->lock);
-
- if (uid_valid(uid)) {
- old = idr_find(&domain->user_idr, __kuid_val(uid));
- /*
- * If the object is about to be destroyed, ignore it and
- * replace the slot in the IDR later on.
- */
- if (old && kref_get_unless_zero(&old->kref)) {
- mutex_unlock(&domain->lock);
- return old;
- }
- }
-
- u = kzalloc(sizeof(*u), GFP_KERNEL);
- if (!u) {
- ret = -ENOMEM;
- goto exit;
- }
-
- kref_init(&u->kref);
- u->domain = kdbus_domain_ref(domain);
- u->uid = uid;
- atomic_set(&u->buses, 0);
- atomic_set(&u->connections, 0);
-
- if (uid_valid(uid)) {
- if (old) {
- idr_replace(&domain->user_idr, u, __kuid_val(uid));
- old->uid = INVALID_UID; /* mark old as removed */
- } else {
- ret = idr_alloc(&domain->user_idr, u, __kuid_val(uid),
- __kuid_val(uid) + 1, GFP_KERNEL);
- if (ret < 0)
- goto exit;
- }
- }
-
- /*
- * Allocate the smallest possible index for this user; used
- * in arrays for accounting user quota in receiver queues.
- */
- ret = ida_simple_get(&domain->user_ida, 1, 0, GFP_KERNEL);
- if (ret < 0)
- goto exit;
-
- u->id = ret;
- mutex_unlock(&domain->lock);
- return u;
-
-exit:
- if (u) {
- if (uid_valid(u->uid))
- idr_remove(&domain->user_idr, __kuid_val(u->uid));
- kdbus_domain_unref(u->domain);
- kfree(u);
- }
- mutex_unlock(&domain->lock);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_user_free(struct kref *kref)
-{
- struct kdbus_user *user = container_of(kref, struct kdbus_user, kref);
-
- WARN_ON(atomic_read(&user->buses) > 0);
- WARN_ON(atomic_read(&user->connections) > 0);
-
- mutex_lock(&user->domain->lock);
- ida_simple_remove(&user->domain->user_ida, user->id);
- if (uid_valid(user->uid))
- idr_remove(&user->domain->user_idr, __kuid_val(user->uid));
- mutex_unlock(&user->domain->lock);
-
- kdbus_domain_unref(user->domain);
- kfree(user);
-}
-
-/**
- * kdbus_user_ref() - take a user reference
- * @u: User
- *
- * Return: @u is returned
- */
-struct kdbus_user *kdbus_user_ref(struct kdbus_user *u)
-{
- if (u)
- kref_get(&u->kref);
- return u;
-}
-
-/**
- * kdbus_user_unref() - drop a user reference
- * @u: User
- *
- * Return: NULL
- */
-struct kdbus_user *kdbus_user_unref(struct kdbus_user *u)
-{
- if (u)
- kref_put(&u->kref, __kdbus_user_free);
- return NULL;
-}
diff --git a/ipc/kdbus/domain.h b/ipc/kdbus/domain.h
deleted file mode 100644
index 447a2bd4d..000000000
--- a/ipc/kdbus/domain.h
+++ /dev/null
@@ -1,77 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_DOMAIN_H
-#define __KDBUS_DOMAIN_H
-
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kref.h>
-#include <linux/user_namespace.h>
-
-#include "node.h"
-
-/**
- * struct kdbus_domain - domain for buses
- * @node: Underlying API node
- * @lock: Domain data lock
- * @last_id: Last used object id
- * @user_idr: Set of all users indexed by UID
- * @user_ida: Set of all users to compute small indices
- * @user_namespace: User namespace, pinned at creation time
- * @dentry: Root dentry of VFS mount (don't use outside of kdbusfs)
- */
-struct kdbus_domain {
- struct kdbus_node node;
- struct mutex lock;
- atomic64_t last_id;
- struct idr user_idr;
- struct ida user_ida;
- struct user_namespace *user_namespace;
- struct dentry *dentry;
-};
-
-/**
- * struct kdbus_user - resource accounting for users
- * @kref: Reference counter
- * @domain: Domain of the user
- * @id: Index of this user
- * @uid: UID of the user
- * @buses: Number of buses the user has created
- * @connections: Number of connections the user has created
- */
-struct kdbus_user {
- struct kref kref;
- struct kdbus_domain *domain;
- unsigned int id;
- kuid_t uid;
- atomic_t buses;
- atomic_t connections;
-};
-
-#define kdbus_domain_from_node(_node) \
- container_of((_node), struct kdbus_domain, node)
-
-struct kdbus_domain *kdbus_domain_new(unsigned int access);
-struct kdbus_domain *kdbus_domain_ref(struct kdbus_domain *domain);
-struct kdbus_domain *kdbus_domain_unref(struct kdbus_domain *domain);
-int kdbus_domain_populate(struct kdbus_domain *domain, unsigned int access);
-
-#define KDBUS_USER_KERNEL_ID 0 /* ID 0 is reserved for kernel accounting */
-
-struct kdbus_user *kdbus_user_lookup(struct kdbus_domain *domain, kuid_t uid);
-struct kdbus_user *kdbus_user_ref(struct kdbus_user *u);
-struct kdbus_user *kdbus_user_unref(struct kdbus_user *u);
-
-#endif
diff --git a/ipc/kdbus/endpoint.c b/ipc/kdbus/endpoint.c
deleted file mode 100644
index 5694ff6dc..000000000
--- a/ipc/kdbus/endpoint.c
+++ /dev/null
@@ -1,303 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "message.h"
-#include "policy.h"
-
-static void kdbus_ep_free(struct kdbus_node *node)
-{
- struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node);
-
- WARN_ON(!list_empty(&ep->conn_list));
-
- kdbus_policy_db_clear(&ep->policy_db);
- kdbus_bus_unref(ep->bus);
- kdbus_user_unref(ep->user);
- kfree(ep);
-}
-
-static void kdbus_ep_release(struct kdbus_node *node, bool was_active)
-{
- struct kdbus_ep *ep = container_of(node, struct kdbus_ep, node);
-
- /* disconnect all connections to this endpoint */
- for (;;) {
- struct kdbus_conn *conn;
-
- mutex_lock(&ep->lock);
- conn = list_first_entry_or_null(&ep->conn_list,
- struct kdbus_conn,
- ep_entry);
- if (!conn) {
- mutex_unlock(&ep->lock);
- break;
- }
-
- /* take reference, release lock, disconnect without lock */
- kdbus_conn_ref(conn);
- mutex_unlock(&ep->lock);
-
- kdbus_conn_disconnect(conn, false);
- kdbus_conn_unref(conn);
- }
-}
-
-/**
- * kdbus_ep_new() - create a new endpoint
- * @bus: The bus this endpoint will be created for
- * @name: The name of the endpoint
- * @access: The access flags for this node (KDBUS_MAKE_ACCESS_*)
- * @uid: The uid of the node
- * @gid: The gid of the node
- * @is_custom: Whether this is a custom endpoint
- *
- * This function will create a new endpoint with the given
- * name and properties for a given bus.
- *
- * Return: a new kdbus_ep on success, ERR_PTR on failure.
- */
-struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name,
- unsigned int access, kuid_t uid, kgid_t gid,
- bool is_custom)
-{
- struct kdbus_ep *e;
- int ret;
-
- /*
- * Validate only custom endpoints names, default endpoints
- * with a "bus" name are created when the bus is created
- */
- if (is_custom) {
- ret = kdbus_verify_uid_prefix(name, bus->domain->user_namespace,
- uid);
- if (ret < 0)
- return ERR_PTR(ret);
- }
-
- e = kzalloc(sizeof(*e), GFP_KERNEL);
- if (!e)
- return ERR_PTR(-ENOMEM);
-
- kdbus_node_init(&e->node, KDBUS_NODE_ENDPOINT);
-
- e->node.free_cb = kdbus_ep_free;
- e->node.release_cb = kdbus_ep_release;
- e->node.uid = uid;
- e->node.gid = gid;
- e->node.mode = S_IRUSR | S_IWUSR;
- if (access & (KDBUS_MAKE_ACCESS_GROUP | KDBUS_MAKE_ACCESS_WORLD))
- e->node.mode |= S_IRGRP | S_IWGRP;
- if (access & KDBUS_MAKE_ACCESS_WORLD)
- e->node.mode |= S_IROTH | S_IWOTH;
-
- mutex_init(&e->lock);
- INIT_LIST_HEAD(&e->conn_list);
- kdbus_policy_db_init(&e->policy_db);
- e->bus = kdbus_bus_ref(bus);
-
- ret = kdbus_node_link(&e->node, &bus->node, name);
- if (ret < 0)
- goto exit_unref;
-
- /*
- * Transactions on custom endpoints are never accounted on the global
- * user limits. Instead, for each custom endpoint, we create a custom,
- * unique user, which all transactions are accounted on. Regardless of
- * the user using that endpoint, it is always accounted on the same
- * user-object. This budget is not shared with ordinary users on
- * non-custom endpoints.
- */
- if (is_custom) {
- e->user = kdbus_user_lookup(bus->domain, INVALID_UID);
- if (IS_ERR(e->user)) {
- ret = PTR_ERR(e->user);
- e->user = NULL;
- goto exit_unref;
- }
- }
-
- return e;
-
-exit_unref:
- kdbus_node_drain(&e->node);
- kdbus_node_unref(&e->node);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_ep_ref() - increase the reference counter of a kdbus_ep
- * @ep: The endpoint to reference
- *
- * Every user of an endpoint, except for its creator, must add a reference to
- * the kdbus_ep instance using this function.
- *
- * Return: the ep itself
- */
-struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep)
-{
- if (ep)
- kdbus_node_ref(&ep->node);
- return ep;
-}
-
-/**
- * kdbus_ep_unref() - decrease the reference counter of a kdbus_ep
- * @ep: The ep to unref
- *
- * Release a reference. If the reference count drops to 0, the ep will be
- * freed.
- *
- * Return: NULL
- */
-struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep)
-{
- if (ep)
- kdbus_node_unref(&ep->node);
- return NULL;
-}
-
-/**
- * kdbus_ep_is_privileged() - check whether a file is privileged
- * @ep: endpoint to operate on
- * @file: file to test
- *
- * Return: True if @file is privileged in the domain of @ep.
- */
-bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file)
-{
- return !ep->user &&
- file_ns_capable(file, ep->bus->domain->user_namespace,
- CAP_IPC_OWNER);
-}
-
-/**
- * kdbus_ep_is_owner() - check whether a file should be treated as bus owner
- * @ep: endpoint to operate on
- * @file: file to test
- *
- * Return: True if @file should be treated as bus owner on @ep
- */
-bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file)
-{
- return !ep->user &&
- (uid_eq(file->f_cred->euid, ep->bus->node.uid) ||
- kdbus_ep_is_privileged(ep, file));
-}
-
-/**
- * kdbus_cmd_ep_make() - handle KDBUS_CMD_ENDPOINT_MAKE
- * @bus: bus to operate on
- * @argp: command payload
- *
- * Return: NULL or newly created endpoint on success, ERR_PTR on failure.
- */
-struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp)
-{
- const char *item_make_name;
- struct kdbus_ep *ep = NULL;
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_MAKE_NAME, .mandatory = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MAKE_ACCESS_GROUP |
- KDBUS_MAKE_ACCESS_WORLD,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret < 0)
- return ERR_PTR(ret);
- if (ret > 0)
- return NULL;
-
- item_make_name = argv[1].item->str;
-
- ep = kdbus_ep_new(bus, item_make_name, cmd->flags,
- current_euid(), current_egid(), true);
- if (IS_ERR(ep)) {
- ret = PTR_ERR(ep);
- ep = NULL;
- goto exit;
- }
-
- if (!kdbus_node_activate(&ep->node)) {
- ret = -ESHUTDOWN;
- goto exit;
- }
-
-exit:
- ret = kdbus_args_clear(&args, ret);
- if (ret < 0) {
- if (ep) {
- kdbus_node_drain(&ep->node);
- kdbus_ep_unref(ep);
- }
- return ERR_PTR(ret);
- }
- return ep;
-}
-
-/**
- * kdbus_cmd_ep_update() - handle KDBUS_CMD_ENDPOINT_UPDATE
- * @ep: endpoint to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp)
-{
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME, .multiple = true },
- { .type = KDBUS_ITEM_POLICY_ACCESS, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_policy_set(&ep->policy_db, args.items, args.items_size,
- 0, true, ep);
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/endpoint.h b/ipc/kdbus/endpoint.h
deleted file mode 100644
index e0da59f01..000000000
--- a/ipc/kdbus/endpoint.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_ENDPOINT_H
-#define __KDBUS_ENDPOINT_H
-
-#include <linux/list.h>
-#include <linux/mutex.h>
-#include <linux/uidgid.h>
-#include "node.h"
-#include "policy.h"
-
-struct kdbus_bus;
-struct kdbus_user;
-
-/**
- * struct kdbus_ep - endpoint to access a bus
- * @node: The kdbus node
- * @lock: Endpoint data lock
- * @bus: Bus behind this endpoint
- * @user: Custom enpoints account against an anonymous user
- * @policy_db: Uploaded policy
- * @conn_list: Connections of this endpoint
- *
- * An endpoint offers access to a bus; the default endpoint node name is "bus".
- * Additional custom endpoints to the same bus can be created and they can
- * carry their own policies/filters.
- */
-struct kdbus_ep {
- struct kdbus_node node;
- struct mutex lock;
-
- /* static */
- struct kdbus_bus *bus;
- struct kdbus_user *user;
-
- /* protected by own locks */
- struct kdbus_policy_db policy_db;
-
- /* protected by ep->lock */
- struct list_head conn_list;
-};
-
-#define kdbus_ep_from_node(_node) \
- container_of((_node), struct kdbus_ep, node)
-
-struct kdbus_ep *kdbus_ep_new(struct kdbus_bus *bus, const char *name,
- unsigned int access, kuid_t uid, kgid_t gid,
- bool policy);
-struct kdbus_ep *kdbus_ep_ref(struct kdbus_ep *ep);
-struct kdbus_ep *kdbus_ep_unref(struct kdbus_ep *ep);
-
-bool kdbus_ep_is_privileged(struct kdbus_ep *ep, struct file *file);
-bool kdbus_ep_is_owner(struct kdbus_ep *ep, struct file *file);
-
-struct kdbus_ep *kdbus_cmd_ep_make(struct kdbus_bus *bus, void __user *argp);
-int kdbus_cmd_ep_update(struct kdbus_ep *ep, void __user *argp);
-
-#endif
diff --git a/ipc/kdbus/fs.c b/ipc/kdbus/fs.c
deleted file mode 100644
index 6330c61e5..000000000
--- a/ipc/kdbus/fs.c
+++ /dev/null
@@ -1,508 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/fsnotify.h>
-#include <linux/init.h>
-#include <linux/ipc_namespace.h>
-#include <linux/magic.h>
-#include <linux/module.h>
-#include <linux/mount.h>
-#include <linux/mutex.h>
-#include <linux/namei.h>
-#include <linux/pagemap.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include "bus.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "node.h"
-
-#define kdbus_node_from_dentry(_dentry) \
- ((struct kdbus_node *)(_dentry)->d_fsdata)
-
-static struct inode *fs_inode_get(struct super_block *sb,
- struct kdbus_node *node);
-
-/*
- * Directory Management
- */
-
-static inline unsigned char kdbus_dt_type(struct kdbus_node *node)
-{
- switch (node->type) {
- case KDBUS_NODE_DOMAIN:
- case KDBUS_NODE_BUS:
- return DT_DIR;
- case KDBUS_NODE_CONTROL:
- case KDBUS_NODE_ENDPOINT:
- return DT_REG;
- }
-
- return DT_UNKNOWN;
-}
-
-static int fs_dir_fop_iterate(struct file *file, struct dir_context *ctx)
-{
- struct dentry *dentry = file->f_path.dentry;
- struct kdbus_node *parent = kdbus_node_from_dentry(dentry);
- struct kdbus_node *old, *next = file->private_data;
-
- /*
- * kdbusfs directory iterator (modelled after sysfs/kernfs)
- * When iterating kdbusfs directories, we iterate all children of the
- * parent kdbus_node object. We use ctx->pos to store the hash of the
- * child and file->private_data to store a reference to the next node
- * object. If ctx->pos is not modified via llseek while you iterate a
- * directory, then we use the file->private_data node pointer to
- * directly access the next node in the tree.
- * However, if you directly seek on the directory, we have to find the
- * closest node to that position and cannot use our node pointer. This
- * means iterating the rb-tree to find the closest match and start over
- * from there.
- * Note that hash values are not necessarily unique. Therefore, llseek
- * is not guaranteed to seek to the same node that you got when you
- * retrieved the position. Seeking to 0, 1, 2 and >=INT_MAX is safe,
- * though. We could use the inode-number as position, but this would
- * require another rb-tree for fast access. Kernfs and others already
- * ignore those conflicts, so we should be fine, too.
- */
-
- if (!dir_emit_dots(file, ctx))
- return 0;
-
- /* acquire @next; if deactivated, or seek detected, find next node */
- old = next;
- if (next && ctx->pos == next->hash) {
- if (kdbus_node_acquire(next))
- kdbus_node_ref(next);
- else
- next = kdbus_node_next_child(parent, next);
- } else {
- next = kdbus_node_find_closest(parent, ctx->pos);
- }
- kdbus_node_unref(old);
-
- while (next) {
- /* emit @next */
- file->private_data = next;
- ctx->pos = next->hash;
-
- kdbus_node_release(next);
-
- if (!dir_emit(ctx, next->name, strlen(next->name), next->id,
- kdbus_dt_type(next)))
- return 0;
-
- /* find next node after @next */
- old = next;
- next = kdbus_node_next_child(parent, next);
- kdbus_node_unref(old);
- }
-
- file->private_data = NULL;
- ctx->pos = INT_MAX;
-
- return 0;
-}
-
-static loff_t fs_dir_fop_llseek(struct file *file, loff_t offset, int whence)
-{
- struct inode *inode = file_inode(file);
- loff_t ret;
-
- /* protect f_off against fop_iterate */
- mutex_lock(&inode->i_mutex);
- ret = generic_file_llseek(file, offset, whence);
- mutex_unlock(&inode->i_mutex);
-
- return ret;
-}
-
-static int fs_dir_fop_release(struct inode *inode, struct file *file)
-{
- kdbus_node_unref(file->private_data);
- return 0;
-}
-
-static const struct file_operations fs_dir_fops = {
- .read = generic_read_dir,
- .iterate = fs_dir_fop_iterate,
- .llseek = fs_dir_fop_llseek,
- .release = fs_dir_fop_release,
-};
-
-static struct dentry *fs_dir_iop_lookup(struct inode *dir,
- struct dentry *dentry,
- unsigned int flags)
-{
- struct dentry *dnew = NULL;
- struct kdbus_node *parent;
- struct kdbus_node *node;
- struct inode *inode;
-
- parent = kdbus_node_from_dentry(dentry->d_parent);
- if (!kdbus_node_acquire(parent))
- return NULL;
-
- /* returns reference to _acquired_ child node */
- node = kdbus_node_find_child(parent, dentry->d_name.name);
- if (node) {
- dentry->d_fsdata = node;
- inode = fs_inode_get(dir->i_sb, node);
- if (IS_ERR(inode))
- dnew = ERR_CAST(inode);
- else
- dnew = d_splice_alias(inode, dentry);
-
- kdbus_node_release(node);
- }
-
- kdbus_node_release(parent);
- return dnew;
-}
-
-static const struct inode_operations fs_dir_iops = {
- .permission = generic_permission,
- .lookup = fs_dir_iop_lookup,
-};
-
-/*
- * Inode Management
- */
-
-static const struct inode_operations fs_inode_iops = {
- .permission = generic_permission,
-};
-
-static struct inode *fs_inode_get(struct super_block *sb,
- struct kdbus_node *node)
-{
- struct inode *inode;
-
- inode = iget_locked(sb, node->id);
- if (!inode)
- return ERR_PTR(-ENOMEM);
- if (!(inode->i_state & I_NEW))
- return inode;
-
- inode->i_private = kdbus_node_ref(node);
- inode->i_mapping->a_ops = &empty_aops;
- inode->i_mode = node->mode & S_IALLUGO;
- inode->i_atime = inode->i_ctime = inode->i_mtime = CURRENT_TIME;
- inode->i_uid = node->uid;
- inode->i_gid = node->gid;
-
- switch (node->type) {
- case KDBUS_NODE_DOMAIN:
- case KDBUS_NODE_BUS:
- inode->i_mode |= S_IFDIR;
- inode->i_op = &fs_dir_iops;
- inode->i_fop = &fs_dir_fops;
- set_nlink(inode, 2);
- break;
- case KDBUS_NODE_CONTROL:
- case KDBUS_NODE_ENDPOINT:
- inode->i_mode |= S_IFREG;
- inode->i_op = &fs_inode_iops;
- inode->i_fop = &kdbus_handle_ops;
- break;
- }
-
- unlock_new_inode(inode);
-
- return inode;
-}
-
-/*
- * Superblock Management
- */
-
-static int fs_super_dop_revalidate(struct dentry *dentry, unsigned int flags)
-{
- struct kdbus_node *node;
-
- /* Force lookup on negatives */
- if (!dentry->d_inode)
- return 0;
-
- node = kdbus_node_from_dentry(dentry);
-
- /* see whether the node has been removed */
- if (!kdbus_node_is_active(node))
- return 0;
-
- return 1;
-}
-
-static void fs_super_dop_release(struct dentry *dentry)
-{
- kdbus_node_unref(dentry->d_fsdata);
-}
-
-static const struct dentry_operations fs_super_dops = {
- .d_revalidate = fs_super_dop_revalidate,
- .d_release = fs_super_dop_release,
-};
-
-static void fs_super_sop_evict_inode(struct inode *inode)
-{
- struct kdbus_node *node = kdbus_node_from_inode(inode);
-
- truncate_inode_pages_final(&inode->i_data);
- clear_inode(inode);
- kdbus_node_unref(node);
-}
-
-static const struct super_operations fs_super_sops = {
- .statfs = simple_statfs,
- .drop_inode = generic_delete_inode,
- .evict_inode = fs_super_sop_evict_inode,
-};
-
-static int fs_super_fill(struct super_block *sb)
-{
- struct kdbus_domain *domain = sb->s_fs_info;
- struct inode *inode;
- int ret;
-
- sb->s_blocksize = PAGE_CACHE_SIZE;
- sb->s_blocksize_bits = PAGE_CACHE_SHIFT;
- sb->s_magic = KDBUS_SUPER_MAGIC;
- sb->s_maxbytes = MAX_LFS_FILESIZE;
- sb->s_op = &fs_super_sops;
- sb->s_time_gran = 1;
-
- inode = fs_inode_get(sb, &domain->node);
- if (IS_ERR(inode))
- return PTR_ERR(inode);
-
- sb->s_root = d_make_root(inode);
- if (!sb->s_root) {
- /* d_make_root iput()s the inode on failure */
- return -ENOMEM;
- }
-
- /* sb holds domain reference */
- sb->s_root->d_fsdata = &domain->node;
- sb->s_d_op = &fs_super_dops;
-
- /* sb holds root reference */
- domain->dentry = sb->s_root;
-
- if (!kdbus_node_activate(&domain->node))
- return -ESHUTDOWN;
-
- ret = kdbus_domain_populate(domain, KDBUS_MAKE_ACCESS_WORLD);
- if (ret < 0)
- return ret;
-
- sb->s_flags |= MS_ACTIVE;
- return 0;
-}
-
-static void fs_super_kill(struct super_block *sb)
-{
- struct kdbus_domain *domain = sb->s_fs_info;
-
- if (domain) {
- kdbus_node_drain(&domain->node);
- domain->dentry = NULL;
- }
-
- kill_anon_super(sb);
- kdbus_domain_unref(domain);
-}
-
-static int fs_super_set(struct super_block *sb, void *data)
-{
- int ret;
-
- ret = set_anon_super(sb, data);
- if (!ret)
- sb->s_fs_info = data;
-
- return ret;
-}
-
-static struct dentry *fs_super_mount(struct file_system_type *fs_type,
- int flags, const char *dev_name,
- void *data)
-{
- struct kdbus_domain *domain;
- struct super_block *sb;
- int ret;
-
- domain = kdbus_domain_new(KDBUS_MAKE_ACCESS_WORLD);
- if (IS_ERR(domain))
- return ERR_CAST(domain);
-
- sb = sget(fs_type, NULL, fs_super_set, flags, domain);
- if (IS_ERR(sb)) {
- kdbus_node_drain(&domain->node);
- kdbus_domain_unref(domain);
- return ERR_CAST(sb);
- }
-
- WARN_ON(sb->s_fs_info != domain);
- WARN_ON(sb->s_root);
-
- ret = fs_super_fill(sb);
- if (ret < 0) {
- /* calls into ->kill_sb() when done */
- deactivate_locked_super(sb);
- return ERR_PTR(ret);
- }
-
- return dget(sb->s_root);
-}
-
-static struct file_system_type fs_type = {
- .name = KBUILD_MODNAME "fs",
- .owner = THIS_MODULE,
- .mount = fs_super_mount,
- .kill_sb = fs_super_kill,
- .fs_flags = FS_USERNS_MOUNT,
-};
-
-/**
- * kdbus_fs_init() - register kdbus filesystem
- *
- * This registers a filesystem with the VFS layer. The filesystem is called
- * `KBUILD_MODNAME "fs"', which usually resolves to `kdbusfs'. The nameing
- * scheme allows to set KBUILD_MODNAME to "kdbus2" and you will get an
- * independent filesystem for developers.
- *
- * Each mount of the kdbusfs filesystem has an kdbus_domain attached.
- * Operations on this mount will only affect the attached domain. On each mount
- * a new domain is automatically created and used for this mount exclusively.
- * If you want to share a domain across multiple mounts, you need to bind-mount
- * it.
- *
- * Mounts of kdbusfs (with a different domain each) are unrelated to each other
- * and will never have any effect on any domain but their own.
- *
- * Return: 0 on success, negative error otherwise.
- */
-int kdbus_fs_init(void)
-{
- return register_filesystem(&fs_type);
-}
-
-/**
- * kdbus_fs_exit() - unregister kdbus filesystem
- *
- * This does the reverse to kdbus_fs_init(). It unregisters the kdbusfs
- * filesystem from VFS and cleans up any allocated resources.
- */
-void kdbus_fs_exit(void)
-{
- unregister_filesystem(&fs_type);
-}
-
-/* acquire domain of @node, making sure all ancestors are active */
-static struct kdbus_domain *fs_acquire_domain(struct kdbus_node *node)
-{
- struct kdbus_domain *domain;
- struct kdbus_node *iter;
-
- /* caller must guarantee that @node is linked */
- for (iter = node; iter->parent; iter = iter->parent)
- if (!kdbus_node_is_active(iter->parent))
- return NULL;
-
- /* root nodes are always domains */
- if (WARN_ON(iter->type != KDBUS_NODE_DOMAIN))
- return NULL;
-
- domain = kdbus_domain_from_node(iter);
- if (!kdbus_node_acquire(&domain->node))
- return NULL;
-
- return domain;
-}
-
-/**
- * kdbus_fs_flush() - flush dcache entries of a node
- * @node: Node to flush entries of
- *
- * This flushes all VFS filesystem cache entries for a node and all its
- * children. This should be called whenever a node is destroyed during
- * runtime. It will flush the cache entries so the linked objects can be
- * deallocated.
- *
- * This is a no-op if you call it on active nodes (they really should stay in
- * cache) or on nodes with deactivated parents (flushing the parent is enough).
- * Furthermore, there is no need to call it on nodes whose lifetime is bound to
- * their parents'. In those cases, the parent-flush will always also flush the
- * children.
- */
-void kdbus_fs_flush(struct kdbus_node *node)
-{
- struct dentry *dentry, *parent_dentry = NULL;
- struct kdbus_domain *domain;
- struct qstr name;
-
- /* active nodes should remain in cache */
- if (!kdbus_node_is_deactivated(node))
- return;
-
- /* nodes that were never linked were never instantiated */
- if (!node->parent)
- return;
-
- /* acquire domain and verify all ancestors are active */
- domain = fs_acquire_domain(node);
- if (!domain)
- return;
-
- switch (node->type) {
- case KDBUS_NODE_ENDPOINT:
- if (WARN_ON(!node->parent || !node->parent->name))
- goto exit;
-
- name.name = node->parent->name;
- name.len = strlen(node->parent->name);
- parent_dentry = d_hash_and_lookup(domain->dentry, &name);
- if (IS_ERR_OR_NULL(parent_dentry))
- goto exit;
-
- /* fallthrough */
- case KDBUS_NODE_BUS:
- if (WARN_ON(!node->name))
- goto exit;
-
- name.name = node->name;
- name.len = strlen(node->name);
- dentry = d_hash_and_lookup(parent_dentry ? : domain->dentry,
- &name);
- if (!IS_ERR_OR_NULL(dentry)) {
- d_invalidate(dentry);
- dput(dentry);
- }
-
- dput(parent_dentry);
- break;
-
- default:
- /* all other types are bound to their parent lifetime */
- break;
- }
-
-exit:
- kdbus_node_release(&domain->node);
-}
diff --git a/ipc/kdbus/fs.h b/ipc/kdbus/fs.h
deleted file mode 100644
index 62f7d6abf..000000000
--- a/ipc/kdbus/fs.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUSFS_H
-#define __KDBUSFS_H
-
-#include <linux/kernel.h>
-
-struct kdbus_node;
-
-int kdbus_fs_init(void);
-void kdbus_fs_exit(void);
-void kdbus_fs_flush(struct kdbus_node *node);
-
-#define kdbus_node_from_inode(_inode) \
- ((struct kdbus_node *)(_inode)->i_private)
-
-#endif
diff --git a/ipc/kdbus/handle.c b/ipc/kdbus/handle.c
deleted file mode 100644
index 2f82c2a32..000000000
--- a/ipc/kdbus/handle.c
+++ /dev/null
@@ -1,691 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/kdev_t.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/syscalls.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-#include "domain.h"
-#include "policy.h"
-
-static int kdbus_args_verify(struct kdbus_args *args)
-{
- struct kdbus_item *item;
- size_t i;
- int ret;
-
- KDBUS_ITEMS_FOREACH(item, args->items, args->items_size) {
- struct kdbus_arg *arg = NULL;
-
- if (!KDBUS_ITEM_VALID(item, args->items, args->items_size))
- return -EINVAL;
-
- for (i = 0; i < args->argc; ++i)
- if (args->argv[i].type == item->type)
- break;
- if (i >= args->argc)
- return -EINVAL;
-
- arg = &args->argv[i];
-
- ret = kdbus_item_validate(item);
- if (ret < 0)
- return ret;
-
- if (arg->item && !arg->multiple)
- return -EINVAL;
-
- arg->item = item;
- }
-
- if (!KDBUS_ITEMS_END(item, args->items, args->items_size))
- return -EINVAL;
-
- return 0;
-}
-
-static int kdbus_args_negotiate(struct kdbus_args *args)
-{
- struct kdbus_item __user *user;
- struct kdbus_item *negotiation;
- size_t i, j, num;
-
- /*
- * If KDBUS_FLAG_NEGOTIATE is set, we overwrite the flags field with
- * the set of supported flags. Furthermore, if an KDBUS_ITEM_NEGOTIATE
- * item is passed, we iterate its payload (array of u64, each set to an
- * item type) and clear all unsupported item-types to 0.
- * The caller might do this recursively, if other flags or objects are
- * embedded in the payload itself.
- */
-
- if (args->cmd->flags & KDBUS_FLAG_NEGOTIATE) {
- if (put_user(args->allowed_flags & ~KDBUS_FLAG_NEGOTIATE,
- &args->user->flags))
- return -EFAULT;
- }
-
- if (args->argc < 1 || args->argv[0].type != KDBUS_ITEM_NEGOTIATE ||
- !args->argv[0].item)
- return 0;
-
- negotiation = args->argv[0].item;
- user = (struct kdbus_item __user *)
- ((u8 __user *)args->user +
- ((u8 *)negotiation - (u8 *)args->cmd));
- num = KDBUS_ITEM_PAYLOAD_SIZE(negotiation) / sizeof(u64);
-
- for (i = 0; i < num; ++i) {
- for (j = 0; j < args->argc; ++j)
- if (negotiation->data64[i] == args->argv[j].type)
- break;
-
- if (j < args->argc)
- continue;
-
- /* this item is not supported, clear it out */
- negotiation->data64[i] = 0;
- if (put_user(negotiation->data64[i], &user->data64[i]))
- return -EFAULT;
- }
-
- return 0;
-}
-
-/**
- * __kdbus_args_parse() - parse payload of kdbus command
- * @args: object to parse data into
- * @is_cmd: whether this is a command or msg payload
- * @argp: user-space location of command payload to parse
- * @type_size: overall size of command payload to parse
- * @items_offset: offset of items array in command payload
- * @out: output variable to store pointer to copied payload
- *
- * This parses the ioctl payload at user-space location @argp into @args. @args
- * must be pre-initialized by the caller to reflect the supported flags and
- * items of this command. This parser will then copy the command payload into
- * kernel-space, verify correctness and consistency and cache pointers to parsed
- * items and other data in @args.
- *
- * If this function succeeded, you must call kdbus_args_clear() to release
- * allocated resources before destroying @args.
- *
- * This can also be used to import kdbus_msg objects. In that case, @is_cmd must
- * be set to 'false' and the 'return_flags' field will not be touched (as it
- * doesn't exist on kdbus_msg).
- *
- * Return: On failure a negative error code is returned. Otherwise, 1 is
- * returned if negotiation was requested, 0 if not.
- */
-int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp,
- size_t type_size, size_t items_offset, void **out)
-{
- u64 user_size;
- int ret, i;
-
- ret = kdbus_copy_from_user(&user_size, argp, sizeof(user_size));
- if (ret < 0)
- return ret;
-
- if (user_size < type_size)
- return -EINVAL;
- if (user_size > KDBUS_CMD_MAX_SIZE)
- return -EMSGSIZE;
-
- if (user_size <= sizeof(args->cmd_buf)) {
- if (copy_from_user(args->cmd_buf, argp, user_size))
- return -EFAULT;
- args->cmd = (void*)args->cmd_buf;
- } else {
- args->cmd = memdup_user(argp, user_size);
- if (IS_ERR(args->cmd))
- return PTR_ERR(args->cmd);
- }
-
- if (args->cmd->size != user_size) {
- ret = -EINVAL;
- goto error;
- }
-
- if (is_cmd)
- args->cmd->return_flags = 0;
- args->user = argp;
- args->items = (void *)((u8 *)args->cmd + items_offset);
- args->items_size = args->cmd->size - items_offset;
- args->is_cmd = is_cmd;
-
- if (args->cmd->flags & ~args->allowed_flags) {
- ret = -EINVAL;
- goto error;
- }
-
- ret = kdbus_args_verify(args);
- if (ret < 0)
- goto error;
-
- ret = kdbus_args_negotiate(args);
- if (ret < 0)
- goto error;
-
- /* mandatory items must be given (but not on negotiation) */
- if (!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE)) {
- for (i = 0; i < args->argc; ++i)
- if (args->argv[i].mandatory && !args->argv[i].item) {
- ret = -EINVAL;
- goto error;
- }
- }
-
- *out = args->cmd;
- return !!(args->cmd->flags & KDBUS_FLAG_NEGOTIATE);
-
-error:
- return kdbus_args_clear(args, ret);
-}
-
-/**
- * kdbus_args_clear() - release allocated command resources
- * @args: object to release resources of
- * @ret: return value of this command
- *
- * This frees all allocated resources on @args and copies the command result
- * flags into user-space. @ret is usually returned unchanged by this function,
- * so it can be used in the final 'return' statement of the command handler.
- *
- * Return: -EFAULT if return values cannot be copied into user-space, otherwise
- * @ret is returned unchanged.
- */
-int kdbus_args_clear(struct kdbus_args *args, int ret)
-{
- if (!args)
- return ret;
-
- if (!IS_ERR_OR_NULL(args->cmd)) {
- if (args->is_cmd && put_user(args->cmd->return_flags,
- &args->user->return_flags))
- ret = -EFAULT;
- if (args->cmd != (void*)args->cmd_buf)
- kfree(args->cmd);
- args->cmd = NULL;
- }
-
- return ret;
-}
-
-/**
- * enum kdbus_handle_type - type an handle can be of
- * @KDBUS_HANDLE_NONE: no type set, yet
- * @KDBUS_HANDLE_BUS_OWNER: bus owner
- * @KDBUS_HANDLE_EP_OWNER: endpoint owner
- * @KDBUS_HANDLE_CONNECTED: endpoint connection after HELLO
- */
-enum kdbus_handle_type {
- KDBUS_HANDLE_NONE,
- KDBUS_HANDLE_BUS_OWNER,
- KDBUS_HANDLE_EP_OWNER,
- KDBUS_HANDLE_CONNECTED,
-};
-
-/**
- * struct kdbus_handle - handle to the kdbus system
- * @lock: handle lock
- * @type: type of this handle (KDBUS_HANDLE_*)
- * @bus_owner: bus this handle owns
- * @ep_owner: endpoint this handle owns
- * @conn: connection this handle owns
- */
-struct kdbus_handle {
- struct mutex lock;
-
- enum kdbus_handle_type type;
- union {
- struct kdbus_bus *bus_owner;
- struct kdbus_ep *ep_owner;
- struct kdbus_conn *conn;
- };
-};
-
-static int kdbus_handle_open(struct inode *inode, struct file *file)
-{
- struct kdbus_handle *handle;
- struct kdbus_node *node;
- int ret;
-
- node = kdbus_node_from_inode(inode);
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- handle = kzalloc(sizeof(*handle), GFP_KERNEL);
- if (!handle) {
- ret = -ENOMEM;
- goto exit;
- }
-
- mutex_init(&handle->lock);
- handle->type = KDBUS_HANDLE_NONE;
-
- file->private_data = handle;
- ret = 0;
-
-exit:
- kdbus_node_release(node);
- return ret;
-}
-
-static int kdbus_handle_release(struct inode *inode, struct file *file)
-{
- struct kdbus_handle *handle = file->private_data;
-
- switch (handle->type) {
- case KDBUS_HANDLE_BUS_OWNER:
- if (handle->bus_owner) {
- kdbus_node_drain(&handle->bus_owner->node);
- kdbus_bus_unref(handle->bus_owner);
- }
- break;
- case KDBUS_HANDLE_EP_OWNER:
- if (handle->ep_owner) {
- kdbus_node_drain(&handle->ep_owner->node);
- kdbus_ep_unref(handle->ep_owner);
- }
- break;
- case KDBUS_HANDLE_CONNECTED:
- kdbus_conn_disconnect(handle->conn, false);
- kdbus_conn_unref(handle->conn);
- break;
- case KDBUS_HANDLE_NONE:
- /* nothing to clean up */
- break;
- }
-
- kfree(handle);
-
- return 0;
-}
-
-static long kdbus_handle_ioctl_control(struct file *file, unsigned int cmd,
- void __user *argp)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = file_inode(file)->i_private;
- struct kdbus_domain *domain;
- int ret = 0;
-
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- /*
- * The parent of control-nodes is always a domain, make sure to pin it
- * so the parent is actually valid.
- */
- domain = kdbus_domain_from_node(node->parent);
- if (!kdbus_node_acquire(&domain->node)) {
- kdbus_node_release(node);
- return -ESHUTDOWN;
- }
-
- switch (cmd) {
- case KDBUS_CMD_BUS_MAKE: {
- struct kdbus_bus *bus;
-
- bus = kdbus_cmd_bus_make(domain, argp);
- if (IS_ERR_OR_NULL(bus)) {
- ret = PTR_ERR_OR_ZERO(bus);
- break;
- }
-
- handle->bus_owner = bus;
- ret = KDBUS_HANDLE_BUS_OWNER;
- break;
- }
-
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(&domain->node);
- kdbus_node_release(node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_ep(struct file *file, unsigned int cmd,
- void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = file_inode(file)->i_private;
- struct kdbus_ep *ep, *file_ep = kdbus_ep_from_node(node);
- struct kdbus_bus *bus = file_ep->bus;
- struct kdbus_conn *conn;
- int ret = 0;
-
- if (!kdbus_node_acquire(node))
- return -ESHUTDOWN;
-
- switch (cmd) {
- case KDBUS_CMD_ENDPOINT_MAKE: {
- /* creating custom endpoints is a privileged operation */
- if (!kdbus_ep_is_owner(file_ep, file)) {
- ret = -EPERM;
- break;
- }
-
- ep = kdbus_cmd_ep_make(bus, buf);
- if (IS_ERR_OR_NULL(ep)) {
- ret = PTR_ERR_OR_ZERO(ep);
- break;
- }
-
- handle->ep_owner = ep;
- ret = KDBUS_HANDLE_EP_OWNER;
- break;
- }
-
- case KDBUS_CMD_HELLO:
- conn = kdbus_cmd_hello(file_ep, file, buf);
- if (IS_ERR_OR_NULL(conn)) {
- ret = PTR_ERR_OR_ZERO(conn);
- break;
- }
-
- handle->conn = conn;
- ret = KDBUS_HANDLE_CONNECTED;
- break;
-
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_ep_owner(struct file *file, unsigned int command,
- void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_ep *ep = handle->ep_owner;
- int ret;
-
- if (!kdbus_node_acquire(&ep->node))
- return -ESHUTDOWN;
-
- switch (command) {
- case KDBUS_CMD_ENDPOINT_UPDATE:
- ret = kdbus_cmd_ep_update(ep, buf);
- break;
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_node_release(&ep->node);
- return ret;
-}
-
-static long kdbus_handle_ioctl_connected(struct file *file,
- unsigned int command, void __user *buf)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_conn *conn = handle->conn;
- struct kdbus_conn *release_conn = NULL;
- int ret;
-
- release_conn = conn;
- ret = kdbus_conn_acquire(release_conn);
- if (ret < 0)
- return ret;
-
- switch (command) {
- case KDBUS_CMD_BYEBYE:
- /*
- * BYEBYE is special; we must not acquire a connection when
- * calling into kdbus_conn_disconnect() or we will deadlock,
- * because kdbus_conn_disconnect() will wait for all acquired
- * references to be dropped.
- */
- kdbus_conn_release(release_conn);
- release_conn = NULL;
- ret = kdbus_cmd_byebye_unlocked(conn, buf);
- break;
- case KDBUS_CMD_NAME_ACQUIRE:
- ret = kdbus_cmd_name_acquire(conn, buf);
- break;
- case KDBUS_CMD_NAME_RELEASE:
- ret = kdbus_cmd_name_release(conn, buf);
- break;
- case KDBUS_CMD_LIST:
- ret = kdbus_cmd_list(conn, buf);
- break;
- case KDBUS_CMD_CONN_INFO:
- ret = kdbus_cmd_conn_info(conn, buf);
- break;
- case KDBUS_CMD_BUS_CREATOR_INFO:
- ret = kdbus_cmd_bus_creator_info(conn, buf);
- break;
- case KDBUS_CMD_UPDATE:
- ret = kdbus_cmd_update(conn, buf);
- break;
- case KDBUS_CMD_MATCH_ADD:
- ret = kdbus_cmd_match_add(conn, buf);
- break;
- case KDBUS_CMD_MATCH_REMOVE:
- ret = kdbus_cmd_match_remove(conn, buf);
- break;
- case KDBUS_CMD_SEND:
- ret = kdbus_cmd_send(conn, file, buf);
- break;
- case KDBUS_CMD_RECV:
- ret = kdbus_cmd_recv(conn, buf);
- break;
- case KDBUS_CMD_FREE:
- ret = kdbus_cmd_free(conn, buf);
- break;
- default:
- ret = -EBADFD;
- break;
- }
-
- kdbus_conn_release(release_conn);
- return ret;
-}
-
-static long kdbus_handle_ioctl(struct file *file, unsigned int cmd,
- unsigned long arg)
-{
- struct kdbus_handle *handle = file->private_data;
- struct kdbus_node *node = kdbus_node_from_inode(file_inode(file));
- void __user *argp = (void __user *)arg;
- long ret = -EBADFD;
-
- switch (cmd) {
- case KDBUS_CMD_BUS_MAKE:
- case KDBUS_CMD_ENDPOINT_MAKE:
- case KDBUS_CMD_HELLO:
- mutex_lock(&handle->lock);
- if (handle->type == KDBUS_HANDLE_NONE) {
- if (node->type == KDBUS_NODE_CONTROL)
- ret = kdbus_handle_ioctl_control(file, cmd,
- argp);
- else if (node->type == KDBUS_NODE_ENDPOINT)
- ret = kdbus_handle_ioctl_ep(file, cmd, argp);
-
- if (ret > 0) {
- /*
- * The data given via open() is not sufficient
- * to setup a kdbus handle. Hence, we require
- * the user to perform a setup ioctl. This setup
- * can only be performed once and defines the
- * type of the handle. The different setup
- * ioctls are locked against each other so they
- * cannot race. Once the handle type is set,
- * the type-dependent ioctls are enabled. To
- * improve performance, we don't lock those via
- * handle->lock. Instead, we issue a
- * write-barrier before performing the
- * type-change, which pairs with smp_rmb() in
- * all handlers that access the type field. This
- * guarantees the handle is fully setup, if
- * handle->type is set. If handle->type is
- * unset, you must not make any assumptions
- * without taking handle->lock.
- * Note that handle->type is only set once. It
- * will never change afterwards.
- */
- smp_wmb();
- handle->type = ret;
- }
- }
- mutex_unlock(&handle->lock);
- break;
-
- case KDBUS_CMD_ENDPOINT_UPDATE:
- case KDBUS_CMD_BYEBYE:
- case KDBUS_CMD_NAME_ACQUIRE:
- case KDBUS_CMD_NAME_RELEASE:
- case KDBUS_CMD_LIST:
- case KDBUS_CMD_CONN_INFO:
- case KDBUS_CMD_BUS_CREATOR_INFO:
- case KDBUS_CMD_UPDATE:
- case KDBUS_CMD_MATCH_ADD:
- case KDBUS_CMD_MATCH_REMOVE:
- case KDBUS_CMD_SEND:
- case KDBUS_CMD_RECV:
- case KDBUS_CMD_FREE: {
- enum kdbus_handle_type type;
-
- /*
- * This read-barrier pairs with smp_wmb() of the handle setup.
- * it guarantees the handle is fully written, in case the
- * type has been set. It allows us to access the handle without
- * taking handle->lock, given the guarantee that the type is
- * only ever set once, and stays constant afterwards.
- * Furthermore, the handle object itself is not modified in any
- * way after the type is set. That is, the type-field is the
- * last field that is written on any handle. If it has not been
- * set, we must not access the handle here.
- */
- type = handle->type;
- smp_rmb();
-
- if (type == KDBUS_HANDLE_EP_OWNER)
- ret = kdbus_handle_ioctl_ep_owner(file, cmd, argp);
- else if (type == KDBUS_HANDLE_CONNECTED)
- ret = kdbus_handle_ioctl_connected(file, cmd, argp);
-
- break;
- }
- default:
- ret = -ENOTTY;
- break;
- }
-
- return ret < 0 ? ret : 0;
-}
-
-static unsigned int kdbus_handle_poll(struct file *file,
- struct poll_table_struct *wait)
-{
- struct kdbus_handle *handle = file->private_data;
- enum kdbus_handle_type type;
- unsigned int mask = POLLOUT | POLLWRNORM;
-
- /*
- * This pairs with smp_wmb() during handle setup. It guarantees that
- * _iff_ the handle type is set, handle->conn is valid. Furthermore,
- * _iff_ the type is set, the handle object is constant and never
- * changed again. If it's not set, we must not access the handle but
- * bail out. We also must assume no setup has taken place, yet.
- */
- type = handle->type;
- smp_rmb();
-
- /* Only a connected endpoint can read/write data */
- if (type != KDBUS_HANDLE_CONNECTED)
- return POLLERR | POLLHUP;
-
- poll_wait(file, &handle->conn->wait, wait);
-
- /*
- * Verify the connection hasn't been deactivated _after_ adding the
- * wait-queue. This guarantees, that if the connection is deactivated
- * after we checked it, the waitqueue is signaled and we're called
- * again.
- */
- if (!kdbus_conn_active(handle->conn))
- return POLLERR | POLLHUP;
-
- if (!list_empty(&handle->conn->queue.msg_list) ||
- atomic_read(&handle->conn->lost_count) > 0)
- mask |= POLLIN | POLLRDNORM;
-
- return mask;
-}
-
-static int kdbus_handle_mmap(struct file *file, struct vm_area_struct *vma)
-{
- struct kdbus_handle *handle = file->private_data;
- enum kdbus_handle_type type;
- int ret = -EBADFD;
-
- /*
- * This pairs with smp_wmb() during handle setup. It guarantees that
- * _iff_ the handle type is set, handle->conn is valid. Furthermore,
- * _iff_ the type is set, the handle object is constant and never
- * changed again. If it's not set, we must not access the handle but
- * bail out. We also must assume no setup has taken place, yet.
- */
- type = handle->type;
- smp_rmb();
-
- /* Only connected handles have a pool we can map */
- if (type == KDBUS_HANDLE_CONNECTED)
- ret = kdbus_pool_mmap(handle->conn->pool, vma);
-
- return ret;
-}
-
-const struct file_operations kdbus_handle_ops = {
- .owner = THIS_MODULE,
- .open = kdbus_handle_open,
- .release = kdbus_handle_release,
- .poll = kdbus_handle_poll,
- .llseek = noop_llseek,
- .unlocked_ioctl = kdbus_handle_ioctl,
- .mmap = kdbus_handle_mmap,
-#ifdef CONFIG_COMPAT
- .compat_ioctl = kdbus_handle_ioctl,
-#endif
-};
diff --git a/ipc/kdbus/handle.h b/ipc/kdbus/handle.h
deleted file mode 100644
index 5dde2c10b..000000000
--- a/ipc/kdbus/handle.h
+++ /dev/null
@@ -1,103 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_HANDLE_H
-#define __KDBUS_HANDLE_H
-
-#include <linux/fs.h>
-#include <uapi/linux/kdbus.h>
-
-extern const struct file_operations kdbus_handle_ops;
-
-/**
- * kdbus_arg - information and state of a single ioctl command item
- * @type: item type
- * @item: set by the parser to the first found item of this type
- * @multiple: whether multiple items of this type are allowed
- * @mandatory: whether at least one item of this type is required
- *
- * This structure describes a single item in an ioctl command payload. The
- * caller has to pre-fill the type and flags, the parser will then use this
- * information to verify the ioctl payload. @item is set by the parser to point
- * to the first occurrence of the item.
- */
-struct kdbus_arg {
- u64 type;
- struct kdbus_item *item;
- bool multiple : 1;
- bool mandatory : 1;
-};
-
-/**
- * kdbus_args - information and state of ioctl command parser
- * @allowed_flags: set of flags this command supports
- * @argc: number of items in @argv
- * @argv: array of items this command supports
- * @user: set by parser to user-space location of current command
- * @cmd: set by parser to kernel copy of command payload
- * @cmd_buf: inline buf to avoid kmalloc() on small cmds
- * @items: points to item array in @cmd
- * @items_size: size of @items in bytes
- * @is_cmd: whether this is a command-payload or msg-payload
- *
- * This structure is used to parse ioctl command payloads on each invocation.
- * The ioctl handler has to pre-fill the flags and allowed items before passing
- * the object to kdbus_args_parse(). The parser will copy the command payload
- * into kernel-space and verify the correctness of the data.
- *
- * We use a 256 bytes buffer for small command payloads, to be allocated on
- * stack on syscall entrance.
- */
-struct kdbus_args {
- u64 allowed_flags;
- size_t argc;
- struct kdbus_arg *argv;
-
- struct kdbus_cmd __user *user;
- struct kdbus_cmd *cmd;
- u8 cmd_buf[256];
-
- struct kdbus_item *items;
- size_t items_size;
- bool is_cmd : 1;
-};
-
-int __kdbus_args_parse(struct kdbus_args *args, bool is_cmd, void __user *argp,
- size_t type_size, size_t items_offset, void **out);
-int kdbus_args_clear(struct kdbus_args *args, int ret);
-
-#define kdbus_args_parse(_args, _argp, _v) \
- ({ \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \
- offsetof(struct kdbus_cmd, size)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \
- offsetof(struct kdbus_cmd, flags)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), return_flags) != \
- offsetof(struct kdbus_cmd, return_flags)); \
- __kdbus_args_parse((_args), 1, (_argp), sizeof(**(_v)), \
- offsetof(typeof(**(_v)), items), \
- (void **)(_v)); \
- })
-
-#define kdbus_args_parse_msg(_args, _argp, _v) \
- ({ \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), size) != \
- offsetof(struct kdbus_cmd, size)); \
- BUILD_BUG_ON(offsetof(typeof(**(_v)), flags) != \
- offsetof(struct kdbus_cmd, flags)); \
- __kdbus_args_parse((_args), 0, (_argp), sizeof(**(_v)), \
- offsetof(typeof(**(_v)), items), \
- (void **)(_v)); \
- })
-
-#endif
diff --git a/ipc/kdbus/item.c b/ipc/kdbus/item.c
deleted file mode 100644
index ce78dba03..000000000
--- a/ipc/kdbus/item.c
+++ /dev/null
@@ -1,293 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/ctype.h>
-#include <linux/fs.h>
-#include <linux/string.h>
-
-#include "item.h"
-#include "limits.h"
-#include "util.h"
-
-/*
- * This verifies the string at position @str with size @size is properly
- * zero-terminated and does not contain a 0-byte but at the end.
- */
-static bool kdbus_str_valid(const char *str, size_t size)
-{
- return size > 0 && memchr(str, '\0', size) == str + size - 1;
-}
-
-/**
- * kdbus_item_validate_name() - validate an item containing a name
- * @item: Item to validate
- *
- * Return: zero on success or an negative error code on failure
- */
-int kdbus_item_validate_name(const struct kdbus_item *item)
-{
- const char *name = item->str;
- unsigned int i;
- size_t len;
-
- if (item->size < KDBUS_ITEM_HEADER_SIZE + 2)
- return -EINVAL;
-
- if (item->size > KDBUS_ITEM_HEADER_SIZE +
- KDBUS_SYSNAME_MAX_LEN + 1)
- return -ENAMETOOLONG;
-
- if (!kdbus_str_valid(name, KDBUS_ITEM_PAYLOAD_SIZE(item)))
- return -EINVAL;
-
- len = strlen(name);
- if (len == 0)
- return -EINVAL;
-
- for (i = 0; i < len; i++) {
- if (isalpha(name[i]))
- continue;
- if (isdigit(name[i]))
- continue;
- if (name[i] == '_')
- continue;
- if (i > 0 && i + 1 < len && (name[i] == '-' || name[i] == '.'))
- continue;
-
- return -EINVAL;
- }
-
- return 0;
-}
-
-/**
- * kdbus_item_validate() - validate a single item
- * @item: item to validate
- *
- * Return: 0 if item is valid, negative error code if not.
- */
-int kdbus_item_validate(const struct kdbus_item *item)
-{
- size_t payload_size = KDBUS_ITEM_PAYLOAD_SIZE(item);
- size_t l;
- int ret;
-
- BUILD_BUG_ON(KDBUS_ITEM_HEADER_SIZE !=
- sizeof(struct kdbus_item_header));
-
- if (item->size < KDBUS_ITEM_HEADER_SIZE)
- return -EINVAL;
-
- switch (item->type) {
- case KDBUS_ITEM_NEGOTIATE:
- if (payload_size % sizeof(u64) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_PAYLOAD_VEC:
- case KDBUS_ITEM_PAYLOAD_OFF:
- if (payload_size != sizeof(struct kdbus_vec))
- return -EINVAL;
- if (item->vec.size == 0 || item->vec.size > SIZE_MAX)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- if (payload_size != sizeof(struct kdbus_memfd))
- return -EINVAL;
- if (item->memfd.size == 0 || item->memfd.size > SIZE_MAX)
- return -EINVAL;
- if (item->memfd.fd < 0)
- return -EBADF;
- break;
-
- case KDBUS_ITEM_FDS:
- if (payload_size % sizeof(int) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CANCEL_FD:
- if (payload_size != sizeof(int))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_PARAMETER:
- if (payload_size != sizeof(struct kdbus_bloom_parameter))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_FILTER:
- /* followed by the bloom-mask, depends on the bloom-size */
- if (payload_size < sizeof(struct kdbus_bloom_filter))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_BLOOM_MASK:
- /* size depends on bloom-size of bus */
- break;
-
- case KDBUS_ITEM_CONN_DESCRIPTION:
- case KDBUS_ITEM_MAKE_NAME:
- ret = kdbus_item_validate_name(item);
- if (ret < 0)
- return ret;
- break;
-
- case KDBUS_ITEM_ATTACH_FLAGS_SEND:
- case KDBUS_ITEM_ATTACH_FLAGS_RECV:
- case KDBUS_ITEM_ID:
- case KDBUS_ITEM_DST_ID:
- if (payload_size != sizeof(u64))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_TIMESTAMP:
- if (payload_size != sizeof(struct kdbus_timestamp))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CREDS:
- if (payload_size != sizeof(struct kdbus_creds))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_AUXGROUPS:
- if (payload_size % sizeof(u32) != 0)
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_NAME:
- case KDBUS_ITEM_DST_NAME:
- case KDBUS_ITEM_PID_COMM:
- case KDBUS_ITEM_TID_COMM:
- case KDBUS_ITEM_EXE:
- case KDBUS_ITEM_CMDLINE:
- case KDBUS_ITEM_CGROUP:
- case KDBUS_ITEM_SECLABEL:
- if (!kdbus_str_valid(item->str, payload_size))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_CAPS:
- if (payload_size < sizeof(u32))
- return -EINVAL;
- if (payload_size < sizeof(u32) +
- 4 * CAP_TO_INDEX(item->caps.last_cap) * sizeof(u32))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_AUDIT:
- if (payload_size != sizeof(struct kdbus_audit))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_POLICY_ACCESS:
- if (payload_size != sizeof(struct kdbus_policy_access))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- if (payload_size < sizeof(struct kdbus_notify_name_change))
- return -EINVAL;
- l = payload_size - offsetof(struct kdbus_notify_name_change,
- name);
- if (l > 0 && !kdbus_str_valid(item->name_change.name, l))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- if (payload_size != sizeof(struct kdbus_notify_id_change))
- return -EINVAL;
- break;
-
- case KDBUS_ITEM_REPLY_TIMEOUT:
- case KDBUS_ITEM_REPLY_DEAD:
- if (payload_size != 0)
- return -EINVAL;
- break;
-
- default:
- break;
- }
-
- return 0;
-}
-
-/**
- * kdbus_items_validate() - validate items passed by user-space
- * @items: items to validate
- * @items_size: number of items
- *
- * This verifies that the passed items pointer is consistent and valid.
- * Furthermore, each item is checked for:
- * - valid "size" value
- * - payload is of expected type
- * - payload is fully included in the item
- * - string payloads are zero-terminated
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_items_validate(const struct kdbus_item *items, size_t items_size)
-{
- const struct kdbus_item *item;
- int ret;
-
- KDBUS_ITEMS_FOREACH(item, items, items_size) {
- if (!KDBUS_ITEM_VALID(item, items, items_size))
- return -EINVAL;
-
- ret = kdbus_item_validate(item);
- if (ret < 0)
- return ret;
- }
-
- if (!KDBUS_ITEMS_END(item, items, items_size))
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * kdbus_item_set() - Set item content
- * @item: The item to modify
- * @type: The item type to set (KDBUS_ITEM_*)
- * @data: Data to copy to item->data, may be %NULL
- * @len: Number of bytes in @data
- *
- * This sets type, size and data fields of an item. If @data is NULL, the data
- * memory is cleared.
- *
- * Note that you must align your @data memory to 8 bytes. Trailing padding (in
- * case @len is not 8byte aligned) is cleared by this call.
- *
- * Returns: Pointer to the following item.
- */
-struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type,
- const void *data, size_t len)
-{
- item->type = type;
- item->size = KDBUS_ITEM_HEADER_SIZE + len;
-
- if (data) {
- memcpy(item->data, data, len);
- memset(item->data + len, 0, KDBUS_ALIGN8(len) - len);
- } else {
- memset(item->data, 0, KDBUS_ALIGN8(len));
- }
-
- return KDBUS_ITEM_NEXT(item);
-}
diff --git a/ipc/kdbus/item.h b/ipc/kdbus/item.h
deleted file mode 100644
index 3a7e6ccc2..000000000
--- a/ipc/kdbus/item.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_ITEM_H
-#define __KDBUS_ITEM_H
-
-#include <linux/kernel.h>
-#include <uapi/linux/kdbus.h>
-
-#include "util.h"
-
-/* generic access and iterators over a stream of items */
-#define KDBUS_ITEM_NEXT(_i) (typeof(_i))((u8 *)(_i) + KDBUS_ALIGN8((_i)->size))
-#define KDBUS_ITEMS_SIZE(_h, _is) ((_h)->size - offsetof(typeof(*(_h)), _is))
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(_s) KDBUS_ALIGN8(KDBUS_ITEM_HEADER_SIZE + (_s))
-#define KDBUS_ITEM_PAYLOAD_SIZE(_i) ((_i)->size - KDBUS_ITEM_HEADER_SIZE)
-
-#define KDBUS_ITEMS_FOREACH(_i, _is, _s) \
- for ((_i) = (_is); \
- ((u8 *)(_i) < (u8 *)(_is) + (_s)) && \
- ((u8 *)(_i) >= (u8 *)(_is)); \
- (_i) = KDBUS_ITEM_NEXT(_i))
-
-#define KDBUS_ITEM_VALID(_i, _is, _s) \
- ((_i)->size >= KDBUS_ITEM_HEADER_SIZE && \
- (u8 *)(_i) + (_i)->size > (u8 *)(_i) && \
- (u8 *)(_i) + (_i)->size <= (u8 *)(_is) + (_s) && \
- (u8 *)(_i) >= (u8 *)(_is))
-
-#define KDBUS_ITEMS_END(_i, _is, _s) \
- ((u8 *)(_i) == ((u8 *)(_is) + KDBUS_ALIGN8(_s)))
-
-/**
- * struct kdbus_item_header - Describes the fix part of an item
- * @size: The total size of the item
- * @type: The item type, one of KDBUS_ITEM_*
- */
-struct kdbus_item_header {
- u64 size;
- u64 type;
-};
-
-int kdbus_item_validate_name(const struct kdbus_item *item);
-int kdbus_item_validate(const struct kdbus_item *item);
-int kdbus_items_validate(const struct kdbus_item *items, size_t items_size);
-struct kdbus_item *kdbus_item_set(struct kdbus_item *item, u64 type,
- const void *data, size_t len);
-
-#endif
diff --git a/ipc/kdbus/limits.h b/ipc/kdbus/limits.h
deleted file mode 100644
index bd47119cd..000000000
--- a/ipc/kdbus/limits.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_DEFAULTS_H
-#define __KDBUS_DEFAULTS_H
-
-#include <linux/kernel.h>
-
-/* maximum size of message header and items */
-#define KDBUS_MSG_MAX_SIZE SZ_8K
-
-/* maximum number of memfd items per message */
-#define KDBUS_MSG_MAX_MEMFD_ITEMS 16
-
-/* max size of ioctl command data */
-#define KDBUS_CMD_MAX_SIZE SZ_32K
-
-/* maximum number of inflight fds in a target queue per user */
-#define KDBUS_CONN_MAX_FDS_PER_USER 16
-
-/* maximum message payload size */
-#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE SZ_2M
-
-/* maximum size of bloom bit field in bytes */
-#define KDBUS_BUS_BLOOM_MAX_SIZE SZ_4K
-
-/* maximum length of well-known bus name */
-#define KDBUS_NAME_MAX_LEN 255
-
-/* maximum length of bus, domain, ep name */
-#define KDBUS_SYSNAME_MAX_LEN 63
-
-/* maximum number of matches per connection */
-#define KDBUS_MATCH_MAX 4096
-
-/* maximum number of queued messages from the same individual user */
-#define KDBUS_CONN_MAX_MSGS 256
-
-/* maximum number of well-known names per connection */
-#define KDBUS_CONN_MAX_NAMES 256
-
-/* maximum number of queued requests waiting for a reply */
-#define KDBUS_CONN_MAX_REQUESTS_PENDING 128
-
-/* maximum number of connections per user in one domain */
-#define KDBUS_USER_MAX_CONN 1024
-
-/* maximum number of buses per user in one domain */
-#define KDBUS_USER_MAX_BUSES 16
-
-#endif
diff --git a/ipc/kdbus/main.c b/ipc/kdbus/main.c
deleted file mode 100644
index c2117ea53..000000000
--- a/ipc/kdbus/main.c
+++ /dev/null
@@ -1,111 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/module.h>
-
-#include "util.h"
-#include "fs.h"
-#include "handle.h"
-#include "metadata.h"
-#include "node.h"
-
-/*
- * This is a simplified outline of the internal kdbus object relations, for
- * those interested in the inner life of the driver implementation.
- *
- * From a mount point's (domain's) perspective:
- *
- * struct kdbus_domain
- * |» struct kdbus_user *user (many, owned)
- * '» struct kdbus_node node (embedded)
- * |» struct kdbus_node children (many, referenced)
- * |» struct kdbus_node *parent (pinned)
- * '» struct kdbus_bus (many, pinned)
- * |» struct kdbus_node node (embedded)
- * '» struct kdbus_ep (many, pinned)
- * |» struct kdbus_node node (embedded)
- * |» struct kdbus_bus *bus (pinned)
- * |» struct kdbus_conn conn_list (many, pinned)
- * | |» struct kdbus_ep *ep (pinned)
- * | |» struct kdbus_name_entry *activator_of (owned)
- * | |» struct kdbus_match_db *match_db (owned)
- * | |» struct kdbus_meta *meta (owned)
- * | |» struct kdbus_match_db *match_db (owned)
- * | | '» struct kdbus_match_entry (many, owned)
- * | |
- * | |» struct kdbus_pool *pool (owned)
- * | | '» struct kdbus_pool_slice *slices (many, owned)
- * | | '» struct kdbus_pool *pool (pinned)
- * | |
- * | |» struct kdbus_user *user (pinned)
- * | `» struct kdbus_queue_entry entries (many, embedded)
- * | |» struct kdbus_pool_slice *slice (pinned)
- * | |» struct kdbus_conn_reply *reply (owned)
- * | '» struct kdbus_user *user (pinned)
- * |
- * '» struct kdbus_user *user (pinned)
- * '» struct kdbus_policy_db policy_db (embedded)
- * |» struct kdbus_policy_db_entry (many, owned)
- * | |» struct kdbus_conn (pinned)
- * | '» struct kdbus_ep (pinned)
- * |
- * '» struct kdbus_policy_db_cache_entry (many, owned)
- * '» struct kdbus_conn (pinned)
- *
- * For the life-time of a file descriptor derived from calling open() on a file
- * inside the mount point:
- *
- * struct kdbus_handle
- * |» struct kdbus_meta *meta (owned)
- * |» struct kdbus_ep *ep (pinned)
- * |» struct kdbus_conn *conn (owned)
- * '» struct kdbus_ep *ep (owned)
- */
-
-static int __init kdbus_init(void)
-{
- int ret;
-
- ret = sysfs_create_mount_point(fs_kobj, KBUILD_MODNAME);
- if (ret)
- return ret;
-
- ret = kdbus_fs_init();
- if (ret < 0) {
- pr_err("cannot register filesystem: %d\n", ret);
- goto exit_dir;
- }
-
- pr_info("initialized\n");
- return 0;
-
-exit_dir:
- sysfs_remove_mount_point(fs_kobj, KBUILD_MODNAME);
- return ret;
-}
-
-static void __exit kdbus_exit(void)
-{
- kdbus_fs_exit();
- sysfs_remove_mount_point(fs_kobj, KBUILD_MODNAME);
- ida_destroy(&kdbus_node_ida);
-}
-
-module_init(kdbus_init);
-module_exit(kdbus_exit);
-MODULE_LICENSE("GPL");
-MODULE_DESCRIPTION("D-Bus, powerful, easy to use interprocess communication");
-MODULE_ALIAS_FS(KBUILD_MODNAME "fs");
diff --git a/ipc/kdbus/match.c b/ipc/kdbus/match.c
deleted file mode 100644
index 4ee6a1f2e..000000000
--- a/ipc/kdbus/match.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/hash.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-
-/**
- * struct kdbus_match_db - message filters
- * @entries_list: List of matches
- * @mdb_rwlock: Match data lock
- * @entries_count: Number of entries in database
- */
-struct kdbus_match_db {
- struct list_head entries_list;
- struct rw_semaphore mdb_rwlock;
- unsigned int entries_count;
-};
-
-/**
- * struct kdbus_match_entry - a match database entry
- * @cookie: User-supplied cookie to lookup the entry
- * @list_entry: The list entry element for the db list
- * @rules_list: The list head for tracking rules of this entry
- */
-struct kdbus_match_entry {
- u64 cookie;
- struct list_head list_entry;
- struct list_head rules_list;
-};
-
-/**
- * struct kdbus_bloom_mask - mask to match against filter
- * @generations: Number of generations carried
- * @data: Array of bloom bit fields
- */
-struct kdbus_bloom_mask {
- u64 generations;
- u64 *data;
-};
-
-/**
- * struct kdbus_match_rule - a rule appended to a match entry
- * @type: An item type to match against
- * @bloom_mask: Bloom mask to match a message's filter against, used
- * with KDBUS_ITEM_BLOOM_MASK
- * @name: Name to match against, used with KDBUS_ITEM_NAME,
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
- * @old_id: ID to match against, used with
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
- * KDBUS_ITEM_ID_REMOVE
- * @new_id: ID to match against, used with
- * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE},
- * KDBUS_ITEM_ID_REMOVE
- * @src_id: ID to match against, used with KDBUS_ITEM_ID
- * @dst_id: Message destination ID, used with KDBUS_ITEM_DST_ID
- * @rules_entry: Entry in the entry's rules list
- */
-struct kdbus_match_rule {
- u64 type;
- union {
- struct kdbus_bloom_mask bloom_mask;
- struct {
- char *name;
- u64 old_id;
- u64 new_id;
- };
- u64 src_id;
- u64 dst_id;
- };
- struct list_head rules_entry;
-};
-
-static void kdbus_match_rule_free(struct kdbus_match_rule *rule)
-{
- if (!rule)
- return;
-
- switch (rule->type) {
- case KDBUS_ITEM_BLOOM_MASK:
- kfree(rule->bloom_mask.data);
- break;
-
- case KDBUS_ITEM_NAME:
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- kfree(rule->name);
- break;
-
- case KDBUS_ITEM_ID:
- case KDBUS_ITEM_DST_ID:
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- break;
-
- default:
- BUG();
- }
-
- list_del(&rule->rules_entry);
- kfree(rule);
-}
-
-static void kdbus_match_entry_free(struct kdbus_match_entry *entry)
-{
- struct kdbus_match_rule *r, *tmp;
-
- if (!entry)
- return;
-
- list_for_each_entry_safe(r, tmp, &entry->rules_list, rules_entry)
- kdbus_match_rule_free(r);
-
- list_del(&entry->list_entry);
- kfree(entry);
-}
-
-/**
- * kdbus_match_db_free() - free match db resources
- * @mdb: The match database
- */
-void kdbus_match_db_free(struct kdbus_match_db *mdb)
-{
- struct kdbus_match_entry *entry, *tmp;
-
- if (!mdb)
- return;
-
- list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
- kdbus_match_entry_free(entry);
-
- kfree(mdb);
-}
-
-/**
- * kdbus_match_db_new() - create a new match database
- *
- * Return: a new kdbus_match_db on success, ERR_PTR on failure.
- */
-struct kdbus_match_db *kdbus_match_db_new(void)
-{
- struct kdbus_match_db *d;
-
- d = kzalloc(sizeof(*d), GFP_KERNEL);
- if (!d)
- return ERR_PTR(-ENOMEM);
-
- init_rwsem(&d->mdb_rwlock);
- INIT_LIST_HEAD(&d->entries_list);
-
- return d;
-}
-
-static bool kdbus_match_bloom(const struct kdbus_bloom_filter *filter,
- const struct kdbus_bloom_mask *mask,
- const struct kdbus_conn *conn)
-{
- size_t n = conn->ep->bus->bloom.size / sizeof(u64);
- const u64 *m;
- size_t i;
-
- /*
- * The message's filter carries a generation identifier, the
- * match's mask possibly carries an array of multiple generations
- * of the mask. Select the mask with the closest match of the
- * filter's generation.
- */
- m = mask->data + (min(filter->generation, mask->generations - 1) * n);
-
- /*
- * The message's filter contains the messages properties,
- * the match's mask contains the properties to look for in the
- * message. Check the mask bit field against the filter bit field,
- * if the message possibly carries the properties the connection
- * has subscribed to.
- */
- for (i = 0; i < n; i++)
- if ((filter->data[i] & m[i]) != m[i])
- return false;
-
- return true;
-}
-
-static bool kdbus_match_rule_conn(const struct kdbus_match_rule *r,
- struct kdbus_conn *c,
- const struct kdbus_staging *s)
-{
- lockdep_assert_held(&c->ep->bus->name_registry->rwlock);
-
- switch (r->type) {
- case KDBUS_ITEM_BLOOM_MASK:
- return kdbus_match_bloom(s->bloom_filter, &r->bloom_mask, c);
- case KDBUS_ITEM_ID:
- return r->src_id == c->id || r->src_id == KDBUS_MATCH_ID_ANY;
- case KDBUS_ITEM_DST_ID:
- return r->dst_id == s->msg->dst_id ||
- r->dst_id == KDBUS_MATCH_ID_ANY;
- case KDBUS_ITEM_NAME:
- return kdbus_conn_has_name(c, r->name);
- default:
- return false;
- }
-}
-
-static bool kdbus_match_rule_kernel(const struct kdbus_match_rule *r,
- const struct kdbus_staging *s)
-{
- struct kdbus_item *n = s->notify;
-
- if (WARN_ON(!n) || n->type != r->type)
- return false;
-
- switch (r->type) {
- case KDBUS_ITEM_ID_ADD:
- return r->new_id == KDBUS_MATCH_ID_ANY ||
- r->new_id == n->id_change.id;
- case KDBUS_ITEM_ID_REMOVE:
- return r->old_id == KDBUS_MATCH_ID_ANY ||
- r->old_id == n->id_change.id;
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_CHANGE:
- case KDBUS_ITEM_NAME_REMOVE:
- return (r->old_id == KDBUS_MATCH_ID_ANY ||
- r->old_id == n->name_change.old_id.id) &&
- (r->new_id == KDBUS_MATCH_ID_ANY ||
- r->new_id == n->name_change.new_id.id) &&
- (!r->name || !strcmp(r->name, n->name_change.name));
- default:
- return false;
- }
-}
-
-static bool kdbus_match_rules(const struct kdbus_match_entry *entry,
- struct kdbus_conn *c,
- const struct kdbus_staging *s)
-{
- struct kdbus_match_rule *r;
-
- list_for_each_entry(r, &entry->rules_list, rules_entry)
- if ((c && !kdbus_match_rule_conn(r, c, s)) ||
- (!c && !kdbus_match_rule_kernel(r, s)))
- return false;
-
- return true;
-}
-
-/**
- * kdbus_match_db_match_msg() - match a msg object agains the database entries
- * @mdb: The match database
- * @conn_src: The connection object originating the message
- * @staging: Staging object containing the message to match against
- *
- * This function will walk through all the database entries previously uploaded
- * with kdbus_match_db_add(). As soon as any of them has an all-satisfied rule
- * set, this function will return true.
- *
- * The caller must hold the registry lock of conn_src->ep->bus, in case conn_src
- * is non-NULL.
- *
- * Return: true if there was a matching database entry, false otherwise.
- */
-bool kdbus_match_db_match_msg(struct kdbus_match_db *mdb,
- struct kdbus_conn *conn_src,
- const struct kdbus_staging *staging)
-{
- struct kdbus_match_entry *entry;
- bool matched = false;
-
- down_read(&mdb->mdb_rwlock);
- list_for_each_entry(entry, &mdb->entries_list, list_entry) {
- matched = kdbus_match_rules(entry, conn_src, staging);
- if (matched)
- break;
- }
- up_read(&mdb->mdb_rwlock);
-
- return matched;
-}
-
-static int kdbus_match_db_remove_unlocked(struct kdbus_match_db *mdb,
- u64 cookie)
-{
- struct kdbus_match_entry *entry, *tmp;
- bool found = false;
-
- list_for_each_entry_safe(entry, tmp, &mdb->entries_list, list_entry)
- if (entry->cookie == cookie) {
- kdbus_match_entry_free(entry);
- --mdb->entries_count;
- found = true;
- }
-
- return found ? 0 : -EBADSLT;
-}
-
-/**
- * kdbus_cmd_match_add() - handle KDBUS_CMD_MATCH_ADD
- * @conn: connection to operate on
- * @argp: command payload
- *
- * One call to this function (or one ioctl(KDBUS_CMD_MATCH_ADD), respectively,
- * adds one new database entry with n rules attached to it. Each rule is
- * described with an kdbus_item, and an entry is considered matching if all
- * its rules are satisfied.
- *
- * The items attached to a kdbus_cmd_match struct have the following mapping:
- *
- * KDBUS_ITEM_BLOOM_MASK: A bloom mask
- * KDBUS_ITEM_NAME: A connection's source name
- * KDBUS_ITEM_ID: A connection ID
- * KDBUS_ITEM_DST_ID: A connection ID
- * KDBUS_ITEM_NAME_ADD:
- * KDBUS_ITEM_NAME_REMOVE:
- * KDBUS_ITEM_NAME_CHANGE: Well-known name changes, carry
- * kdbus_notify_name_change
- * KDBUS_ITEM_ID_ADD:
- * KDBUS_ITEM_ID_REMOVE: Connection ID changes, carry
- * kdbus_notify_id_change
- *
- * For kdbus_notify_{id,name}_change structs, only the ID and name fields
- * are looked at when adding an entry. The flags are unused.
- *
- * Also note that KDBUS_ITEM_BLOOM_MASK, KDBUS_ITEM_NAME, KDBUS_ITEM_ID,
- * and KDBUS_ITEM_DST_ID are used to match messages from userspace, while the
- * others apply to kernel-generated notifications.
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_match_db *mdb = conn->match_db;
- struct kdbus_match_entry *entry = NULL;
- struct kdbus_cmd_match *cmd;
- struct kdbus_item *item;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_BLOOM_MASK, .multiple = true },
- { .type = KDBUS_ITEM_NAME, .multiple = true },
- { .type = KDBUS_ITEM_ID, .multiple = true },
- { .type = KDBUS_ITEM_DST_ID, .multiple = true },
- { .type = KDBUS_ITEM_NAME_ADD, .multiple = true },
- { .type = KDBUS_ITEM_NAME_REMOVE, .multiple = true },
- { .type = KDBUS_ITEM_NAME_CHANGE, .multiple = true },
- { .type = KDBUS_ITEM_ID_ADD, .multiple = true },
- { .type = KDBUS_ITEM_ID_REMOVE, .multiple = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_MATCH_REPLACE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry) {
- ret = -ENOMEM;
- goto exit;
- }
-
- entry->cookie = cmd->cookie;
- INIT_LIST_HEAD(&entry->list_entry);
- INIT_LIST_HEAD(&entry->rules_list);
-
- KDBUS_ITEMS_FOREACH(item, cmd->items, KDBUS_ITEMS_SIZE(cmd, items)) {
- struct kdbus_match_rule *rule;
- size_t size = item->size - offsetof(struct kdbus_item, data);
-
- rule = kzalloc(sizeof(*rule), GFP_KERNEL);
- if (!rule) {
- ret = -ENOMEM;
- goto exit;
- }
-
- rule->type = item->type;
- INIT_LIST_HEAD(&rule->rules_entry);
-
- switch (item->type) {
- case KDBUS_ITEM_BLOOM_MASK: {
- u64 bsize = conn->ep->bus->bloom.size;
- u64 generations;
- u64 remainder;
-
- generations = div64_u64_rem(size, bsize, &remainder);
- if (size < bsize || remainder > 0) {
- ret = -EDOM;
- break;
- }
-
- rule->bloom_mask.data = kmemdup(item->data,
- size, GFP_KERNEL);
- if (!rule->bloom_mask.data) {
- ret = -ENOMEM;
- break;
- }
-
- rule->bloom_mask.generations = generations;
- break;
- }
-
- case KDBUS_ITEM_NAME:
- if (!kdbus_name_is_valid(item->str, false)) {
- ret = -EINVAL;
- break;
- }
-
- rule->name = kstrdup(item->str, GFP_KERNEL);
- if (!rule->name)
- ret = -ENOMEM;
-
- break;
-
- case KDBUS_ITEM_ID:
- rule->src_id = item->id;
- break;
-
- case KDBUS_ITEM_DST_ID:
- rule->dst_id = item->id;
- break;
-
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- rule->old_id = item->name_change.old_id.id;
- rule->new_id = item->name_change.new_id.id;
-
- if (size > sizeof(struct kdbus_notify_name_change)) {
- rule->name = kstrdup(item->name_change.name,
- GFP_KERNEL);
- if (!rule->name)
- ret = -ENOMEM;
- }
-
- break;
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- if (item->type == KDBUS_ITEM_ID_ADD)
- rule->new_id = item->id_change.id;
- else
- rule->old_id = item->id_change.id;
-
- break;
- }
-
- if (ret < 0) {
- kdbus_match_rule_free(rule);
- goto exit;
- }
-
- list_add_tail(&rule->rules_entry, &entry->rules_list);
- }
-
- down_write(&mdb->mdb_rwlock);
-
- /* Remove any entry that has the same cookie as the current one. */
- if (cmd->flags & KDBUS_MATCH_REPLACE)
- kdbus_match_db_remove_unlocked(mdb, entry->cookie);
-
- /*
- * If the above removal caught any entry, there will be room for the
- * new one.
- */
- if (++mdb->entries_count > KDBUS_MATCH_MAX) {
- --mdb->entries_count;
- ret = -EMFILE;
- } else {
- list_add_tail(&entry->list_entry, &mdb->entries_list);
- entry = NULL;
- }
-
- up_write(&mdb->mdb_rwlock);
-
-exit:
- kdbus_match_entry_free(entry);
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_match_remove() - handle KDBUS_CMD_MATCH_REMOVE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd_match *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- down_write(&conn->match_db->mdb_rwlock);
- ret = kdbus_match_db_remove_unlocked(conn->match_db, cmd->cookie);
- up_write(&conn->match_db->mdb_rwlock);
-
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/match.h b/ipc/kdbus/match.h
deleted file mode 100644
index ceb492f8e..000000000
--- a/ipc/kdbus/match.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_MATCH_H
-#define __KDBUS_MATCH_H
-
-struct kdbus_conn;
-struct kdbus_match_db;
-struct kdbus_staging;
-
-struct kdbus_match_db *kdbus_match_db_new(void);
-void kdbus_match_db_free(struct kdbus_match_db *db);
-int kdbus_match_db_add(struct kdbus_conn *conn,
- struct kdbus_cmd_match *cmd);
-int kdbus_match_db_remove(struct kdbus_conn *conn,
- struct kdbus_cmd_match *cmd);
-bool kdbus_match_db_match_msg(struct kdbus_match_db *db,
- struct kdbus_conn *conn_src,
- const struct kdbus_staging *staging);
-
-int kdbus_cmd_match_add(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_match_remove(struct kdbus_conn *conn, void __user *argp);
-
-#endif
diff --git a/ipc/kdbus/message.c b/ipc/kdbus/message.c
deleted file mode 100644
index ae565cd34..000000000
--- a/ipc/kdbus/message.c
+++ /dev/null
@@ -1,1040 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/capability.h>
-#include <linux/cgroup.h>
-#include <linux/cred.h>
-#include <linux/file.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <net/sock.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "match.h"
-#include "message.h"
-#include "names.h"
-#include "policy.h"
-
-static const char * const zeros = "\0\0\0\0\0\0\0";
-
-static struct kdbus_gaps *kdbus_gaps_new(size_t n_memfds, size_t n_fds)
-{
- size_t size_offsets, size_memfds, size_fds, size;
- struct kdbus_gaps *gaps;
-
- size_offsets = n_memfds * sizeof(*gaps->memfd_offsets);
- size_memfds = n_memfds * sizeof(*gaps->memfd_files);
- size_fds = n_fds * sizeof(*gaps->fd_files);
- size = sizeof(*gaps) + size_offsets + size_memfds + size_fds;
-
- gaps = kzalloc(size, GFP_KERNEL);
- if (!gaps)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&gaps->kref);
- gaps->n_memfds = 0; /* we reserve n_memfds, but don't enforce them */
- gaps->memfd_offsets = (void *)(gaps + 1);
- gaps->memfd_files = (void *)((u8 *)gaps->memfd_offsets + size_offsets);
- gaps->n_fds = 0; /* we reserve n_fds, but don't enforce them */
- gaps->fd_files = (void *)((u8 *)gaps->memfd_files + size_memfds);
-
- return gaps;
-}
-
-static void kdbus_gaps_free(struct kref *kref)
-{
- struct kdbus_gaps *gaps = container_of(kref, struct kdbus_gaps, kref);
- size_t i;
-
- for (i = 0; i < gaps->n_fds; ++i)
- if (gaps->fd_files[i])
- fput(gaps->fd_files[i]);
- for (i = 0; i < gaps->n_memfds; ++i)
- if (gaps->memfd_files[i])
- fput(gaps->memfd_files[i]);
-
- kfree(gaps);
-}
-
-/**
- * kdbus_gaps_ref() - gain reference
- * @gaps: gaps object
- *
- * Return: @gaps is returned
- */
-struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps)
-{
- if (gaps)
- kref_get(&gaps->kref);
- return gaps;
-}
-
-/**
- * kdbus_gaps_unref() - drop reference
- * @gaps: gaps object
- *
- * Return: NULL
- */
-struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps)
-{
- if (gaps)
- kref_put(&gaps->kref, kdbus_gaps_free);
- return NULL;
-}
-
-/**
- * kdbus_gaps_install() - install file-descriptors
- * @gaps: gaps object, or NULL
- * @slice: pool slice that contains the message
- * @out_incomplete output variable to note incomplete fds
- *
- * This function installs all file-descriptors of @gaps into the current
- * process and copies the file-descriptor numbers into the target pool slice.
- *
- * If the file-descriptors were only partially installed, then @out_incomplete
- * will be set to true. Otherwise, it's set to false.
- *
- * Return: 0 on success, negative error code on failure
- */
-int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice,
- bool *out_incomplete)
-{
- bool incomplete_fds = false;
- struct kvec kvec;
- size_t i, n_fds;
- int ret, *fds;
-
- if (!gaps) {
- /* nothing to do */
- *out_incomplete = incomplete_fds;
- return 0;
- }
-
- n_fds = gaps->n_fds + gaps->n_memfds;
- if (n_fds < 1) {
- /* nothing to do */
- *out_incomplete = incomplete_fds;
- return 0;
- }
-
- fds = kmalloc_array(n_fds, sizeof(*fds), GFP_TEMPORARY);
- n_fds = 0;
- if (!fds)
- return -ENOMEM;
-
- /* 1) allocate fds and copy them over */
-
- if (gaps->n_fds > 0) {
- for (i = 0; i < gaps->n_fds; ++i) {
- int fd;
-
- fd = get_unused_fd_flags(O_CLOEXEC);
- if (fd < 0)
- incomplete_fds = true;
-
- WARN_ON(!gaps->fd_files[i]);
-
- fds[n_fds++] = fd < 0 ? -1 : fd;
- }
-
- /*
- * The file-descriptor array can only be present once per
- * message. Hence, prepare all fds and then copy them over with
- * a single kvec.
- */
-
- WARN_ON(!gaps->fd_offset);
-
- kvec.iov_base = fds;
- kvec.iov_len = gaps->n_fds * sizeof(*fds);
- ret = kdbus_pool_slice_copy_kvec(slice, gaps->fd_offset,
- &kvec, 1, kvec.iov_len);
- if (ret < 0)
- goto exit;
- }
-
- for (i = 0; i < gaps->n_memfds; ++i) {
- int memfd;
-
- memfd = get_unused_fd_flags(O_CLOEXEC);
- if (memfd < 0) {
- incomplete_fds = true;
- /* memfds are initialized to -1, skip copying it */
- continue;
- }
-
- fds[n_fds++] = memfd;
-
- /*
- * memfds have to be copied individually as they each are put
- * into a separate item. This should not be an issue, though,
- * as usually there is no need to send more than one memfd per
- * message.
- */
-
- WARN_ON(!gaps->memfd_offsets[i]);
- WARN_ON(!gaps->memfd_files[i]);
-
- kvec.iov_base = &memfd;
- kvec.iov_len = sizeof(memfd);
- ret = kdbus_pool_slice_copy_kvec(slice, gaps->memfd_offsets[i],
- &kvec, 1, kvec.iov_len);
- if (ret < 0)
- goto exit;
- }
-
- /* 2) install fds now that everything was successful */
-
- for (i = 0; i < gaps->n_fds; ++i)
- if (fds[i] >= 0)
- fd_install(fds[i], get_file(gaps->fd_files[i]));
- for (i = 0; i < gaps->n_memfds; ++i)
- if (fds[gaps->n_fds + i] >= 0)
- fd_install(fds[gaps->n_fds + i],
- get_file(gaps->memfd_files[i]));
-
- ret = 0;
-
-exit:
- if (ret < 0)
- for (i = 0; i < n_fds; ++i)
- put_unused_fd(fds[i]);
- kfree(fds);
- *out_incomplete = incomplete_fds;
- return ret;
-}
-
-static struct file *kdbus_get_fd(int fd)
-{
- struct file *f, *ret;
- struct inode *inode;
- struct socket *sock;
-
- if (fd < 0)
- return ERR_PTR(-EBADF);
-
- f = fget_raw(fd);
- if (!f)
- return ERR_PTR(-EBADF);
-
- inode = file_inode(f);
- sock = S_ISSOCK(inode->i_mode) ? SOCKET_I(inode) : NULL;
-
- if (f->f_mode & FMODE_PATH)
- ret = f; /* O_PATH is always allowed */
- else if (f->f_op == &kdbus_handle_ops)
- ret = ERR_PTR(-EOPNOTSUPP); /* disallow kdbus-fd over kdbus */
- else if (sock && sock->sk && sock->ops && sock->ops->family == PF_UNIX)
- ret = ERR_PTR(-EOPNOTSUPP); /* disallow UDS over kdbus */
- else
- ret = f; /* all other are allowed */
-
- if (f != ret)
- fput(f);
-
- return ret;
-}
-
-static struct file *kdbus_get_memfd(const struct kdbus_memfd *memfd)
-{
- const int m = F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL;
- struct file *f, *ret;
- int s;
-
- if (memfd->fd < 0)
- return ERR_PTR(-EBADF);
-
- f = fget(memfd->fd);
- if (!f)
- return ERR_PTR(-EBADF);
-
- s = shmem_get_seals(f);
- if (s < 0)
- ret = ERR_PTR(-EMEDIUMTYPE);
- else if ((s & m) != m)
- ret = ERR_PTR(-ETXTBSY);
- else if (memfd->start + memfd->size > (u64)i_size_read(file_inode(f)))
- ret = ERR_PTR(-EFAULT);
- else
- ret = f;
-
- if (f != ret)
- fput(f);
-
- return ret;
-}
-
-static int kdbus_msg_examine(struct kdbus_msg *msg, struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd, size_t *out_n_memfds,
- size_t *out_n_fds, size_t *out_n_parts)
-{
- struct kdbus_item *item, *fds = NULL, *bloom = NULL, *dstname = NULL;
- u64 n_parts, n_memfds, n_fds, vec_size;
-
- /*
- * Step 1:
- * Validate the message and command parameters.
- */
-
- /* KDBUS_PAYLOAD_KERNEL is reserved to kernel messages */
- if (msg->payload_type == KDBUS_PAYLOAD_KERNEL)
- return -EINVAL;
-
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST) {
- /* broadcasts must be marked as signals */
- if (!(msg->flags & KDBUS_MSG_SIGNAL))
- return -EBADMSG;
- /* broadcasts cannot have timeouts */
- if (msg->timeout_ns > 0)
- return -ENOTUNIQ;
- }
-
- if (msg->flags & KDBUS_MSG_EXPECT_REPLY) {
- /* if you expect a reply, you must specify a timeout */
- if (msg->timeout_ns == 0)
- return -EINVAL;
- /* signals cannot have replies */
- if (msg->flags & KDBUS_MSG_SIGNAL)
- return -ENOTUNIQ;
- } else {
- /* must expect reply if sent as synchronous call */
- if (cmd->flags & KDBUS_SEND_SYNC_REPLY)
- return -EINVAL;
- /* cannot mark replies as signal */
- if (msg->cookie_reply && (msg->flags & KDBUS_MSG_SIGNAL))
- return -EINVAL;
- }
-
- /*
- * Step 2:
- * Validate all passed items. While at it, select some statistics that
- * are required to allocate state objects later on.
- *
- * Generic item validation has already been done via
- * kdbus_item_validate(). Furthermore, the number of items is naturally
- * limited by the maximum message size. Hence, only non-generic item
- * checks are performed here (mainly integer overflow tests).
- */
-
- n_parts = 0;
- n_memfds = 0;
- n_fds = 0;
- vec_size = 0;
-
- KDBUS_ITEMS_FOREACH(item, msg->items, KDBUS_ITEMS_SIZE(msg, items)) {
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_VEC: {
- void __force __user *ptr = KDBUS_PTR(item->vec.address);
- u64 size = item->vec.size;
-
- if (vec_size + size < vec_size)
- return -EMSGSIZE;
- if (vec_size + size > KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE)
- return -EMSGSIZE;
- if (ptr && unlikely(!access_ok(VERIFY_READ, ptr, size)))
- return -EFAULT;
-
- if (ptr || size % 8) /* data or padding */
- ++n_parts;
- break;
- }
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- u64 start = item->memfd.start;
- u64 size = item->memfd.size;
-
- if (start + size < start)
- return -EMSGSIZE;
- if (n_memfds >= KDBUS_MSG_MAX_MEMFD_ITEMS)
- return -E2BIG;
-
- ++n_memfds;
- if (size % 8) /* vec-padding required */
- ++n_parts;
- break;
- }
- case KDBUS_ITEM_FDS: {
- if (fds)
- return -EEXIST;
-
- fds = item;
- n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int);
- if (n_fds > KDBUS_CONN_MAX_FDS_PER_USER)
- return -EMFILE;
-
- break;
- }
- case KDBUS_ITEM_BLOOM_FILTER: {
- u64 bloom_size;
-
- if (bloom)
- return -EEXIST;
-
- bloom = item;
- bloom_size = KDBUS_ITEM_PAYLOAD_SIZE(item) -
- offsetof(struct kdbus_bloom_filter, data);
- if (!KDBUS_IS_ALIGNED8(bloom_size))
- return -EFAULT;
- if (bloom_size != bus->bloom.size)
- return -EDOM;
-
- break;
- }
- case KDBUS_ITEM_DST_NAME: {
- if (dstname)
- return -EEXIST;
-
- dstname = item;
- if (!kdbus_name_is_valid(item->str, false))
- return -EINVAL;
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST)
- return -EBADMSG;
-
- break;
- }
- default:
- return -EINVAL;
- }
- }
-
- /*
- * Step 3:
- * Validate that required items were actually passed, and that no item
- * contradicts the message flags.
- */
-
- /* bloom filters must be attached _iff_ it's a signal */
- if (!(msg->flags & KDBUS_MSG_SIGNAL) != !bloom)
- return -EBADMSG;
- /* destination name is required if no ID is given */
- if (msg->dst_id == KDBUS_DST_ID_NAME && !dstname)
- return -EDESTADDRREQ;
- /* cannot send file-descriptors attached to broadcasts */
- if (msg->dst_id == KDBUS_DST_ID_BROADCAST && fds)
- return -ENOTUNIQ;
-
- *out_n_memfds = n_memfds;
- *out_n_fds = n_fds;
- *out_n_parts = n_parts;
-
- return 0;
-}
-
-static bool kdbus_staging_merge_vecs(struct kdbus_staging *staging,
- struct kdbus_item **prev_item,
- struct iovec **prev_vec,
- const struct kdbus_item *merge)
-{
- void __user *ptr = (void __user *)KDBUS_PTR(merge->vec.address);
- u64 padding = merge->vec.size % 8;
- struct kdbus_item *prev = *prev_item;
- struct iovec *vec = *prev_vec;
-
- /* XXX: merging is disabled so far */
- if (0 && prev && prev->type == KDBUS_ITEM_PAYLOAD_OFF &&
- !merge->vec.address == !prev->vec.address) {
- /*
- * If we merge two VECs, we can always drop the second
- * PAYLOAD_VEC item. Hence, include its size in the previous
- * one.
- */
- prev->vec.size += merge->vec.size;
-
- if (ptr) {
- /*
- * If we merge two data VECs, we need two iovecs to copy
- * the data. But the items can be easily merged by
- * summing their lengths.
- */
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = merge->vec.size;
- vec->iov_base = ptr;
- staging->n_payload += vec->iov_len;
- } else if (padding) {
- /*
- * If we merge two 0-vecs with the second 0-vec
- * requiring padding, we need to insert an iovec to copy
- * the 0-padding. We try merging it with the previous
- * 0-padding iovec. This might end up with an
- * iov_len==0, in which case we simply drop the iovec.
- */
- if (vec) {
- staging->n_payload -= vec->iov_len;
- vec->iov_len = prev->vec.size % 8;
- if (!vec->iov_len) {
- --staging->n_parts;
- vec = NULL;
- } else {
- staging->n_payload += vec->iov_len;
- }
- } else {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = padding;
- vec->iov_base = (char __user *)zeros;
- staging->n_payload += vec->iov_len;
- }
- } else {
- /*
- * If we merge two 0-vecs with the second 0-vec having
- * no padding, we know the padding of the first stays
- * the same. Hence, @vec needs no adjustment.
- */
- }
-
- /* successfully merged with previous item */
- merge = prev;
- } else {
- /*
- * If we cannot merge the payload item with the previous one,
- * we simply insert a new iovec for the data/padding.
- */
- if (ptr) {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = merge->vec.size;
- vec->iov_base = ptr;
- staging->n_payload += vec->iov_len;
- } else if (padding) {
- vec = &staging->parts[staging->n_parts++];
- vec->iov_len = padding;
- vec->iov_base = (char __user *)zeros;
- staging->n_payload += vec->iov_len;
- } else {
- vec = NULL;
- }
- }
-
- *prev_item = (struct kdbus_item *)merge;
- *prev_vec = vec;
-
- return merge == prev;
-}
-
-static int kdbus_staging_import(struct kdbus_staging *staging)
-{
- struct kdbus_item *it, *item, *last, *prev_payload;
- struct kdbus_gaps *gaps = staging->gaps;
- struct kdbus_msg *msg = staging->msg;
- struct iovec *part, *prev_part;
- bool drop_item;
-
- drop_item = false;
- last = NULL;
- prev_payload = NULL;
- prev_part = NULL;
-
- /*
- * We modify msg->items along the way; make sure to use @item as offset
- * to the next item (instead of the iterator @it).
- */
- for (it = item = msg->items;
- it >= msg->items &&
- (u8 *)it < (u8 *)msg + msg->size &&
- (u8 *)it + it->size <= (u8 *)msg + msg->size; ) {
- /*
- * If we dropped items along the way, move current item to
- * front. We must not access @it afterwards, but use @item
- * instead!
- */
- if (it != item)
- memmove(item, it, it->size);
- it = (void *)((u8 *)it + KDBUS_ALIGN8(item->size));
-
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_VEC: {
- size_t offset = staging->n_payload;
-
- if (kdbus_staging_merge_vecs(staging, &prev_payload,
- &prev_part, item)) {
- drop_item = true;
- } else if (item->vec.address) {
- /* real offset is patched later on */
- item->type = KDBUS_ITEM_PAYLOAD_OFF;
- item->vec.offset = offset;
- } else {
- item->type = KDBUS_ITEM_PAYLOAD_OFF;
- item->vec.offset = ~0ULL;
- }
-
- break;
- }
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- struct file *f;
-
- f = kdbus_get_memfd(&item->memfd);
- if (IS_ERR(f))
- return PTR_ERR(f);
-
- gaps->memfd_files[gaps->n_memfds] = f;
- gaps->memfd_offsets[gaps->n_memfds] =
- (u8 *)&item->memfd.fd - (u8 *)msg;
- ++gaps->n_memfds;
-
- /* memfds cannot be merged */
- prev_payload = item;
- prev_part = NULL;
-
- /* insert padding to make following VECs aligned */
- if (item->memfd.size % 8) {
- part = &staging->parts[staging->n_parts++];
- part->iov_len = item->memfd.size % 8;
- part->iov_base = (char __user *)zeros;
- staging->n_payload += part->iov_len;
- }
-
- break;
- }
- case KDBUS_ITEM_FDS: {
- size_t i, n_fds;
-
- n_fds = KDBUS_ITEM_PAYLOAD_SIZE(item) / sizeof(int);
- for (i = 0; i < n_fds; ++i) {
- struct file *f;
-
- f = kdbus_get_fd(item->fds[i]);
- if (IS_ERR(f))
- return PTR_ERR(f);
-
- gaps->fd_files[gaps->n_fds++] = f;
- }
-
- gaps->fd_offset = (u8 *)item->fds - (u8 *)msg;
-
- break;
- }
- case KDBUS_ITEM_BLOOM_FILTER:
- staging->bloom_filter = &item->bloom_filter;
- break;
- case KDBUS_ITEM_DST_NAME:
- staging->dst_name = item->str;
- break;
- }
-
- /* drop item if we merged it with a previous one */
- if (drop_item) {
- drop_item = false;
- } else {
- last = item;
- item = KDBUS_ITEM_NEXT(item);
- }
- }
-
- /* adjust message size regarding dropped items */
- msg->size = offsetof(struct kdbus_msg, items);
- if (last)
- msg->size += ((u8 *)last - (u8 *)msg->items) + last->size;
-
- return 0;
-}
-
-static void kdbus_staging_reserve(struct kdbus_staging *staging)
-{
- struct iovec *part;
-
- part = &staging->parts[staging->n_parts++];
- part->iov_base = (void __user *)zeros;
- part->iov_len = 0;
-}
-
-static struct kdbus_staging *kdbus_staging_new(struct kdbus_bus *bus,
- size_t n_parts,
- size_t msg_extra_size)
-{
- const size_t reserved_parts = 5; /* see below for explanation */
- struct kdbus_staging *staging;
- int ret;
-
- n_parts += reserved_parts;
-
- staging = kzalloc(sizeof(*staging) + n_parts * sizeof(*staging->parts) +
- msg_extra_size, GFP_TEMPORARY);
- if (!staging)
- return ERR_PTR(-ENOMEM);
-
- staging->msg_seqnum = atomic64_inc_return(&bus->last_message_id);
- staging->n_parts = 0; /* we reserve n_parts, but don't enforce them */
- staging->parts = (void *)(staging + 1);
-
- if (msg_extra_size) /* if requested, allocate message, too */
- staging->msg = (void *)((u8 *)staging->parts +
- n_parts * sizeof(*staging->parts));
-
- staging->meta_proc = kdbus_meta_proc_new();
- if (IS_ERR(staging->meta_proc)) {
- ret = PTR_ERR(staging->meta_proc);
- staging->meta_proc = NULL;
- goto error;
- }
-
- staging->meta_conn = kdbus_meta_conn_new();
- if (IS_ERR(staging->meta_conn)) {
- ret = PTR_ERR(staging->meta_conn);
- staging->meta_conn = NULL;
- goto error;
- }
-
- /*
- * Prepare iovecs to copy the message into the target pool. We use the
- * following iovecs:
- * * iovec to copy "kdbus_msg.size"
- * * iovec to copy "struct kdbus_msg" (minus size) plus items
- * * iovec for possible padding after the items
- * * iovec for metadata items
- * * iovec for possible padding after the items
- *
- * Make sure to update @reserved_parts if you add more parts here.
- */
-
- kdbus_staging_reserve(staging); /* msg.size */
- kdbus_staging_reserve(staging); /* msg (minus msg.size) plus items */
- kdbus_staging_reserve(staging); /* msg padding */
- kdbus_staging_reserve(staging); /* meta */
- kdbus_staging_reserve(staging); /* meta padding */
-
- return staging;
-
-error:
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
-}
-
-struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus,
- u64 dst, u64 cookie_timeout,
- size_t it_size, size_t it_type)
-{
- struct kdbus_staging *staging;
- size_t size;
-
- size = offsetof(struct kdbus_msg, items) +
- KDBUS_ITEM_HEADER_SIZE + it_size;
-
- staging = kdbus_staging_new(bus, 0, KDBUS_ALIGN8(size));
- if (IS_ERR(staging))
- return ERR_CAST(staging);
-
- staging->msg->size = size;
- staging->msg->flags = (dst == KDBUS_DST_ID_BROADCAST) ?
- KDBUS_MSG_SIGNAL : 0;
- staging->msg->dst_id = dst;
- staging->msg->src_id = KDBUS_SRC_ID_KERNEL;
- staging->msg->payload_type = KDBUS_PAYLOAD_KERNEL;
- staging->msg->cookie_reply = cookie_timeout;
- staging->notify = staging->msg->items;
- staging->notify->size = KDBUS_ITEM_HEADER_SIZE + it_size;
- staging->notify->type = it_type;
-
- return staging;
-}
-
-struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd,
- struct kdbus_msg *msg)
-{
- const size_t reserved_parts = 1; /* see below for explanation */
- size_t n_memfds, n_fds, n_parts;
- struct kdbus_staging *staging;
- int ret;
-
- /*
- * Examine user-supplied message and figure out how many resources we
- * need to allocate in our staging area. This requires us to iterate
- * the message twice, but saves us from re-allocating our resources
- * all the time.
- */
-
- ret = kdbus_msg_examine(msg, bus, cmd, &n_memfds, &n_fds, &n_parts);
- if (ret < 0)
- return ERR_PTR(ret);
-
- n_parts += reserved_parts;
-
- /*
- * Allocate staging area with the number of required resources. Make
- * sure that we have enough iovecs for all required parts pre-allocated
- * so this will hopefully be the only memory allocation for this
- * message transaction.
- */
-
- staging = kdbus_staging_new(bus, n_parts, 0);
- if (IS_ERR(staging))
- return ERR_CAST(staging);
-
- staging->msg = msg;
-
- /*
- * If the message contains memfds or fd items, we need to remember some
- * state so we can fill in the requested information at RECV time.
- * File-descriptors cannot be passed at SEND time. Hence, allocate a
- * gaps-object to remember that state. That gaps object is linked to
- * from the staging area, but will also be linked to from the message
- * queue of each peer. Hence, each receiver owns a reference to it, and
- * it will later be used to fill the 'gaps' in message that couldn't be
- * filled at SEND time.
- * Note that the 'gaps' object is read-only once the staging-allocator
- * returns. There might be connections receiving a queued message while
- * the sender still broadcasts the message to other receivers.
- */
-
- if (n_memfds > 0 || n_fds > 0) {
- staging->gaps = kdbus_gaps_new(n_memfds, n_fds);
- if (IS_ERR(staging->gaps)) {
- ret = PTR_ERR(staging->gaps);
- staging->gaps = NULL;
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
- }
- }
-
- /*
- * kdbus_staging_new() already reserves parts for message setup. For
- * user-supplied messages, we add the following iovecs:
- * ... variable number of iovecs for payload ...
- * * final iovec for possible padding of payload
- *
- * Make sure to update @reserved_parts if you add more parts here.
- */
-
- ret = kdbus_staging_import(staging); /* payload */
- kdbus_staging_reserve(staging); /* payload padding */
-
- if (ret < 0)
- goto error;
-
- return staging;
-
-error:
- kdbus_staging_free(staging);
- return ERR_PTR(ret);
-}
-
-struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging)
-{
- if (!staging)
- return NULL;
-
- kdbus_meta_conn_unref(staging->meta_conn);
- kdbus_meta_proc_unref(staging->meta_proc);
- kdbus_gaps_unref(staging->gaps);
- kfree(staging);
-
- return NULL;
-}
-
-static int kdbus_staging_collect_metadata(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst,
- u64 *out_attach)
-{
- u64 attach;
- int ret;
-
- if (src)
- attach = kdbus_meta_msg_mask(src, dst);
- else
- attach = KDBUS_ATTACH_TIMESTAMP; /* metadata for kernel msgs */
-
- if (src && !src->meta_fake) {
- ret = kdbus_meta_proc_collect(staging->meta_proc, attach);
- if (ret < 0)
- return ret;
- }
-
- ret = kdbus_meta_conn_collect(staging->meta_conn, src,
- staging->msg_seqnum, attach);
- if (ret < 0)
- return ret;
-
- *out_attach = attach;
- return 0;
-}
-
-/**
- * kdbus_staging_emit() - emit linearized message in target pool
- * @staging: staging object to create message from
- * @src: sender of the message (or NULL)
- * @dst: target connection to allocate message for
- *
- * This allocates a pool-slice for @dst and copies the message provided by
- * @staging into it. The new slice is then returned to the caller for further
- * processing. It's not linked into any queue, yet.
- *
- * Return: Newly allocated slice or ERR_PTR on failure.
- */
-struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst)
-{
- struct kdbus_item *item, *meta_items = NULL;
- struct kdbus_pool_slice *slice = NULL;
- size_t off, size, meta_size;
- struct iovec *v;
- u64 attach, msg_size;
- int ret;
-
- /*
- * Step 1:
- * Collect metadata from @src depending on the attach-flags allowed for
- * @dst. Translate it into the namespaces pinned by @dst.
- */
-
- ret = kdbus_staging_collect_metadata(staging, src, dst, &attach);
- if (ret < 0)
- goto error;
-
- ret = kdbus_meta_emit(staging->meta_proc, NULL, staging->meta_conn,
- dst, attach, &meta_items, &meta_size);
- if (ret < 0)
- goto error;
-
- /*
- * Step 2:
- * Setup iovecs for the message. See kdbus_staging_new() for allocation
- * of those iovecs. All reserved iovecs have been initialized with
- * iov_len=0 + iov_base=zeros. Furthermore, the iovecs to copy the
- * actual message payload have already been initialized and need not be
- * touched.
- */
-
- v = staging->parts;
- msg_size = staging->msg->size;
-
- /* msg.size */
- v->iov_len = sizeof(msg_size);
- v->iov_base = (void __user *)&msg_size;
- ++v;
-
- /* msg (after msg.size) plus items */
- v->iov_len = staging->msg->size - sizeof(staging->msg->size);
- v->iov_base = (void __user *)((u8 *)staging->msg +
- sizeof(staging->msg->size));
- ++v;
-
- /* padding after msg */
- v->iov_len = KDBUS_ALIGN8(staging->msg->size) - staging->msg->size;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- if (meta_size > 0) {
- /* metadata items */
- v->iov_len = meta_size;
- v->iov_base = (void __user *)meta_items;
- ++v;
-
- /* padding after metadata */
- v->iov_len = KDBUS_ALIGN8(meta_size) - meta_size;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- msg_size = KDBUS_ALIGN8(msg_size) + meta_size;
- } else {
- /* metadata items */
- v->iov_len = 0;
- v->iov_base = (void __user *)zeros;
- ++v;
-
- /* padding after metadata */
- v->iov_len = 0;
- v->iov_base = (void __user *)zeros;
- ++v;
- }
-
- /* ... payload iovecs are already filled in ... */
-
- /* compute overall size and fill in padding after payload */
- size = KDBUS_ALIGN8(msg_size);
-
- if (staging->n_payload > 0) {
- size += staging->n_payload;
-
- v = &staging->parts[staging->n_parts - 1];
- v->iov_len = KDBUS_ALIGN8(size) - size;
- v->iov_base = (void __user *)zeros;
-
- size = KDBUS_ALIGN8(size);
- }
-
- /*
- * Step 3:
- * The PAYLOAD_OFF items in the message contain a relative 'offset'
- * field that tells the receiver where to find the actual payload. This
- * offset is relative to the start of the message, and as such depends
- * on the size of the metadata items we inserted. This size is variable
- * and changes for each peer we send the message to. Hence, we remember
- * the last relative offset that was used to calculate the 'offset'
- * fields. For each message, we re-calculate it and patch all items, in
- * case it changed.
- */
-
- off = KDBUS_ALIGN8(msg_size);
-
- if (off != staging->i_payload) {
- KDBUS_ITEMS_FOREACH(item, staging->msg->items,
- KDBUS_ITEMS_SIZE(staging->msg, items)) {
- if (item->type != KDBUS_ITEM_PAYLOAD_OFF)
- continue;
-
- item->vec.offset -= staging->i_payload;
- item->vec.offset += off;
- }
-
- staging->i_payload = off;
- }
-
- /*
- * Step 4:
- * Allocate pool slice and copy over all data. Make sure to properly
- * account on user quota.
- */
-
- ret = kdbus_conn_quota_inc(dst, src ? src->user : NULL, size,
- staging->gaps ? staging->gaps->n_fds : 0);
- if (ret < 0)
- goto error;
-
- slice = kdbus_pool_slice_alloc(dst->pool, size, true);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto error;
- }
-
- WARN_ON(kdbus_pool_slice_size(slice) != size);
-
- ret = kdbus_pool_slice_copy_iovec(slice, 0, staging->parts,
- staging->n_parts, size);
- if (ret < 0)
- goto error;
-
- /* all done, return slice to caller */
- goto exit;
-
-error:
- if (slice)
- kdbus_conn_quota_dec(dst, src ? src->user : NULL, size,
- staging->gaps ? staging->gaps->n_fds : 0);
- kdbus_pool_slice_release(slice);
- slice = ERR_PTR(ret);
-exit:
- kfree(meta_items);
- return slice;
-}
diff --git a/ipc/kdbus/message.h b/ipc/kdbus/message.h
deleted file mode 100644
index 298f9c99d..000000000
--- a/ipc/kdbus/message.h
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_MESSAGE_H
-#define __KDBUS_MESSAGE_H
-
-#include <linux/fs.h>
-#include <linux/kref.h>
-#include <uapi/linux/kdbus.h>
-
-struct kdbus_bus;
-struct kdbus_conn;
-struct kdbus_meta_conn;
-struct kdbus_meta_proc;
-struct kdbus_pool_slice;
-
-/**
- * struct kdbus_gaps - gaps in message to be filled later
- * @kref: Reference counter
- * @n_memfd_offs: Number of memfds
- * @memfd_offs: Offsets of kdbus_memfd items in target slice
- * @n_fds: Number of fds
- * @fds: Array of sent fds
- * @fds_offset: Offset of fd-array in target slice
- *
- * The 'gaps' object is used to track data that is needed to fill gaps in a
- * message at RECV time. Usually, we try to compile the whole message at SEND
- * time. This has the advantage, that we don't have to cache any information and
- * can keep the memory consumption small. Furthermore, all copy operations can
- * be combined into a single function call, which speeds up transactions
- * considerably.
- * However, things like file-descriptors can only be fully installed at RECV
- * time. The gaps object tracks this data and pins it until a message is
- * received. The gaps object is shared between all receivers of the same
- * message.
- */
-struct kdbus_gaps {
- struct kref kref;
-
- /* state tracking for KDBUS_ITEM_PAYLOAD_MEMFD entries */
- size_t n_memfds;
- u64 *memfd_offsets;
- struct file **memfd_files;
-
- /* state tracking for KDBUS_ITEM_FDS */
- size_t n_fds;
- struct file **fd_files;
- u64 fd_offset;
-};
-
-struct kdbus_gaps *kdbus_gaps_ref(struct kdbus_gaps *gaps);
-struct kdbus_gaps *kdbus_gaps_unref(struct kdbus_gaps *gaps);
-int kdbus_gaps_install(struct kdbus_gaps *gaps, struct kdbus_pool_slice *slice,
- bool *out_incomplete);
-
-/**
- * struct kdbus_staging - staging area to import messages
- * @msg: User-supplied message
- * @gaps: Gaps-object created during import (or NULL if empty)
- * @msg_seqnum: Message sequence number
- * @notify_entry: Entry into list of kernel-generated notifications
- * @i_payload: Current relative index of start of payload
- * @n_payload: Total number of bytes needed for payload
- * @n_parts: Number of parts
- * @parts: Array of iovecs that make up the whole message
- * @meta_proc: Process metadata of the sender (or NULL if empty)
- * @meta_conn: Connection metadata of the sender (or NULL if empty)
- * @bloom_filter: Pointer to the bloom-item in @msg, or NULL
- * @dst_name: Pointer to the dst-name-item in @msg, or NULL
- * @notify: Pointer to the notification item in @msg, or NULL
- *
- * The kdbus_staging object is a temporary staging area to import user-supplied
- * messages into the kernel. It is only used during SEND and dropped once the
- * message is queued. Any data that cannot be collected during SEND, is
- * collected in a kdbus_gaps object and attached to the message queue.
- */
-struct kdbus_staging {
- struct kdbus_msg *msg;
- struct kdbus_gaps *gaps;
- u64 msg_seqnum;
- struct list_head notify_entry;
-
- /* crafted iovecs to copy the message */
- size_t i_payload;
- size_t n_payload;
- size_t n_parts;
- struct iovec *parts;
-
- /* metadata state */
- struct kdbus_meta_proc *meta_proc;
- struct kdbus_meta_conn *meta_conn;
-
- /* cached pointers into @msg */
- const struct kdbus_bloom_filter *bloom_filter;
- const char *dst_name;
- struct kdbus_item *notify;
-};
-
-struct kdbus_staging *kdbus_staging_new_kernel(struct kdbus_bus *bus,
- u64 dst, u64 cookie_timeout,
- size_t it_size, size_t it_type);
-struct kdbus_staging *kdbus_staging_new_user(struct kdbus_bus *bus,
- struct kdbus_cmd_send *cmd,
- struct kdbus_msg *msg);
-struct kdbus_staging *kdbus_staging_free(struct kdbus_staging *staging);
-struct kdbus_pool_slice *kdbus_staging_emit(struct kdbus_staging *staging,
- struct kdbus_conn *src,
- struct kdbus_conn *dst);
-
-#endif
diff --git a/ipc/kdbus/metadata.c b/ipc/kdbus/metadata.c
deleted file mode 100644
index 71ca475a8..000000000
--- a/ipc/kdbus/metadata.c
+++ /dev/null
@@ -1,1347 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/audit.h>
-#include <linux/capability.h>
-#include <linux/cgroup.h>
-#include <linux/cred.h>
-#include <linux/file.h>
-#include <linux/fs_struct.h>
-#include <linux/init.h>
-#include <linux/kref.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/security.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uidgid.h>
-#include <linux/uio.h>
-#include <linux/user_namespace.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "item.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-
-/**
- * struct kdbus_meta_proc - Process metadata
- * @kref: Reference counting
- * @lock: Object lock
- * @collected: Bitmask of collected items
- * @valid: Bitmask of collected and valid items
- * @cred: Credentials
- * @pid: PID of process
- * @tgid: TGID of process
- * @ppid: PPID of process
- * @tid_comm: TID comm line
- * @pid_comm: PID comm line
- * @exe_path: Executable path
- * @root_path: Root-FS path
- * @cmdline: Command-line
- * @cgroup: Full cgroup path
- * @seclabel: Seclabel
- * @audit_loginuid: Audit login-UID
- * @audit_sessionid: Audit session-ID
- */
-struct kdbus_meta_proc {
- struct kref kref;
- struct mutex lock;
- u64 collected;
- u64 valid;
-
- /* KDBUS_ITEM_CREDS */
- /* KDBUS_ITEM_AUXGROUPS */
- /* KDBUS_ITEM_CAPS */
- const struct cred *cred;
-
- /* KDBUS_ITEM_PIDS */
- struct pid *pid;
- struct pid *tgid;
- struct pid *ppid;
-
- /* KDBUS_ITEM_TID_COMM */
- char tid_comm[TASK_COMM_LEN];
- /* KDBUS_ITEM_PID_COMM */
- char pid_comm[TASK_COMM_LEN];
-
- /* KDBUS_ITEM_EXE */
- struct path exe_path;
- struct path root_path;
-
- /* KDBUS_ITEM_CMDLINE */
- char *cmdline;
-
- /* KDBUS_ITEM_CGROUP */
- char *cgroup;
-
- /* KDBUS_ITEM_SECLABEL */
- char *seclabel;
-
- /* KDBUS_ITEM_AUDIT */
- kuid_t audit_loginuid;
- unsigned int audit_sessionid;
-};
-
-/**
- * struct kdbus_meta_conn
- * @kref: Reference counting
- * @lock: Object lock
- * @collected: Bitmask of collected items
- * @valid: Bitmask of collected and valid items
- * @ts: Timestamp values
- * @owned_names_items: Serialized items for owned names
- * @owned_names_size: Size of @owned_names_items
- * @conn_description: Connection description
- */
-struct kdbus_meta_conn {
- struct kref kref;
- struct mutex lock;
- u64 collected;
- u64 valid;
-
- /* KDBUS_ITEM_TIMESTAMP */
- struct kdbus_timestamp ts;
-
- /* KDBUS_ITEM_OWNED_NAME */
- struct kdbus_item *owned_names_items;
- size_t owned_names_size;
-
- /* KDBUS_ITEM_CONN_DESCRIPTION */
- char *conn_description;
-};
-
-/* fixed size equivalent of "kdbus_caps" */
-struct kdbus_meta_caps {
- u32 last_cap;
- struct {
- u32 caps[_KERNEL_CAPABILITY_U32S];
- } set[4];
-};
-
-/**
- * kdbus_meta_proc_new() - Create process metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_proc *kdbus_meta_proc_new(void)
-{
- struct kdbus_meta_proc *mp;
-
- mp = kzalloc(sizeof(*mp), GFP_KERNEL);
- if (!mp)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&mp->kref);
- mutex_init(&mp->lock);
-
- return mp;
-}
-
-static void kdbus_meta_proc_free(struct kref *kref)
-{
- struct kdbus_meta_proc *mp = container_of(kref, struct kdbus_meta_proc,
- kref);
-
- path_put(&mp->exe_path);
- path_put(&mp->root_path);
- if (mp->cred)
- put_cred(mp->cred);
- put_pid(mp->ppid);
- put_pid(mp->tgid);
- put_pid(mp->pid);
-
- kfree(mp->seclabel);
- kfree(mp->cmdline);
- kfree(mp->cgroup);
- kfree(mp);
-}
-
-/**
- * kdbus_meta_proc_ref() - Gain reference
- * @mp: Process metadata object
- *
- * Return: @mp is returned
- */
-struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp)
-{
- if (mp)
- kref_get(&mp->kref);
- return mp;
-}
-
-/**
- * kdbus_meta_proc_unref() - Drop reference
- * @mp: Process metadata object
- *
- * Return: NULL
- */
-struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp)
-{
- if (mp)
- kref_put(&mp->kref, kdbus_meta_proc_free);
- return NULL;
-}
-
-static void kdbus_meta_proc_collect_pids(struct kdbus_meta_proc *mp)
-{
- struct task_struct *parent;
-
- mp->pid = get_pid(task_pid(current));
- mp->tgid = get_pid(task_tgid(current));
-
- rcu_read_lock();
- parent = rcu_dereference(current->real_parent);
- mp->ppid = get_pid(task_tgid(parent));
- rcu_read_unlock();
-
- mp->valid |= KDBUS_ATTACH_PIDS;
-}
-
-static void kdbus_meta_proc_collect_tid_comm(struct kdbus_meta_proc *mp)
-{
- get_task_comm(mp->tid_comm, current);
- mp->valid |= KDBUS_ATTACH_TID_COMM;
-}
-
-static void kdbus_meta_proc_collect_pid_comm(struct kdbus_meta_proc *mp)
-{
- get_task_comm(mp->pid_comm, current->group_leader);
- mp->valid |= KDBUS_ATTACH_PID_COMM;
-}
-
-static void kdbus_meta_proc_collect_exe(struct kdbus_meta_proc *mp)
-{
- struct file *exe_file;
-
- rcu_read_lock();
- exe_file = rcu_dereference(current->mm->exe_file);
- if (exe_file) {
- mp->exe_path = exe_file->f_path;
- path_get(&mp->exe_path);
- get_fs_root(current->fs, &mp->root_path);
- mp->valid |= KDBUS_ATTACH_EXE;
- }
- rcu_read_unlock();
-}
-
-static int kdbus_meta_proc_collect_cmdline(struct kdbus_meta_proc *mp)
-{
- struct mm_struct *mm = current->mm;
- char *cmdline;
-
- if (!mm->arg_end)
- return 0;
-
- cmdline = strndup_user((const char __user *)mm->arg_start,
- mm->arg_end - mm->arg_start);
- if (IS_ERR(cmdline))
- return PTR_ERR(cmdline);
-
- mp->cmdline = cmdline;
- mp->valid |= KDBUS_ATTACH_CMDLINE;
-
- return 0;
-}
-
-static int kdbus_meta_proc_collect_cgroup(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_CGROUPS
- void *page;
- char *s;
-
- page = (void *)__get_free_page(GFP_TEMPORARY);
- if (!page)
- return -ENOMEM;
-
- s = task_cgroup_path(current, page, PAGE_SIZE);
- if (s) {
- mp->cgroup = kstrdup(s, GFP_KERNEL);
- if (!mp->cgroup) {
- free_page((unsigned long)page);
- return -ENOMEM;
- }
- }
-
- free_page((unsigned long)page);
- mp->valid |= KDBUS_ATTACH_CGROUP;
-#endif
-
- return 0;
-}
-
-static int kdbus_meta_proc_collect_seclabel(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_SECURITY
- char *ctx = NULL;
- u32 sid, len;
- int ret;
-
- security_task_getsecid(current, &sid);
- ret = security_secid_to_secctx(sid, &ctx, &len);
- if (ret < 0) {
- /*
- * EOPNOTSUPP means no security module is active,
- * lets skip adding the seclabel then. This effectively
- * drops the SECLABEL item.
- */
- return (ret == -EOPNOTSUPP) ? 0 : ret;
- }
-
- mp->seclabel = kstrdup(ctx, GFP_KERNEL);
- security_release_secctx(ctx, len);
- if (!mp->seclabel)
- return -ENOMEM;
-
- mp->valid |= KDBUS_ATTACH_SECLABEL;
-#endif
-
- return 0;
-}
-
-static void kdbus_meta_proc_collect_audit(struct kdbus_meta_proc *mp)
-{
-#ifdef CONFIG_AUDITSYSCALL
- mp->audit_loginuid = audit_get_loginuid(current);
- mp->audit_sessionid = audit_get_sessionid(current);
- mp->valid |= KDBUS_ATTACH_AUDIT;
-#endif
-}
-
-/**
- * kdbus_meta_proc_collect() - Collect process metadata
- * @mp: Process metadata object
- * @what: Attach flags to collect
- *
- * This collects process metadata from current and saves it in @mp.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what)
-{
- int ret;
-
- if (!mp || !(what & (KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_EXE |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_AUDIT)))
- return 0;
-
- mutex_lock(&mp->lock);
-
- /* creds, auxgrps and caps share "struct cred" as context */
- {
- const u64 m_cred = KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_CAPS;
-
- if ((what & m_cred) && !(mp->collected & m_cred)) {
- mp->cred = get_current_cred();
- mp->valid |= m_cred;
- mp->collected |= m_cred;
- }
- }
-
- if ((what & KDBUS_ATTACH_PIDS) &&
- !(mp->collected & KDBUS_ATTACH_PIDS)) {
- kdbus_meta_proc_collect_pids(mp);
- mp->collected |= KDBUS_ATTACH_PIDS;
- }
-
- if ((what & KDBUS_ATTACH_TID_COMM) &&
- !(mp->collected & KDBUS_ATTACH_TID_COMM)) {
- kdbus_meta_proc_collect_tid_comm(mp);
- mp->collected |= KDBUS_ATTACH_TID_COMM;
- }
-
- if ((what & KDBUS_ATTACH_PID_COMM) &&
- !(mp->collected & KDBUS_ATTACH_PID_COMM)) {
- kdbus_meta_proc_collect_pid_comm(mp);
- mp->collected |= KDBUS_ATTACH_PID_COMM;
- }
-
- if ((what & KDBUS_ATTACH_EXE) &&
- !(mp->collected & KDBUS_ATTACH_EXE)) {
- kdbus_meta_proc_collect_exe(mp);
- mp->collected |= KDBUS_ATTACH_EXE;
- }
-
- if ((what & KDBUS_ATTACH_CMDLINE) &&
- !(mp->collected & KDBUS_ATTACH_CMDLINE)) {
- ret = kdbus_meta_proc_collect_cmdline(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_CMDLINE;
- }
-
- if ((what & KDBUS_ATTACH_CGROUP) &&
- !(mp->collected & KDBUS_ATTACH_CGROUP)) {
- ret = kdbus_meta_proc_collect_cgroup(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_CGROUP;
- }
-
- if ((what & KDBUS_ATTACH_SECLABEL) &&
- !(mp->collected & KDBUS_ATTACH_SECLABEL)) {
- ret = kdbus_meta_proc_collect_seclabel(mp);
- if (ret < 0)
- goto exit_unlock;
- mp->collected |= KDBUS_ATTACH_SECLABEL;
- }
-
- if ((what & KDBUS_ATTACH_AUDIT) &&
- !(mp->collected & KDBUS_ATTACH_AUDIT)) {
- kdbus_meta_proc_collect_audit(mp);
- mp->collected |= KDBUS_ATTACH_AUDIT;
- }
-
- ret = 0;
-
-exit_unlock:
- mutex_unlock(&mp->lock);
- return ret;
-}
-
-/**
- * kdbus_meta_fake_new() - Create fake metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_fake *kdbus_meta_fake_new(void)
-{
- struct kdbus_meta_fake *mf;
-
- mf = kzalloc(sizeof(*mf), GFP_KERNEL);
- if (!mf)
- return ERR_PTR(-ENOMEM);
-
- return mf;
-}
-
-/**
- * kdbus_meta_fake_free() - Free fake metadata object
- * @mf: Fake metadata object
- *
- * Return: NULL
- */
-struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf)
-{
- if (mf) {
- put_pid(mf->ppid);
- put_pid(mf->tgid);
- put_pid(mf->pid);
- kfree(mf->seclabel);
- kfree(mf);
- }
-
- return NULL;
-}
-
-/**
- * kdbus_meta_fake_collect() - Fill fake metadata from faked credentials
- * @mf: Fake metadata object
- * @creds: Creds to set, may be %NULL
- * @pids: PIDs to set, may be %NULL
- * @seclabel: Seclabel to set, may be %NULL
- *
- * This function takes information stored in @creds, @pids and @seclabel and
- * resolves them to kernel-representations, if possible. This call uses the
- * current task's namespaces to resolve the given information.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel)
-{
- if (mf->valid)
- return -EALREADY;
-
- if (creds) {
- struct user_namespace *ns = current_user_ns();
-
- mf->uid = make_kuid(ns, creds->uid);
- mf->euid = make_kuid(ns, creds->euid);
- mf->suid = make_kuid(ns, creds->suid);
- mf->fsuid = make_kuid(ns, creds->fsuid);
-
- mf->gid = make_kgid(ns, creds->gid);
- mf->egid = make_kgid(ns, creds->egid);
- mf->sgid = make_kgid(ns, creds->sgid);
- mf->fsgid = make_kgid(ns, creds->fsgid);
-
- if ((creds->uid != (uid_t)-1 && !uid_valid(mf->uid)) ||
- (creds->euid != (uid_t)-1 && !uid_valid(mf->euid)) ||
- (creds->suid != (uid_t)-1 && !uid_valid(mf->suid)) ||
- (creds->fsuid != (uid_t)-1 && !uid_valid(mf->fsuid)) ||
- (creds->gid != (gid_t)-1 && !gid_valid(mf->gid)) ||
- (creds->egid != (gid_t)-1 && !gid_valid(mf->egid)) ||
- (creds->sgid != (gid_t)-1 && !gid_valid(mf->sgid)) ||
- (creds->fsgid != (gid_t)-1 && !gid_valid(mf->fsgid)))
- return -EINVAL;
-
- mf->valid |= KDBUS_ATTACH_CREDS;
- }
-
- if (pids) {
- mf->pid = get_pid(find_vpid(pids->tid));
- mf->tgid = get_pid(find_vpid(pids->pid));
- mf->ppid = get_pid(find_vpid(pids->ppid));
-
- if ((pids->tid != 0 && !mf->pid) ||
- (pids->pid != 0 && !mf->tgid) ||
- (pids->ppid != 0 && !mf->ppid)) {
- put_pid(mf->pid);
- put_pid(mf->tgid);
- put_pid(mf->ppid);
- mf->pid = NULL;
- mf->tgid = NULL;
- mf->ppid = NULL;
- return -EINVAL;
- }
-
- mf->valid |= KDBUS_ATTACH_PIDS;
- }
-
- if (seclabel) {
- mf->seclabel = kstrdup(seclabel, GFP_KERNEL);
- if (!mf->seclabel)
- return -ENOMEM;
-
- mf->valid |= KDBUS_ATTACH_SECLABEL;
- }
-
- return 0;
-}
-
-/**
- * kdbus_meta_conn_new() - Create connection metadata object
- *
- * Return: Pointer to new object on success, ERR_PTR on failure.
- */
-struct kdbus_meta_conn *kdbus_meta_conn_new(void)
-{
- struct kdbus_meta_conn *mc;
-
- mc = kzalloc(sizeof(*mc), GFP_KERNEL);
- if (!mc)
- return ERR_PTR(-ENOMEM);
-
- kref_init(&mc->kref);
- mutex_init(&mc->lock);
-
- return mc;
-}
-
-static void kdbus_meta_conn_free(struct kref *kref)
-{
- struct kdbus_meta_conn *mc =
- container_of(kref, struct kdbus_meta_conn, kref);
-
- kfree(mc->conn_description);
- kfree(mc->owned_names_items);
- kfree(mc);
-}
-
-/**
- * kdbus_meta_conn_ref() - Gain reference
- * @mc: Connection metadata object
- */
-struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc)
-{
- if (mc)
- kref_get(&mc->kref);
- return mc;
-}
-
-/**
- * kdbus_meta_conn_unref() - Drop reference
- * @mc: Connection metadata object
- */
-struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc)
-{
- if (mc)
- kref_put(&mc->kref, kdbus_meta_conn_free);
- return NULL;
-}
-
-static void kdbus_meta_conn_collect_timestamp(struct kdbus_meta_conn *mc,
- u64 msg_seqnum)
-{
- mc->ts.monotonic_ns = ktime_get_ns();
- mc->ts.realtime_ns = ktime_get_real_ns();
-
- if (msg_seqnum)
- mc->ts.seqnum = msg_seqnum;
-
- mc->valid |= KDBUS_ATTACH_TIMESTAMP;
-}
-
-static int kdbus_meta_conn_collect_names(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn)
-{
- const struct kdbus_name_owner *owner;
- struct kdbus_item *item;
- size_t slen, size;
-
- lockdep_assert_held(&conn->ep->bus->name_registry->rwlock);
-
- size = 0;
- /* open-code length calculation to avoid final padding */
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (!(owner->flags & KDBUS_NAME_IN_QUEUE))
- size = KDBUS_ALIGN8(size) + KDBUS_ITEM_HEADER_SIZE +
- sizeof(struct kdbus_name) +
- strlen(owner->name->name) + 1;
-
- if (!size)
- return 0;
-
- /* make sure we include zeroed padding for convenience helpers */
- item = kmalloc(KDBUS_ALIGN8(size), GFP_KERNEL);
- if (!item)
- return -ENOMEM;
-
- mc->owned_names_items = item;
- mc->owned_names_size = size;
-
- list_for_each_entry(owner, &conn->names_list, conn_entry) {
- if (owner->flags & KDBUS_NAME_IN_QUEUE)
- continue;
-
- slen = strlen(owner->name->name) + 1;
- kdbus_item_set(item, KDBUS_ITEM_OWNED_NAME, NULL,
- sizeof(struct kdbus_name) + slen);
- item->name.flags = owner->flags;
- memcpy(item->name.name, owner->name->name, slen);
- item = KDBUS_ITEM_NEXT(item);
- }
-
- /* sanity check: the buffer should be completely written now */
- WARN_ON((u8 *)item !=
- (u8 *)mc->owned_names_items + KDBUS_ALIGN8(size));
-
- mc->valid |= KDBUS_ATTACH_NAMES;
- return 0;
-}
-
-static int kdbus_meta_conn_collect_description(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn)
-{
- if (!conn->description)
- return 0;
-
- mc->conn_description = kstrdup(conn->description, GFP_KERNEL);
- if (!mc->conn_description)
- return -ENOMEM;
-
- mc->valid |= KDBUS_ATTACH_CONN_DESCRIPTION;
- return 0;
-}
-
-/**
- * kdbus_meta_conn_collect() - Collect connection metadata
- * @mc: Message metadata object
- * @conn: Connection to collect data from
- * @msg_seqnum: Sequence number of the message to send
- * @what: Attach flags to collect
- *
- * This collects connection metadata from @msg_seqnum and @conn and saves it
- * in @mc.
- *
- * If KDBUS_ATTACH_NAMES is set in @what and @conn is non-NULL, the caller must
- * hold the name-registry read-lock of conn->ep->bus->registry.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 msg_seqnum, u64 what)
-{
- int ret;
-
- if (!mc || !(what & (KDBUS_ATTACH_TIMESTAMP |
- KDBUS_ATTACH_NAMES |
- KDBUS_ATTACH_CONN_DESCRIPTION)))
- return 0;
-
- mutex_lock(&mc->lock);
-
- if (msg_seqnum && (what & KDBUS_ATTACH_TIMESTAMP) &&
- !(mc->collected & KDBUS_ATTACH_TIMESTAMP)) {
- kdbus_meta_conn_collect_timestamp(mc, msg_seqnum);
- mc->collected |= KDBUS_ATTACH_TIMESTAMP;
- }
-
- if (conn && (what & KDBUS_ATTACH_NAMES) &&
- !(mc->collected & KDBUS_ATTACH_NAMES)) {
- ret = kdbus_meta_conn_collect_names(mc, conn);
- if (ret < 0)
- goto exit_unlock;
- mc->collected |= KDBUS_ATTACH_NAMES;
- }
-
- if (conn && (what & KDBUS_ATTACH_CONN_DESCRIPTION) &&
- !(mc->collected & KDBUS_ATTACH_CONN_DESCRIPTION)) {
- ret = kdbus_meta_conn_collect_description(mc, conn);
- if (ret < 0)
- goto exit_unlock;
- mc->collected |= KDBUS_ATTACH_CONN_DESCRIPTION;
- }
-
- ret = 0;
-
-exit_unlock:
- mutex_unlock(&mc->lock);
- return ret;
-}
-
-static void kdbus_meta_export_caps(struct kdbus_meta_caps *out,
- const struct kdbus_meta_proc *mp,
- struct user_namespace *user_ns)
-{
- struct user_namespace *iter;
- const struct cred *cred = mp->cred;
- bool parent = false, owner = false;
- int i;
-
- /*
- * This translates the effective capabilities of 'cred' into the given
- * user-namespace. If the given user-namespace is a child-namespace of
- * the user-namespace of 'cred', the mask can be copied verbatim. If
- * not, the mask is cleared.
- * There's one exception: If 'cred' is the owner of any user-namespace
- * in the path between the given user-namespace and the user-namespace
- * of 'cred', then it has all effective capabilities set. This means,
- * the user who created a user-namespace always has all effective
- * capabilities in any child namespaces. Note that this is based on the
- * uid of the namespace creator, not the task hierarchy.
- */
- for (iter = user_ns; iter; iter = iter->parent) {
- if (iter == cred->user_ns) {
- parent = true;
- break;
- }
-
- if (iter == &init_user_ns)
- break;
-
- if ((iter->parent == cred->user_ns) &&
- uid_eq(iter->owner, cred->euid)) {
- owner = true;
- break;
- }
- }
-
- out->last_cap = CAP_LAST_CAP;
-
- CAP_FOR_EACH_U32(i) {
- if (parent) {
- out->set[0].caps[i] = cred->cap_inheritable.cap[i];
- out->set[1].caps[i] = cred->cap_permitted.cap[i];
- out->set[2].caps[i] = cred->cap_effective.cap[i];
- out->set[3].caps[i] = cred->cap_bset.cap[i];
- } else if (owner) {
- out->set[0].caps[i] = 0U;
- out->set[1].caps[i] = ~0U;
- out->set[2].caps[i] = ~0U;
- out->set[3].caps[i] = ~0U;
- } else {
- out->set[0].caps[i] = 0U;
- out->set[1].caps[i] = 0U;
- out->set[2].caps[i] = 0U;
- out->set[3].caps[i] = 0U;
- }
- }
-
- /* clear unused bits */
- for (i = 0; i < 4; i++)
- out->set[i].caps[CAP_TO_INDEX(CAP_LAST_CAP)] &=
- CAP_LAST_U32_VALID_MASK;
-}
-
-/* This is equivalent to from_kuid_munged(), but maps INVALID_UID to itself */
-static uid_t kdbus_from_kuid_keep(struct user_namespace *ns, kuid_t uid)
-{
- return uid_valid(uid) ? from_kuid_munged(ns, uid) : ((uid_t)-1);
-}
-
-/* This is equivalent to from_kgid_munged(), but maps INVALID_GID to itself */
-static gid_t kdbus_from_kgid_keep(struct user_namespace *ns, kgid_t gid)
-{
- return gid_valid(gid) ? from_kgid_munged(ns, gid) : ((gid_t)-1);
-}
-
-struct kdbus_meta_staging {
- const struct kdbus_meta_proc *mp;
- const struct kdbus_meta_fake *mf;
- const struct kdbus_meta_conn *mc;
- const struct kdbus_conn *conn;
- u64 mask;
-
- void *exe;
- const char *exe_path;
-};
-
-static size_t kdbus_meta_measure(struct kdbus_meta_staging *staging)
-{
- const struct kdbus_meta_proc *mp = staging->mp;
- const struct kdbus_meta_fake *mf = staging->mf;
- const struct kdbus_meta_conn *mc = staging->mc;
- const u64 mask = staging->mask;
- size_t size = 0;
-
- /* process metadata */
-
- if (mf && (mask & KDBUS_ATTACH_CREDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
- else if (mp && (mask & KDBUS_ATTACH_CREDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_creds));
-
- if (mf && (mask & KDBUS_ATTACH_PIDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids));
- else if (mp && (mask & KDBUS_ATTACH_PIDS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_pids));
-
- if (mp && (mask & KDBUS_ATTACH_AUXGROUPS))
- size += KDBUS_ITEM_SIZE(mp->cred->group_info->ngroups *
- sizeof(u64));
-
- if (mp && (mask & KDBUS_ATTACH_TID_COMM))
- size += KDBUS_ITEM_SIZE(strlen(mp->tid_comm) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_PID_COMM))
- size += KDBUS_ITEM_SIZE(strlen(mp->pid_comm) + 1);
-
- if (staging->exe_path && (mask & KDBUS_ATTACH_EXE))
- size += KDBUS_ITEM_SIZE(strlen(staging->exe_path) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CMDLINE))
- size += KDBUS_ITEM_SIZE(strlen(mp->cmdline) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CGROUP))
- size += KDBUS_ITEM_SIZE(strlen(mp->cgroup) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_CAPS))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_meta_caps));
-
- if (mf && (mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mf->seclabel) + 1);
- else if (mp && (mask & KDBUS_ATTACH_SECLABEL))
- size += KDBUS_ITEM_SIZE(strlen(mp->seclabel) + 1);
-
- if (mp && (mask & KDBUS_ATTACH_AUDIT))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_audit));
-
- /* connection metadata */
-
- if (mc && (mask & KDBUS_ATTACH_NAMES))
- size += KDBUS_ALIGN8(mc->owned_names_size);
-
- if (mc && (mask & KDBUS_ATTACH_CONN_DESCRIPTION))
- size += KDBUS_ITEM_SIZE(strlen(mc->conn_description) + 1);
-
- if (mc && (mask & KDBUS_ATTACH_TIMESTAMP))
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_timestamp));
-
- return size;
-}
-
-static struct kdbus_item *kdbus_write_head(struct kdbus_item **iter,
- u64 type, u64 size)
-{
- struct kdbus_item *item = *iter;
- size_t padding;
-
- item->type = type;
- item->size = KDBUS_ITEM_HEADER_SIZE + size;
-
- /* clear padding */
- padding = KDBUS_ALIGN8(item->size) - item->size;
- if (padding)
- memset(item->data + size, 0, padding);
-
- *iter = KDBUS_ITEM_NEXT(item);
- return item;
-}
-
-static struct kdbus_item *kdbus_write_full(struct kdbus_item **iter,
- u64 type, u64 size, const void *data)
-{
- struct kdbus_item *item;
-
- item = kdbus_write_head(iter, type, size);
- memcpy(item->data, data, size);
- return item;
-}
-
-static size_t kdbus_meta_write(struct kdbus_meta_staging *staging, void *mem,
- size_t size)
-{
- struct user_namespace *user_ns = staging->conn->cred->user_ns;
- struct pid_namespace *pid_ns = ns_of_pid(staging->conn->pid);
- struct kdbus_item *item = NULL, *items = mem;
- u8 *end, *owned_names_end = NULL;
-
- /* process metadata */
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_CREDS)) {
- const struct kdbus_meta_fake *mf = staging->mf;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_CREDS,
- sizeof(struct kdbus_creds));
- item->creds = (struct kdbus_creds){
- .uid = kdbus_from_kuid_keep(user_ns, mf->uid),
- .euid = kdbus_from_kuid_keep(user_ns, mf->euid),
- .suid = kdbus_from_kuid_keep(user_ns, mf->suid),
- .fsuid = kdbus_from_kuid_keep(user_ns, mf->fsuid),
- .gid = kdbus_from_kgid_keep(user_ns, mf->gid),
- .egid = kdbus_from_kgid_keep(user_ns, mf->egid),
- .sgid = kdbus_from_kgid_keep(user_ns, mf->sgid),
- .fsgid = kdbus_from_kgid_keep(user_ns, mf->fsgid),
- };
- } else if (staging->mp && (staging->mask & KDBUS_ATTACH_CREDS)) {
- const struct cred *c = staging->mp->cred;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_CREDS,
- sizeof(struct kdbus_creds));
- item->creds = (struct kdbus_creds){
- .uid = kdbus_from_kuid_keep(user_ns, c->uid),
- .euid = kdbus_from_kuid_keep(user_ns, c->euid),
- .suid = kdbus_from_kuid_keep(user_ns, c->suid),
- .fsuid = kdbus_from_kuid_keep(user_ns, c->fsuid),
- .gid = kdbus_from_kgid_keep(user_ns, c->gid),
- .egid = kdbus_from_kgid_keep(user_ns, c->egid),
- .sgid = kdbus_from_kgid_keep(user_ns, c->sgid),
- .fsgid = kdbus_from_kgid_keep(user_ns, c->fsgid),
- };
- }
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_PIDS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_PIDS,
- sizeof(struct kdbus_pids));
- item->pids = (struct kdbus_pids){
- .pid = pid_nr_ns(staging->mf->tgid, pid_ns),
- .tid = pid_nr_ns(staging->mf->pid, pid_ns),
- .ppid = pid_nr_ns(staging->mf->ppid, pid_ns),
- };
- } else if (staging->mp && (staging->mask & KDBUS_ATTACH_PIDS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_PIDS,
- sizeof(struct kdbus_pids));
- item->pids = (struct kdbus_pids){
- .pid = pid_nr_ns(staging->mp->tgid, pid_ns),
- .tid = pid_nr_ns(staging->mp->pid, pid_ns),
- .ppid = pid_nr_ns(staging->mp->ppid, pid_ns),
- };
- }
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_AUXGROUPS)) {
- const struct group_info *info = staging->mp->cred->group_info;
- size_t i;
-
- item = kdbus_write_head(&items, KDBUS_ITEM_AUXGROUPS,
- info->ngroups * sizeof(u64));
- for (i = 0; i < info->ngroups; ++i)
- item->data64[i] = from_kgid_munged(user_ns,
- GROUP_AT(info, i));
- }
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_TID_COMM))
- item = kdbus_write_full(&items, KDBUS_ITEM_TID_COMM,
- strlen(staging->mp->tid_comm) + 1,
- staging->mp->tid_comm);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_PID_COMM))
- item = kdbus_write_full(&items, KDBUS_ITEM_PID_COMM,
- strlen(staging->mp->pid_comm) + 1,
- staging->mp->pid_comm);
-
- if (staging->exe_path && (staging->mask & KDBUS_ATTACH_EXE))
- item = kdbus_write_full(&items, KDBUS_ITEM_EXE,
- strlen(staging->exe_path) + 1,
- staging->exe_path);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CMDLINE))
- item = kdbus_write_full(&items, KDBUS_ITEM_CMDLINE,
- strlen(staging->mp->cmdline) + 1,
- staging->mp->cmdline);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CGROUP))
- item = kdbus_write_full(&items, KDBUS_ITEM_CGROUP,
- strlen(staging->mp->cgroup) + 1,
- staging->mp->cgroup);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_CAPS)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_CAPS,
- sizeof(struct kdbus_meta_caps));
- kdbus_meta_export_caps((void*)&item->caps, staging->mp,
- user_ns);
- }
-
- if (staging->mf && (staging->mask & KDBUS_ATTACH_SECLABEL))
- item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
- strlen(staging->mf->seclabel) + 1,
- staging->mf->seclabel);
- else if (staging->mp && (staging->mask & KDBUS_ATTACH_SECLABEL))
- item = kdbus_write_full(&items, KDBUS_ITEM_SECLABEL,
- strlen(staging->mp->seclabel) + 1,
- staging->mp->seclabel);
-
- if (staging->mp && (staging->mask & KDBUS_ATTACH_AUDIT)) {
- item = kdbus_write_head(&items, KDBUS_ITEM_AUDIT,
- sizeof(struct kdbus_audit));
- item->audit = (struct kdbus_audit){
- .loginuid = from_kuid(user_ns,
- staging->mp->audit_loginuid),
- .sessionid = staging->mp->audit_sessionid,
- };
- }
-
- /* connection metadata */
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_NAMES)) {
- memcpy(items, staging->mc->owned_names_items,
- KDBUS_ALIGN8(staging->mc->owned_names_size));
- owned_names_end = (u8 *)items + staging->mc->owned_names_size;
- items = (void *)KDBUS_ALIGN8((unsigned long)owned_names_end);
- }
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_CONN_DESCRIPTION))
- item = kdbus_write_full(&items, KDBUS_ITEM_CONN_DESCRIPTION,
- strlen(staging->mc->conn_description) + 1,
- staging->mc->conn_description);
-
- if (staging->mc && (staging->mask & KDBUS_ATTACH_TIMESTAMP))
- item = kdbus_write_full(&items, KDBUS_ITEM_TIMESTAMP,
- sizeof(staging->mc->ts),
- &staging->mc->ts);
-
- /*
- * Return real size (minus trailing padding). In case of 'owned_names'
- * we cannot deduce it from item->size, so treat it special.
- */
-
- if (items == (void *)KDBUS_ALIGN8((unsigned long)owned_names_end))
- end = owned_names_end;
- else if (item)
- end = (u8 *)item + item->size;
- else
- end = mem;
-
- WARN_ON((u8 *)items - (u8 *)mem != size);
- WARN_ON((void *)KDBUS_ALIGN8((unsigned long)end) != (void *)items);
-
- return end - (u8 *)mem;
-}
-
-int kdbus_meta_emit(struct kdbus_meta_proc *mp,
- struct kdbus_meta_fake *mf,
- struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 mask,
- struct kdbus_item **out_items,
- size_t *out_size)
-{
- struct kdbus_meta_staging staging = {};
- struct kdbus_item *items = NULL;
- size_t size = 0;
- int ret;
-
- if (WARN_ON(mf && mp))
- mp = NULL;
-
- staging.mp = mp;
- staging.mf = mf;
- staging.mc = mc;
- staging.conn = conn;
-
- /* get mask of valid items */
- if (mf)
- staging.mask |= mf->valid;
- if (mp) {
- mutex_lock(&mp->lock);
- staging.mask |= mp->valid;
- mutex_unlock(&mp->lock);
- }
- if (mc) {
- mutex_lock(&mc->lock);
- staging.mask |= mc->valid;
- mutex_unlock(&mc->lock);
- }
-
- staging.mask &= mask;
-
- if (!staging.mask) { /* bail out if nothing to do */
- ret = 0;
- goto exit;
- }
-
- /* EXE is special as it needs a temporary page to assemble */
- if (mp && (staging.mask & KDBUS_ATTACH_EXE)) {
- struct path p;
-
- /*
- * XXX: We need access to __d_path() so we can write the path
- * relative to conn->root_path. Once upstream, we need
- * EXPORT_SYMBOL(__d_path) or an equivalent of d_path() that
- * takes the root path directly. Until then, we drop this item
- * if the root-paths differ.
- */
-
- get_fs_root(current->fs, &p);
- if (path_equal(&p, &conn->root_path)) {
- staging.exe = (void *)__get_free_page(GFP_TEMPORARY);
- if (!staging.exe) {
- path_put(&p);
- ret = -ENOMEM;
- goto exit;
- }
-
- staging.exe_path = d_path(&mp->exe_path, staging.exe,
- PAGE_SIZE);
- if (IS_ERR(staging.exe_path)) {
- path_put(&p);
- ret = PTR_ERR(staging.exe_path);
- goto exit;
- }
- }
- path_put(&p);
- }
-
- size = kdbus_meta_measure(&staging);
- if (!size) { /* bail out if nothing to do */
- ret = 0;
- goto exit;
- }
-
- items = kmalloc(size, GFP_KERNEL);
- if (!items) {
- ret = -ENOMEM;
- goto exit;
- }
-
- size = kdbus_meta_write(&staging, items, size);
- if (!size) {
- kfree(items);
- items = NULL;
- }
-
- ret = 0;
-
-exit:
- if (staging.exe)
- free_page((unsigned long)staging.exe);
- if (ret >= 0) {
- *out_items = items;
- *out_size = size;
- }
- return ret;
-}
-
-enum {
- KDBUS_META_PROC_NONE,
- KDBUS_META_PROC_NORMAL,
-};
-
-/**
- * kdbus_proc_permission() - check /proc permissions on target pid
- * @pid_ns: namespace we operate in
- * @cred: credentials of requestor
- * @target: target process
- *
- * This checks whether a process with credentials @cred can access information
- * of @target in the namespace @pid_ns. This tries to follow /proc permissions,
- * but is slightly more restrictive.
- *
- * Return: The /proc access level (KDBUS_META_PROC_*) is returned.
- */
-static unsigned int kdbus_proc_permission(const struct pid_namespace *pid_ns,
- const struct cred *cred,
- struct pid *target)
-{
- if (pid_ns->hide_pid < 1)
- return KDBUS_META_PROC_NORMAL;
-
- /* XXX: we need groups_search() exported for aux-groups */
- if (gid_eq(cred->egid, pid_ns->pid_gid))
- return KDBUS_META_PROC_NORMAL;
-
- /*
- * XXX: If ptrace_may_access(PTRACE_MODE_READ) is granted, you can
- * overwrite hide_pid. However, ptrace_may_access() only supports
- * checking 'current', hence, we cannot use this here. But we
- * simply decide to not support this override, so no need to worry.
- */
-
- return KDBUS_META_PROC_NONE;
-}
-
-/**
- * kdbus_meta_proc_mask() - calculate which metadata would be visible to
- * a connection via /proc
- * @prv_pid: pid of metadata provider
- * @req_pid: pid of metadata requestor
- * @req_cred: credentials of metadata reqeuestor
- * @wanted: metadata that is requested
- *
- * This checks which metadata items of @prv_pid can be read via /proc by the
- * requestor @req_pid.
- *
- * Return: Set of metadata flags the requestor can see (limited by @wanted).
- */
-static u64 kdbus_meta_proc_mask(struct pid *prv_pid,
- struct pid *req_pid,
- const struct cred *req_cred,
- u64 wanted)
-{
- struct pid_namespace *prv_ns, *req_ns;
- unsigned int proc;
-
- prv_ns = ns_of_pid(prv_pid);
- req_ns = ns_of_pid(req_pid);
-
- /*
- * If the sender is not visible in the receiver namespace, then the
- * receiver cannot access the sender via its own procfs. Hence, we do
- * not attach any additional metadata.
- */
- if (!pid_nr_ns(prv_pid, req_ns))
- return 0;
-
- /*
- * If the pid-namespace of the receiver has hide_pid set, it cannot see
- * any process but its own. We shortcut this /proc permission check if
- * provider and requestor are the same. If not, we perform rather
- * expensive /proc permission checks.
- */
- if (prv_pid == req_pid)
- proc = KDBUS_META_PROC_NORMAL;
- else
- proc = kdbus_proc_permission(req_ns, req_cred, prv_pid);
-
- /* you need /proc access to read standard process attributes */
- if (proc < KDBUS_META_PROC_NORMAL)
- wanted &= ~(KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_AUDIT |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_EXE);
-
- /* clear all non-/proc flags */
- return wanted & (KDBUS_ATTACH_TID_COMM |
- KDBUS_ATTACH_PID_COMM |
- KDBUS_ATTACH_SECLABEL |
- KDBUS_ATTACH_CMDLINE |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_AUDIT |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_EXE);
-}
-
-/**
- * kdbus_meta_get_mask() - calculate attach flags mask for metadata request
- * @prv_pid: pid of metadata provider
- * @prv_mask: mask of metadata the provide grants unchecked
- * @req_pid: pid of metadata requestor
- * @req_cred: credentials of metadata requestor
- * @req_mask: mask of metadata that is requested
- *
- * This calculates the metadata items that the requestor @req_pid can access
- * from the metadata provider @prv_pid. This permission check consists of
- * several different parts:
- * - Providers can grant metadata items unchecked. Regardless of their type,
- * they're always granted to the requestor. This mask is passed as @prv_mask.
- * - Basic items (credentials and connection metadata) are granted implicitly
- * to everyone. They're publicly available to any bus-user that can see the
- * provider.
- * - Process credentials that are not granted implicitly follow the same
- * permission checks as /proc. This means, we always assume a requestor
- * process has access to their *own* /proc mount, if they have access to
- * kdbusfs.
- *
- * Return: Mask of metadata that is granted.
- */
-static u64 kdbus_meta_get_mask(struct pid *prv_pid, u64 prv_mask,
- struct pid *req_pid,
- const struct cred *req_cred, u64 req_mask)
-{
- u64 missing, impl_mask, proc_mask = 0;
-
- /*
- * Connection metadata and basic unix process credentials are
- * transmitted implicitly, and cannot be suppressed. Both are required
- * to perform user-space policies on the receiver-side. Furthermore,
- * connection metadata is public state, anyway, and unix credentials
- * are needed for UDS-compatibility. We extend them slightly by
- * auxiliary groups and additional uids/gids/pids.
- */
- impl_mask = /* connection metadata */
- KDBUS_ATTACH_CONN_DESCRIPTION |
- KDBUS_ATTACH_TIMESTAMP |
- KDBUS_ATTACH_NAMES |
- /* credentials and pids */
- KDBUS_ATTACH_AUXGROUPS |
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS;
-
- /*
- * Calculate the set of metadata that is not granted implicitly nor by
- * the sender, but still requested by the receiver. If any are left,
- * perform rather expensive /proc access checks for them.
- */
- missing = req_mask & ~((prv_mask | impl_mask) & req_mask);
- if (missing)
- proc_mask = kdbus_meta_proc_mask(prv_pid, req_pid, req_cred,
- missing);
-
- return (prv_mask | impl_mask | proc_mask) & req_mask;
-}
-
-/**
- */
-u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask)
-{
- return kdbus_meta_get_mask(conn->pid,
- atomic64_read(&conn->attach_flags_send),
- task_pid(current),
- current_cred(),
- mask);
-}
-
-/**
- */
-u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd,
- const struct kdbus_conn *rcv)
-{
- return kdbus_meta_get_mask(task_pid(current),
- atomic64_read(&snd->attach_flags_send),
- rcv->pid,
- rcv->cred,
- atomic64_read(&rcv->attach_flags_recv));
-}
diff --git a/ipc/kdbus/metadata.h b/ipc/kdbus/metadata.h
deleted file mode 100644
index dba7cc7fd..000000000
--- a/ipc/kdbus/metadata.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_METADATA_H
-#define __KDBUS_METADATA_H
-
-#include <linux/kernel.h>
-
-struct kdbus_conn;
-struct kdbus_pool_slice;
-
-struct kdbus_meta_proc;
-struct kdbus_meta_conn;
-
-/**
- * struct kdbus_meta_fake - Fake metadata
- * @valid: Bitmask of collected and valid items
- * @uid: UID of process
- * @euid: EUID of process
- * @suid: SUID of process
- * @fsuid: FSUID of process
- * @gid: GID of process
- * @egid: EGID of process
- * @sgid: SGID of process
- * @fsgid: FSGID of process
- * @pid: PID of process
- * @tgid: TGID of process
- * @ppid: PPID of process
- * @seclabel: Seclabel
- */
-struct kdbus_meta_fake {
- u64 valid;
-
- /* KDBUS_ITEM_CREDS */
- kuid_t uid, euid, suid, fsuid;
- kgid_t gid, egid, sgid, fsgid;
-
- /* KDBUS_ITEM_PIDS */
- struct pid *pid, *tgid, *ppid;
-
- /* KDBUS_ITEM_SECLABEL */
- char *seclabel;
-};
-
-struct kdbus_meta_proc *kdbus_meta_proc_new(void);
-struct kdbus_meta_proc *kdbus_meta_proc_ref(struct kdbus_meta_proc *mp);
-struct kdbus_meta_proc *kdbus_meta_proc_unref(struct kdbus_meta_proc *mp);
-int kdbus_meta_proc_collect(struct kdbus_meta_proc *mp, u64 what);
-
-struct kdbus_meta_fake *kdbus_meta_fake_new(void);
-struct kdbus_meta_fake *kdbus_meta_fake_free(struct kdbus_meta_fake *mf);
-int kdbus_meta_fake_collect(struct kdbus_meta_fake *mf,
- const struct kdbus_creds *creds,
- const struct kdbus_pids *pids,
- const char *seclabel);
-
-struct kdbus_meta_conn *kdbus_meta_conn_new(void);
-struct kdbus_meta_conn *kdbus_meta_conn_ref(struct kdbus_meta_conn *mc);
-struct kdbus_meta_conn *kdbus_meta_conn_unref(struct kdbus_meta_conn *mc);
-int kdbus_meta_conn_collect(struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 msg_seqnum, u64 what);
-
-int kdbus_meta_emit(struct kdbus_meta_proc *mp,
- struct kdbus_meta_fake *mf,
- struct kdbus_meta_conn *mc,
- struct kdbus_conn *conn,
- u64 mask,
- struct kdbus_item **out_items,
- size_t *out_size);
-u64 kdbus_meta_info_mask(const struct kdbus_conn *conn, u64 mask);
-u64 kdbus_meta_msg_mask(const struct kdbus_conn *snd,
- const struct kdbus_conn *rcv);
-
-#endif
diff --git a/ipc/kdbus/names.c b/ipc/kdbus/names.c
deleted file mode 100644
index bf44ca3f1..000000000
--- a/ipc/kdbus/names.c
+++ /dev/null
@@ -1,854 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/ctype.h>
-#include <linux/fs.h>
-#include <linux/hash.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "handle.h"
-#include "item.h"
-#include "names.h"
-#include "notify.h"
-#include "policy.h"
-
-#define KDBUS_NAME_SAVED_MASK (KDBUS_NAME_ALLOW_REPLACEMENT | \
- KDBUS_NAME_QUEUE)
-
-static bool kdbus_name_owner_is_used(struct kdbus_name_owner *owner)
-{
- return !list_empty(&owner->name_entry) ||
- owner == owner->name->activator;
-}
-
-static struct kdbus_name_owner *
-kdbus_name_owner_new(struct kdbus_conn *conn, struct kdbus_name_entry *name,
- u64 flags)
-{
- struct kdbus_name_owner *owner;
-
- kdbus_conn_assert_active(conn);
-
- if (conn->name_count >= KDBUS_CONN_MAX_NAMES)
- return ERR_PTR(-E2BIG);
-
- owner = kmalloc(sizeof(*owner), GFP_KERNEL);
- if (!owner)
- return ERR_PTR(-ENOMEM);
-
- owner->flags = flags & KDBUS_NAME_SAVED_MASK;
- owner->conn = conn;
- owner->name = name;
- list_add_tail(&owner->conn_entry, &conn->names_list);
- INIT_LIST_HEAD(&owner->name_entry);
-
- ++conn->name_count;
- return owner;
-}
-
-static void kdbus_name_owner_free(struct kdbus_name_owner *owner)
-{
- if (!owner)
- return;
-
- WARN_ON(kdbus_name_owner_is_used(owner));
- --owner->conn->name_count;
- list_del(&owner->conn_entry);
- kfree(owner);
-}
-
-static struct kdbus_name_owner *
-kdbus_name_owner_find(struct kdbus_name_entry *name, struct kdbus_conn *conn)
-{
- struct kdbus_name_owner *owner;
-
- /*
- * Use conn->names_list over name->queue to make sure boundaries of
- * this linear search are controlled by the connection itself.
- * Furthermore, this will find normal owners as well as activators
- * without any additional code.
- */
- list_for_each_entry(owner, &conn->names_list, conn_entry)
- if (owner->name == name)
- return owner;
-
- return NULL;
-}
-
-static bool kdbus_name_entry_is_used(struct kdbus_name_entry *name)
-{
- return !list_empty(&name->queue) || name->activator;
-}
-
-static struct kdbus_name_owner *
-kdbus_name_entry_first(struct kdbus_name_entry *name)
-{
- return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
- name_entry);
-}
-
-static struct kdbus_name_entry *
-kdbus_name_entry_new(struct kdbus_name_registry *r, u32 hash,
- const char *name_str)
-{
- struct kdbus_name_entry *name;
- size_t namelen;
-
- lockdep_assert_held(&r->rwlock);
-
- namelen = strlen(name_str);
-
- name = kmalloc(sizeof(*name) + namelen + 1, GFP_KERNEL);
- if (!name)
- return ERR_PTR(-ENOMEM);
-
- name->name_id = ++r->name_seq_last;
- name->activator = NULL;
- INIT_LIST_HEAD(&name->queue);
- hash_add(r->entries_hash, &name->hentry, hash);
- memcpy(name->name, name_str, namelen + 1);
-
- return name;
-}
-
-static void kdbus_name_entry_free(struct kdbus_name_entry *name)
-{
- if (!name)
- return;
-
- WARN_ON(kdbus_name_entry_is_used(name));
- hash_del(&name->hentry);
- kfree(name);
-}
-
-static struct kdbus_name_entry *
-kdbus_name_entry_find(struct kdbus_name_registry *r, u32 hash,
- const char *name_str)
-{
- struct kdbus_name_entry *name;
-
- lockdep_assert_held(&r->rwlock);
-
- hash_for_each_possible(r->entries_hash, name, hentry, hash)
- if (!strcmp(name->name, name_str))
- return name;
-
- return NULL;
-}
-
-/**
- * kdbus_name_registry_new() - create a new name registry
- *
- * Return: a new kdbus_name_registry on success, ERR_PTR on failure.
- */
-struct kdbus_name_registry *kdbus_name_registry_new(void)
-{
- struct kdbus_name_registry *r;
-
- r = kmalloc(sizeof(*r), GFP_KERNEL);
- if (!r)
- return ERR_PTR(-ENOMEM);
-
- hash_init(r->entries_hash);
- init_rwsem(&r->rwlock);
- r->name_seq_last = 0;
-
- return r;
-}
-
-/**
- * kdbus_name_registry_free() - free name registry
- * @r: name registry to free, or NULL
- *
- * Free a name registry and cleanup all internal objects. This is a no-op if
- * you pass NULL as registry.
- */
-void kdbus_name_registry_free(struct kdbus_name_registry *r)
-{
- if (!r)
- return;
-
- WARN_ON(!hash_empty(r->entries_hash));
- kfree(r);
-}
-
-/**
- * kdbus_name_lookup_unlocked() - lookup name in registry
- * @reg: name registry
- * @name: name to lookup
- *
- * This looks up @name in the given name-registry and returns the
- * kdbus_name_entry object. The caller must hold the registry-lock and must not
- * access the returned object after releasing the lock.
- *
- * Return: Pointer to name-entry, or NULL if not found.
- */
-struct kdbus_name_entry *
-kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name)
-{
- return kdbus_name_entry_find(reg, kdbus_strhash(name), name);
-}
-
-static int kdbus_name_become_activator(struct kdbus_name_owner *owner,
- u64 *return_flags)
-{
- if (kdbus_name_owner_is_used(owner))
- return -EALREADY;
- if (owner->name->activator)
- return -EEXIST;
-
- owner->name->activator = owner;
- owner->flags |= KDBUS_NAME_ACTIVATOR;
-
- if (kdbus_name_entry_first(owner->name)) {
- owner->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- owner->flags |= KDBUS_NAME_PRIMARY;
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_ADD,
- 0, owner->conn->id,
- 0, owner->flags,
- owner->name->name);
- }
-
- if (return_flags)
- *return_flags = owner->flags | KDBUS_NAME_ACQUIRED;
-
- return 0;
-}
-
-static int kdbus_name_update(struct kdbus_name_owner *owner, u64 flags,
- u64 *return_flags)
-{
- struct kdbus_name_owner *primary, *activator;
- struct kdbus_name_entry *name;
- struct kdbus_bus *bus;
- u64 nflags = 0;
- int ret = 0;
-
- name = owner->name;
- bus = owner->conn->ep->bus;
- primary = kdbus_name_entry_first(name);
- activator = name->activator;
-
- /* cannot be activator and acquire a name */
- if (owner == activator)
- return -EUCLEAN;
-
- /* update saved flags */
- owner->flags = flags & KDBUS_NAME_SAVED_MASK;
-
- if (!primary) {
- /*
- * No primary owner (but maybe an activator). Take over the
- * name.
- */
-
- list_add(&owner->name_entry, &name->queue);
- owner->flags |= KDBUS_NAME_PRIMARY;
- nflags |= KDBUS_NAME_ACQUIRED;
-
- /* move messages to new owner on activation */
- if (activator) {
- kdbus_conn_move_messages(owner->conn, activator->conn,
- name->name_id);
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
- activator->conn->id, owner->conn->id,
- activator->flags, owner->flags,
- name->name);
- activator->flags &= ~KDBUS_NAME_PRIMARY;
- activator->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_ADD,
- 0, owner->conn->id,
- 0, owner->flags,
- name->name);
- }
-
- } else if (owner == primary) {
- /*
- * Already the primary owner of the name, flags were already
- * updated. Nothing to do.
- */
-
- owner->flags |= KDBUS_NAME_PRIMARY;
-
- } else if ((primary->flags & KDBUS_NAME_ALLOW_REPLACEMENT) &&
- (flags & KDBUS_NAME_REPLACE_EXISTING)) {
- /*
- * We're not the primary owner but can replace it. Move us
- * ahead of the primary owner and acquire the name (possibly
- * skipping queued owners ahead of us).
- */
-
- list_del_init(&owner->name_entry);
- list_add(&owner->name_entry, &name->queue);
- owner->flags |= KDBUS_NAME_PRIMARY;
- nflags |= KDBUS_NAME_ACQUIRED;
-
- kdbus_notify_name_change(bus, KDBUS_ITEM_NAME_CHANGE,
- primary->conn->id, owner->conn->id,
- primary->flags, owner->flags,
- name->name);
-
- /* requeue old primary, or drop if queueing not wanted */
- if (primary->flags & KDBUS_NAME_QUEUE) {
- primary->flags &= ~KDBUS_NAME_PRIMARY;
- primary->flags |= KDBUS_NAME_IN_QUEUE;
- } else {
- list_del_init(&primary->name_entry);
- kdbus_name_owner_free(primary);
- }
-
- } else if (flags & KDBUS_NAME_QUEUE) {
- /*
- * Name is already occupied and we cannot take it over, but
- * queuing is allowed. Put us silently on the queue, if not
- * already there.
- */
-
- owner->flags |= KDBUS_NAME_IN_QUEUE;
- if (!kdbus_name_owner_is_used(owner)) {
- list_add_tail(&owner->name_entry, &name->queue);
- nflags |= KDBUS_NAME_ACQUIRED;
- }
- } else if (kdbus_name_owner_is_used(owner)) {
- /*
- * Already queued on name, but re-queueing was not requested.
- * Make sure to unlink it from the name, the caller is
- * responsible for releasing it.
- */
-
- list_del_init(&owner->name_entry);
- } else {
- /*
- * Name is already claimed and queueing is not requested.
- * Return error to the caller.
- */
-
- ret = -EEXIST;
- }
-
- if (return_flags)
- *return_flags = owner->flags | nflags;
-
- return ret;
-}
-
-int kdbus_name_acquire(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn, const char *name_str,
- u64 flags, u64 *return_flags)
-{
- struct kdbus_name_entry *name = NULL;
- struct kdbus_name_owner *owner = NULL;
- u32 hash;
- int ret;
-
- kdbus_conn_assert_active(conn);
-
- down_write(&reg->rwlock);
-
- /*
- * Verify the connection has access to the name. Do this before testing
- * for double-acquisitions and other errors to make sure we do not leak
- * information about this name through possible custom endpoints.
- */
- if (!kdbus_conn_policy_own_name(conn, current_cred(), name_str)) {
- ret = -EPERM;
- goto exit;
- }
-
- /*
- * Lookup the name entry. If it already exists, search for an owner
- * entry as we might already own that name. If either does not exist,
- * we will allocate a fresh one.
- */
- hash = kdbus_strhash(name_str);
- name = kdbus_name_entry_find(reg, hash, name_str);
- if (name) {
- owner = kdbus_name_owner_find(name, conn);
- } else {
- name = kdbus_name_entry_new(reg, hash, name_str);
- if (IS_ERR(name)) {
- ret = PTR_ERR(name);
- name = NULL;
- goto exit;
- }
- }
-
- /* create name owner object if not already queued */
- if (!owner) {
- owner = kdbus_name_owner_new(conn, name, flags);
- if (IS_ERR(owner)) {
- ret = PTR_ERR(owner);
- owner = NULL;
- goto exit;
- }
- }
-
- if (flags & KDBUS_NAME_ACTIVATOR)
- ret = kdbus_name_become_activator(owner, return_flags);
- else
- ret = kdbus_name_update(owner, flags, return_flags);
- if (ret < 0)
- goto exit;
-
-exit:
- if (owner && !kdbus_name_owner_is_used(owner))
- kdbus_name_owner_free(owner);
- if (name && !kdbus_name_entry_is_used(name))
- kdbus_name_entry_free(name);
- up_write(&reg->rwlock);
- kdbus_notify_flush(conn->ep->bus);
- return ret;
-}
-
-static void kdbus_name_release_unlocked(struct kdbus_name_owner *owner)
-{
- struct kdbus_name_owner *primary, *next;
- struct kdbus_name_entry *name;
-
- name = owner->name;
- primary = kdbus_name_entry_first(name);
-
- list_del_init(&owner->name_entry);
- if (owner == name->activator)
- name->activator = NULL;
-
- if (!primary || owner == primary) {
- next = kdbus_name_entry_first(name);
- if (!next)
- next = name->activator;
-
- if (next) {
- /* hand to next in queue */
- next->flags &= ~KDBUS_NAME_IN_QUEUE;
- next->flags |= KDBUS_NAME_PRIMARY;
- if (next == name->activator)
- kdbus_conn_move_messages(next->conn,
- owner->conn,
- name->name_id);
-
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_CHANGE,
- owner->conn->id, next->conn->id,
- owner->flags, next->flags,
- name->name);
- } else {
- kdbus_notify_name_change(owner->conn->ep->bus,
- KDBUS_ITEM_NAME_REMOVE,
- owner->conn->id, 0,
- owner->flags, 0,
- name->name);
- }
- }
-
- kdbus_name_owner_free(owner);
- if (!kdbus_name_entry_is_used(name))
- kdbus_name_entry_free(name);
-}
-
-static int kdbus_name_release(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn,
- const char *name_str)
-{
- struct kdbus_name_owner *owner;
- struct kdbus_name_entry *name;
- int ret = 0;
-
- down_write(&reg->rwlock);
- name = kdbus_name_entry_find(reg, kdbus_strhash(name_str), name_str);
- if (name) {
- owner = kdbus_name_owner_find(name, conn);
- if (owner)
- kdbus_name_release_unlocked(owner);
- else
- ret = -EADDRINUSE;
- } else {
- ret = -ESRCH;
- }
- up_write(&reg->rwlock);
-
- kdbus_notify_flush(conn->ep->bus);
- return ret;
-}
-
-/**
- * kdbus_name_release_all() - remove all name entries of a given connection
- * @reg: name registry
- * @conn: connection
- */
-void kdbus_name_release_all(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn)
-{
- struct kdbus_name_owner *owner;
-
- down_write(&reg->rwlock);
-
- while ((owner = list_first_entry_or_null(&conn->names_list,
- struct kdbus_name_owner,
- conn_entry)))
- kdbus_name_release_unlocked(owner);
-
- up_write(&reg->rwlock);
-
- kdbus_notify_flush(conn->ep->bus);
-}
-
-/**
- * kdbus_name_is_valid() - check if a name is valid
- * @p: The name to check
- * @allow_wildcard: Whether or not to allow a wildcard name
- *
- * A name is valid if all of the following criterias are met:
- *
- * - The name has two or more elements separated by a period ('.') character.
- * - All elements must contain at least one character.
- * - Each element must only contain the ASCII characters "[A-Z][a-z][0-9]_-"
- * and must not begin with a digit.
- * - The name must not exceed KDBUS_NAME_MAX_LEN.
- * - If @allow_wildcard is true, the name may end on '.*'
- */
-bool kdbus_name_is_valid(const char *p, bool allow_wildcard)
-{
- bool dot, found_dot = false;
- const char *q;
-
- for (dot = true, q = p; *q; q++) {
- if (*q == '.') {
- if (dot)
- return false;
-
- found_dot = true;
- dot = true;
- } else {
- bool good;
-
- good = isalpha(*q) || (!dot && isdigit(*q)) ||
- *q == '_' || *q == '-' ||
- (allow_wildcard && dot &&
- *q == '*' && *(q + 1) == '\0');
-
- if (!good)
- return false;
-
- dot = false;
- }
- }
-
- if (q - p > KDBUS_NAME_MAX_LEN)
- return false;
-
- if (dot)
- return false;
-
- if (!found_dot)
- return false;
-
- return true;
-}
-
-/**
- * kdbus_cmd_name_acquire() - handle KDBUS_CMD_NAME_ACQUIRE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp)
-{
- const char *item_name;
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME, .mandatory = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_NAME_REPLACE_EXISTING |
- KDBUS_NAME_ALLOW_REPLACEMENT |
- KDBUS_NAME_QUEUE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- item_name = argv[1].item->str;
- if (!kdbus_name_is_valid(item_name, false)) {
- ret = -EINVAL;
- goto exit;
- }
-
- ret = kdbus_name_acquire(conn->ep->bus->name_registry, conn, item_name,
- cmd->flags, &cmd->return_flags);
-
-exit:
- return kdbus_args_clear(&args, ret);
-}
-
-/**
- * kdbus_cmd_name_release() - handle KDBUS_CMD_NAME_RELEASE
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_cmd *cmd;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- { .type = KDBUS_ITEM_NAME, .mandatory = true },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- if (!kdbus_conn_is_ordinary(conn))
- return -EOPNOTSUPP;
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- ret = kdbus_name_release(conn->ep->bus->name_registry, conn,
- argv[1].item->str);
- return kdbus_args_clear(&args, ret);
-}
-
-static int kdbus_list_write(struct kdbus_conn *conn,
- struct kdbus_conn *c,
- struct kdbus_pool_slice *slice,
- size_t *pos,
- struct kdbus_name_owner *o,
- bool write)
-{
- struct kvec kvec[4];
- size_t cnt = 0;
- int ret;
-
- /* info header */
- struct kdbus_info info = {
- .size = 0,
- .id = c->id,
- .flags = c->flags,
- };
-
- /* fake the header of a kdbus_name item */
- struct {
- u64 size;
- u64 type;
- u64 flags;
- } h = {};
-
- if (o && !kdbus_conn_policy_see_name_unlocked(conn, current_cred(),
- o->name->name))
- return 0;
-
- kdbus_kvec_set(&kvec[cnt++], &info, sizeof(info), &info.size);
-
- /* append name */
- if (o) {
- size_t slen = strlen(o->name->name) + 1;
-
- h.size = offsetof(struct kdbus_item, name.name) + slen;
- h.type = KDBUS_ITEM_OWNED_NAME;
- h.flags = o->flags;
-
- kdbus_kvec_set(&kvec[cnt++], &h, sizeof(h), &info.size);
- kdbus_kvec_set(&kvec[cnt++], o->name->name, slen, &info.size);
- cnt += !!kdbus_kvec_pad(&kvec[cnt], &info.size);
- }
-
- if (write) {
- ret = kdbus_pool_slice_copy_kvec(slice, *pos, kvec,
- cnt, info.size);
- if (ret < 0)
- return ret;
- }
-
- *pos += info.size;
- return 0;
-}
-
-static int kdbus_list_all(struct kdbus_conn *conn, u64 flags,
- struct kdbus_pool_slice *slice,
- size_t *pos, bool write)
-{
- struct kdbus_conn *c;
- size_t p = *pos;
- int ret, i;
-
- hash_for_each(conn->ep->bus->conn_hash, i, c, hentry) {
- bool added = false;
-
- /* skip monitors */
- if (kdbus_conn_is_monitor(c))
- continue;
-
- /* all names the connection owns */
- if (flags & (KDBUS_LIST_NAMES |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED)) {
- struct kdbus_name_owner *o;
-
- list_for_each_entry(o, &c->names_list, conn_entry) {
- if (o->flags & KDBUS_NAME_ACTIVATOR) {
- if (!(flags & KDBUS_LIST_ACTIVATORS))
- continue;
-
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- } else if (o->flags & KDBUS_NAME_IN_QUEUE) {
- if (!(flags & KDBUS_LIST_QUEUED))
- continue;
-
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- } else if (flags & KDBUS_LIST_NAMES) {
- ret = kdbus_list_write(conn, c, slice,
- &p, o, write);
- if (ret < 0) {
- mutex_unlock(&c->lock);
- return ret;
- }
-
- added = true;
- }
- }
- }
-
- /* nothing added so far, just add the unique ID */
- if (!added && (flags & KDBUS_LIST_UNIQUE)) {
- ret = kdbus_list_write(conn, c, slice, &p, NULL, write);
- if (ret < 0)
- return ret;
- }
- }
-
- *pos = p;
- return 0;
-}
-
-/**
- * kdbus_cmd_list() - handle KDBUS_CMD_LIST
- * @conn: connection to operate on
- * @argp: command payload
- *
- * Return: >=0 on success, negative error code on failure.
- */
-int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp)
-{
- struct kdbus_name_registry *reg = conn->ep->bus->name_registry;
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_cmd_list *cmd;
- size_t pos, size;
- int ret;
-
- struct kdbus_arg argv[] = {
- { .type = KDBUS_ITEM_NEGOTIATE },
- };
- struct kdbus_args args = {
- .allowed_flags = KDBUS_FLAG_NEGOTIATE |
- KDBUS_LIST_UNIQUE |
- KDBUS_LIST_NAMES |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED,
- .argv = argv,
- .argc = ARRAY_SIZE(argv),
- };
-
- ret = kdbus_args_parse(&args, argp, &cmd);
- if (ret != 0)
- return ret;
-
- /* lock order: domain -> bus -> ep -> names -> conn */
- down_read(&reg->rwlock);
- down_read(&conn->ep->bus->conn_rwlock);
- down_read(&conn->ep->policy_db.entries_rwlock);
-
- /* size of records */
- size = 0;
- ret = kdbus_list_all(conn, cmd->flags, NULL, &size, false);
- if (ret < 0)
- goto exit_unlock;
-
- if (size == 0) {
- kdbus_pool_publish_empty(conn->pool, &cmd->offset,
- &cmd->list_size);
- } else {
- slice = kdbus_pool_slice_alloc(conn->pool, size, false);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto exit_unlock;
- }
-
- /* copy the records */
- pos = 0;
- ret = kdbus_list_all(conn, cmd->flags, slice, &pos, true);
- if (ret < 0)
- goto exit_unlock;
-
- WARN_ON(pos != size);
- kdbus_pool_slice_publish(slice, &cmd->offset, &cmd->list_size);
- }
-
- if (kdbus_member_set_user(&cmd->offset, argp, typeof(*cmd), offset) ||
- kdbus_member_set_user(&cmd->list_size, argp,
- typeof(*cmd), list_size))
- ret = -EFAULT;
-
-exit_unlock:
- up_read(&conn->ep->policy_db.entries_rwlock);
- up_read(&conn->ep->bus->conn_rwlock);
- up_read(&reg->rwlock);
- kdbus_pool_slice_release(slice);
- return kdbus_args_clear(&args, ret);
-}
diff --git a/ipc/kdbus/names.h b/ipc/kdbus/names.h
deleted file mode 100644
index edac59ddd..000000000
--- a/ipc/kdbus/names.h
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_NAMES_H
-#define __KDBUS_NAMES_H
-
-#include <linux/hashtable.h>
-#include <linux/rwsem.h>
-
-struct kdbus_name_entry;
-struct kdbus_name_owner;
-struct kdbus_name_registry;
-
-/**
- * struct kdbus_name_registry - names registered for a bus
- * @entries_hash: Map of entries
- * @lock: Registry data lock
- * @name_seq_last: Last used sequence number to assign to a name entry
- */
-struct kdbus_name_registry {
- DECLARE_HASHTABLE(entries_hash, 8);
- struct rw_semaphore rwlock;
- u64 name_seq_last;
-};
-
-/**
- * struct kdbus_name_entry - well-know name entry
- * @name_id: sequence number of name entry to be able to uniquely
- * identify a name over its registration lifetime
- * @activator: activator of this name, or NULL
- * @queue: list of queued owners
- * @hentry: entry in registry map
- * @name: well-known name
- */
-struct kdbus_name_entry {
- u64 name_id;
- struct kdbus_name_owner *activator;
- struct list_head queue;
- struct hlist_node hentry;
- char name[];
-};
-
-/**
- * struct kdbus_name_owner - owner of a well-known name
- * @flags: KDBUS_NAME_* flags of this owner
- * @conn: connection owning the name
- * @name: name that is owned
- * @conn_entry: link into @conn
- * @name_entry: link into @name
- */
-struct kdbus_name_owner {
- u64 flags;
- struct kdbus_conn *conn;
- struct kdbus_name_entry *name;
- struct list_head conn_entry;
- struct list_head name_entry;
-};
-
-bool kdbus_name_is_valid(const char *p, bool allow_wildcard);
-
-struct kdbus_name_registry *kdbus_name_registry_new(void);
-void kdbus_name_registry_free(struct kdbus_name_registry *reg);
-
-struct kdbus_name_entry *
-kdbus_name_lookup_unlocked(struct kdbus_name_registry *reg, const char *name);
-
-int kdbus_name_acquire(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn, const char *name,
- u64 flags, u64 *return_flags);
-void kdbus_name_release_all(struct kdbus_name_registry *reg,
- struct kdbus_conn *conn);
-
-int kdbus_cmd_name_acquire(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_name_release(struct kdbus_conn *conn, void __user *argp);
-int kdbus_cmd_list(struct kdbus_conn *conn, void __user *argp);
-
-/**
- * kdbus_name_get_owner() - get current owner of a name
- * @name: name to get current owner of
- *
- * This returns a pointer to the current owner of a name (or its activator if
- * there is no owner). The caller must make sure @name is valid and does not
- * vanish.
- *
- * Return: Pointer to current owner or NULL if there is none.
- */
-static inline struct kdbus_name_owner *
-kdbus_name_get_owner(struct kdbus_name_entry *name)
-{
- return list_first_entry_or_null(&name->queue, struct kdbus_name_owner,
- name_entry) ? : name->activator;
-}
-
-#endif
diff --git a/ipc/kdbus/node.c b/ipc/kdbus/node.c
deleted file mode 100644
index 986aca39c..000000000
--- a/ipc/kdbus/node.c
+++ /dev/null
@@ -1,948 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/atomic.h>
-#include <linux/fs.h>
-#include <linux/idr.h>
-#include <linux/kdev_t.h>
-#include <linux/rbtree.h>
-#include <linux/rwsem.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/wait.h>
-
-#include "bus.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "fs.h"
-#include "handle.h"
-#include "node.h"
-#include "util.h"
-
-/**
- * DOC: kdbus nodes
- *
- * Nodes unify lifetime management across exposed kdbus objects and provide a
- * hierarchy. Each kdbus object, that might be exposed to user-space, has a
- * kdbus_node object embedded and is linked into the hierarchy. Each node can
- * have any number (0-n) of child nodes linked. Each child retains a reference
- * to its parent node. For root-nodes, the parent is NULL.
- *
- * Each node object goes through a bunch of states during it's lifetime:
- * * NEW
- * * LINKED (can be skipped by NEW->FREED transition)
- * * ACTIVE (can be skipped by LINKED->INACTIVE transition)
- * * INACTIVE
- * * DRAINED
- * * FREED
- *
- * Each node is allocated by the caller and initialized via kdbus_node_init().
- * This never fails and sets the object into state NEW. From now on, ref-counts
- * on the node manage its lifetime. During init, the ref-count is set to 1. Once
- * it drops to 0, the node goes to state FREED and the node->free_cb() callback
- * is called to deallocate any memory.
- *
- * After initializing a node, you usually link it into the hierarchy. You need
- * to provide a parent node and a name. The node will be linked as child to the
- * parent and a globally unique ID is assigned to the child. The name of the
- * child must be unique for all children of this parent. Otherwise, linking the
- * child will fail with -EEXIST.
- * Note that the child is not marked active, yet. Admittedly, it prevents any
- * other node from being linked with the same name (thus, it reserves that
- * name), but any child-lookup (via name or unique ID) will never return this
- * child unless it has been marked active.
- *
- * Once successfully linked, you can use kdbus_node_activate() to activate a
- * child. This will mark the child active. This state can be skipped by directly
- * deactivating the child via kdbus_node_deactivate() (see below).
- * By activating a child, you enable any lookups on this child to succeed from
- * now on. Furthermore, any code that got its hands on a reference to the node,
- * can from now on "acquire" the node.
- *
- * Active References (or: 'acquiring' and 'releasing' a node)
- * Additionally to normal object references, nodes support something we call
- * "active references". An active reference can be acquired via
- * kdbus_node_acquire() and released via kdbus_node_release(). A caller
- * _must_ own a normal object reference whenever calling those functions.
- * Unlike object references, acquiring an active reference can fail (by
- * returning 'false' from kdbus_node_acquire()). An active reference can
- * only be acquired if the node is marked active. If it is not marked
- * active, yet, or if it was already deactivated, no more active references
- * can be acquired, ever!
- * Active references are used to track tasks working on a node. Whenever a
- * task enters kernel-space to perform an action on a node, it acquires an
- * active reference, performs the action and releases the reference again.
- * While holding an active reference, the node is guaranteed to stay active.
- * If the node is deactivated in parallel, the node is marked as
- * deactivated, then we wait for all active references to be dropped, before
- * we finally proceed with any cleanups. That is, if you hold an active
- * reference to a node, any resources that are bound to the "active" state
- * are guaranteed to stay accessible until you release your reference.
- *
- * Active-references are very similar to rw-locks, where acquiring a node is
- * equal to try-read-lock and releasing to read-unlock. Deactivating a node
- * means write-lock and never releasing it again.
- * Unlike rw-locks, the 'active reference' concept is more versatile and
- * avoids unusual rw-lock usage (never releasing a write-lock..).
- *
- * It is safe to acquire multiple active-references recursively. But you
- * need to check the return value of kdbus_node_acquire() on _each_ call. It
- * may stop granting references at _any_ time.
- *
- * You're free to perform any operations you want while holding an active
- * reference, except sleeping for an indefinite period. Sleeping for a fixed
- * amount of time is fine, but you usually should not wait on wait-queues
- * without a timeout.
- * For example, if you wait for I/O to happen, you should gather all data
- * and schedule the I/O operation, then release your active reference and
- * wait for it to complete. Then try to acquire a new reference. If it
- * fails, perform any cleanup (the node is now dead). Otherwise, you can
- * finish your operation.
- *
- * All nodes can be deactivated via kdbus_node_deactivate() at any time. You can
- * call this multiple times, even in parallel or on nodes that were never
- * linked, and it will just work. Furthermore, all children will be deactivated
- * recursively as well. If a node is deactivated, there might still be active
- * references that were acquired before calling kdbus_node_deactivate(). The
- * owner of an object must call kdbus_node_drain() (which is a superset of
- * kdbus_node_deactivate()) before dropping their reference. This will
- * deactivate the node and also synchronously wait for all active references to
- * be dropped. Hence, once kdbus_node_drain() returns, the node is fully
- * released and no active references exist, anymore.
- * kdbus_node_drain() can be called at any times, multiple times, and in
- * parallel on multiple threads. All calls are synchronized internally and will
- * return only once the node is fully drained. The only restriction is, you
- * must not hold an active reference when calling kdbus_node_drain() (unlike
- * deactivation, which allows the caller to hold an active reference).
- *
- * When a node is activated, we acquire a normal object reference to the node.
- * This reference is dropped after deactivation is fully done (and only if the
- * node really was activated). This allows callers to link+activate a child node
- * and then drop all refs. This has the effect that nobody owns a reference to
- * the node, except for the parent node. Hence, if the parent is deactivated
- * (and thus all children are deactivated, too), this will automatically
- * release the child node.
- *
- * Currently, nodes provide a bunch of resources that external code can use
- * directly. This includes:
- *
- * * node->waitq: Each node has its own wait-queue that is used to manage
- * the 'active' state. When a node is deactivated, we wait on
- * this queue until all active refs are dropped. Analogously,
- * when you release an active reference on a deactivated
- * node, and the active ref-count drops to 0, we wake up a
- * single thread on this queue. Furthermore, once the
- * ->release_cb() callback finished, we wake up all waiters.
- * The node-owner is free to re-use this wait-queue for other
- * purposes. As node-management uses this queue only during
- * deactivation, it is usually totally fine to re-use the
- * queue for other, preferably low-overhead, use-cases.
- *
- * * node->type: This field defines the type of the owner of this node. It
- * must be set during node initialization and must remain
- * constant. The node management never looks at this value,
- * but external users might use to gain access to the owner
- * object of a node.
- * It is totally up to the owner of the node to define what
- * their type means. Usually it means you can access the
- * parent structure via container_of(), as long as you hold an
- * active reference to the node.
- *
- * * node->free_cb: callback after all references are dropped
- * node->release_cb: callback during node deactivation
- * These fields must be set by the node owner during
- * node initialization. They must remain constant. If
- * NULL, they're skipped.
- *
- * * node->mode: filesystem access modes
- * node->uid: filesystem owner uid
- * node->gid: filesystem owner gid
- * These fields must be set by the node owner during node
- * initialization. They must remain constant and may be
- * accessed by other callers to properly initialize
- * filesystem nodes.
- *
- * * node->id: This is an unsigned 32bit integer allocated by an IDA. It is
- * always kept as small as possible during allocation and is
- * globally unique across all nodes allocated by this module. 0
- * is reserved as "not assigned" and is the default.
- * The ID is assigned during kdbus_node_link() and is kept until
- * the object is freed. Thus, the ID surpasses the active
- * lifetime of a node. As long as you hold an object reference
- * to a node (and the node was linked once), the ID is valid and
- * unique.
- *
- * * node->name: name of this node
- * node->hash: 31bit hash-value of @name (range [2..INT_MAX-1])
- * These values follow the same lifetime rules as node->id.
- * They're initialized when the node is linked and then remain
- * constant until the last object reference is dropped.
- * Unlike the id, the name is only unique across all siblings
- * and only until the node is deactivated. Currently, the name
- * is even unique if linked but not activated, yet. This might
- * change in the future, though. Code should not rely on this.
- *
- * * node->lock: lock to protect node->children, node->rb, node->parent
- * * node->parent: Reference to parent node. This is set during LINK time
- * and is dropped during destruction. You can freely access
- * this field, but it may be NULL (root node).
- * * node->children: rb-tree of all linked children of this node. You must
- * not access this directly, but use one of the iterator
- * or lookup helpers.
- */
-
-/*
- * Bias values track states of "active references". They're all negative. If a
- * node is active, its active-ref-counter is >=0 and tracks all active
- * references. Once a node is deactivaed, we subtract NODE_BIAS. This means, the
- * counter is now negative but still counts the active references. Once it drops
- * to exactly NODE_BIAS, we know all active references were dropped. Exactly one
- * thread will change it to NODE_RELEASE now, perform cleanup and then put it
- * into NODE_DRAINED. Once drained, all other threads that tried deactivating
- * the node will now be woken up (thus, they wait until the node is fully done).
- * The initial state during node-setup is NODE_NEW. If a node is directly
- * deactivated without having ever been active, it is put into
- * NODE_RELEASE_DIRECT instead of NODE_BIAS. This tracks this one-bit state
- * across node-deactivation. The task putting it into NODE_RELEASE now knows
- * whether the node was active before or not.
- *
- * Some archs implement atomic_sub(v) with atomic_add(-v), so reserve INT_MIN
- * to avoid overflows if multiplied by -1.
- */
-#define KDBUS_NODE_BIAS (INT_MIN + 5)
-#define KDBUS_NODE_RELEASE_DIRECT (KDBUS_NODE_BIAS - 1)
-#define KDBUS_NODE_RELEASE (KDBUS_NODE_BIAS - 2)
-#define KDBUS_NODE_DRAINED (KDBUS_NODE_BIAS - 3)
-#define KDBUS_NODE_NEW (KDBUS_NODE_BIAS - 4)
-
-/* global unique ID mapping for kdbus nodes */
-DEFINE_IDA(kdbus_node_ida);
-
-/**
- * kdbus_node_name_hash() - hash a name
- * @name: The string to hash
- *
- * This computes the hash of @name. It is guaranteed to be in the range
- * [2..INT_MAX-1]. The values 1, 2 and INT_MAX are unused as they are reserved
- * for the filesystem code.
- *
- * Return: hash value of the passed string
- */
-static unsigned int kdbus_node_name_hash(const char *name)
-{
- unsigned int hash;
-
- /* reserve hash numbers 0, 1 and >=INT_MAX for magic directories */
- hash = kdbus_strhash(name) & INT_MAX;
- if (hash < 2)
- hash += 2;
- if (hash >= INT_MAX)
- hash = INT_MAX - 1;
-
- return hash;
-}
-
-/**
- * kdbus_node_name_compare() - compare a name with a node's name
- * @hash: hash of the string to compare the node with
- * @name: name to compare the node with
- * @node: node to compare the name with
- *
- * This compares a query string against a kdbus node. If the kdbus node has the
- * given name, this returns 0. Otherwise, this returns >0 / <0 depending
- * whether the query string is greater / less than the node.
- *
- * Note: If @node is drained but has the name @name, this returns 1. The
- * reason for this is that we treat drained nodes as "renamed". The
- * slot of such nodes is no longer occupied and new nodes can claim it.
- * Obviously, this has the side-effect that you cannot match drained
- * nodes, as they will never return 0 on name-matches. But this is
- * intentional, as there is no reason why anyone would ever want to match
- * on drained nodes.
- *
- * Return: 0 if @name and @hash exactly match the information in @node, or
- * an integer less than or greater than zero if @name is found, respectively,
- * to be less than or be greater than the string stored in @node.
- */
-static int kdbus_node_name_compare(unsigned int hash, const char *name,
- const struct kdbus_node *node)
-{
- int ret;
-
- if (hash != node->hash)
- return hash - node->hash;
-
- ret = strcmp(name, node->name);
- if (ret != 0)
- return ret;
-
- return atomic_read(&node->active) == KDBUS_NODE_DRAINED;
-}
-
-/**
- * kdbus_node_init() - initialize a kdbus_node
- * @node: Pointer to the node to initialize
- * @type: The type the node will have (KDBUS_NODE_*)
- *
- * The caller is responsible of allocating @node and initializating it to zero.
- * Once this call returns, you must use the node_ref() and node_unref()
- * functions to manage this node.
- */
-void kdbus_node_init(struct kdbus_node *node, unsigned int type)
-{
- atomic_set(&node->refcnt, 1);
- mutex_init(&node->lock);
- node->id = 0;
- node->type = type;
- RB_CLEAR_NODE(&node->rb);
- node->children = RB_ROOT;
- init_waitqueue_head(&node->waitq);
- atomic_set(&node->active, KDBUS_NODE_NEW);
-}
-
-/**
- * kdbus_node_link() - link a node into the nodes system
- * @node: Pointer to the node to initialize
- * @parent: Pointer to a parent node, may be %NULL
- * @name: The name of the node (or NULL if root node)
- *
- * This links a node into the hierarchy. This must not be called multiple times.
- * If @parent is NULL, the node becomes a new root node.
- *
- * This call will fail if @name is not unique across all its siblings or if no
- * ID could be allocated. You must not activate a node if linking failed! It is
- * safe to deactivate it, though.
- *
- * Once you linked a node, you must call kdbus_node_drain() before you drop
- * the last reference (even if you never activate the node).
- *
- * Return: 0 on success. negative error otherwise.
- */
-int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
- const char *name)
-{
- int ret;
-
- if (WARN_ON(node->type != KDBUS_NODE_DOMAIN && !parent))
- return -EINVAL;
-
- if (WARN_ON(parent && !name))
- return -EINVAL;
-
- if (name) {
- node->name = kstrdup(name, GFP_KERNEL);
- if (!node->name)
- return -ENOMEM;
-
- node->hash = kdbus_node_name_hash(name);
- }
-
- ret = ida_simple_get(&kdbus_node_ida, 1, 0, GFP_KERNEL);
- if (ret < 0)
- return ret;
-
- node->id = ret;
- ret = 0;
-
- if (parent) {
- struct rb_node **n, *prev;
-
- if (!kdbus_node_acquire(parent))
- return -ESHUTDOWN;
-
- mutex_lock(&parent->lock);
-
- n = &parent->children.rb_node;
- prev = NULL;
-
- while (*n) {
- struct kdbus_node *pos;
- int result;
-
- pos = kdbus_node_from_rb(*n);
- prev = *n;
- result = kdbus_node_name_compare(node->hash,
- node->name,
- pos);
- if (result == 0) {
- ret = -EEXIST;
- goto exit_unlock;
- }
-
- if (result < 0)
- n = &pos->rb.rb_left;
- else
- n = &pos->rb.rb_right;
- }
-
- /* add new node and rebalance the tree */
- rb_link_node(&node->rb, prev, n);
- rb_insert_color(&node->rb, &parent->children);
- node->parent = kdbus_node_ref(parent);
-
-exit_unlock:
- mutex_unlock(&parent->lock);
- kdbus_node_release(parent);
- }
-
- return ret;
-}
-
-/**
- * kdbus_node_ref() - Acquire object reference
- * @node: node to acquire reference to (or NULL)
- *
- * This acquires a new reference to @node. You must already own a reference when
- * calling this!
- * If @node is NULL, this is a no-op.
- *
- * Return: @node is returned
- */
-struct kdbus_node *kdbus_node_ref(struct kdbus_node *node)
-{
- if (node)
- atomic_inc(&node->refcnt);
- return node;
-}
-
-/**
- * kdbus_node_unref() - Drop object reference
- * @node: node to drop reference to (or NULL)
- *
- * This drops an object reference to @node. You must not access the node if you
- * no longer own a reference.
- * If the ref-count drops to 0, the object will be destroyed (->free_cb will be
- * called).
- *
- * If you linked or activated the node, you must deactivate the node before you
- * drop your last reference! If you didn't link or activate the node, you can
- * drop any reference you want.
- *
- * Note that this calls into ->free_cb() and thus _might_ sleep. The ->free_cb()
- * callbacks must not acquire any outer locks, though. So you can safely drop
- * references while holding locks (apart from node->parent->lock).
- *
- * If @node is NULL, this is a no-op.
- *
- * Return: This always returns NULL
- */
-struct kdbus_node *kdbus_node_unref(struct kdbus_node *node)
-{
- if (node && atomic_dec_and_test(&node->refcnt)) {
- struct kdbus_node safe = *node;
-
- WARN_ON(atomic_read(&node->active) != KDBUS_NODE_DRAINED);
-
- if (node->parent) {
- mutex_lock(&node->parent->lock);
- if (!RB_EMPTY_NODE(&node->rb)) {
- rb_erase(&node->rb,
- &node->parent->children);
- RB_CLEAR_NODE(&node->rb);
- }
- mutex_unlock(&node->parent->lock);
- }
-
- if (node->free_cb)
- node->free_cb(node);
- if (safe.id > 0)
- ida_simple_remove(&kdbus_node_ida, safe.id);
-
- kfree(safe.name);
- kdbus_node_unref(safe.parent);
- }
-
- return NULL;
-}
-
-/**
- * kdbus_node_is_active() - test whether a node is active
- * @node: node to test
- *
- * This checks whether @node is active. That means, @node was linked and
- * activated by the node owner and hasn't been deactivated, yet. If, and only
- * if, a node is active, kdbus_node_acquire() will be able to acquire active
- * references.
- *
- * Note that this function does not give any lifetime guarantees. After this
- * call returns, the node might be deactivated immediately. Normally, what you
- * want is to acquire a real active reference via kdbus_node_acquire().
- *
- * Return: true if @node is active, false otherwise
- */
-bool kdbus_node_is_active(struct kdbus_node *node)
-{
- return atomic_read(&node->active) >= 0;
-}
-
-/**
- * kdbus_node_is_deactivated() - test whether a node was already deactivated
- * @node: node to test
- *
- * This checks whether kdbus_node_deactivate() was called on @node. Note that
- * this might be true even if you never deactivated the node directly, but only
- * one of its ancestors.
- *
- * Note that even if this returns 'false', the node might get deactivated
- * immediately after the call returns.
- *
- * Return: true if @node was already deactivated, false if not
- */
-bool kdbus_node_is_deactivated(struct kdbus_node *node)
-{
- int v;
-
- v = atomic_read(&node->active);
- return v != KDBUS_NODE_NEW && v < 0;
-}
-
-/**
- * kdbus_node_activate() - activate a node
- * @node: node to activate
- *
- * This marks @node as active if, and only if, the node wasn't activated nor
- * deactivated, yet, and the parent is still active. Any but the first call to
- * kdbus_node_activate() is a no-op.
- * If you called kdbus_node_deactivate() before, then even the first call to
- * kdbus_node_activate() will be a no-op.
- *
- * This call doesn't give any lifetime guarantees. The node might get
- * deactivated immediately after this call returns. Or the parent might already
- * be deactivated, which will make this call a no-op.
- *
- * If this call successfully activated a node, it will take an object reference
- * to it. This reference is dropped after the node is deactivated. Therefore,
- * the object owner can safely drop their reference to @node iff they know that
- * its parent node will get deactivated at some point. Once the parent node is
- * deactivated, it will deactivate all its child and thus drop this reference
- * again.
- *
- * Return: True if this call successfully activated the node, otherwise false.
- * Note that this might return false, even if the node is still active
- * (eg., if you called this a second time).
- */
-bool kdbus_node_activate(struct kdbus_node *node)
-{
- bool res = false;
-
- mutex_lock(&node->lock);
- if (atomic_read(&node->active) == KDBUS_NODE_NEW) {
- atomic_sub(KDBUS_NODE_NEW, &node->active);
- /* activated nodes have ref +1 */
- kdbus_node_ref(node);
- res = true;
- }
- mutex_unlock(&node->lock);
-
- return res;
-}
-
-/**
- * kdbus_node_recurse_unlock() - advance iterator on a tree
- * @start: node at which the iteration started
- * @node: previously visited node
- *
- * This helper advances an iterator by one, when traversing a node tree. It is
- * supposed to be used like this:
- *
- * struct kdbus_node *n;
- *
- * n = start;
- * while (n) {
- * mutex_lock(&n->lock);
- * ... visit @n ...
- * n = kdbus_node_recurse_unlock(start, n);
- * }
- *
- * This helpers takes as input the start-node of the iteration and the current
- * position. It returns a pointer to the next node to visit. The caller must
- * hold a reference to @start during the whole iteration. Furthermore, @node
- * must be locked when entering this helper. On return, the lock is released.
- *
- * The order of visit is pre-order traversal.
- *
- * If @node is deactivated before recursing its children, then it is guaranteed
- * that all children will be visited. If @node is still active, new nodes might
- * be inserted during traversal, and thus might be missed.
- *
- * Also note that the node-locks are released while traversing children. You
- * must not rely on the locks to be held during the whole traversal. Each node
- * that is visited is pinned by this helper, so the caller can rely on owning a
- * reference. It is dropped, once all of the children of the node have been
- * visited (recursively).
- *
- * You *must not* bail out of a traversal early, otherwise you'll leak
- * ref-counts to all nodes in the current depth-path.
- *
- * Return: Reference to next node, or NULL.
- */
-static struct kdbus_node *kdbus_node_recurse_unlock(struct kdbus_node *start,
- struct kdbus_node *node)
-{
- struct kdbus_node *t, *prev = NULL;
- struct rb_node *rb;
-
- lockdep_assert_held(&node->lock);
-
- rb = rb_first(&node->children);
- if (!rb) {
- do {
- mutex_unlock(&node->lock);
- kdbus_node_unref(prev);
-
- if (node == start)
- return NULL;
-
- prev = node;
- node = node->parent;
-
- mutex_lock(&node->lock);
- rb = rb_next(&prev->rb);
- } while (!rb);
- }
-
- t = kdbus_node_ref(kdbus_node_from_rb(rb));
- mutex_unlock(&node->lock);
- kdbus_node_unref(prev);
- return t;
-}
-
-/**
- * kdbus_node_deactivate() - deactivate a node
- * @node: node to deactivate
- *
- * This recursively deactivates the passed node and all its children. The nodes
- * are marked as deactivated, but they're not drained. Hence, even after this
- * call returns, there might still be someone holding an active reference to
- * any of the nodes. However, no new active references can be acquired after
- * this returns.
- *
- * It is safe to call this multiple times (even in parallel). Each call is
- * guaranteed to only return after _all_ nodes have been deactivated.
- */
-void kdbus_node_deactivate(struct kdbus_node *node)
-{
- struct kdbus_node *pos;
- int v;
-
- pos = node;
- while (pos) {
- mutex_lock(&pos->lock);
-
- /*
- * Add BIAS to pos->active to mark it as inactive. If it was
- * never active before, immediately mark it as RELEASE_INACTIVE
- * so that this case can be detected later on.
- * If the node was already deactivated, make sure to still
- * recurse into the children. Otherwise, we might return before
- * a racing thread finished deactivating all children. But we
- * want to guarantee that the whole tree is deactivated once
- * this returns.
- */
- v = atomic_read(&pos->active);
- if (v >= 0)
- atomic_add_return(KDBUS_NODE_BIAS, &pos->active);
- else if (v == KDBUS_NODE_NEW)
- atomic_set(&pos->active, KDBUS_NODE_RELEASE_DIRECT);
-
- pos = kdbus_node_recurse_unlock(node, pos);
- }
-}
-
-/**
- * kdbus_node_drain() - drain a node
- * @node: node to drain
- *
- * This function recursively deactivates this node and all its children and
- * then waits for all active references to be dropped. This function is a
- * superset of kdbus_node_deactivate(), as it additionally drains all nodes. It
- * returns only once all children and the node itself were recursively drained
- * (even if you call this function multiple times in parallel).
- *
- * It is safe to call this function on _any_ node that was initialized _any_
- * number of times.
- *
- * This call may sleep, as it waits for all active references to be dropped.
- */
-void kdbus_node_drain(struct kdbus_node *node)
-{
- struct kdbus_node *pos;
- int v;
-
- kdbus_node_deactivate(node);
-
- pos = node;
- while (pos) {
- /* wait until all active references were dropped */
- wait_event(pos->waitq,
- atomic_read(&pos->active) <= KDBUS_NODE_BIAS);
-
- /* mark object as RELEASE */
- mutex_lock(&pos->lock);
- v = atomic_read(&pos->active);
- if (v == KDBUS_NODE_BIAS || v == KDBUS_NODE_RELEASE_DIRECT)
- atomic_set(&pos->active, KDBUS_NODE_RELEASE);
- mutex_unlock(&pos->lock);
-
- /*
- * If this is the thread that marked the object as RELEASE, we
- * perform the actual release. Otherwise, we wait until the
- * release is done and the node is marked as DRAINED.
- */
- if (v == KDBUS_NODE_BIAS || v == KDBUS_NODE_RELEASE_DIRECT) {
- if (pos->release_cb)
- pos->release_cb(pos, v == KDBUS_NODE_BIAS);
-
- /* mark as DRAINED */
- atomic_set(&pos->active, KDBUS_NODE_DRAINED);
- wake_up_all(&pos->waitq);
-
- /* drop VFS cache */
- kdbus_fs_flush(pos);
-
- /*
- * If the node was activated and someone subtracted BIAS
- * from it to deactivate it, we, and only us, are
- * responsible to release the extra ref-count that was
- * taken once in kdbus_node_activate().
- * If the node was never activated, no-one ever
- * subtracted BIAS, but instead skipped that state and
- * immediately went to NODE_RELEASE_DIRECT. In that case
- * we must not drop the reference.
- */
- if (v == KDBUS_NODE_BIAS)
- kdbus_node_unref(pos);
- } else {
- /* wait until object is DRAINED */
- wait_event(pos->waitq,
- atomic_read(&pos->active) == KDBUS_NODE_DRAINED);
- }
-
- mutex_lock(&pos->lock);
- pos = kdbus_node_recurse_unlock(node, pos);
- }
-}
-
-/**
- * kdbus_node_acquire() - Acquire an active ref on a node
- * @node: The node
- *
- * This acquires an active-reference to @node. This will only succeed if the
- * node is active. You must release this active reference via
- * kdbus_node_release() again.
- *
- * See the introduction to "active references" for more details.
- *
- * Return: %true if @node was non-NULL and active
- */
-bool kdbus_node_acquire(struct kdbus_node *node)
-{
- return node && atomic_inc_unless_negative(&node->active);
-}
-
-/**
- * kdbus_node_release() - Release an active ref on a node
- * @node: The node
- *
- * This releases an active reference that was previously acquired via
- * kdbus_node_acquire(). See kdbus_node_acquire() for details.
- */
-void kdbus_node_release(struct kdbus_node *node)
-{
- if (node && atomic_dec_return(&node->active) == KDBUS_NODE_BIAS)
- wake_up(&node->waitq);
-}
-
-/**
- * kdbus_node_find_child() - Find child by name
- * @node: parent node to search through
- * @name: name of child node
- *
- * This searches through all children of @node for a child-node with name @name.
- * If not found, or if the child is deactivated, NULL is returned. Otherwise,
- * the child is acquired and a new reference is returned.
- *
- * If you're done with the child, you need to release it and drop your
- * reference.
- *
- * This function does not acquire the parent node. However, if the parent was
- * already deactivated, then kdbus_node_deactivate() will, at some point, also
- * deactivate the child. Therefore, we can rely on the explicit ordering during
- * deactivation.
- *
- * Return: Reference to acquired child node, or NULL if not found / not active.
- */
-struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node,
- const char *name)
-{
- struct kdbus_node *child;
- struct rb_node *rb;
- unsigned int hash;
- int ret;
-
- hash = kdbus_node_name_hash(name);
-
- mutex_lock(&node->lock);
- rb = node->children.rb_node;
- while (rb) {
- child = kdbus_node_from_rb(rb);
- ret = kdbus_node_name_compare(hash, name, child);
- if (ret < 0)
- rb = rb->rb_left;
- else if (ret > 0)
- rb = rb->rb_right;
- else
- break;
- }
- if (rb && kdbus_node_acquire(child))
- kdbus_node_ref(child);
- else
- child = NULL;
- mutex_unlock(&node->lock);
-
- return child;
-}
-
-static struct kdbus_node *node_find_closest_unlocked(struct kdbus_node *node,
- unsigned int hash,
- const char *name)
-{
- struct kdbus_node *n, *pos = NULL;
- struct rb_node *rb;
- int res;
-
- /*
- * Find the closest child with ``node->hash >= hash'', or, if @name is
- * valid, ``node->name >= name'' (where '>=' is the lex. order).
- */
-
- rb = node->children.rb_node;
- while (rb) {
- n = kdbus_node_from_rb(rb);
-
- if (name)
- res = kdbus_node_name_compare(hash, name, n);
- else
- res = hash - n->hash;
-
- if (res <= 0) {
- rb = rb->rb_left;
- pos = n;
- } else { /* ``hash > n->hash'', ``name > n->name'' */
- rb = rb->rb_right;
- }
- }
-
- return pos;
-}
-
-/**
- * kdbus_node_find_closest() - Find closest child-match
- * @node: parent node to search through
- * @hash: hash value to find closest match for
- *
- * Find the closest child of @node with a hash greater than or equal to @hash.
- * The closest match is the left-most child of @node with this property. Which
- * means, it is the first child with that hash returned by
- * kdbus_node_next_child(), if you'd iterate the whole parent node.
- *
- * Return: Reference to acquired child, or NULL if none found.
- */
-struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node,
- unsigned int hash)
-{
- struct kdbus_node *child;
- struct rb_node *rb;
-
- mutex_lock(&node->lock);
-
- child = node_find_closest_unlocked(node, hash, NULL);
- while (child && !kdbus_node_acquire(child)) {
- rb = rb_next(&child->rb);
- if (rb)
- child = kdbus_node_from_rb(rb);
- else
- child = NULL;
- }
- kdbus_node_ref(child);
-
- mutex_unlock(&node->lock);
-
- return child;
-}
-
-/**
- * kdbus_node_next_child() - Acquire next child
- * @node: parent node
- * @prev: previous child-node position or NULL
- *
- * This function returns a reference to the next active child of @node, after
- * the passed position @prev. If @prev is NULL, a reference to the first active
- * child is returned. If no more active children are found, NULL is returned.
- *
- * This function acquires the next child it returns. If you're done with the
- * returned pointer, you need to release _and_ unref it.
- *
- * The passed in pointer @prev is not modified by this function, and it does
- * *not* have to be active. If @prev was acquired via different means, or if it
- * was unlinked from its parent before you pass it in, then this iterator will
- * still return the next active child (it will have to search through the
- * rb-tree based on the node-name, though).
- * However, @prev must not be linked to a different parent than @node!
- *
- * Return: Reference to next acquired child, or NULL if at the end.
- */
-struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node,
- struct kdbus_node *prev)
-{
- struct kdbus_node *pos = NULL;
- struct rb_node *rb;
-
- mutex_lock(&node->lock);
-
- if (!prev) {
- /*
- * New iteration; find first node in rb-tree and try to acquire
- * it. If we got it, directly return it as first element.
- * Otherwise, the loop below will find the next active node.
- */
- rb = rb_first(&node->children);
- if (!rb)
- goto exit;
- pos = kdbus_node_from_rb(rb);
- if (kdbus_node_acquire(pos))
- goto exit;
- } else {
- /*
- * The current iterator is still linked to the parent. Set it
- * as current position and use the loop below to find the next
- * active element.
- */
- pos = prev;
- }
-
- /* @pos was already returned or is inactive; find next active node */
- do {
- rb = rb_next(&pos->rb);
- if (rb)
- pos = kdbus_node_from_rb(rb);
- else
- pos = NULL;
- } while (pos && !kdbus_node_acquire(pos));
-
-exit:
- /* @pos is NULL or acquired. Take ref if non-NULL and return it */
- kdbus_node_ref(pos);
- mutex_unlock(&node->lock);
- return pos;
-}
diff --git a/ipc/kdbus/node.h b/ipc/kdbus/node.h
deleted file mode 100644
index 16c6fd574..000000000
--- a/ipc/kdbus/node.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_NODE_H
-#define __KDBUS_NODE_H
-
-#include <linux/atomic.h>
-#include <linux/kernel.h>
-#include <linux/mutex.h>
-#include <linux/wait.h>
-
-struct kdbus_node;
-
-enum kdbus_node_type {
- KDBUS_NODE_DOMAIN,
- KDBUS_NODE_CONTROL,
- KDBUS_NODE_BUS,
- KDBUS_NODE_ENDPOINT,
-};
-
-typedef void (*kdbus_node_free_t) (struct kdbus_node *node);
-typedef void (*kdbus_node_release_t) (struct kdbus_node *node, bool was_active);
-
-struct kdbus_node {
- struct mutex lock;
- atomic_t refcnt;
- atomic_t active;
- wait_queue_head_t waitq;
-
- /* static members */
- unsigned int type;
- kdbus_node_free_t free_cb;
- kdbus_node_release_t release_cb;
- umode_t mode;
- kuid_t uid;
- kgid_t gid;
-
- /* valid once linked */
- char *name;
- unsigned int hash;
- unsigned int id;
- struct kdbus_node *parent; /* may be NULL */
- struct rb_node rb;
-
- /* dynamic list of children */
- struct rb_root children;
-};
-
-#define kdbus_node_from_rb(_node) rb_entry((_node), struct kdbus_node, rb)
-
-extern struct ida kdbus_node_ida;
-
-void kdbus_node_init(struct kdbus_node *node, unsigned int type);
-
-int kdbus_node_link(struct kdbus_node *node, struct kdbus_node *parent,
- const char *name);
-
-struct kdbus_node *kdbus_node_ref(struct kdbus_node *node);
-struct kdbus_node *kdbus_node_unref(struct kdbus_node *node);
-
-bool kdbus_node_is_active(struct kdbus_node *node);
-bool kdbus_node_is_deactivated(struct kdbus_node *node);
-bool kdbus_node_activate(struct kdbus_node *node);
-void kdbus_node_deactivate(struct kdbus_node *node);
-void kdbus_node_drain(struct kdbus_node *node);
-
-bool kdbus_node_acquire(struct kdbus_node *node);
-void kdbus_node_release(struct kdbus_node *node);
-
-struct kdbus_node *kdbus_node_find_child(struct kdbus_node *node,
- const char *name);
-struct kdbus_node *kdbus_node_find_closest(struct kdbus_node *node,
- unsigned int hash);
-struct kdbus_node *kdbus_node_next_child(struct kdbus_node *node,
- struct kdbus_node *prev);
-
-#endif
diff --git a/ipc/kdbus/notify.c b/ipc/kdbus/notify.c
deleted file mode 100644
index 375758c48..000000000
--- a/ipc/kdbus/notify.c
+++ /dev/null
@@ -1,204 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/spinlock.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "endpoint.h"
-#include "item.h"
-#include "message.h"
-#include "notify.h"
-
-static inline void kdbus_notify_add_tail(struct kdbus_staging *staging,
- struct kdbus_bus *bus)
-{
- spin_lock(&bus->notify_lock);
- list_add_tail(&staging->notify_entry, &bus->notify_list);
- spin_unlock(&bus->notify_lock);
-}
-
-static int kdbus_notify_reply(struct kdbus_bus *bus, u64 id,
- u64 cookie, u64 msg_type)
-{
- struct kdbus_staging *s;
-
- s = kdbus_staging_new_kernel(bus, id, cookie, 0, msg_type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_reply_timeout() - queue a timeout reply
- * @bus: Bus which queues the messages
- * @id: The destination's connection ID
- * @cookie: The cookie to set in the reply.
- *
- * Queues a message that has a KDBUS_ITEM_REPLY_TIMEOUT item attached.
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie)
-{
- return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_TIMEOUT);
-}
-
-/**
- * kdbus_notify_reply_dead() - queue a 'dead' reply
- * @bus: Bus which queues the messages
- * @id: The destination's connection ID
- * @cookie: The cookie to set in the reply.
- *
- * Queues a message that has a KDBUS_ITEM_REPLY_DEAD item attached.
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie)
-{
- return kdbus_notify_reply(bus, id, cookie, KDBUS_ITEM_REPLY_DEAD);
-}
-
-/**
- * kdbus_notify_name_change() - queue a notification about a name owner change
- * @bus: Bus which queues the messages
- * @type: The type if the notification; KDBUS_ITEM_NAME_ADD,
- * KDBUS_ITEM_NAME_CHANGE or KDBUS_ITEM_NAME_REMOVE
- * @old_id: The id of the connection that used to own the name
- * @new_id: The id of the new owner connection
- * @old_flags: The flags to pass in the KDBUS_ITEM flags field for
- * the old owner
- * @new_flags: The flags to pass in the KDBUS_ITEM flags field for
- * the new owner
- * @name: The name that was removed or assigned to a new owner
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
- u64 old_id, u64 new_id,
- u64 old_flags, u64 new_flags,
- const char *name)
-{
- size_t name_len, extra_size;
- struct kdbus_staging *s;
-
- name_len = strlen(name) + 1;
- extra_size = sizeof(struct kdbus_notify_name_change) + name_len;
-
- s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0,
- extra_size, type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- s->notify->name_change.old_id.id = old_id;
- s->notify->name_change.old_id.flags = old_flags;
- s->notify->name_change.new_id.id = new_id;
- s->notify->name_change.new_id.flags = new_flags;
- memcpy(s->notify->name_change.name, name, name_len);
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_id_change() - queue a notification about a unique ID change
- * @bus: Bus which queues the messages
- * @type: The type if the notification; KDBUS_ITEM_ID_ADD or
- * KDBUS_ITEM_ID_REMOVE
- * @id: The id of the connection that was added or removed
- * @flags: The flags to pass in the KDBUS_ITEM flags field
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags)
-{
- struct kdbus_staging *s;
- size_t extra_size;
-
- extra_size = sizeof(struct kdbus_notify_id_change);
- s = kdbus_staging_new_kernel(bus, KDBUS_DST_ID_BROADCAST, 0,
- extra_size, type);
- if (IS_ERR(s))
- return PTR_ERR(s);
-
- s->notify->id_change.id = id;
- s->notify->id_change.flags = flags;
-
- kdbus_notify_add_tail(s, bus);
- return 0;
-}
-
-/**
- * kdbus_notify_flush() - send a list of collected messages
- * @bus: Bus which queues the messages
- *
- * The list is empty after sending the messages.
- */
-void kdbus_notify_flush(struct kdbus_bus *bus)
-{
- LIST_HEAD(notify_list);
- struct kdbus_staging *s, *tmp;
-
- mutex_lock(&bus->notify_flush_lock);
- down_read(&bus->name_registry->rwlock);
-
- spin_lock(&bus->notify_lock);
- list_splice_init(&bus->notify_list, &notify_list);
- spin_unlock(&bus->notify_lock);
-
- list_for_each_entry_safe(s, tmp, &notify_list, notify_entry) {
- if (s->msg->dst_id != KDBUS_DST_ID_BROADCAST) {
- struct kdbus_conn *conn;
-
- conn = kdbus_bus_find_conn_by_id(bus, s->msg->dst_id);
- if (conn) {
- kdbus_bus_eavesdrop(bus, NULL, s);
- kdbus_conn_entry_insert(NULL, conn, s, NULL,
- NULL);
- kdbus_conn_unref(conn);
- }
- } else {
- kdbus_bus_broadcast(bus, NULL, s);
- }
-
- list_del(&s->notify_entry);
- kdbus_staging_free(s);
- }
-
- up_read(&bus->name_registry->rwlock);
- mutex_unlock(&bus->notify_flush_lock);
-}
-
-/**
- * kdbus_notify_free() - free a list of collected messages
- * @bus: Bus which queues the messages
- */
-void kdbus_notify_free(struct kdbus_bus *bus)
-{
- struct kdbus_staging *s, *tmp;
-
- list_for_each_entry_safe(s, tmp, &bus->notify_list, notify_entry) {
- list_del(&s->notify_entry);
- kdbus_staging_free(s);
- }
-}
diff --git a/ipc/kdbus/notify.h b/ipc/kdbus/notify.h
deleted file mode 100644
index 03df464cb..000000000
--- a/ipc/kdbus/notify.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_NOTIFY_H
-#define __KDBUS_NOTIFY_H
-
-struct kdbus_bus;
-
-int kdbus_notify_id_change(struct kdbus_bus *bus, u64 type, u64 id, u64 flags);
-int kdbus_notify_reply_timeout(struct kdbus_bus *bus, u64 id, u64 cookie);
-int kdbus_notify_reply_dead(struct kdbus_bus *bus, u64 id, u64 cookie);
-int kdbus_notify_name_change(struct kdbus_bus *bus, u64 type,
- u64 old_id, u64 new_id,
- u64 old_flags, u64 new_flags,
- const char *name);
-void kdbus_notify_flush(struct kdbus_bus *bus);
-void kdbus_notify_free(struct kdbus_bus *bus);
-
-#endif
diff --git a/ipc/kdbus/policy.c b/ipc/kdbus/policy.c
deleted file mode 100644
index f2618e15e..000000000
--- a/ipc/kdbus/policy.c
+++ /dev/null
@@ -1,489 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/dcache.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/mutex.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "domain.h"
-#include "item.h"
-#include "names.h"
-#include "policy.h"
-
-#define KDBUS_POLICY_HASH_SIZE 64
-
-/**
- * struct kdbus_policy_db_entry_access - a database entry access item
- * @type: One of KDBUS_POLICY_ACCESS_* types
- * @access: Access to grant. One of KDBUS_POLICY_*
- * @uid: For KDBUS_POLICY_ACCESS_USER, the global uid
- * @gid: For KDBUS_POLICY_ACCESS_GROUP, the global gid
- * @list: List entry item for the entry's list
- *
- * This is the internal version of struct kdbus_policy_db_access.
- */
-struct kdbus_policy_db_entry_access {
- u8 type; /* USER, GROUP, WORLD */
- u8 access; /* OWN, TALK, SEE */
- union {
- kuid_t uid; /* global uid */
- kgid_t gid; /* global gid */
- };
- struct list_head list;
-};
-
-/**
- * struct kdbus_policy_db_entry - a policy database entry
- * @name: The name to match the policy entry against
- * @hentry: The hash entry for the database's entries_hash
- * @access_list: List head for keeping tracks of the entry's
- * access items.
- * @owner: The owner of this entry. Can be a kdbus_conn or
- * a kdbus_ep object.
- * @wildcard: The name is a wildcard, such as ending on '.*'
- */
-struct kdbus_policy_db_entry {
- char *name;
- struct hlist_node hentry;
- struct list_head access_list;
- const void *owner;
- bool wildcard:1;
-};
-
-static void kdbus_policy_entry_free(struct kdbus_policy_db_entry *e)
-{
- struct kdbus_policy_db_entry_access *a, *tmp;
-
- list_for_each_entry_safe(a, tmp, &e->access_list, list) {
- list_del(&a->list);
- kfree(a);
- }
-
- kfree(e->name);
- kfree(e);
-}
-
-static unsigned int kdbus_strnhash(const char *str, size_t len)
-{
- unsigned long hash = init_name_hash();
-
- while (len--)
- hash = partial_name_hash(*str++, hash);
-
- return end_name_hash(hash);
-}
-
-static const struct kdbus_policy_db_entry *
-kdbus_policy_lookup(struct kdbus_policy_db *db, const char *name, u32 hash)
-{
- struct kdbus_policy_db_entry *e;
- const char *dot;
- size_t len;
-
- /* find exact match */
- hash_for_each_possible(db->entries_hash, e, hentry, hash)
- if (strcmp(e->name, name) == 0 && !e->wildcard)
- return e;
-
- /* find wildcard match */
-
- dot = strrchr(name, '.');
- if (!dot)
- return NULL;
-
- len = dot - name;
- hash = kdbus_strnhash(name, len);
-
- hash_for_each_possible(db->entries_hash, e, hentry, hash)
- if (e->wildcard && !strncmp(e->name, name, len) &&
- !e->name[len])
- return e;
-
- return NULL;
-}
-
-/**
- * kdbus_policy_db_clear - release all memory from a policy db
- * @db: The policy database
- */
-void kdbus_policy_db_clear(struct kdbus_policy_db *db)
-{
- struct kdbus_policy_db_entry *e;
- struct hlist_node *tmp;
- unsigned int i;
-
- /* purge entries */
- down_write(&db->entries_rwlock);
- hash_for_each_safe(db->entries_hash, i, tmp, e, hentry) {
- hash_del(&e->hentry);
- kdbus_policy_entry_free(e);
- }
- up_write(&db->entries_rwlock);
-}
-
-/**
- * kdbus_policy_db_init() - initialize a new policy database
- * @db: The location of the database
- *
- * This initializes a new policy-db. The underlying memory must have been
- * cleared to zero by the caller.
- */
-void kdbus_policy_db_init(struct kdbus_policy_db *db)
-{
- hash_init(db->entries_hash);
- init_rwsem(&db->entries_rwlock);
-}
-
-/**
- * kdbus_policy_query_unlocked() - Query the policy database
- * @db: Policy database
- * @cred: Credentials to test against
- * @name: Name to query
- * @hash: Hash value of @name
- *
- * Same as kdbus_policy_query() but requires the caller to lock the policy
- * database against concurrent writes.
- *
- * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none.
- */
-int kdbus_policy_query_unlocked(struct kdbus_policy_db *db,
- const struct cred *cred, const char *name,
- unsigned int hash)
-{
- struct kdbus_policy_db_entry_access *a;
- const struct kdbus_policy_db_entry *e;
- int i, highest = -EPERM;
-
- e = kdbus_policy_lookup(db, name, hash);
- if (!e)
- return -EPERM;
-
- list_for_each_entry(a, &e->access_list, list) {
- if ((int)a->access <= highest)
- continue;
-
- switch (a->type) {
- case KDBUS_POLICY_ACCESS_USER:
- if (uid_eq(cred->euid, a->uid))
- highest = a->access;
- break;
- case KDBUS_POLICY_ACCESS_GROUP:
- if (gid_eq(cred->egid, a->gid)) {
- highest = a->access;
- break;
- }
-
- for (i = 0; i < cred->group_info->ngroups; i++) {
- kgid_t gid = GROUP_AT(cred->group_info, i);
-
- if (gid_eq(gid, a->gid)) {
- highest = a->access;
- break;
- }
- }
-
- break;
- case KDBUS_POLICY_ACCESS_WORLD:
- highest = a->access;
- break;
- }
-
- /* OWN is the highest possible policy */
- if (highest >= KDBUS_POLICY_OWN)
- break;
- }
-
- return highest;
-}
-
-/**
- * kdbus_policy_query() - Query the policy database
- * @db: Policy database
- * @cred: Credentials to test against
- * @name: Name to query
- * @hash: Hash value of @name
- *
- * Query the policy database @db for the access rights of @cred to the name
- * @name. The access rights of @cred are returned, or -EPERM if no access is
- * granted.
- *
- * This call effectively searches for the highest access-right granted to
- * @cred. The caller should really cache those as policy lookups are rather
- * expensive.
- *
- * Return: The highest KDBUS_POLICY_* access type found, or -EPERM if none.
- */
-int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred,
- const char *name, unsigned int hash)
-{
- int ret;
-
- down_read(&db->entries_rwlock);
- ret = kdbus_policy_query_unlocked(db, cred, name, hash);
- up_read(&db->entries_rwlock);
-
- return ret;
-}
-
-static void __kdbus_policy_remove_owner(struct kdbus_policy_db *db,
- const void *owner)
-{
- struct kdbus_policy_db_entry *e;
- struct hlist_node *tmp;
- int i;
-
- hash_for_each_safe(db->entries_hash, i, tmp, e, hentry)
- if (e->owner == owner) {
- hash_del(&e->hentry);
- kdbus_policy_entry_free(e);
- }
-}
-
-/**
- * kdbus_policy_remove_owner() - remove all entries related to a connection
- * @db: The policy database
- * @owner: The connection which items to remove
- */
-void kdbus_policy_remove_owner(struct kdbus_policy_db *db,
- const void *owner)
-{
- down_write(&db->entries_rwlock);
- __kdbus_policy_remove_owner(db, owner);
- up_write(&db->entries_rwlock);
-}
-
-/*
- * Convert user provided policy access to internal kdbus policy
- * access
- */
-static struct kdbus_policy_db_entry_access *
-kdbus_policy_make_access(const struct kdbus_policy_access *uaccess)
-{
- int ret;
- struct kdbus_policy_db_entry_access *a;
-
- a = kzalloc(sizeof(*a), GFP_KERNEL);
- if (!a)
- return ERR_PTR(-ENOMEM);
-
- ret = -EINVAL;
- switch (uaccess->access) {
- case KDBUS_POLICY_SEE:
- case KDBUS_POLICY_TALK:
- case KDBUS_POLICY_OWN:
- a->access = uaccess->access;
- break;
- default:
- goto err;
- }
-
- switch (uaccess->type) {
- case KDBUS_POLICY_ACCESS_USER:
- a->uid = make_kuid(current_user_ns(), uaccess->id);
- if (!uid_valid(a->uid))
- goto err;
-
- break;
- case KDBUS_POLICY_ACCESS_GROUP:
- a->gid = make_kgid(current_user_ns(), uaccess->id);
- if (!gid_valid(a->gid))
- goto err;
-
- break;
- case KDBUS_POLICY_ACCESS_WORLD:
- break;
- default:
- goto err;
- }
-
- a->type = uaccess->type;
-
- return a;
-
-err:
- kfree(a);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_policy_set() - set a connection's policy rules
- * @db: The policy database
- * @items: A list of kdbus_item elements that contain both
- * names and access rules to set.
- * @items_size: The total size of the items.
- * @max_policies: The maximum number of policy entries to allow.
- * Pass 0 for no limit.
- * @allow_wildcards: Boolean value whether wildcard entries (such
- * ending on '.*') should be allowed.
- * @owner: The owner of the new policy items.
- *
- * This function sets a new set of policies for a given owner. The names and
- * access rules are gathered by walking the list of items passed in as
- * argument. An item of type KDBUS_ITEM_NAME is expected before any number of
- * KDBUS_ITEM_POLICY_ACCESS items. If there are more repetitions of this
- * pattern than denoted in @max_policies, -EINVAL is returned.
- *
- * In order to allow atomic replacement of rules, the function first removes
- * all entries that have been created for the given owner previously.
- *
- * Callers to this function must make sure that the owner is a custom
- * endpoint, or if the endpoint is a default endpoint, then it must be
- * either a policy holder or an activator.
- *
- * Return: 0 on success, negative errno on failure.
- */
-int kdbus_policy_set(struct kdbus_policy_db *db,
- const struct kdbus_item *items,
- size_t items_size,
- size_t max_policies,
- bool allow_wildcards,
- const void *owner)
-{
- struct kdbus_policy_db_entry_access *a;
- struct kdbus_policy_db_entry *e, *p;
- const struct kdbus_item *item;
- struct hlist_node *tmp;
- HLIST_HEAD(entries);
- HLIST_HEAD(restore);
- size_t count = 0;
- int i, ret = 0;
- u32 hash;
-
- /* Walk the list of items and look for new policies */
- e = NULL;
- KDBUS_ITEMS_FOREACH(item, items, items_size) {
- switch (item->type) {
- case KDBUS_ITEM_NAME: {
- size_t len;
-
- if (max_policies && ++count > max_policies) {
- ret = -E2BIG;
- goto exit;
- }
-
- if (!kdbus_name_is_valid(item->str, true)) {
- ret = -EINVAL;
- goto exit;
- }
-
- e = kzalloc(sizeof(*e), GFP_KERNEL);
- if (!e) {
- ret = -ENOMEM;
- goto exit;
- }
-
- INIT_LIST_HEAD(&e->access_list);
- e->owner = owner;
- hlist_add_head(&e->hentry, &entries);
-
- e->name = kstrdup(item->str, GFP_KERNEL);
- if (!e->name) {
- ret = -ENOMEM;
- goto exit;
- }
-
- /*
- * If a supplied name ends with an '.*', cut off that
- * part, only store anything before it, and mark the
- * entry as wildcard.
- */
- len = strlen(e->name);
- if (len > 2 &&
- e->name[len - 3] == '.' &&
- e->name[len - 2] == '*') {
- if (!allow_wildcards) {
- ret = -EINVAL;
- goto exit;
- }
-
- e->name[len - 3] = '\0';
- e->wildcard = true;
- }
-
- break;
- }
-
- case KDBUS_ITEM_POLICY_ACCESS:
- if (!e) {
- ret = -EINVAL;
- goto exit;
- }
-
- a = kdbus_policy_make_access(&item->policy_access);
- if (IS_ERR(a)) {
- ret = PTR_ERR(a);
- goto exit;
- }
-
- list_add_tail(&a->list, &e->access_list);
- break;
- }
- }
-
- down_write(&db->entries_rwlock);
-
- /* remember previous entries to restore in case of failure */
- hash_for_each_safe(db->entries_hash, i, tmp, e, hentry)
- if (e->owner == owner) {
- hash_del(&e->hentry);
- hlist_add_head(&e->hentry, &restore);
- }
-
- hlist_for_each_entry_safe(e, tmp, &entries, hentry) {
- /* prevent duplicates */
- hash = kdbus_strhash(e->name);
- hash_for_each_possible(db->entries_hash, p, hentry, hash)
- if (strcmp(e->name, p->name) == 0 &&
- e->wildcard == p->wildcard) {
- ret = -EEXIST;
- goto restore;
- }
-
- hlist_del(&e->hentry);
- hash_add(db->entries_hash, &e->hentry, hash);
- }
-
-restore:
- /* if we failed, flush all entries we added so far */
- if (ret < 0)
- __kdbus_policy_remove_owner(db, owner);
-
- /* if we failed, restore entries, otherwise release them */
- hlist_for_each_entry_safe(e, tmp, &restore, hentry) {
- hlist_del(&e->hentry);
- if (ret < 0) {
- hash = kdbus_strhash(e->name);
- hash_add(db->entries_hash, &e->hentry, hash);
- } else {
- kdbus_policy_entry_free(e);
- }
- }
-
- up_write(&db->entries_rwlock);
-
-exit:
- hlist_for_each_entry_safe(e, tmp, &entries, hentry) {
- hlist_del(&e->hentry);
- kdbus_policy_entry_free(e);
- }
-
- return ret;
-}
diff --git a/ipc/kdbus/policy.h b/ipc/kdbus/policy.h
deleted file mode 100644
index 15dd7bc12..000000000
--- a/ipc/kdbus/policy.h
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_POLICY_H
-#define __KDBUS_POLICY_H
-
-#include <linux/hashtable.h>
-#include <linux/rwsem.h>
-
-struct kdbus_conn;
-struct kdbus_item;
-
-/**
- * struct kdbus_policy_db - policy database
- * @entries_hash: Hashtable of entries
- * @entries_rwlock: Mutex to protect the database's access entries
- */
-struct kdbus_policy_db {
- DECLARE_HASHTABLE(entries_hash, 6);
- struct rw_semaphore entries_rwlock;
-};
-
-void kdbus_policy_db_init(struct kdbus_policy_db *db);
-void kdbus_policy_db_clear(struct kdbus_policy_db *db);
-
-int kdbus_policy_query_unlocked(struct kdbus_policy_db *db,
- const struct cred *cred, const char *name,
- unsigned int hash);
-int kdbus_policy_query(struct kdbus_policy_db *db, const struct cred *cred,
- const char *name, unsigned int hash);
-
-void kdbus_policy_remove_owner(struct kdbus_policy_db *db,
- const void *owner);
-int kdbus_policy_set(struct kdbus_policy_db *db,
- const struct kdbus_item *items,
- size_t items_size,
- size_t max_policies,
- bool allow_wildcards,
- const void *owner);
-
-#endif
diff --git a/ipc/kdbus/pool.c b/ipc/kdbus/pool.c
deleted file mode 100644
index c65043e8c..000000000
--- a/ipc/kdbus/pool.c
+++ /dev/null
@@ -1,728 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/aio.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/highmem.h>
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/pagemap.h>
-#include <linux/rbtree.h>
-#include <linux/sched.h>
-#include <linux/shmem_fs.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-
-#include "pool.h"
-#include "util.h"
-
-/**
- * struct kdbus_pool - the receiver's buffer
- * @f: The backing shmem file
- * @size: The size of the file
- * @accounted_size: Currently accounted memory in bytes
- * @lock: Pool data lock
- * @slices: All slices sorted by address
- * @slices_busy: Tree of allocated slices
- * @slices_free: Tree of free slices
- *
- * The receiver's buffer, managed as a pool of allocated and free
- * slices containing the queued messages.
- *
- * Messages sent with KDBUS_CMD_SEND are copied directly by the
- * sending process into the receiver's pool.
- *
- * Messages received with KDBUS_CMD_RECV just return the offset
- * to the data placed in the pool.
- *
- * The internally allocated memory needs to be returned by the receiver
- * with KDBUS_CMD_FREE.
- */
-struct kdbus_pool {
- struct file *f;
- size_t size;
- size_t accounted_size;
- struct mutex lock;
-
- struct list_head slices;
- struct rb_root slices_busy;
- struct rb_root slices_free;
-};
-
-/**
- * struct kdbus_pool_slice - allocated element in kdbus_pool
- * @pool: Pool this slice belongs to
- * @off: Offset of slice in the shmem file
- * @size: Size of slice
- * @entry: Entry in "all slices" list
- * @rb_node: Entry in free or busy list
- * @free: Unused slice
- * @accounted: Accounted as queue slice
- * @ref_kernel: Kernel holds a reference
- * @ref_user: Userspace holds a reference
- *
- * The pool has one or more slices, always spanning the entire size of the
- * pool.
- *
- * Every slice is an element in a list sorted by the buffer address, to
- * provide access to the next neighbor slice.
- *
- * Every slice is member in either the busy or the free tree. The free
- * tree is organized by slice size, the busy tree organized by buffer
- * offset.
- */
-struct kdbus_pool_slice {
- struct kdbus_pool *pool;
- size_t off;
- size_t size;
-
- struct list_head entry;
- struct rb_node rb_node;
-
- bool free:1;
- bool accounted:1;
- bool ref_kernel:1;
- bool ref_user:1;
-};
-
-static struct kdbus_pool_slice *kdbus_pool_slice_new(struct kdbus_pool *pool,
- size_t off, size_t size)
-{
- struct kdbus_pool_slice *slice;
-
- slice = kzalloc(sizeof(*slice), GFP_KERNEL);
- if (!slice)
- return NULL;
-
- slice->pool = pool;
- slice->off = off;
- slice->size = size;
- slice->free = true;
- return slice;
-}
-
-/* insert a slice into the free tree */
-static void kdbus_pool_add_free_slice(struct kdbus_pool *pool,
- struct kdbus_pool_slice *slice)
-{
- struct rb_node **n;
- struct rb_node *pn = NULL;
-
- n = &pool->slices_free.rb_node;
- while (*n) {
- struct kdbus_pool_slice *pslice;
-
- pn = *n;
- pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
- if (slice->size < pslice->size)
- n = &pn->rb_left;
- else
- n = &pn->rb_right;
- }
-
- rb_link_node(&slice->rb_node, pn, n);
- rb_insert_color(&slice->rb_node, &pool->slices_free);
-}
-
-/* insert a slice into the busy tree */
-static void kdbus_pool_add_busy_slice(struct kdbus_pool *pool,
- struct kdbus_pool_slice *slice)
-{
- struct rb_node **n;
- struct rb_node *pn = NULL;
-
- n = &pool->slices_busy.rb_node;
- while (*n) {
- struct kdbus_pool_slice *pslice;
-
- pn = *n;
- pslice = rb_entry(pn, struct kdbus_pool_slice, rb_node);
- if (slice->off < pslice->off)
- n = &pn->rb_left;
- else if (slice->off > pslice->off)
- n = &pn->rb_right;
- else
- BUG();
- }
-
- rb_link_node(&slice->rb_node, pn, n);
- rb_insert_color(&slice->rb_node, &pool->slices_busy);
-}
-
-static struct kdbus_pool_slice *kdbus_pool_find_slice(struct kdbus_pool *pool,
- size_t off)
-{
- struct rb_node *n;
-
- n = pool->slices_busy.rb_node;
- while (n) {
- struct kdbus_pool_slice *s;
-
- s = rb_entry(n, struct kdbus_pool_slice, rb_node);
- if (off < s->off)
- n = n->rb_left;
- else if (off > s->off)
- n = n->rb_right;
- else
- return s;
- }
-
- return NULL;
-}
-
-/**
- * kdbus_pool_slice_alloc() - allocate memory from a pool
- * @pool: The receiver's pool
- * @size: The number of bytes to allocate
- * @accounted: Whether this slice should be accounted for
- *
- * The returned slice is used for kdbus_pool_slice_release() to
- * free the allocated memory. If either @kvec or @iovec is non-NULL, the data
- * will be copied from kernel or userspace memory into the new slice at
- * offset 0.
- *
- * Return: the allocated slice on success, ERR_PTR on failure.
- */
-struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
- size_t size, bool accounted)
-{
- size_t slice_size = KDBUS_ALIGN8(size);
- struct rb_node *n, *found = NULL;
- struct kdbus_pool_slice *s;
- int ret = 0;
-
- if (WARN_ON(!size))
- return ERR_PTR(-EINVAL);
-
- /* search a free slice with the closest matching size */
- mutex_lock(&pool->lock);
- n = pool->slices_free.rb_node;
- while (n) {
- s = rb_entry(n, struct kdbus_pool_slice, rb_node);
- if (slice_size < s->size) {
- found = n;
- n = n->rb_left;
- } else if (slice_size > s->size) {
- n = n->rb_right;
- } else {
- found = n;
- break;
- }
- }
-
- /* no slice with the minimum size found in the pool */
- if (!found) {
- ret = -EXFULL;
- goto exit_unlock;
- }
-
- /* no exact match, use the closest one */
- if (!n) {
- struct kdbus_pool_slice *s_new;
-
- s = rb_entry(found, struct kdbus_pool_slice, rb_node);
-
- /* split-off the remainder of the size to its own slice */
- s_new = kdbus_pool_slice_new(pool, s->off + slice_size,
- s->size - slice_size);
- if (!s_new) {
- ret = -ENOMEM;
- goto exit_unlock;
- }
-
- list_add(&s_new->entry, &s->entry);
- kdbus_pool_add_free_slice(pool, s_new);
-
- /* adjust our size now that we split-off another slice */
- s->size = slice_size;
- }
-
- /* move slice from free to the busy tree */
- rb_erase(found, &pool->slices_free);
- kdbus_pool_add_busy_slice(pool, s);
-
- WARN_ON(s->ref_kernel || s->ref_user);
-
- s->ref_kernel = true;
- s->free = false;
- s->accounted = accounted;
- if (accounted)
- pool->accounted_size += s->size;
- mutex_unlock(&pool->lock);
-
- return s;
-
-exit_unlock:
- mutex_unlock(&pool->lock);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
-{
- struct kdbus_pool *pool = slice->pool;
-
- /* don't free the slice if either has a reference */
- if (slice->ref_kernel || slice->ref_user)
- return;
-
- if (WARN_ON(slice->free))
- return;
-
- rb_erase(&slice->rb_node, &pool->slices_busy);
-
- /* merge with the next free slice */
- if (!list_is_last(&slice->entry, &pool->slices)) {
- struct kdbus_pool_slice *s;
-
- s = list_entry(slice->entry.next,
- struct kdbus_pool_slice, entry);
- if (s->free) {
- rb_erase(&s->rb_node, &pool->slices_free);
- list_del(&s->entry);
- slice->size += s->size;
- kfree(s);
- }
- }
-
- /* merge with previous free slice */
- if (pool->slices.next != &slice->entry) {
- struct kdbus_pool_slice *s;
-
- s = list_entry(slice->entry.prev,
- struct kdbus_pool_slice, entry);
- if (s->free) {
- rb_erase(&s->rb_node, &pool->slices_free);
- list_del(&slice->entry);
- s->size += slice->size;
- kfree(slice);
- slice = s;
- }
- }
-
- slice->free = true;
- kdbus_pool_add_free_slice(pool, slice);
-}
-
-/**
- * kdbus_pool_slice_release() - drop kernel-reference on allocated slice
- * @slice: Slice allocated from the pool
- *
- * This releases the kernel-reference on the given slice. If the
- * kernel-reference and the user-reference on a slice are dropped, the slice is
- * returned to the pool.
- *
- * So far, we do not implement full ref-counting on slices. Each, kernel and
- * user-space can have exactly one reference to a slice. If both are dropped at
- * the same time, the slice is released.
- */
-void kdbus_pool_slice_release(struct kdbus_pool_slice *slice)
-{
- struct kdbus_pool *pool;
-
- if (!slice)
- return;
-
- /* @slice may be freed, so keep local ptr to @pool */
- pool = slice->pool;
-
- mutex_lock(&pool->lock);
- /* kernel must own a ref to @slice to drop it */
- WARN_ON(!slice->ref_kernel);
- slice->ref_kernel = false;
- /* no longer kernel-owned, de-account slice */
- if (slice->accounted && !WARN_ON(pool->accounted_size < slice->size))
- pool->accounted_size -= slice->size;
- __kdbus_pool_slice_release(slice);
- mutex_unlock(&pool->lock);
-}
-
-/**
- * kdbus_pool_release_offset() - release a public offset
- * @pool: pool to operate on
- * @off: offset to release
- *
- * This should be called whenever user-space frees a slice given to them. It
- * verifies the slice is available and public, and then drops it. It ensures
- * correct locking and barriers against queues.
- *
- * Return: 0 on success, ENXIO if the offset is invalid or not public.
- */
-int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off)
-{
- struct kdbus_pool_slice *slice;
- int ret = 0;
-
- /* 'pool->size' is used as dummy offset for empty slices */
- if (off == pool->size)
- return 0;
-
- mutex_lock(&pool->lock);
- slice = kdbus_pool_find_slice(pool, off);
- if (slice && slice->ref_user) {
- slice->ref_user = false;
- __kdbus_pool_slice_release(slice);
- } else {
- ret = -ENXIO;
- }
- mutex_unlock(&pool->lock);
-
- return ret;
-}
-
-/**
- * kdbus_pool_publish_empty() - publish empty slice to user-space
- * @pool: pool to operate on
- * @off: output storage for offset, or NULL
- * @size: output storage for size, or NULL
- *
- * This is the same as kdbus_pool_slice_publish(), but uses a dummy slice with
- * size 0. The returned offset points to the end of the pool and is never
- * returned on real slices.
- */
-void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size)
-{
- if (off)
- *off = pool->size;
- if (size)
- *size = 0;
-}
-
-/**
- * kdbus_pool_slice_publish() - publish slice to user-space
- * @slice: The slice
- * @out_offset: Output storage for offset, or NULL
- * @out_size: Output storage for size, or NULL
- *
- * This prepares a slice to be published to user-space.
- *
- * This call combines the following operations:
- * * the memory region is flushed so the user's memory view is consistent
- * * the slice is marked as referenced by user-space, so user-space has to
- * call KDBUS_CMD_FREE to release it
- * * the offset and size of the slice are written to the given output
- * arguments, if non-NULL
- */
-void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
- u64 *out_offset, u64 *out_size)
-{
- mutex_lock(&slice->pool->lock);
- /* kernel must own a ref to @slice to gain a user-space ref */
- WARN_ON(!slice->ref_kernel);
- slice->ref_user = true;
- mutex_unlock(&slice->pool->lock);
-
- if (out_offset)
- *out_offset = slice->off;
- if (out_size)
- *out_size = slice->size;
-}
-
-/**
- * kdbus_pool_slice_offset() - Get a slice's offset inside the pool
- * @slice: Slice to return the offset of
- *
- * Return: The internal offset @slice inside the pool.
- */
-off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice)
-{
- return slice->off;
-}
-
-/**
- * kdbus_pool_slice_size() - get size of a pool slice
- * @slice: slice to query
- *
- * Return: size of the given slice
- */
-size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice)
-{
- return slice->size;
-}
-
-/**
- * kdbus_pool_new() - create a new pool
- * @name: Name of the (deleted) file which shows up in
- * /proc, used for debugging
- * @size: Maximum size of the pool
- *
- * Return: a new kdbus_pool on success, ERR_PTR on failure.
- */
-struct kdbus_pool *kdbus_pool_new(const char *name, size_t size)
-{
- struct kdbus_pool_slice *s;
- struct kdbus_pool *p;
- struct file *f;
- char *n = NULL;
- int ret;
-
- p = kzalloc(sizeof(*p), GFP_KERNEL);
- if (!p)
- return ERR_PTR(-ENOMEM);
-
- if (name) {
- n = kasprintf(GFP_KERNEL, KBUILD_MODNAME "-conn:%s", name);
- if (!n) {
- ret = -ENOMEM;
- goto exit_free;
- }
- }
-
- f = shmem_file_setup(n ?: KBUILD_MODNAME "-conn", size, 0, 0);
- kfree(n);
-
- if (IS_ERR(f)) {
- ret = PTR_ERR(f);
- goto exit_free;
- }
-
- ret = get_write_access(file_inode(f));
- if (ret < 0)
- goto exit_put_shmem;
-
- /* allocate first slice spanning the entire pool */
- s = kdbus_pool_slice_new(p, 0, size);
- if (!s) {
- ret = -ENOMEM;
- goto exit_put_write;
- }
-
- p->f = f;
- p->size = size;
- p->slices_free = RB_ROOT;
- p->slices_busy = RB_ROOT;
- mutex_init(&p->lock);
-
- INIT_LIST_HEAD(&p->slices);
- list_add(&s->entry, &p->slices);
-
- kdbus_pool_add_free_slice(p, s);
- return p;
-
-exit_put_write:
- put_write_access(file_inode(f));
-exit_put_shmem:
- fput(f);
-exit_free:
- kfree(p);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_pool_free() - destroy pool
- * @pool: The receiver's pool
- */
-void kdbus_pool_free(struct kdbus_pool *pool)
-{
- struct kdbus_pool_slice *s, *tmp;
-
- if (!pool)
- return;
-
- list_for_each_entry_safe(s, tmp, &pool->slices, entry) {
- list_del(&s->entry);
- kfree(s);
- }
-
- put_write_access(file_inode(pool->f));
- fput(pool->f);
- kfree(pool);
-}
-
-/**
- * kdbus_pool_accounted() - retrieve accounting information
- * @pool: pool to query
- * @size: output for overall pool size
- * @acc: output for currently accounted size
- *
- * This returns accounting information of the pool. Note that the data might
- * change after the function returns, as the pool lock is dropped. You need to
- * protect the data via other means, if you need reliable accounting.
- */
-void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc)
-{
- mutex_lock(&pool->lock);
- if (size)
- *size = pool->size;
- if (acc)
- *acc = pool->accounted_size;
- mutex_unlock(&pool->lock);
-}
-
-/**
- * kdbus_pool_slice_copy_iovec() - copy user memory to a slice
- * @slice: The slice to write to
- * @off: Offset in the slice to write to
- * @iov: iovec array, pointing to data to copy
- * @iov_len: Number of elements in @iov
- * @total_len: Total number of bytes described in members of @iov
- *
- * User memory referenced by @iov will be copied into @slice at offset @off.
- *
- * Return: the numbers of bytes copied, negative errno on failure.
- */
-ssize_t
-kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice, loff_t off,
- struct iovec *iov, size_t iov_len, size_t total_len)
-{
- struct iov_iter iter;
- ssize_t len;
-
- if (WARN_ON(off + total_len > slice->size))
- return -EFAULT;
-
- off += slice->off;
- iov_iter_init(&iter, WRITE, iov, iov_len, total_len);
- len = vfs_iter_write(slice->pool->f, &iter, &off);
-
- return (len >= 0 && len != total_len) ? -EFAULT : len;
-}
-
-/**
- * kdbus_pool_slice_copy_kvec() - copy kernel memory to a slice
- * @slice: The slice to write to
- * @off: Offset in the slice to write to
- * @kvec: kvec array, pointing to data to copy
- * @kvec_len: Number of elements in @kvec
- * @total_len: Total number of bytes described in members of @kvec
- *
- * Kernel memory referenced by @kvec will be copied into @slice at offset @off.
- *
- * Return: the numbers of bytes copied, negative errno on failure.
- */
-ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
- loff_t off, struct kvec *kvec,
- size_t kvec_len, size_t total_len)
-{
- struct iov_iter iter;
- mm_segment_t old_fs;
- ssize_t len;
-
- if (WARN_ON(off + total_len > slice->size))
- return -EFAULT;
-
- off += slice->off;
- iov_iter_kvec(&iter, WRITE | ITER_KVEC, kvec, kvec_len, total_len);
-
- old_fs = get_fs();
- set_fs(get_ds());
- len = vfs_iter_write(slice->pool->f, &iter, &off);
- set_fs(old_fs);
-
- return (len >= 0 && len != total_len) ? -EFAULT : len;
-}
-
-/**
- * kdbus_pool_slice_copy() - copy data from one slice into another
- * @slice_dst: destination slice
- * @slice_src: source slice
- *
- * Return: 0 on success, negative error number on failure.
- */
-int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
- const struct kdbus_pool_slice *slice_src)
-{
- struct file *f_src = slice_src->pool->f;
- struct file *f_dst = slice_dst->pool->f;
- struct inode *i_dst = file_inode(f_dst);
- struct address_space *mapping_dst = f_dst->f_mapping;
- const struct address_space_operations *aops = mapping_dst->a_ops;
- unsigned long len = slice_src->size;
- loff_t off_src = slice_src->off;
- loff_t off_dst = slice_dst->off;
- mm_segment_t old_fs;
- int ret = 0;
-
- if (WARN_ON(slice_src->size != slice_dst->size) ||
- WARN_ON(slice_src->free || slice_dst->free))
- return -EINVAL;
-
- mutex_lock(&i_dst->i_mutex);
- old_fs = get_fs();
- set_fs(get_ds());
- while (len > 0) {
- unsigned long page_off;
- unsigned long copy_len;
- char __user *kaddr;
- struct page *page;
- ssize_t n_read;
- void *fsdata;
- long status;
-
- page_off = off_dst & (PAGE_CACHE_SIZE - 1);
- copy_len = min_t(unsigned long,
- PAGE_CACHE_SIZE - page_off, len);
-
- status = aops->write_begin(f_dst, mapping_dst, off_dst,
- copy_len, 0, &page, &fsdata);
- if (unlikely(status < 0)) {
- ret = status;
- break;
- }
-
- kaddr = (char __force __user *)kmap(page) + page_off;
- n_read = __vfs_read(f_src, kaddr, copy_len, &off_src);
- kunmap(page);
- mark_page_accessed(page);
- flush_dcache_page(page);
-
- if (unlikely(n_read != copy_len)) {
- ret = -EFAULT;
- break;
- }
-
- status = aops->write_end(f_dst, mapping_dst, off_dst,
- copy_len, copy_len, page, fsdata);
- if (unlikely(status != copy_len)) {
- ret = -EFAULT;
- break;
- }
-
- off_dst += copy_len;
- len -= copy_len;
- }
- set_fs(old_fs);
- mutex_unlock(&i_dst->i_mutex);
-
- return ret;
-}
-
-/**
- * kdbus_pool_mmap() - map the pool into the process
- * @pool: The receiver's pool
- * @vma: passed by mmap() syscall
- *
- * Return: the result of the mmap() call, negative errno on failure.
- */
-int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma)
-{
- /* deny write access to the pool */
- if (vma->vm_flags & VM_WRITE)
- return -EPERM;
- vma->vm_flags &= ~VM_MAYWRITE;
-
- /* do not allow to map more than the size of the file */
- if ((vma->vm_end - vma->vm_start) > pool->size)
- return -EFAULT;
-
- /* replace the connection file with our shmem file */
- if (vma->vm_file)
- fput(vma->vm_file);
- vma->vm_file = get_file(pool->f);
-
- return pool->f->f_op->mmap(pool->f, vma);
-}
diff --git a/ipc/kdbus/pool.h b/ipc/kdbus/pool.h
deleted file mode 100644
index a9038213a..000000000
--- a/ipc/kdbus/pool.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_POOL_H
-#define __KDBUS_POOL_H
-
-#include <linux/uio.h>
-
-struct kdbus_pool;
-struct kdbus_pool_slice;
-
-struct kdbus_pool *kdbus_pool_new(const char *name, size_t size);
-void kdbus_pool_free(struct kdbus_pool *pool);
-void kdbus_pool_accounted(struct kdbus_pool *pool, size_t *size, size_t *acc);
-int kdbus_pool_mmap(const struct kdbus_pool *pool, struct vm_area_struct *vma);
-int kdbus_pool_release_offset(struct kdbus_pool *pool, size_t off);
-void kdbus_pool_publish_empty(struct kdbus_pool *pool, u64 *off, u64 *size);
-
-struct kdbus_pool_slice *kdbus_pool_slice_alloc(struct kdbus_pool *pool,
- size_t size, bool accounted);
-void kdbus_pool_slice_release(struct kdbus_pool_slice *slice);
-void kdbus_pool_slice_publish(struct kdbus_pool_slice *slice,
- u64 *out_offset, u64 *out_size);
-off_t kdbus_pool_slice_offset(const struct kdbus_pool_slice *slice);
-size_t kdbus_pool_slice_size(const struct kdbus_pool_slice *slice);
-int kdbus_pool_slice_copy(const struct kdbus_pool_slice *slice_dst,
- const struct kdbus_pool_slice *slice_src);
-ssize_t kdbus_pool_slice_copy_kvec(const struct kdbus_pool_slice *slice,
- loff_t off, struct kvec *kvec,
- size_t kvec_count, size_t total_len);
-ssize_t kdbus_pool_slice_copy_iovec(const struct kdbus_pool_slice *slice,
- loff_t off, struct iovec *iov,
- size_t iov_count, size_t total_len);
-
-#endif
diff --git a/ipc/kdbus/queue.c b/ipc/kdbus/queue.c
deleted file mode 100644
index f9c44d7ba..000000000
--- a/ipc/kdbus/queue.c
+++ /dev/null
@@ -1,363 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/audit.h>
-#include <linux/file.h>
-#include <linux/fs.h>
-#include <linux/hashtable.h>
-#include <linux/idr.h>
-#include <linux/init.h>
-#include <linux/math64.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/poll.h>
-#include <linux/sched.h>
-#include <linux/sizes.h>
-#include <linux/slab.h>
-#include <linux/syscalls.h>
-#include <linux/uio.h>
-
-#include "util.h"
-#include "domain.h"
-#include "connection.h"
-#include "item.h"
-#include "message.h"
-#include "metadata.h"
-#include "queue.h"
-#include "reply.h"
-
-/**
- * kdbus_queue_init() - initialize data structure related to a queue
- * @queue: The queue to initialize
- */
-void kdbus_queue_init(struct kdbus_queue *queue)
-{
- INIT_LIST_HEAD(&queue->msg_list);
- queue->msg_prio_queue = RB_ROOT;
-}
-
-/**
- * kdbus_queue_peek() - Retrieves an entry from a queue
- * @queue: The queue
- * @priority: The minimum priority of the entry to peek
- * @use_priority: Boolean flag whether or not to peek by priority
- *
- * Look for a entry in a queue, either by priority, or the oldest one (FIFO).
- * The entry is not freed, put off the queue's lists or anything else.
- *
- * Return: the peeked queue entry on success, NULL if no suitable msg is found
- */
-struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue,
- s64 priority, bool use_priority)
-{
- struct kdbus_queue_entry *e;
-
- if (list_empty(&queue->msg_list))
- return NULL;
-
- if (use_priority) {
- /* get next entry with highest priority */
- e = rb_entry(queue->msg_prio_highest,
- struct kdbus_queue_entry, prio_node);
-
- /* no entry with the requested priority */
- if (e->priority > priority)
- return NULL;
- } else {
- /* ignore the priority, return the next entry in the entry */
- e = list_first_entry(&queue->msg_list,
- struct kdbus_queue_entry, entry);
- }
-
- return e;
-}
-
-static void kdbus_queue_entry_link(struct kdbus_queue_entry *entry)
-{
- struct kdbus_queue *queue = &entry->conn->queue;
- struct rb_node **n, *pn = NULL;
- bool highest = true;
-
- lockdep_assert_held(&entry->conn->lock);
- if (WARN_ON(!list_empty(&entry->entry)))
- return;
-
- /* sort into priority entry tree */
- n = &queue->msg_prio_queue.rb_node;
- while (*n) {
- struct kdbus_queue_entry *e;
-
- pn = *n;
- e = rb_entry(pn, struct kdbus_queue_entry, prio_node);
-
- /* existing node for this priority, add to its list */
- if (likely(entry->priority == e->priority)) {
- list_add_tail(&entry->prio_entry, &e->prio_entry);
- goto prio_done;
- }
-
- if (entry->priority < e->priority) {
- n = &pn->rb_left;
- } else {
- n = &pn->rb_right;
- highest = false;
- }
- }
-
- /* cache highest-priority entry */
- if (highest)
- queue->msg_prio_highest = &entry->prio_node;
-
- /* new node for this priority */
- rb_link_node(&entry->prio_node, pn, n);
- rb_insert_color(&entry->prio_node, &queue->msg_prio_queue);
- INIT_LIST_HEAD(&entry->prio_entry);
-
-prio_done:
- /* add to unsorted fifo list */
- list_add_tail(&entry->entry, &queue->msg_list);
-}
-
-static void kdbus_queue_entry_unlink(struct kdbus_queue_entry *entry)
-{
- struct kdbus_queue *queue = &entry->conn->queue;
-
- lockdep_assert_held(&entry->conn->lock);
- if (list_empty(&entry->entry))
- return;
-
- list_del_init(&entry->entry);
-
- if (list_empty(&entry->prio_entry)) {
- /*
- * Single entry for this priority, update cached
- * highest-priority entry, remove the tree node.
- */
- if (queue->msg_prio_highest == &entry->prio_node)
- queue->msg_prio_highest = rb_next(&entry->prio_node);
-
- rb_erase(&entry->prio_node, &queue->msg_prio_queue);
- } else {
- struct kdbus_queue_entry *q;
-
- /*
- * Multiple entries for this priority entry, get next one in
- * the list. Update cached highest-priority entry, store the
- * new one as the tree node.
- */
- q = list_first_entry(&entry->prio_entry,
- struct kdbus_queue_entry, prio_entry);
- list_del(&entry->prio_entry);
-
- if (queue->msg_prio_highest == &entry->prio_node)
- queue->msg_prio_highest = &q->prio_node;
-
- rb_replace_node(&entry->prio_node, &q->prio_node,
- &queue->msg_prio_queue);
- }
-}
-
-/**
- * kdbus_queue_entry_new() - allocate a queue entry
- * @src: source connection, or NULL
- * @dst: destination connection
- * @s: staging object carrying the message
- *
- * Allocates a queue entry based on a given msg and allocate space for
- * the message payload and the requested metadata in the connection's pool.
- * The entry is not actually added to the queue's lists at this point.
- *
- * Return: the allocated entry on success, or an ERR_PTR on failures.
- */
-struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src,
- struct kdbus_conn *dst,
- struct kdbus_staging *s)
-{
- struct kdbus_queue_entry *entry;
- int ret;
-
- entry = kzalloc(sizeof(*entry), GFP_KERNEL);
- if (!entry)
- return ERR_PTR(-ENOMEM);
-
- INIT_LIST_HEAD(&entry->entry);
- entry->priority = s->msg->priority;
- entry->conn = kdbus_conn_ref(dst);
- entry->gaps = kdbus_gaps_ref(s->gaps);
-
- entry->slice = kdbus_staging_emit(s, src, dst);
- if (IS_ERR(entry->slice)) {
- ret = PTR_ERR(entry->slice);
- entry->slice = NULL;
- goto error;
- }
-
- entry->user = src ? kdbus_user_ref(src->user) : NULL;
- return entry;
-
-error:
- kdbus_queue_entry_free(entry);
- return ERR_PTR(ret);
-}
-
-/**
- * kdbus_queue_entry_free() - free resources of an entry
- * @entry: The entry to free
- *
- * Removes resources allocated by a queue entry, along with the entry itself.
- * Note that the entry's slice is not freed at this point.
- */
-void kdbus_queue_entry_free(struct kdbus_queue_entry *entry)
-{
- if (!entry)
- return;
-
- lockdep_assert_held(&entry->conn->lock);
-
- kdbus_queue_entry_unlink(entry);
- kdbus_reply_unref(entry->reply);
-
- if (entry->slice) {
- kdbus_conn_quota_dec(entry->conn, entry->user,
- kdbus_pool_slice_size(entry->slice),
- entry->gaps ? entry->gaps->n_fds : 0);
- kdbus_pool_slice_release(entry->slice);
- }
-
- kdbus_user_unref(entry->user);
- kdbus_gaps_unref(entry->gaps);
- kdbus_conn_unref(entry->conn);
- kfree(entry);
-}
-
-/**
- * kdbus_queue_entry_install() - install message components into the
- * receiver's process
- * @entry: The queue entry to install
- * @return_flags: Pointer to store the return flags for userspace
- * @install_fds: Whether or not to install associated file descriptors
- *
- * Return: 0 on success.
- */
-int kdbus_queue_entry_install(struct kdbus_queue_entry *entry,
- u64 *return_flags, bool install_fds)
-{
- bool incomplete_fds = false;
- int ret;
-
- lockdep_assert_held(&entry->conn->lock);
-
- ret = kdbus_gaps_install(entry->gaps, entry->slice, &incomplete_fds);
- if (ret < 0)
- return ret;
-
- if (incomplete_fds)
- *return_flags |= KDBUS_RECV_RETURN_INCOMPLETE_FDS;
- return 0;
-}
-
-/**
- * kdbus_queue_entry_enqueue() - enqueue an entry
- * @entry: entry to enqueue
- * @reply: reply to link to this entry (or NULL if none)
- *
- * This enqueues an unqueued entry into the message queue of the linked
- * connection. It also binds a reply object to the entry so we can remember it
- * when the message is moved.
- *
- * Once this call returns (and the connection lock is released), this entry can
- * be dequeued by the target connection. Note that the entry will not be removed
- * from the queue until it is destroyed.
- */
-void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry,
- struct kdbus_reply *reply)
-{
- lockdep_assert_held(&entry->conn->lock);
-
- if (WARN_ON(entry->reply) || WARN_ON(!list_empty(&entry->entry)))
- return;
-
- entry->reply = kdbus_reply_ref(reply);
- kdbus_queue_entry_link(entry);
-}
-
-/**
- * kdbus_queue_entry_move() - move queue entry
- * @e: queue entry to move
- * @dst: destination connection to queue the entry on
- *
- * This moves a queue entry onto a different connection. It allocates a new
- * slice on the target connection and copies the message over. If the copy
- * succeeded, we move the entry from @src to @dst.
- *
- * On failure, the entry is left untouched.
- *
- * The queue entry must be queued right now, and after the call succeeds it will
- * be queued on the destination, but no longer on the source.
- *
- * The caller must hold the connection lock of the source *and* destination.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_queue_entry_move(struct kdbus_queue_entry *e,
- struct kdbus_conn *dst)
-{
- struct kdbus_pool_slice *slice = NULL;
- struct kdbus_conn *src = e->conn;
- size_t size, fds;
- int ret;
-
- lockdep_assert_held(&src->lock);
- lockdep_assert_held(&dst->lock);
-
- if (WARN_ON(list_empty(&e->entry)))
- return -EINVAL;
- if (src == dst)
- return 0;
-
- size = kdbus_pool_slice_size(e->slice);
- fds = e->gaps ? e->gaps->n_fds : 0;
-
- ret = kdbus_conn_quota_inc(dst, e->user, size, fds);
- if (ret < 0)
- return ret;
-
- slice = kdbus_pool_slice_alloc(dst->pool, size, true);
- if (IS_ERR(slice)) {
- ret = PTR_ERR(slice);
- slice = NULL;
- goto error;
- }
-
- ret = kdbus_pool_slice_copy(slice, e->slice);
- if (ret < 0)
- goto error;
-
- kdbus_queue_entry_unlink(e);
- kdbus_conn_quota_dec(src, e->user, size, fds);
- kdbus_pool_slice_release(e->slice);
- kdbus_conn_unref(e->conn);
-
- e->slice = slice;
- e->conn = kdbus_conn_ref(dst);
- kdbus_queue_entry_link(e);
-
- return 0;
-
-error:
- kdbus_pool_slice_release(slice);
- kdbus_conn_quota_dec(dst, e->user, size, fds);
- return ret;
-}
diff --git a/ipc/kdbus/queue.h b/ipc/kdbus/queue.h
deleted file mode 100644
index bf686d182..000000000
--- a/ipc/kdbus/queue.h
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_QUEUE_H
-#define __KDBUS_QUEUE_H
-
-#include <linux/list.h>
-#include <linux/rbtree.h>
-
-struct kdbus_conn;
-struct kdbus_pool_slice;
-struct kdbus_reply;
-struct kdbus_staging;
-struct kdbus_user;
-
-/**
- * struct kdbus_queue - a connection's message queue
- * @msg_list: List head for kdbus_queue_entry objects
- * @msg_prio_queue: RB tree root for messages, sorted by priority
- * @msg_prio_highest: Link to the RB node referencing the message with the
- * highest priority in the tree.
- */
-struct kdbus_queue {
- struct list_head msg_list;
- struct rb_root msg_prio_queue;
- struct rb_node *msg_prio_highest;
-};
-
-/**
- * struct kdbus_queue_entry - messages waiting to be read
- * @entry: Entry in the connection's list
- * @prio_node: Entry in the priority queue tree
- * @prio_entry: Queue tree node entry in the list of one priority
- * @priority: Message priority
- * @dst_name_id: The sequence number of the name this message is
- * addressed to, 0 for messages sent to an ID
- * @conn: Connection this entry is queued on
- * @gaps: Gaps object to fill message gaps at RECV time
- * @user: User used for accounting
- * @slice: Slice in the receiver's pool for the message
- * @reply: The reply block if a reply to this message is expected
- */
-struct kdbus_queue_entry {
- struct list_head entry;
- struct rb_node prio_node;
- struct list_head prio_entry;
-
- s64 priority;
- u64 dst_name_id;
-
- struct kdbus_conn *conn;
- struct kdbus_gaps *gaps;
- struct kdbus_user *user;
- struct kdbus_pool_slice *slice;
- struct kdbus_reply *reply;
-};
-
-void kdbus_queue_init(struct kdbus_queue *queue);
-struct kdbus_queue_entry *kdbus_queue_peek(struct kdbus_queue *queue,
- s64 priority, bool use_priority);
-
-struct kdbus_queue_entry *kdbus_queue_entry_new(struct kdbus_conn *src,
- struct kdbus_conn *dst,
- struct kdbus_staging *s);
-void kdbus_queue_entry_free(struct kdbus_queue_entry *entry);
-int kdbus_queue_entry_install(struct kdbus_queue_entry *entry,
- u64 *return_flags, bool install_fds);
-void kdbus_queue_entry_enqueue(struct kdbus_queue_entry *entry,
- struct kdbus_reply *reply);
-int kdbus_queue_entry_move(struct kdbus_queue_entry *entry,
- struct kdbus_conn *dst);
-
-#endif /* __KDBUS_QUEUE_H */
diff --git a/ipc/kdbus/reply.c b/ipc/kdbus/reply.c
deleted file mode 100644
index e6791d86e..000000000
--- a/ipc/kdbus/reply.c
+++ /dev/null
@@ -1,252 +0,0 @@
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/mutex.h>
-#include <linux/slab.h>
-#include <linux/uio.h>
-
-#include "bus.h"
-#include "connection.h"
-#include "endpoint.h"
-#include "message.h"
-#include "metadata.h"
-#include "names.h"
-#include "domain.h"
-#include "item.h"
-#include "notify.h"
-#include "policy.h"
-#include "reply.h"
-#include "util.h"
-
-/**
- * kdbus_reply_new() - Allocate and set up a new kdbus_reply object
- * @reply_src: The connection a reply is expected from
- * @reply_dst: The connection this reply object belongs to
- * @msg: Message associated with the reply
- * @name_entry: Name entry used to send the message
- * @sync: Whether or not to make this reply synchronous
- *
- * Allocate and fill a new kdbus_reply object.
- *
- * Return: New kdbus_conn object on success, ERR_PTR on error.
- */
-struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
- struct kdbus_conn *reply_dst,
- const struct kdbus_msg *msg,
- struct kdbus_name_entry *name_entry,
- bool sync)
-{
- struct kdbus_reply *r;
- int ret;
-
- if (atomic_inc_return(&reply_dst->request_count) >
- KDBUS_CONN_MAX_REQUESTS_PENDING) {
- ret = -EMLINK;
- goto exit_dec_request_count;
- }
-
- r = kzalloc(sizeof(*r), GFP_KERNEL);
- if (!r) {
- ret = -ENOMEM;
- goto exit_dec_request_count;
- }
-
- kref_init(&r->kref);
- INIT_LIST_HEAD(&r->entry);
- r->reply_src = kdbus_conn_ref(reply_src);
- r->reply_dst = kdbus_conn_ref(reply_dst);
- r->cookie = msg->cookie;
- r->name_id = name_entry ? name_entry->name_id : 0;
- r->deadline_ns = msg->timeout_ns;
-
- if (sync) {
- r->sync = true;
- r->waiting = true;
- }
-
- return r;
-
-exit_dec_request_count:
- atomic_dec(&reply_dst->request_count);
- return ERR_PTR(ret);
-}
-
-static void __kdbus_reply_free(struct kref *kref)
-{
- struct kdbus_reply *reply =
- container_of(kref, struct kdbus_reply, kref);
-
- atomic_dec(&reply->reply_dst->request_count);
- kdbus_conn_unref(reply->reply_src);
- kdbus_conn_unref(reply->reply_dst);
- kfree(reply);
-}
-
-/**
- * kdbus_reply_ref() - Increase reference on kdbus_reply
- * @r: The reply, may be %NULL
- *
- * Return: The reply object with an extra reference
- */
-struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r)
-{
- if (r)
- kref_get(&r->kref);
- return r;
-}
-
-/**
- * kdbus_reply_unref() - Decrease reference on kdbus_reply
- * @r: The reply, may be %NULL
- *
- * Return: NULL
- */
-struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r)
-{
- if (r)
- kref_put(&r->kref, __kdbus_reply_free);
- return NULL;
-}
-
-/**
- * kdbus_reply_link() - Link reply object into target connection
- * @r: Reply to link
- */
-void kdbus_reply_link(struct kdbus_reply *r)
-{
- if (WARN_ON(!list_empty(&r->entry)))
- return;
-
- list_add(&r->entry, &r->reply_dst->reply_list);
- kdbus_reply_ref(r);
-}
-
-/**
- * kdbus_reply_unlink() - Unlink reply object from target connection
- * @r: Reply to unlink
- */
-void kdbus_reply_unlink(struct kdbus_reply *r)
-{
- if (!list_empty(&r->entry)) {
- list_del_init(&r->entry);
- kdbus_reply_unref(r);
- }
-}
-
-/**
- * kdbus_sync_reply_wakeup() - Wake a synchronously blocking reply
- * @reply: The reply object
- * @err: Error code to set on the remote side
- *
- * Wake up remote peer (method origin) with the appropriate synchronous reply
- * code.
- */
-void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err)
-{
- if (WARN_ON(!reply->sync))
- return;
-
- reply->waiting = false;
- reply->err = err;
- wake_up_interruptible(&reply->reply_dst->wait);
-}
-
-/**
- * kdbus_reply_find() - Find the corresponding reply object
- * @replying: The replying connection or NULL
- * @reply_dst: The connection the reply will be sent to
- * (method origin)
- * @cookie: The cookie of the requesting message
- *
- * Lookup a reply object that should be sent as a reply by
- * @replying to @reply_dst with the given cookie.
- *
- * Callers must take the @reply_dst lock.
- *
- * Return: the corresponding reply object or NULL if not found
- */
-struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
- struct kdbus_conn *reply_dst,
- u64 cookie)
-{
- struct kdbus_reply *r;
-
- list_for_each_entry(r, &reply_dst->reply_list, entry) {
- if (r->cookie == cookie &&
- (!replying || r->reply_src == replying))
- return r;
- }
-
- return NULL;
-}
-
-/**
- * kdbus_reply_list_scan_work() - Worker callback to scan the replies of a
- * connection for exceeded timeouts
- * @work: Work struct of the connection to scan
- *
- * Walk the list of replies stored with a connection and look for entries
- * that have exceeded their timeout. If such an entry is found, a timeout
- * notification is sent to the waiting peer, and the reply is removed from
- * the list.
- *
- * The work is rescheduled to the nearest timeout found during the list
- * iteration.
- */
-void kdbus_reply_list_scan_work(struct work_struct *work)
-{
- struct kdbus_conn *conn =
- container_of(work, struct kdbus_conn, work.work);
- struct kdbus_reply *reply, *reply_tmp;
- u64 deadline = ~0ULL;
- u64 now;
-
- now = ktime_get_ns();
-
- mutex_lock(&conn->lock);
- if (!kdbus_conn_active(conn)) {
- mutex_unlock(&conn->lock);
- return;
- }
-
- list_for_each_entry_safe(reply, reply_tmp, &conn->reply_list, entry) {
- /*
- * If the reply block is waiting for synchronous I/O,
- * the timeout is handled by wait_event_*_timeout(),
- * so we don't have to care for it here.
- */
- if (reply->sync && !reply->interrupted)
- continue;
-
- WARN_ON(reply->reply_dst != conn);
-
- if (reply->deadline_ns > now) {
- /* remember next timeout */
- if (deadline > reply->deadline_ns)
- deadline = reply->deadline_ns;
-
- continue;
- }
-
- /*
- * A zero deadline means the connection died, was
- * cleaned up already and the notification was sent.
- * Don't send notifications for reply trackers that were
- * left in an interrupted syscall state.
- */
- if (reply->deadline_ns != 0 && !reply->interrupted)
- kdbus_notify_reply_timeout(conn->ep->bus, conn->id,
- reply->cookie);
-
- kdbus_reply_unlink(reply);
- }
-
- /* rearm delayed work with next timeout */
- if (deadline != ~0ULL)
- schedule_delayed_work(&conn->work,
- nsecs_to_jiffies(deadline - now));
-
- mutex_unlock(&conn->lock);
-
- kdbus_notify_flush(conn->ep->bus);
-}
diff --git a/ipc/kdbus/reply.h b/ipc/kdbus/reply.h
deleted file mode 100644
index 68d52321a..000000000
--- a/ipc/kdbus/reply.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_REPLY_H
-#define __KDBUS_REPLY_H
-
-/**
- * struct kdbus_reply - an entry of kdbus_conn's list of replies
- * @kref: Ref-count of this object
- * @entry: The entry of the connection's reply_list
- * @reply_src: The connection the reply will be sent from
- * @reply_dst: The connection the reply will be sent to
- * @queue_entry: The queue entry item that is prepared by the replying
- * connection
- * @deadline_ns: The deadline of the reply, in nanoseconds
- * @cookie: The cookie of the requesting message
- * @name_id: ID of the well-known name the original msg was sent to
- * @sync: The reply block is waiting for synchronous I/O
- * @waiting: The condition to synchronously wait for
- * @interrupted: The sync reply was left in an interrupted state
- * @err: The error code for the synchronous reply
- */
-struct kdbus_reply {
- struct kref kref;
- struct list_head entry;
- struct kdbus_conn *reply_src;
- struct kdbus_conn *reply_dst;
- struct kdbus_queue_entry *queue_entry;
- u64 deadline_ns;
- u64 cookie;
- u64 name_id;
- bool sync:1;
- bool waiting:1;
- bool interrupted:1;
- int err;
-};
-
-struct kdbus_reply *kdbus_reply_new(struct kdbus_conn *reply_src,
- struct kdbus_conn *reply_dst,
- const struct kdbus_msg *msg,
- struct kdbus_name_entry *name_entry,
- bool sync);
-
-struct kdbus_reply *kdbus_reply_ref(struct kdbus_reply *r);
-struct kdbus_reply *kdbus_reply_unref(struct kdbus_reply *r);
-
-void kdbus_reply_link(struct kdbus_reply *r);
-void kdbus_reply_unlink(struct kdbus_reply *r);
-
-struct kdbus_reply *kdbus_reply_find(struct kdbus_conn *replying,
- struct kdbus_conn *reply_dst,
- u64 cookie);
-
-void kdbus_sync_reply_wakeup(struct kdbus_reply *reply, int err);
-void kdbus_reply_list_scan_work(struct work_struct *work);
-
-#endif /* __KDBUS_REPLY_H */
diff --git a/ipc/kdbus/util.c b/ipc/kdbus/util.c
deleted file mode 100644
index 72b188330..000000000
--- a/ipc/kdbus/util.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <linux/capability.h>
-#include <linux/cred.h>
-#include <linux/ctype.h>
-#include <linux/err.h>
-#include <linux/file.h>
-#include <linux/slab.h>
-#include <linux/string.h>
-#include <linux/uaccess.h>
-#include <linux/uio.h>
-#include <linux/user_namespace.h>
-
-#include "limits.h"
-#include "util.h"
-
-/**
- * kdbus_copy_from_user() - copy aligned data from user-space
- * @dest: target buffer in kernel memory
- * @user_ptr: user-provided source buffer
- * @size: memory size to copy from user
- *
- * This copies @size bytes from @user_ptr into the kernel, just like
- * copy_from_user() does. But we enforce an 8-byte alignment and reject any
- * unaligned user-space pointers.
- *
- * Return: 0 on success, negative error code on failure.
- */
-int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size)
-{
- if (!KDBUS_IS_ALIGNED8((uintptr_t)user_ptr))
- return -EFAULT;
-
- if (copy_from_user(dest, user_ptr, size))
- return -EFAULT;
-
- return 0;
-}
-
-/**
- * kdbus_verify_uid_prefix() - verify UID prefix of a user-supplied name
- * @name: user-supplied name to verify
- * @user_ns: user-namespace to act in
- * @kuid: Kernel internal uid of user
- *
- * This verifies that the user-supplied name @name has their UID as prefix. This
- * is the default name-spacing policy we enforce on user-supplied names for
- * public kdbus entities like buses and endpoints.
- *
- * The user must supply names prefixed with "<UID>-", whereas the UID is
- * interpreted in the user-namespace of the domain. If the user fails to supply
- * such a prefixed name, we reject it.
- *
- * Return: 0 on success, negative error code on failure
- */
-int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns,
- kuid_t kuid)
-{
- uid_t uid;
- char prefix[16];
-
- /*
- * The kuid must have a mapping into the userns of the domain
- * otherwise do not allow creation of buses nor endpoints.
- */
- uid = from_kuid(user_ns, kuid);
- if (uid == (uid_t) -1)
- return -EINVAL;
-
- snprintf(prefix, sizeof(prefix), "%u-", uid);
- if (strncmp(name, prefix, strlen(prefix)) != 0)
- return -EINVAL;
-
- return 0;
-}
-
-/**
- * kdbus_sanitize_attach_flags() - Sanitize attach flags from user-space
- * @flags: Attach flags provided by userspace
- * @attach_flags: A pointer where to store the valid attach flags
- *
- * Convert attach-flags provided by user-space into a valid mask. If the mask
- * is invalid, an error is returned. The sanitized attach flags are stored in
- * the output parameter.
- *
- * Return: 0 on success, negative error on failure.
- */
-int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags)
-{
- /* 'any' degrades to 'all' for compatibility */
- if (flags == _KDBUS_ATTACH_ANY)
- flags = _KDBUS_ATTACH_ALL;
-
- /* reject unknown attach flags */
- if (flags & ~_KDBUS_ATTACH_ALL)
- return -EINVAL;
-
- *attach_flags = flags;
- return 0;
-}
-
-/**
- * kdbus_kvec_set - helper utility to assemble kvec arrays
- * @kvec: kvec entry to use
- * @src: Source address to set in @kvec
- * @len: Number of bytes in @src
- * @total_len: Pointer to total length variable
- *
- * Set @src and @len in @kvec, and increase @total_len by @len.
- */
-void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len)
-{
- kvec->iov_base = src;
- kvec->iov_len = len;
- *total_len += len;
-}
-
-static const char * const zeros = "\0\0\0\0\0\0\0";
-
-/**
- * kdbus_kvec_pad - conditionally write a padding kvec
- * @kvec: kvec entry to use
- * @len: Total length used for kvec array
- *
- * Check if the current total byte length of the array in @len is aligned to
- * 8 bytes. If it isn't, fill @kvec with padding information and increase @len
- * by the number of bytes stored in @kvec.
- *
- * Return: the number of added padding bytes.
- */
-size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len)
-{
- size_t pad = KDBUS_ALIGN8(*len) - *len;
-
- if (!pad)
- return 0;
-
- kvec->iov_base = (void *)zeros;
- kvec->iov_len = pad;
-
- *len += pad;
-
- return pad;
-}
diff --git a/ipc/kdbus/util.h b/ipc/kdbus/util.h
deleted file mode 100644
index 529716669..000000000
--- a/ipc/kdbus/util.h
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Greg Kroah-Hartman <gregkh@linuxfoundation.org>
- * Copyright (C) 2013-2015 Daniel Mack <daniel@zonque.org>
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- * Copyright (C) 2013-2015 Linux Foundation
- * Copyright (C) 2014-2015 Djalal Harouni <tixxdz@opendz.org>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#ifndef __KDBUS_UTIL_H
-#define __KDBUS_UTIL_H
-
-#include <linux/dcache.h>
-#include <linux/ioctl.h>
-
-#include <uapi/linux/kdbus.h>
-
-/* all exported addresses are 64 bit */
-#define KDBUS_PTR(addr) ((void __user *)(uintptr_t)(addr))
-
-/* all exported sizes are 64 bit and data aligned to 64 bit */
-#define KDBUS_ALIGN8(s) ALIGN((s), 8)
-#define KDBUS_IS_ALIGNED8(s) (IS_ALIGNED(s, 8))
-
-/**
- * kdbus_member_set_user - write a structure member to user memory
- * @_s: Variable to copy from
- * @_b: Buffer to write to
- * @_t: Structure type
- * @_m: Member name in the passed structure
- *
- * Return: the result of copy_to_user()
- */
-#define kdbus_member_set_user(_s, _b, _t, _m) \
-({ \
- u64 __user *_sz = \
- (void __user *)((u8 __user *)(_b) + offsetof(_t, _m)); \
- copy_to_user(_sz, _s, FIELD_SIZEOF(_t, _m)); \
-})
-
-/**
- * kdbus_strhash - calculate a hash
- * @str: String
- *
- * Return: hash value
- */
-static inline unsigned int kdbus_strhash(const char *str)
-{
- unsigned long hash = init_name_hash();
-
- while (*str)
- hash = partial_name_hash(*str++, hash);
-
- return end_name_hash(hash);
-}
-
-int kdbus_verify_uid_prefix(const char *name, struct user_namespace *user_ns,
- kuid_t kuid);
-int kdbus_sanitize_attach_flags(u64 flags, u64 *attach_flags);
-
-int kdbus_copy_from_user(void *dest, void __user *user_ptr, size_t size);
-
-struct kvec;
-
-void kdbus_kvec_set(struct kvec *kvec, void *src, size_t len, u64 *total_len);
-size_t kdbus_kvec_pad(struct kvec *kvec, u64 *len);
-
-#endif
diff --git a/kernel/panic.c b/kernel/panic.c
index 4b150bc0c..41e2b54f3 100644
--- a/kernel/panic.c
+++ b/kernel/panic.c
@@ -157,8 +157,7 @@ void panic(const char *fmt, ...)
* panic() is not being callled from OOPS.
*/
debug_locks_off();
- console_trylock();
- console_unlock();
+ console_flush_on_panic();
if (!panic_blink)
panic_blink = no_blink;
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c
index f9b746700..8362f1979 100644
--- a/kernel/printk/printk.c
+++ b/kernel/printk/printk.c
@@ -2248,13 +2248,24 @@ void console_unlock(void)
static u64 seen_seq;
unsigned long flags;
bool wake_klogd = false;
- bool retry;
+ bool do_cond_resched, retry;
if (console_suspended) {
up_console_sem();
return;
}
+ /*
+ * Console drivers are called under logbuf_lock, so
+ * @console_may_schedule should be cleared before; however, we may
+ * end up dumping a lot of lines, for example, if called from
+ * console registration path, and should invoke cond_resched()
+ * between lines if allowable. Not doing so can cause a very long
+ * scheduling stall on a slow console leading to RCU stall and
+ * softlockup warnings which exacerbate the issue with more
+ * messages practically incapacitating the system.
+ */
+ do_cond_resched = console_may_schedule;
console_may_schedule = 0;
/* flush buffered message fragment immediately to console */
@@ -2326,6 +2337,9 @@ skip:
call_console_drivers(level, ext_text, ext_len, text, len);
start_critical_timings();
local_irq_restore(flags);
+
+ if (do_cond_resched)
+ cond_resched();
}
console_locked = 0;
@@ -2393,6 +2407,25 @@ void console_unblank(void)
console_unlock();
}
+/**
+ * console_flush_on_panic - flush console content on panic
+ *
+ * Immediately output all pending messages no matter what.
+ */
+void console_flush_on_panic(void)
+{
+ /*
+ * If someone else is holding the console lock, trylock will fail
+ * and may_schedule may be set. Ignore and proceed to unlock so
+ * that messages are flushed out. As this can be called from any
+ * context and we don't want to get preempted while flushing,
+ * ensure may_schedule is cleared.
+ */
+ console_trylock();
+ console_may_schedule = 0;
+ console_unlock();
+}
+
/*
* Return the console tty driver structure and its associated index
*/
diff --git a/kernel/sched/core.c b/kernel/sched/core.c
index 732e993b5..eb70592f0 100644
--- a/kernel/sched/core.c
+++ b/kernel/sched/core.c
@@ -6738,7 +6738,7 @@ static void sched_init_numa(void)
sched_domains_numa_masks[i][j] = mask;
- for (k = 0; k < nr_node_ids; k++) {
+ for_each_node(k) {
if (node_distance(j, k) > sched_domains_numa_distance[i])
continue;
diff --git a/kernel/task_work.c b/kernel/task_work.c
index 53fa971d0..f80d564c7 100644
--- a/kernel/task_work.c
+++ b/kernel/task_work.c
@@ -118,3 +118,4 @@ void task_work_run(void)
} while (work);
}
}
+EXPORT_SYMBOL(task_work_run);
diff --git a/kernel/time/hrtimer.c b/kernel/time/hrtimer.c
index 435b8850d..fa909f9fd 100644
--- a/kernel/time/hrtimer.c
+++ b/kernel/time/hrtimer.c
@@ -897,10 +897,10 @@ static int enqueue_hrtimer(struct hrtimer *timer,
*/
static void __remove_hrtimer(struct hrtimer *timer,
struct hrtimer_clock_base *base,
- unsigned long newstate, int reprogram)
+ u8 newstate, int reprogram)
{
struct hrtimer_cpu_base *cpu_base = base->cpu_base;
- unsigned int state = timer->state;
+ u8 state = timer->state;
timer->state = newstate;
if (!(state & HRTIMER_STATE_ENQUEUED))
@@ -930,7 +930,7 @@ static inline int
remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool restart)
{
if (hrtimer_is_queued(timer)) {
- unsigned long state = timer->state;
+ u8 state = timer->state;
int reprogram;
/*
@@ -954,6 +954,22 @@ remove_hrtimer(struct hrtimer *timer, struct hrtimer_clock_base *base, bool rest
return 0;
}
+static inline ktime_t hrtimer_update_lowres(struct hrtimer *timer, ktime_t tim,
+ const enum hrtimer_mode mode)
+{
+#ifdef CONFIG_TIME_LOW_RES
+ /*
+ * CONFIG_TIME_LOW_RES indicates that the system has no way to return
+ * granular time values. For relative timers we add hrtimer_resolution
+ * (i.e. one jiffie) to prevent short timeouts.
+ */
+ timer->is_rel = mode & HRTIMER_MODE_REL;
+ if (timer->is_rel)
+ tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
+#endif
+ return tim;
+}
+
/**
* hrtimer_start_range_ns - (re)start an hrtimer on the current CPU
* @timer: the timer to be added
@@ -974,19 +990,10 @@ void hrtimer_start_range_ns(struct hrtimer *timer, ktime_t tim,
/* Remove an active timer from the queue: */
remove_hrtimer(timer, base, true);
- if (mode & HRTIMER_MODE_REL) {
+ if (mode & HRTIMER_MODE_REL)
tim = ktime_add_safe(tim, base->get_time());
- /*
- * CONFIG_TIME_LOW_RES is a temporary way for architectures
- * to signal that they simply return xtime in
- * do_gettimeoffset(). In this case we want to round up by
- * resolution when starting a relative timer, to avoid short
- * timeouts. This will go away with the GTOD framework.
- */
-#ifdef CONFIG_TIME_LOW_RES
- tim = ktime_add_safe(tim, ktime_set(0, hrtimer_resolution));
-#endif
- }
+
+ tim = hrtimer_update_lowres(timer, tim, mode);
hrtimer_set_expires_range_ns(timer, tim, delta_ns);
@@ -1074,19 +1081,23 @@ EXPORT_SYMBOL_GPL(hrtimer_cancel);
/**
* hrtimer_get_remaining - get remaining time for the timer
* @timer: the timer to read
+ * @adjust: adjust relative timers when CONFIG_TIME_LOW_RES=y
*/
-ktime_t hrtimer_get_remaining(const struct hrtimer *timer)
+ktime_t __hrtimer_get_remaining(const struct hrtimer *timer, bool adjust)
{
unsigned long flags;
ktime_t rem;
lock_hrtimer_base(timer, &flags);
- rem = hrtimer_expires_remaining(timer);
+ if (IS_ENABLED(CONFIG_TIME_LOW_RES) && adjust)
+ rem = hrtimer_expires_remaining_adjusted(timer);
+ else
+ rem = hrtimer_expires_remaining(timer);
unlock_hrtimer_base(timer, &flags);
return rem;
}
-EXPORT_SYMBOL_GPL(hrtimer_get_remaining);
+EXPORT_SYMBOL_GPL(__hrtimer_get_remaining);
#ifdef CONFIG_NO_HZ_COMMON
/**
@@ -1220,6 +1231,14 @@ static void __run_hrtimer(struct hrtimer_cpu_base *cpu_base,
fn = timer->function;
/*
+ * Clear the 'is relative' flag for the TIME_LOW_RES case. If the
+ * timer is restarted with a period then it becomes an absolute
+ * timer. If its not restarted it does not matter.
+ */
+ if (IS_ENABLED(CONFIG_TIME_LOW_RES))
+ timer->is_rel = false;
+
+ /*
* Because we run timers from hardirq context, there is no chance
* they get migrated to another cpu, therefore its safe to unlock
* the timer base.
diff --git a/kernel/time/timer_list.c b/kernel/time/timer_list.c
index f75e35b60..ba7d8b288 100644
--- a/kernel/time/timer_list.c
+++ b/kernel/time/timer_list.c
@@ -69,7 +69,7 @@ print_timer(struct seq_file *m, struct hrtimer *taddr, struct hrtimer *timer,
print_name_offset(m, taddr);
SEQ_printf(m, ", ");
print_name_offset(m, timer->function);
- SEQ_printf(m, ", S:%02lx", timer->state);
+ SEQ_printf(m, ", S:%02x", timer->state);
#ifdef CONFIG_TIMER_STATS
SEQ_printf(m, ", ");
print_name_offset(m, timer->start_site);
diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c
index 87fb9801b..d9293402e 100644
--- a/kernel/trace/trace.c
+++ b/kernel/trace/trace.c
@@ -1751,7 +1751,7 @@ void trace_buffer_unlock_commit_regs(struct trace_array *tr,
{
__buffer_unlock_commit(buffer, event);
- ftrace_trace_stack(tr, buffer, flags, 6, pc, regs);
+ ftrace_trace_stack(tr, buffer, flags, 0, pc, regs);
ftrace_trace_userstack(buffer, flags, pc);
}
EXPORT_SYMBOL_GPL(trace_buffer_unlock_commit_regs);
diff --git a/kernel/trace/trace_stack.c b/kernel/trace/trace_stack.c
index dda9e6742..202df6cff 100644
--- a/kernel/trace/trace_stack.c
+++ b/kernel/trace/trace_stack.c
@@ -126,6 +126,13 @@ check_stack(unsigned long ip, unsigned long *stack)
}
/*
+ * Some archs may not have the passed in ip in the dump.
+ * If that happens, we need to show everything.
+ */
+ if (i == stack_trace_max.nr_entries)
+ i = 0;
+
+ /*
* Now find where in the stack these are.
*/
x = 0;
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
index 6a08ce7d6..acf9da449 100644
--- a/lib/libcrc32c.c
+++ b/lib/libcrc32c.c
@@ -74,3 +74,4 @@ module_exit(libcrc32c_mod_fini);
MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
MODULE_DESCRIPTION("CRC32c (Castagnoli) calculations");
MODULE_LICENSE("GPL");
+MODULE_SOFTDEP("pre: crc32c");
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index 7340353f8..cbe6f0b96 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -989,7 +989,7 @@ long wait_iff_congested(struct zone *zone, int sync, long timeout)
* here rather than calling cond_resched().
*/
if (current->flags & PF_WQ_WORKER)
- schedule_timeout(1);
+ schedule_timeout_uninterruptible(1);
else
cond_resched();
diff --git a/mm/zsmalloc.c b/mm/zsmalloc.c
index 9f15bdd91..fc083996e 100644
--- a/mm/zsmalloc.c
+++ b/mm/zsmalloc.c
@@ -309,7 +309,12 @@ static void free_handle(struct zs_pool *pool, unsigned long handle)
static void record_obj(unsigned long handle, unsigned long obj)
{
- *(unsigned long *)handle = obj;
+ /*
+ * lsb of @obj represents handle lock while other bits
+ * represent object value the handle is pointing so
+ * updating shouldn't do store tearing.
+ */
+ WRITE_ONCE(*(unsigned long *)handle, obj);
}
/* zpool driver */
@@ -1635,6 +1640,13 @@ static int migrate_zspage(struct zs_pool *pool, struct size_class *class,
free_obj = obj_malloc(d_page, class, handle);
zs_object_copy(free_obj, used_obj, class);
index++;
+ /*
+ * record_obj updates handle's value to free_obj and it will
+ * invalidate lock bit(ie, HANDLE_PIN_BIT) of handle, which
+ * breaks synchronization using pin_tag(e,g, zs_free) so
+ * let's keep the lock bit.
+ */
+ free_obj |= BIT(HANDLE_PIN_BIT);
record_obj(handle, free_obj);
unpin_tag(handle);
obj_free(pool, class, used_obj);
diff --git a/samples/Kconfig b/samples/Kconfig
index 72051e348..d54f28c6d 100644
--- a/samples/Kconfig
+++ b/samples/Kconfig
@@ -55,13 +55,6 @@ config SAMPLE_KDB
Build an example of how to dynamically add the hello
command to the kdb shell.
-config SAMPLE_KDBUS
- bool "Build kdbus API example"
- depends on KDBUS
- help
- Build an example of how the kdbus API can be used from
- userspace.
-
config SAMPLE_RPMSG_CLIENT
tristate "Build rpmsg client sample -- loadable modules only"
depends on RPMSG && m
diff --git a/samples/Makefile b/samples/Makefile
index d0c9b3c67..48001d7e2 100644
--- a/samples/Makefile
+++ b/samples/Makefile
@@ -1,5 +1,5 @@
# Makefile for Linux samples code
obj-$(CONFIG_SAMPLES) += kobject/ kprobes/ trace_events/ livepatch/ \
- hw_breakpoint/ kfifo/ kdb/ kdbus/ hidraw/ rpmsg/ \
- seccomp/ configfs/
+ hw_breakpoint/ kfifo/ kdb/ hidraw/ rpmsg/ seccomp/ \
+ configfs/
diff --git a/samples/kdbus/.gitignore b/samples/kdbus/.gitignore
deleted file mode 100644
index ee07d9857..000000000
--- a/samples/kdbus/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-kdbus-workers
diff --git a/samples/kdbus/Makefile b/samples/kdbus/Makefile
deleted file mode 100644
index 137f84272..000000000
--- a/samples/kdbus/Makefile
+++ /dev/null
@@ -1,9 +0,0 @@
-# kbuild trick to avoid linker error. Can be omitted if a module is built.
-obj- := dummy.o
-
-hostprogs-$(CONFIG_SAMPLE_KDBUS) += kdbus-workers
-
-always := $(hostprogs-y)
-
-HOSTCFLAGS_kdbus-workers.o += -I$(objtree)/usr/include
-HOSTLOADLIBES_kdbus-workers := -lrt
diff --git a/samples/kdbus/kdbus-api.h b/samples/kdbus/kdbus-api.h
deleted file mode 100644
index 7f3abae18..000000000
--- a/samples/kdbus/kdbus-api.h
+++ /dev/null
@@ -1,114 +0,0 @@
-#ifndef KDBUS_API_H
-#define KDBUS_API_H
-
-#include <sys/ioctl.h>
-#include <linux/kdbus.h>
-
-#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
-#define KDBUS_FOREACH(iter, first, _size) \
- for ((iter) = (first); \
- ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
- ((uint8_t *)(iter) >= (uint8_t *)(first)); \
- (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
-
-static inline int kdbus_cmd_bus_make(int control_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(control_fd, KDBUS_CMD_BUS_MAKE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_endpoint_make(int bus_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(bus_fd, KDBUS_CMD_ENDPOINT_MAKE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_endpoint_update(int ep_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(ep_fd, KDBUS_CMD_ENDPOINT_UPDATE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_hello(int bus_fd, struct kdbus_cmd_hello *cmd)
-{
- int ret = ioctl(bus_fd, KDBUS_CMD_HELLO, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_update(int fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(fd, KDBUS_CMD_UPDATE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_byebye(int conn_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_BYEBYE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_free(int conn_fd, struct kdbus_cmd_free *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_FREE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_conn_info(int conn_fd, struct kdbus_cmd_info *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_CONN_INFO, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_bus_creator_info(int conn_fd, struct kdbus_cmd_info *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_BUS_CREATOR_INFO, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_list(int fd, struct kdbus_cmd_list *cmd)
-{
- int ret = ioctl(fd, KDBUS_CMD_LIST, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_send(int conn_fd, struct kdbus_cmd_send *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_SEND, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_recv(int conn_fd, struct kdbus_cmd_recv *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_RECV, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_name_acquire(int conn_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_NAME_ACQUIRE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_name_release(int conn_fd, struct kdbus_cmd *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_NAME_RELEASE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_match_add(int conn_fd, struct kdbus_cmd_match *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_ADD, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-static inline int kdbus_cmd_match_remove(int conn_fd, struct kdbus_cmd_match *cmd)
-{
- int ret = ioctl(conn_fd, KDBUS_CMD_MATCH_REMOVE, cmd);
- return (ret < 0) ? (errno > 0 ? -errno : -EINVAL) : 0;
-}
-
-#endif /* KDBUS_API_H */
diff --git a/samples/kdbus/kdbus-workers.c b/samples/kdbus/kdbus-workers.c
deleted file mode 100644
index 5a6dfdce3..000000000
--- a/samples/kdbus/kdbus-workers.c
+++ /dev/null
@@ -1,1346 +0,0 @@
-/*
- * Copyright (C) 2013-2015 David Herrmann <dh.herrmann@gmail.com>
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-/*
- * Example: Workers
- * This program computes prime-numbers based on the sieve of Eratosthenes. The
- * master sets up a shared memory region and spawns workers which clear out the
- * non-primes. The master reacts to keyboard input and to client-requests to
- * control what each worker does. Note that this is in no way meant as efficient
- * way to compute primes. It should only serve as example how a master/worker
- * concept can be implemented with kdbus used as control messages.
- *
- * The main process is called the 'master'. It creates a new, private bus which
- * will be used between the master and its workers to communicate. The master
- * then spawns a fixed number of workers. Whenever a worker dies (detected via
- * SIGCHLD), the master spawns a new worker. When done, the master waits for all
- * workers to exit, prints a status report and exits itself.
- *
- * The master process does *not* keep track of its workers. Instead, this
- * example implements a PULL model. That is, the master acquires a well-known
- * name on the bus which each worker uses to request tasks from the master. If
- * there are no more tasks, the master will return an empty task-list, which
- * casues a worker to exit immediately.
- *
- * As tasks can be computationally expensive, we support cancellation. Whenever
- * the master process is interrupted, it will drop its well-known name on the
- * bus. This causes kdbus to broadcast a name-change notification. The workers
- * check for broadcast messages regularly and will exit if they receive one.
- *
- * This example exists of 4 objects:
- * * master: The master object contains the context of the master process. This
- * process manages the prime-context, spawns workers and assigns
- * prime-ranges to each worker to compute.
- * The master itself does not do any prime-computations itself.
- * * child: The child object contains the context of a worker. It inherits the
- * prime context from its parent (the master) and then creates a new
- * bus context to request prime-ranges to compute.
- * * prime: The "prime" object is used to abstract how we compute primes. When
- * allocated, it prepares a memory region to hold 1 bit for each
- * natural number up to a fixed maximum ('MAX_PRIMES').
- * The memory region is backed by a memfd which we share between
- * processes. Each worker now gets assigned a range of natural
- * numbers which it clears multiples of off the memory region. The
- * master process is responsible of distributing all natural numbers
- * up to the fixed maximum to its workers.
- * * bus: The bus object is an abstraction of the kdbus API. It is pretty
- * straightfoward and only manages the connection-fd plus the
- * memory-mapped pool in a single object.
- *
- * This example is in reversed order, which should make it easier to read
- * top-down, but requires some forward-declarations. Just ignore those.
- */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <sys/syscall.h>
-
-/* glibc < 2.7 does not ship sys/signalfd.h */
-/* we require kernels with __NR_memfd_create */
-#if __GLIBC__ >= 2 && __GLIBC_MINOR__ >= 7 && defined(__NR_memfd_create)
-
-#include <ctype.h>
-#include <errno.h>
-#include <fcntl.h>
-#include <linux/memfd.h>
-#include <signal.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <string.h>
-#include <sys/mman.h>
-#include <sys/poll.h>
-#include <sys/signalfd.h>
-#include <sys/time.h>
-#include <sys/wait.h>
-#include <time.h>
-#include <unistd.h>
-#include "kdbus-api.h"
-
-/* FORWARD DECLARATIONS */
-
-#define POOL_SIZE (16 * 1024 * 1024)
-#define MAX_PRIMES (2UL << 24)
-#define WORKER_COUNT (16)
-#define PRIME_STEPS (65536 * 4)
-
-static const char *arg_busname = "example-workers";
-static const char *arg_modname = "kdbus";
-static const char *arg_master = "org.freedesktop.master";
-
-static int err_assert(int r_errno, const char *msg, const char *func, int line,
- const char *file)
-{
- r_errno = (r_errno != 0) ? -abs(r_errno) : -EFAULT;
- if (r_errno < 0) {
- errno = -r_errno;
- fprintf(stderr, "ERR: %s: %m (%s:%d in %s)\n",
- msg, func, line, file);
- }
- return r_errno;
-}
-
-#define err_r(_r, _msg) err_assert((_r), (_msg), __func__, __LINE__, __FILE__)
-#define err(_msg) err_r(errno, (_msg))
-
-struct prime;
-struct bus;
-struct master;
-struct child;
-
-struct prime {
- int fd;
- uint8_t *area;
- size_t max;
- size_t done;
- size_t status;
-};
-
-static int prime_new(struct prime **out);
-static void prime_free(struct prime *p);
-static bool prime_done(struct prime *p);
-static void prime_consume(struct prime *p, size_t amount);
-static int prime_run(struct prime *p, struct bus *cancel, size_t number);
-static void prime_print(struct prime *p);
-
-struct bus {
- int fd;
- uint8_t *pool;
-};
-
-static int bus_open_connection(struct bus **out, uid_t uid, const char *name,
- uint64_t recv_flags);
-static void bus_close_connection(struct bus *b);
-static void bus_poool_free_slice(struct bus *b, uint64_t offset);
-static int bus_acquire_name(struct bus *b, const char *name);
-static int bus_install_name_loss_match(struct bus *b, const char *name);
-static int bus_poll(struct bus *b);
-static int bus_make(uid_t uid, const char *name);
-
-struct master {
- size_t n_workers;
- size_t max_workers;
-
- int signal_fd;
- int control_fd;
-
- struct prime *prime;
- struct bus *bus;
-};
-
-static int master_new(struct master **out);
-static void master_free(struct master *m);
-static int master_run(struct master *m);
-static int master_poll(struct master *m);
-static int master_handle_stdin(struct master *m);
-static int master_handle_signal(struct master *m);
-static int master_handle_bus(struct master *m);
-static int master_reply(struct master *m, const struct kdbus_msg *msg);
-static int master_waitpid(struct master *m);
-static int master_spawn(struct master *m);
-
-struct child {
- struct bus *bus;
- struct prime *prime;
-};
-
-static int child_new(struct child **out, struct prime *p);
-static void child_free(struct child *c);
-static int child_run(struct child *c);
-
-/* END OF FORWARD DECLARATIONS */
-
-/*
- * This is the main entrypoint of this example. It is pretty straightforward. We
- * create a master object, run the computation, print a status report and then
- * exit. Nothing particularly interesting here, so lets look into the master
- * object...
- */
-int main(int argc, char **argv)
-{
- struct master *m = NULL;
- int r;
-
- r = master_new(&m);
- if (r < 0)
- goto out;
-
- r = master_run(m);
- if (r < 0)
- goto out;
-
- if (0)
- prime_print(m->prime);
-
-out:
- master_free(m);
- if (r < 0 && r != -EINTR)
- fprintf(stderr, "failed\n");
- else
- fprintf(stderr, "done\n");
- return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
-}
-
-/*
- * ...this will allocate a new master context. It keeps track of the current
- * number of children/workers that are running, manages a signalfd to track
- * SIGCHLD, and creates a private kdbus bus. Afterwards, it opens its connection
- * to the bus and acquires a well known-name (arg_master).
- */
-static int master_new(struct master **out)
-{
- struct master *m;
- sigset_t smask;
- int r;
-
- m = calloc(1, sizeof(*m));
- if (!m)
- return err("cannot allocate master");
-
- m->max_workers = WORKER_COUNT;
- m->signal_fd = -1;
- m->control_fd = -1;
-
- /* Block SIGINT and SIGCHLD signals */
- sigemptyset(&smask);
- sigaddset(&smask, SIGINT);
- sigaddset(&smask, SIGCHLD);
- sigprocmask(SIG_BLOCK, &smask, NULL);
-
- m->signal_fd = signalfd(-1, &smask, SFD_CLOEXEC);
- if (m->signal_fd < 0) {
- r = err("cannot create signalfd");
- goto error;
- }
-
- r = prime_new(&m->prime);
- if (r < 0)
- goto error;
-
- m->control_fd = bus_make(getuid(), arg_busname);
- if (m->control_fd < 0) {
- r = m->control_fd;
- goto error;
- }
-
- /*
- * Open a bus connection for the master, and require each received
- * message to have a metadata item of type KDBUS_ITEM_PIDS attached.
- * The current UID is needed to compute the name of the bus node to
- * connect to.
- */
- r = bus_open_connection(&m->bus, getuid(),
- arg_busname, KDBUS_ATTACH_PIDS);
- if (r < 0)
- goto error;
-
- /*
- * Acquire a well-known name on the bus, so children can address
- * messages to the master using KDBUS_DST_ID_NAME as destination-ID
- * of messages.
- */
- r = bus_acquire_name(m->bus, arg_master);
- if (r < 0)
- goto error;
-
- *out = m;
- return 0;
-
-error:
- master_free(m);
- return r;
-}
-
-/* pretty straightforward destructor of a master object */
-static void master_free(struct master *m)
-{
- if (!m)
- return;
-
- bus_close_connection(m->bus);
- if (m->control_fd >= 0)
- close(m->control_fd);
- prime_free(m->prime);
- if (m->signal_fd >= 0)
- close(m->signal_fd);
- free(m);
-}
-
-static int master_run(struct master *m)
-{
- int res, r = 0;
-
- while (!prime_done(m->prime)) {
- while (m->n_workers < m->max_workers) {
- r = master_spawn(m);
- if (r < 0)
- break;
- }
-
- r = master_poll(m);
- if (r < 0)
- break;
- }
-
- if (r < 0) {
- bus_close_connection(m->bus);
- m->bus = NULL;
- }
-
- while (m->n_workers > 0) {
- res = master_poll(m);
- if (res < 0) {
- if (m->bus) {
- bus_close_connection(m->bus);
- m->bus = NULL;
- }
- r = res;
- }
- }
-
- return r == -EINTR ? 0 : r;
-}
-
-static int master_poll(struct master *m)
-{
- struct pollfd fds[3] = {};
- int r = 0, n = 0;
-
- /*
- * Add stdin, the eventfd and the connection owner file descriptor to
- * the pollfd table, and handle incoming traffic on the latter in
- * master_handle_bus().
- */
- fds[n].fd = STDIN_FILENO;
- fds[n++].events = POLLIN;
- fds[n].fd = m->signal_fd;
- fds[n++].events = POLLIN;
- if (m->bus) {
- fds[n].fd = m->bus->fd;
- fds[n++].events = POLLIN;
- }
-
- r = poll(fds, n, -1);
- if (r < 0)
- return err("poll() failed");
-
- if (fds[0].revents & POLLIN)
- r = master_handle_stdin(m);
- else if (fds[0].revents)
- r = err("ERR/HUP on stdin");
- if (r < 0)
- return r;
-
- if (fds[1].revents & POLLIN)
- r = master_handle_signal(m);
- else if (fds[1].revents)
- r = err("ERR/HUP on signalfd");
- if (r < 0)
- return r;
-
- if (fds[2].revents & POLLIN)
- r = master_handle_bus(m);
- else if (fds[2].revents)
- r = err("ERR/HUP on bus");
-
- return r;
-}
-
-static int master_handle_stdin(struct master *m)
-{
- char buf[128];
- ssize_t l;
- int r = 0;
-
- l = read(STDIN_FILENO, buf, sizeof(buf));
- if (l < 0)
- return err("cannot read stdin");
- if (l == 0)
- return err_r(-EINVAL, "EOF on stdin");
-
- while (l-- > 0) {
- switch (buf[l]) {
- case 'q':
- /* quit */
- r = -EINTR;
- break;
- case '\n':
- case ' ':
- /* ignore */
- break;
- default:
- if (isgraph(buf[l]))
- fprintf(stderr, "invalid input '%c'\n", buf[l]);
- else
- fprintf(stderr, "invalid input 0x%x\n", buf[l]);
- break;
- }
- }
-
- return r;
-}
-
-static int master_handle_signal(struct master *m)
-{
- struct signalfd_siginfo val;
- ssize_t l;
-
- l = read(m->signal_fd, &val, sizeof(val));
- if (l < 0)
- return err("cannot read signalfd");
- if (l != sizeof(val))
- return err_r(-EINVAL, "invalid data from signalfd");
-
- switch (val.ssi_signo) {
- case SIGCHLD:
- return master_waitpid(m);
- case SIGINT:
- return err_r(-EINTR, "interrupted");
- default:
- return err_r(-EINVAL, "caught invalid signal");
- }
-}
-
-static int master_handle_bus(struct master *m)
-{
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- const struct kdbus_msg *msg = NULL;
- const struct kdbus_item *item;
- const struct kdbus_vec *vec = NULL;
- int r = 0;
-
- /*
- * To receive a message, the KDBUS_CMD_RECV ioctl is used.
- * It takes an argument of type 'struct kdbus_cmd_recv', which
- * will contain information on the received message when the call
- * returns. See kdbus.message(7).
- */
- r = kdbus_cmd_recv(m->bus->fd, &recv);
- /*
- * EAGAIN is returned when there is no message waiting on this
- * connection. This is not an error - simply bail out.
- */
- if (r == -EAGAIN)
- return 0;
- if (r < 0)
- return err_r(r, "cannot receive message");
-
- /*
- * Messages received by a connection are stored inside the connection's
- * pool, at an offset that has been returned in the 'recv' command
- * struct above. The value describes the relative offset from the
- * start address of the pool. A message is described with
- * 'struct kdbus_msg'. See kdbus.message(7).
- */
- msg = (void *)(m->bus->pool + recv.msg.offset);
-
- /*
- * A messages describes its actual payload in an array of items.
- * KDBUS_FOREACH() is a simple iterator that walks such an array.
- * struct kdbus_msg has a field to denote its total size, which is
- * needed to determine the number of items in the array.
- */
- KDBUS_FOREACH(item, msg->items,
- msg->size - offsetof(struct kdbus_msg, items)) {
- /*
- * An item of type PAYLOAD_OFF describes in-line memory
- * stored in the pool at a described offset. That offset is
- * relative to the start address of the message header.
- * This example program only expects one single item of that
- * type, remembers the struct kdbus_vec member of the item
- * when it sees it, and bails out if there is more than one
- * of them.
- */
- if (item->type == KDBUS_ITEM_PAYLOAD_OFF) {
- if (vec) {
- r = err_r(-EEXIST,
- "message with multiple vecs");
- break;
- }
- vec = &item->vec;
- if (vec->size != 1) {
- r = err_r(-EINVAL, "invalid message size");
- break;
- }
-
- /*
- * MEMFDs are transported as items of type PAYLOAD_MEMFD.
- * If such an item is attached, a new file descriptor was
- * installed into the task when KDBUS_CMD_RECV was called, and
- * its number is stored in item->memfd.fd.
- * Implementers *must* handle this item type and close the
- * file descriptor when no longer needed in order to prevent
- * file descriptor exhaustion. This example program just bails
- * out with an error in this case, as memfds are not expected
- * in this context.
- */
- } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) {
- r = err_r(-EINVAL, "message with memfd");
- break;
- }
- }
- if (r < 0)
- goto exit;
- if (!vec) {
- r = err_r(-EINVAL, "empty message");
- goto exit;
- }
-
- switch (*((const uint8_t *)msg + vec->offset)) {
- case 'r': {
- r = master_reply(m, msg);
- break;
- }
- default:
- r = err_r(-EINVAL, "invalid message type");
- break;
- }
-
-exit:
- /*
- * We are done with the memory slice that was given to us through
- * recv.msg.offset. Tell the kernel it can use it for other content
- * in the future. See kdbus.pool(7).
- */
- bus_poool_free_slice(m->bus, recv.msg.offset);
- return r;
-}
-
-static int master_reply(struct master *m, const struct kdbus_msg *msg)
-{
- struct kdbus_cmd_send cmd;
- struct kdbus_item *item;
- struct kdbus_msg *reply;
- size_t size, status, p[2];
- int r;
-
- /*
- * This functions sends a message over kdbus. To do this, it uses the
- * KDBUS_CMD_SEND ioctl, which takes a command struct argument of type
- * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual
- * message to send. See kdbus.message(7).
- */
- p[0] = m->prime->done;
- p[1] = prime_done(m->prime) ? 0 : PRIME_STEPS;
-
- size = sizeof(*reply);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- /* Prepare the message to send */
- reply = alloca(size);
- memset(reply, 0, size);
- reply->size = size;
-
- /* Each message has a cookie that can be used to send replies */
- reply->cookie = 1;
-
- /* The payload_type is arbitrary, but it must be non-zero */
- reply->payload_type = 0xdeadbeef;
-
- /*
- * We are sending a reply. Let the kernel know the cookie of the
- * message we are replying to.
- */
- reply->cookie_reply = msg->cookie;
-
- /*
- * Messages can either be directed to a well-known name (stored as
- * string) or to a unique name (stored as number). This example does
- * the latter. If the message would be directed to a well-known name
- * instead, the message's dst_id field would be set to
- * KDBUS_DST_ID_NAME, and the name would be attaches in an item of type
- * KDBUS_ITEM_DST_NAME. See below for an example, and also refer to
- * kdbus.message(7).
- */
- reply->dst_id = msg->src_id;
-
- /* Our message has exactly one item to store its payload */
- item = reply->items;
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)p;
- item->vec.size = sizeof(p);
-
- /*
- * Now prepare the command struct, and reference the message we want
- * to send.
- */
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)reply;
-
- /*
- * Finally, employ the command on the connection owner
- * file descriptor.
- */
- r = kdbus_cmd_send(m->bus->fd, &cmd);
- if (r < 0)
- return err_r(r, "cannot send reply");
-
- if (p[1]) {
- prime_consume(m->prime, p[1]);
- status = m->prime->done * 10000 / m->prime->max;
- if (status != m->prime->status) {
- m->prime->status = status;
- fprintf(stderr, "status: %7.3lf%%\n",
- (double)status / 100);
- }
- }
-
- return 0;
-}
-
-static int master_waitpid(struct master *m)
-{
- pid_t pid;
- int r;
-
- while ((pid = waitpid(-1, &r, WNOHANG)) > 0) {
- if (m->n_workers > 0)
- --m->n_workers;
- if (!WIFEXITED(r))
- r = err_r(-EINVAL, "child died unexpectedly");
- else if (WEXITSTATUS(r) != 0)
- r = err_r(-WEXITSTATUS(r), "child failed");
- }
-
- return r;
-}
-
-static int master_spawn(struct master *m)
-{
- struct child *c = NULL;
- struct prime *p = NULL;
- pid_t pid;
- int r;
-
- /* Spawn off one child and call child_run() inside it */
-
- pid = fork();
- if (pid < 0)
- return err("cannot fork");
- if (pid > 0) {
- /* parent */
- ++m->n_workers;
- return 0;
- }
-
- /* child */
-
- p = m->prime;
- m->prime = NULL;
- master_free(m);
-
- r = child_new(&c, p);
- if (r < 0)
- goto exit;
-
- r = child_run(c);
-
-exit:
- child_free(c);
- exit(abs(r));
-}
-
-static int child_new(struct child **out, struct prime *p)
-{
- struct child *c;
- int r;
-
- c = calloc(1, sizeof(*c));
- if (!c)
- return err("cannot allocate child");
-
- c->prime = p;
-
- /*
- * Open a connection to the bus and require each received message to
- * carry a list of the well-known names the sendind connection currently
- * owns. The current UID is needed in order to determine the name of the
- * bus node to connect to.
- */
- r = bus_open_connection(&c->bus, getuid(),
- arg_busname, KDBUS_ATTACH_NAMES);
- if (r < 0)
- goto error;
-
- /*
- * Install a kdbus match so the child's connection gets notified when
- * the master loses its well-known name.
- */
- r = bus_install_name_loss_match(c->bus, arg_master);
- if (r < 0)
- goto error;
-
- *out = c;
- return 0;
-
-error:
- child_free(c);
- return r;
-}
-
-static void child_free(struct child *c)
-{
- if (!c)
- return;
-
- bus_close_connection(c->bus);
- prime_free(c->prime);
- free(c);
-}
-
-static int child_run(struct child *c)
-{
- struct kdbus_cmd_send cmd;
- struct kdbus_item *item;
- struct kdbus_vec *vec = NULL;
- struct kdbus_msg *msg;
- struct timespec spec;
- size_t n, steps, size;
- int r = 0;
-
- /*
- * Let's send a message to the master and ask for work. To do this,
- * we use the KDBUS_CMD_SEND ioctl, which takes an argument of type
- * 'struct kdbus_cmd_send'. This struct stores a pointer to the actual
- * message to send. See kdbus.message(7).
- */
- size = sizeof(*msg);
- size += KDBUS_ITEM_SIZE(strlen(arg_master) + 1);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- msg = alloca(size);
- memset(msg, 0, size);
- msg->size = size;
-
- /*
- * Tell the kernel that we expect a reply to this message. This means
- * that
- *
- * a) The remote peer will gain temporary permission to talk to us
- * even if it would not be allowed to normally.
- *
- * b) A timeout value is required.
- *
- * For asynchronous send commands, if no reply is received, we will
- * get a kernel notification with an item of type
- * KDBUS_ITEM_REPLY_TIMEOUT attached.
- *
- * For synchronous send commands (which this example does), the
- * ioctl will block until a reply is received or the timeout is
- * exceeded.
- */
- msg->flags = KDBUS_MSG_EXPECT_REPLY;
-
- /* Set our cookie. Replies must use this cookie to send their reply. */
- msg->cookie = 1;
-
- /* The payload_type is arbitrary, but it must be non-zero */
- msg->payload_type = 0xdeadbeef;
-
- /*
- * We are sending our message to the current owner of a well-known
- * name. This makes an item of type KDBUS_ITEM_DST_NAME mandatory.
- */
- msg->dst_id = KDBUS_DST_ID_NAME;
-
- /*
- * Set the reply timeout to 5 seconds. Timeouts are always set in
- * absolute timestamps, based con CLOCK_MONOTONIC. See kdbus.message(7).
- */
- clock_gettime(CLOCK_MONOTONIC_COARSE, &spec);
- msg->timeout_ns += (5 + spec.tv_sec) * 1000ULL * 1000ULL * 1000ULL;
- msg->timeout_ns += spec.tv_nsec;
-
- /*
- * Fill the appended items. First, set the well-known name of the
- * destination we want to talk to.
- */
- item = msg->items;
- item->type = KDBUS_ITEM_DST_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(arg_master) + 1;
- strcpy(item->str, arg_master);
-
- /*
- * The 2nd item contains a vector to memory we want to send. It
- * can be content of any type. In our case, we're sending a one-byte
- * string only. The memory referenced by this item will be copied into
- * the pool of the receiver connection, and does not need to be valid
- * after the command is employed.
- */
- item = KDBUS_ITEM_NEXT(item);
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)"r";
- item->vec.size = 1;
-
- /* Set up the command struct and reference the message we prepared */
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- /*
- * The send commands knows a mode in which it will block until a
- * reply to a message is received. This example uses that mode.
- * The pool offset to the received reply will be stored in the command
- * struct after the send command returned. See below.
- */
- cmd.flags = KDBUS_SEND_SYNC_REPLY;
-
- /*
- * Finally, employ the command on the connection owner
- * file descriptor.
- */
- r = kdbus_cmd_send(c->bus->fd, &cmd);
- if (r == -ESRCH || r == -EPIPE || r == -ECONNRESET)
- return 0;
- if (r < 0)
- return err_r(r, "cannot send request to master");
-
- /*
- * The command was sent with the KDBUS_SEND_SYNC_REPLY flag set,
- * and returned successfully, which means that cmd.reply.offset now
- * points to a message inside our connection's pool where the reply
- * is found. This is equivalent to receiving the reply with
- * KDBUS_CMD_RECV, but it doesn't require waiting for the reply with
- * poll() and also saves the ioctl to receive the message.
- */
- msg = (void *)(c->bus->pool + cmd.reply.offset);
-
- /*
- * A messages describes its actual payload in an array of items.
- * KDBUS_FOREACH() is a simple iterator that walks such an array.
- * struct kdbus_msg has a field to denote its total size, which is
- * needed to determine the number of items in the array.
- */
- KDBUS_FOREACH(item, msg->items,
- msg->size - offsetof(struct kdbus_msg, items)) {
- /*
- * An item of type PAYLOAD_OFF describes in-line memory
- * stored in the pool at a described offset. That offset is
- * relative to the start address of the message header.
- * This example program only expects one single item of that
- * type, remembers the struct kdbus_vec member of the item
- * when it sees it, and bails out if there is more than one
- * of them.
- */
- if (item->type == KDBUS_ITEM_PAYLOAD_OFF) {
- if (vec) {
- r = err_r(-EEXIST,
- "message with multiple vecs");
- break;
- }
- vec = &item->vec;
- if (vec->size != 2 * sizeof(size_t)) {
- r = err_r(-EINVAL, "invalid message size");
- break;
- }
- /*
- * MEMFDs are transported as items of type PAYLOAD_MEMFD.
- * If such an item is attached, a new file descriptor was
- * installed into the task when KDBUS_CMD_RECV was called, and
- * its number is stored in item->memfd.fd.
- * Implementers *must* handle this item type close the
- * file descriptor when no longer needed in order to prevent
- * file descriptor exhaustion. This example program just bails
- * out with an error in this case, as memfds are not expected
- * in this context.
- */
- } else if (item->type == KDBUS_ITEM_PAYLOAD_MEMFD) {
- r = err_r(-EINVAL, "message with memfd");
- break;
- }
- }
- if (r < 0)
- goto exit;
- if (!vec) {
- r = err_r(-EINVAL, "empty message");
- goto exit;
- }
-
- n = ((size_t *)((const uint8_t *)msg + vec->offset))[0];
- steps = ((size_t *)((const uint8_t *)msg + vec->offset))[1];
-
- while (steps-- > 0) {
- ++n;
- r = prime_run(c->prime, c->bus, n);
- if (r < 0)
- break;
- r = bus_poll(c->bus);
- if (r != 0) {
- r = r < 0 ? r : -EINTR;
- break;
- }
- }
-
-exit:
- /*
- * We are done with the memory slice that was given to us through
- * cmd.reply.offset. Tell the kernel it can use it for other content
- * in the future. See kdbus.pool(7).
- */
- bus_poool_free_slice(c->bus, cmd.reply.offset);
- return r;
-}
-
-/*
- * Prime Computation
- *
- */
-
-static int prime_new(struct prime **out)
-{
- struct prime *p;
- int r;
-
- p = calloc(1, sizeof(*p));
- if (!p)
- return err("cannot allocate prime memory");
-
- p->fd = -1;
- p->area = MAP_FAILED;
- p->max = MAX_PRIMES;
-
- /*
- * Prepare and map a memfd to store the bit-fields for the number
- * ranges we want to perform the prime detection on.
- */
- p->fd = syscall(__NR_memfd_create, "prime-area", MFD_CLOEXEC);
- if (p->fd < 0) {
- r = err("cannot create memfd");
- goto error;
- }
-
- r = ftruncate(p->fd, p->max / 8 + 1);
- if (r < 0) {
- r = err("cannot ftruncate area");
- goto error;
- }
-
- p->area = mmap(NULL, p->max / 8 + 1, PROT_READ | PROT_WRITE,
- MAP_SHARED, p->fd, 0);
- if (p->area == MAP_FAILED) {
- r = err("cannot mmap memfd");
- goto error;
- }
-
- *out = p;
- return 0;
-
-error:
- prime_free(p);
- return r;
-}
-
-static void prime_free(struct prime *p)
-{
- if (!p)
- return;
-
- if (p->area != MAP_FAILED)
- munmap(p->area, p->max / 8 + 1);
- if (p->fd >= 0)
- close(p->fd);
- free(p);
-}
-
-static bool prime_done(struct prime *p)
-{
- return p->done >= p->max;
-}
-
-static void prime_consume(struct prime *p, size_t amount)
-{
- p->done += amount;
-}
-
-static int prime_run(struct prime *p, struct bus *cancel, size_t number)
-{
- size_t i, n = 0;
- int r;
-
- if (number < 2 || number > 65535)
- return 0;
-
- for (i = number * number;
- i < p->max && i > number;
- i += number) {
- p->area[i / 8] |= 1 << (i % 8);
-
- if (!(++n % (1 << 20))) {
- r = bus_poll(cancel);
- if (r != 0)
- return r < 0 ? r : -EINTR;
- }
- }
-
- return 0;
-}
-
-static void prime_print(struct prime *p)
-{
- size_t i, l = 0;
-
- fprintf(stderr, "PRIMES:");
- for (i = 0; i < p->max; ++i) {
- if (!(p->area[i / 8] & (1 << (i % 8))))
- fprintf(stderr, "%c%7zu", !(l++ % 16) ? '\n' : ' ', i);
- }
- fprintf(stderr, "\nEND\n");
-}
-
-static int bus_open_connection(struct bus **out, uid_t uid, const char *name,
- uint64_t recv_flags)
-{
- struct kdbus_cmd_hello hello;
- char path[128];
- struct bus *b;
- int r;
-
- /*
- * The 'bus' object is our representation of a kdbus connection which
- * stores two details: the connection owner file descriptor, and the
- * mmap()ed memory of its associated pool. See kdbus.connection(7) and
- * kdbus.pool(7).
- */
- b = calloc(1, sizeof(*b));
- if (!b)
- return err("cannot allocate bus memory");
-
- b->fd = -1;
- b->pool = MAP_FAILED;
-
- /* Compute the name of the bus node to connect to. */
- snprintf(path, sizeof(path), "/sys/fs/%s/%lu-%s/bus",
- arg_modname, (unsigned long)uid, name);
- b->fd = open(path, O_RDWR | O_CLOEXEC);
- if (b->fd < 0) {
- r = err("cannot open bus");
- goto error;
- }
-
- /*
- * To make a connection to the bus, the KDBUS_CMD_HELLO ioctl is used.
- * It takes an argument of type 'struct kdbus_cmd_hello'.
- */
- memset(&hello, 0, sizeof(hello));
- hello.size = sizeof(hello);
-
- /*
- * Specify a mask of metadata attach flags, describing metadata items
- * that this new connection allows to be sent.
- */
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
-
- /*
- * Specify a mask of metadata attach flags, describing metadata items
- * that this new connection wants to be receive along with each message.
- */
- hello.attach_flags_recv = recv_flags;
-
- /*
- * A connection may choose the size of its pool, but the number has to
- * comply with two rules: a) it must be greater than 0, and b) it must
- * be a mulitple of PAGE_SIZE. See kdbus.pool(7).
- */
- hello.pool_size = POOL_SIZE;
-
- /*
- * Now employ the command on the file descriptor opened above.
- * This command will turn the file descriptor into a connection-owner
- * file descriptor that controls the life-time of the connection; once
- * it's closed, the connection is shut down.
- */
- r = kdbus_cmd_hello(b->fd, &hello);
- if (r < 0) {
- err_r(r, "HELLO failed");
- goto error;
- }
-
- bus_poool_free_slice(b, hello.offset);
-
- /*
- * Map the pool of the connection. Its size has been set in the
- * command struct above. See kdbus.pool(7).
- */
- b->pool = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, b->fd, 0);
- if (b->pool == MAP_FAILED) {
- r = err("cannot mmap pool");
- goto error;
- }
-
- *out = b;
- return 0;
-
-error:
- bus_close_connection(b);
- return r;
-}
-
-static void bus_close_connection(struct bus *b)
-{
- if (!b)
- return;
-
- /*
- * A bus connection is closed by simply calling close() on the
- * connection owner file descriptor. The unique name and all owned
- * well-known names of the conneciton will disappear.
- * See kdbus.connection(7).
- */
- if (b->pool != MAP_FAILED)
- munmap(b->pool, POOL_SIZE);
- if (b->fd >= 0)
- close(b->fd);
- free(b);
-}
-
-static void bus_poool_free_slice(struct bus *b, uint64_t offset)
-{
- struct kdbus_cmd_free cmd = {
- .size = sizeof(cmd),
- .offset = offset,
- };
- int r;
-
- /*
- * Once we're done with a piece of pool memory that was returned
- * by a command, we have to call the KDBUS_CMD_FREE ioctl on it so it
- * can be reused. The command takes an argument of type
- * 'struct kdbus_cmd_free', in which the pool offset of the slice to
- * free is stored. The ioctl is employed on the connection owner
- * file descriptor. See kdbus.pool(7),
- */
- r = kdbus_cmd_free(b->fd, &cmd);
- if (r < 0)
- err_r(r, "cannot free pool slice");
-}
-
-static int bus_acquire_name(struct bus *b, const char *name)
-{
- struct kdbus_item *item;
- struct kdbus_cmd *cmd;
- size_t size;
- int r;
-
- /*
- * This function acquires a well-known name on the bus through the
- * KDBUS_CMD_NAME_ACQUIRE ioctl. This ioctl takes an argument of type
- * 'struct kdbus_cmd', which is assembled below. See kdbus.name(7).
- */
- size = sizeof(*cmd);
- size += KDBUS_ITEM_SIZE(strlen(name) + 1);
-
- cmd = alloca(size);
- memset(cmd, 0, size);
- cmd->size = size;
-
- /*
- * The command requires an item of type KDBUS_ITEM_NAME, and its
- * content must be a valid bus name.
- */
- item = cmd->items;
- item->type = KDBUS_ITEM_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- strcpy(item->str, name);
-
- /*
- * Employ the command on the connection owner file descriptor.
- */
- r = kdbus_cmd_name_acquire(b->fd, cmd);
- if (r < 0)
- return err_r(r, "cannot acquire name");
-
- return 0;
-}
-
-static int bus_install_name_loss_match(struct bus *b, const char *name)
-{
- struct kdbus_cmd_match *match;
- struct kdbus_item *item;
- size_t size;
- int r;
-
- /*
- * In order to install a match for signal messages, we have to
- * assemble a 'struct kdbus_cmd_match' and use it along with the
- * KDBUS_CMD_MATCH_ADD ioctl. See kdbus.match(7).
- */
- size = sizeof(*match);
- size += KDBUS_ITEM_SIZE(sizeof(item->name_change) + strlen(name) + 1);
-
- match = alloca(size);
- memset(match, 0, size);
- match->size = size;
-
- /*
- * A match is comprised of many 'rules', each of which describes a
- * mandatory detail of the message. All rules of a match must be
- * satified in order to make a message pass.
- */
- item = match->items;
-
- /*
- * In this case, we're interested in notifications that inform us
- * about a well-known name being removed from the bus.
- */
- item->type = KDBUS_ITEM_NAME_REMOVE;
- item->size = KDBUS_ITEM_HEADER_SIZE +
- sizeof(item->name_change) + strlen(name) + 1;
-
- /*
- * We could limit the match further and require a specific unique-ID
- * to be the new or the old owner of the name. In this case, however,
- * we don't, and allow 'any' id.
- */
- item->name_change.old_id.id = KDBUS_MATCH_ID_ANY;
- item->name_change.new_id.id = KDBUS_MATCH_ID_ANY;
-
- /* Copy in the well-known name we're interested in */
- strcpy(item->name_change.name, name);
-
- /*
- * Add the match through the KDBUS_CMD_MATCH_ADD ioctl, employed on
- * the connection owner fd.
- */
- r = kdbus_cmd_match_add(b->fd, match);
- if (r < 0)
- return err_r(r, "cannot add match");
-
- return 0;
-}
-
-static int bus_poll(struct bus *b)
-{
- struct pollfd fds[1] = {};
- int r;
-
- /*
- * A connection endpoint supports poll() and will wake-up the
- * task with POLLIN set once a message has arrived.
- */
- fds[0].fd = b->fd;
- fds[0].events = POLLIN;
- r = poll(fds, sizeof(fds) / sizeof(*fds), 0);
- if (r < 0)
- return err("cannot poll bus");
- return !!(fds[0].revents & POLLIN);
-}
-
-static int bus_make(uid_t uid, const char *name)
-{
- struct kdbus_item *item;
- struct kdbus_cmd *make;
- char path[128], busname[128];
- size_t size;
- int r, fd;
-
- /*
- * Compute the full path to the 'control' node. 'arg_modname' may be
- * set to a different value than 'kdbus' for development purposes.
- * The 'control' node is the primary entry point to kdbus that must be
- * used in order to create a bus. See kdbus(7) and kdbus.bus(7).
- */
- snprintf(path, sizeof(path), "/sys/fs/%s/control", arg_modname);
-
- /*
- * Compute the bus name. A valid bus name must always be prefixed with
- * the EUID of the currently running process in order to avoid name
- * conflicts. See kdbus.bus(7).
- */
- snprintf(busname, sizeof(busname), "%lu-%s", (unsigned long)uid, name);
-
- fd = open(path, O_RDWR | O_CLOEXEC);
- if (fd < 0)
- return err("cannot open control file");
-
- /*
- * The KDBUS_CMD_BUS_MAKE ioctl takes an argument of type
- * 'struct kdbus_cmd', and expects at least two items attached to
- * it: one to decribe the bloom parameters to be propagated to
- * connections of the bus, and the name of the bus that was computed
- * above. Assemble this struct now, and fill it with values.
- */
- size = sizeof(*make);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_parameter));
- size += KDBUS_ITEM_SIZE(strlen(busname) + 1);
-
- make = alloca(size);
- memset(make, 0, size);
- make->size = size;
-
- /*
- * Each item has a 'type' and 'size' field, and must be stored at an
- * 8-byte aligned address. The KDBUS_ITEM_NEXT macro is used to advance
- * the pointer. See kdbus.item(7) for more details.
- */
- item = make->items;
- item->type = KDBUS_ITEM_BLOOM_PARAMETER;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(item->bloom_parameter);
- item->bloom_parameter.size = 8;
- item->bloom_parameter.n_hash = 1;
-
- /* The name of the new bus is stored in the next item. */
- item = KDBUS_ITEM_NEXT(item);
- item->type = KDBUS_ITEM_MAKE_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(busname) + 1;
- strcpy(item->str, busname);
-
- /*
- * Now create the bus via the KDBUS_CMD_BUS_MAKE ioctl and return the
- * fd that was used back to the caller of this function. This fd is now
- * called a 'bus owner file descriptor', and it controls the life-time
- * of the newly created bus; once the file descriptor is closed, the
- * bus goes away, and all connections are shut down. See kdbus.bus(7).
- */
- r = kdbus_cmd_bus_make(fd, make);
- if (r < 0) {
- err_r(r, "cannot make bus");
- close(fd);
- return r;
- }
-
- return fd;
-}
-
-#else
-
-#warning "Skipping compilation due to unsupported libc version"
-
-int main(int argc, char **argv)
-{
- fprintf(stderr,
- "Compilation of %s was skipped due to unsupported libc.\n",
- argv[0]);
-
- return EXIT_FAILURE;
-}
-
-#endif /* libc sanity check */
diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c
index 1334e02ae..3d145a3ff 100644
--- a/security/integrity/evm/evm_main.c
+++ b/security/integrity/evm/evm_main.c
@@ -23,6 +23,7 @@
#include <linux/integrity.h>
#include <linux/evm.h>
#include <crypto/hash.h>
+#include <crypto/algapi.h>
#include "evm.h"
int evm_initialized;
@@ -148,7 +149,7 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
xattr_value_len, calc.digest);
if (rc)
break;
- rc = memcmp(xattr_data->digest, calc.digest,
+ rc = crypto_memneq(xattr_data->digest, calc.digest,
sizeof(calc.digest));
if (rc)
rc = -EINVAL;
diff --git a/sound/core/compress_offload.c b/sound/core/compress_offload.c
index b123c42e7..b554d7f9e 100644
--- a/sound/core/compress_offload.c
+++ b/sound/core/compress_offload.c
@@ -44,6 +44,13 @@
#include <sound/compress_offload.h>
#include <sound/compress_driver.h>
+/* struct snd_compr_codec_caps overflows the ioctl bit size for some
+ * architectures, so we need to disable the relevant ioctls.
+ */
+#if _IOC_SIZEBITS < 14
+#define COMPR_CODEC_CAPS_OVERFLOW
+#endif
+
/* TODO:
* - add substream support for multiple devices in case of
* SND_DYNAMIC_MINORS is not used
@@ -438,6 +445,7 @@ out:
return retval;
}
+#ifndef COMPR_CODEC_CAPS_OVERFLOW
static int
snd_compr_get_codec_caps(struct snd_compr_stream *stream, unsigned long arg)
{
@@ -461,6 +469,7 @@ out:
kfree(caps);
return retval;
}
+#endif /* !COMPR_CODEC_CAPS_OVERFLOW */
/* revisit this with snd_pcm_preallocate_xxx */
static int snd_compr_allocate_buffer(struct snd_compr_stream *stream,
@@ -799,9 +808,11 @@ static long snd_compr_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
case _IOC_NR(SNDRV_COMPRESS_GET_CAPS):
retval = snd_compr_get_caps(stream, arg);
break;
+#ifndef COMPR_CODEC_CAPS_OVERFLOW
case _IOC_NR(SNDRV_COMPRESS_GET_CODEC_CAPS):
retval = snd_compr_get_codec_caps(stream, arg);
break;
+#endif
case _IOC_NR(SNDRV_COMPRESS_SET_PARAMS):
retval = snd_compr_set_params(stream, arg);
break;
diff --git a/sound/core/oss/pcm_oss.c b/sound/core/oss/pcm_oss.c
index 58550cc93..33e72c809 100644
--- a/sound/core/oss/pcm_oss.c
+++ b/sound/core/oss/pcm_oss.c
@@ -834,7 +834,8 @@ static int choose_rate(struct snd_pcm_substream *substream,
return snd_pcm_hw_param_near(substream, params, SNDRV_PCM_HW_PARAM_RATE, best_rate, NULL);
}
-static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
+static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream,
+ bool trylock)
{
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_pcm_hw_params *params, *sparams;
@@ -848,7 +849,10 @@ static int snd_pcm_oss_change_params(struct snd_pcm_substream *substream)
struct snd_mask sformat_mask;
struct snd_mask mask;
- if (mutex_lock_interruptible(&runtime->oss.params_lock))
+ if (trylock) {
+ if (!(mutex_trylock(&runtime->oss.params_lock)))
+ return -EAGAIN;
+ } else if (mutex_lock_interruptible(&runtime->oss.params_lock))
return -EINTR;
sw_params = kmalloc(sizeof(*sw_params), GFP_KERNEL);
params = kmalloc(sizeof(*params), GFP_KERNEL);
@@ -1092,7 +1096,7 @@ static int snd_pcm_oss_get_active_substream(struct snd_pcm_oss_file *pcm_oss_fil
if (asubstream == NULL)
asubstream = substream;
if (substream->runtime->oss.params) {
- err = snd_pcm_oss_change_params(substream);
+ err = snd_pcm_oss_change_params(substream, false);
if (err < 0)
return err;
}
@@ -1132,7 +1136,7 @@ static int snd_pcm_oss_make_ready(struct snd_pcm_substream *substream)
return 0;
runtime = substream->runtime;
if (runtime->oss.params) {
- err = snd_pcm_oss_change_params(substream);
+ err = snd_pcm_oss_change_params(substream, false);
if (err < 0)
return err;
}
@@ -2163,7 +2167,7 @@ static int snd_pcm_oss_get_space(struct snd_pcm_oss_file *pcm_oss_file, int stre
runtime = substream->runtime;
if (runtime->oss.params &&
- (err = snd_pcm_oss_change_params(substream)) < 0)
+ (err = snd_pcm_oss_change_params(substream, false)) < 0)
return err;
info.fragsize = runtime->oss.period_bytes;
@@ -2800,7 +2804,12 @@ static int snd_pcm_oss_mmap(struct file *file, struct vm_area_struct *area)
return -EIO;
if (runtime->oss.params) {
- if ((err = snd_pcm_oss_change_params(substream)) < 0)
+ /* use mutex_trylock() for params_lock for avoiding a deadlock
+ * between mmap_sem and params_lock taken by
+ * copy_from/to_user() in snd_pcm_oss_write/read()
+ */
+ err = snd_pcm_oss_change_params(substream, true);
+ if (err < 0)
return err;
}
#ifdef CONFIG_SND_PCM_OSS_PLUGINS
diff --git a/sound/core/rawmidi.c b/sound/core/rawmidi.c
index a7759846f..795437b10 100644
--- a/sound/core/rawmidi.c
+++ b/sound/core/rawmidi.c
@@ -942,31 +942,36 @@ static long snd_rawmidi_kernel_read1(struct snd_rawmidi_substream *substream,
unsigned long flags;
long result = 0, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long appl_ptr;
+ spin_lock_irqsave(&runtime->lock, flags);
while (count > 0 && runtime->avail) {
count1 = runtime->buffer_size - runtime->appl_ptr;
if (count1 > count)
count1 = count;
- spin_lock_irqsave(&runtime->lock, flags);
if (count1 > (int)runtime->avail)
count1 = runtime->avail;
+
+ /* update runtime->appl_ptr before unlocking for userbuf */
+ appl_ptr = runtime->appl_ptr;
+ runtime->appl_ptr += count1;
+ runtime->appl_ptr %= runtime->buffer_size;
+ runtime->avail -= count1;
+
if (kernelbuf)
- memcpy(kernelbuf + result, runtime->buffer + runtime->appl_ptr, count1);
+ memcpy(kernelbuf + result, runtime->buffer + appl_ptr, count1);
if (userbuf) {
spin_unlock_irqrestore(&runtime->lock, flags);
if (copy_to_user(userbuf + result,
- runtime->buffer + runtime->appl_ptr, count1)) {
+ runtime->buffer + appl_ptr, count1)) {
return result > 0 ? result : -EFAULT;
}
spin_lock_irqsave(&runtime->lock, flags);
}
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
- spin_unlock_irqrestore(&runtime->lock, flags);
result += count1;
count -= count1;
}
+ spin_unlock_irqrestore(&runtime->lock, flags);
return result;
}
@@ -1055,23 +1060,16 @@ int snd_rawmidi_transmit_empty(struct snd_rawmidi_substream *substream)
EXPORT_SYMBOL(snd_rawmidi_transmit_empty);
/**
- * snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * __snd_rawmidi_transmit_peek - copy data from the internal buffer
* @substream: the rawmidi substream
* @buffer: the buffer pointer
* @count: data size to transfer
*
- * Copies data from the internal output buffer to the given buffer.
- *
- * Call this in the interrupt handler when the midi output is ready,
- * and call snd_rawmidi_transmit_ack() after the transmission is
- * finished.
- *
- * Return: The size of copied data, or a negative error code on failure.
+ * This is a variant of snd_rawmidi_transmit_peek() without spinlock.
*/
-int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+int __snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
unsigned char *buffer, int count)
{
- unsigned long flags;
int result, count1;
struct snd_rawmidi_runtime *runtime = substream->runtime;
@@ -1081,7 +1079,6 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
return -EINVAL;
}
result = 0;
- spin_lock_irqsave(&runtime->lock, flags);
if (runtime->avail >= runtime->buffer_size) {
/* warning: lowlevel layer MUST trigger down the hardware */
goto __skip;
@@ -1106,25 +1103,47 @@ int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
}
}
__skip:
+ return result;
+}
+EXPORT_SYMBOL(__snd_rawmidi_transmit_peek);
+
+/**
+ * snd_rawmidi_transmit_peek - copy data from the internal buffer
+ * @substream: the rawmidi substream
+ * @buffer: the buffer pointer
+ * @count: data size to transfer
+ *
+ * Copies data from the internal output buffer to the given buffer.
+ *
+ * Call this in the interrupt handler when the midi output is ready,
+ * and call snd_rawmidi_transmit_ack() after the transmission is
+ * finished.
+ *
+ * Return: The size of copied data, or a negative error code on failure.
+ */
+int snd_rawmidi_transmit_peek(struct snd_rawmidi_substream *substream,
+ unsigned char *buffer, int count)
+{
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&runtime->lock, flags);
+ result = __snd_rawmidi_transmit_peek(substream, buffer, count);
spin_unlock_irqrestore(&runtime->lock, flags);
return result;
}
EXPORT_SYMBOL(snd_rawmidi_transmit_peek);
/**
- * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * __snd_rawmidi_transmit_ack - acknowledge the transmission
* @substream: the rawmidi substream
* @count: the transferred count
*
- * Advances the hardware pointer for the internal output buffer with
- * the given size and updates the condition.
- * Call after the transmission is finished.
- *
- * Return: The advanced size if successful, or a negative error code on failure.
+ * This is a variant of __snd_rawmidi_transmit_ack() without spinlock.
*/
-int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+int __snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
{
- unsigned long flags;
struct snd_rawmidi_runtime *runtime = substream->runtime;
if (runtime->buffer == NULL) {
@@ -1132,7 +1151,6 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
"snd_rawmidi_transmit_ack: output is not active!!!\n");
return -EINVAL;
}
- spin_lock_irqsave(&runtime->lock, flags);
snd_BUG_ON(runtime->avail + count > runtime->buffer_size);
runtime->hw_ptr += count;
runtime->hw_ptr %= runtime->buffer_size;
@@ -1142,9 +1160,32 @@ int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
if (runtime->drain || snd_rawmidi_ready(substream))
wake_up(&runtime->sleep);
}
- spin_unlock_irqrestore(&runtime->lock, flags);
return count;
}
+EXPORT_SYMBOL(__snd_rawmidi_transmit_ack);
+
+/**
+ * snd_rawmidi_transmit_ack - acknowledge the transmission
+ * @substream: the rawmidi substream
+ * @count: the transferred count
+ *
+ * Advances the hardware pointer for the internal output buffer with
+ * the given size and updates the condition.
+ * Call after the transmission is finished.
+ *
+ * Return: The advanced size if successful, or a negative error code on failure.
+ */
+int snd_rawmidi_transmit_ack(struct snd_rawmidi_substream *substream, int count)
+{
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&runtime->lock, flags);
+ result = __snd_rawmidi_transmit_ack(substream, count);
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
+}
EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
/**
@@ -1160,12 +1201,22 @@ EXPORT_SYMBOL(snd_rawmidi_transmit_ack);
int snd_rawmidi_transmit(struct snd_rawmidi_substream *substream,
unsigned char *buffer, int count)
{
+ struct snd_rawmidi_runtime *runtime = substream->runtime;
+ int result;
+ unsigned long flags;
+
+ spin_lock_irqsave(&runtime->lock, flags);
if (!substream->opened)
- return -EBADFD;
- count = snd_rawmidi_transmit_peek(substream, buffer, count);
- if (count < 0)
- return count;
- return snd_rawmidi_transmit_ack(substream, count);
+ result = -EBADFD;
+ else {
+ count = __snd_rawmidi_transmit_peek(substream, buffer, count);
+ if (count <= 0)
+ result = count;
+ else
+ result = __snd_rawmidi_transmit_ack(substream, count);
+ }
+ spin_unlock_irqrestore(&runtime->lock, flags);
+ return result;
}
EXPORT_SYMBOL(snd_rawmidi_transmit);
@@ -1177,8 +1228,9 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
unsigned long flags;
long count1, result;
struct snd_rawmidi_runtime *runtime = substream->runtime;
+ unsigned long appl_ptr;
- if (snd_BUG_ON(!kernelbuf && !userbuf))
+ if (!kernelbuf && !userbuf)
return -EINVAL;
if (snd_BUG_ON(!runtime->buffer))
return -EINVAL;
@@ -1197,12 +1249,19 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
count1 = count;
if (count1 > (long)runtime->avail)
count1 = runtime->avail;
+
+ /* update runtime->appl_ptr before unlocking for userbuf */
+ appl_ptr = runtime->appl_ptr;
+ runtime->appl_ptr += count1;
+ runtime->appl_ptr %= runtime->buffer_size;
+ runtime->avail -= count1;
+
if (kernelbuf)
- memcpy(runtime->buffer + runtime->appl_ptr,
+ memcpy(runtime->buffer + appl_ptr,
kernelbuf + result, count1);
else if (userbuf) {
spin_unlock_irqrestore(&runtime->lock, flags);
- if (copy_from_user(runtime->buffer + runtime->appl_ptr,
+ if (copy_from_user(runtime->buffer + appl_ptr,
userbuf + result, count1)) {
spin_lock_irqsave(&runtime->lock, flags);
result = result > 0 ? result : -EFAULT;
@@ -1210,9 +1269,6 @@ static long snd_rawmidi_kernel_write1(struct snd_rawmidi_substream *substream,
}
spin_lock_irqsave(&runtime->lock, flags);
}
- runtime->appl_ptr += count1;
- runtime->appl_ptr %= runtime->buffer_size;
- runtime->avail -= count1;
result += count1;
count -= count1;
}
diff --git a/sound/core/seq/oss/seq_oss_init.c b/sound/core/seq/oss/seq_oss_init.c
index b1221b297..6779e82b4 100644
--- a/sound/core/seq/oss/seq_oss_init.c
+++ b/sound/core/seq/oss/seq_oss_init.c
@@ -202,7 +202,7 @@ snd_seq_oss_open(struct file *file, int level)
dp->index = i;
if (i >= SNDRV_SEQ_OSS_MAX_CLIENTS) {
- pr_err("ALSA: seq_oss: too many applications\n");
+ pr_debug("ALSA: seq_oss: too many applications\n");
rc = -ENOMEM;
goto _error;
}
diff --git a/sound/core/seq/oss/seq_oss_synth.c b/sound/core/seq/oss/seq_oss_synth.c
index 0f3b38184..b16dbef04 100644
--- a/sound/core/seq/oss/seq_oss_synth.c
+++ b/sound/core/seq/oss/seq_oss_synth.c
@@ -308,7 +308,7 @@ snd_seq_oss_synth_cleanup(struct seq_oss_devinfo *dp)
struct seq_oss_synth *rec;
struct seq_oss_synthinfo *info;
- if (snd_BUG_ON(dp->max_synthdev >= SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
+ if (snd_BUG_ON(dp->max_synthdev > SNDRV_SEQ_OSS_MAX_SYNTH_DEVS))
return;
for (i = 0; i < dp->max_synthdev; i++) {
info = &dp->synths[i];
diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index 13cfa8157..58e79e02f 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -678,6 +678,9 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
else
down_read(&grp->list_mutex);
list_for_each_entry(subs, &grp->list_head, src_list) {
+ /* both ports ready? */
+ if (atomic_read(&subs->ref_count) != 2)
+ continue;
event->dest = subs->info.dest;
if (subs->info.flags & SNDRV_SEQ_PORT_SUBS_TIMESTAMP)
/* convert time according to flag with subscription */
diff --git a/sound/core/seq/seq_ports.c b/sound/core/seq/seq_ports.c
index 55170a20a..921fb2bd8 100644
--- a/sound/core/seq/seq_ports.c
+++ b/sound/core/seq/seq_ports.c
@@ -173,10 +173,6 @@ struct snd_seq_client_port *snd_seq_create_port(struct snd_seq_client *client,
}
/* */
-enum group_type {
- SRC_LIST, DEST_LIST
-};
-
static int subscribe_port(struct snd_seq_client *client,
struct snd_seq_client_port *port,
struct snd_seq_port_subs_info *grp,
@@ -203,6 +199,20 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
return NULL;
}
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_subscribers *subs,
+ bool is_src, bool ack);
+
+static inline struct snd_seq_subscribers *
+get_subscriber(struct list_head *p, bool is_src)
+{
+ if (is_src)
+ return list_entry(p, struct snd_seq_subscribers, src_list);
+ else
+ return list_entry(p, struct snd_seq_subscribers, dest_list);
+}
+
/*
* remove all subscribers on the list
* this is called from port_delete, for each src and dest list.
@@ -210,7 +220,7 @@ static struct snd_seq_client_port *get_client_port(struct snd_seq_addr *addr,
static void clear_subscriber_list(struct snd_seq_client *client,
struct snd_seq_client_port *port,
struct snd_seq_port_subs_info *grp,
- int grptype)
+ int is_src)
{
struct list_head *p, *n;
@@ -219,15 +229,13 @@ static void clear_subscriber_list(struct snd_seq_client *client,
struct snd_seq_client *c;
struct snd_seq_client_port *aport;
- if (grptype == SRC_LIST) {
- subs = list_entry(p, struct snd_seq_subscribers, src_list);
+ subs = get_subscriber(p, is_src);
+ if (is_src)
aport = get_client_port(&subs->info.dest, &c);
- } else {
- subs = list_entry(p, struct snd_seq_subscribers, dest_list);
+ else
aport = get_client_port(&subs->info.sender, &c);
- }
- list_del(p);
- unsubscribe_port(client, port, grp, &subs->info, 0);
+ delete_and_unsubscribe_port(client, port, subs, is_src, false);
+
if (!aport) {
/* looks like the connected port is being deleted.
* we decrease the counter, and when both ports are deleted
@@ -235,21 +243,14 @@ static void clear_subscriber_list(struct snd_seq_client *client,
*/
if (atomic_dec_and_test(&subs->ref_count))
kfree(subs);
- } else {
- /* ok we got the connected port */
- struct snd_seq_port_subs_info *agrp;
- agrp = (grptype == SRC_LIST) ? &aport->c_dest : &aport->c_src;
- down_write(&agrp->list_mutex);
- if (grptype == SRC_LIST)
- list_del(&subs->dest_list);
- else
- list_del(&subs->src_list);
- up_write(&agrp->list_mutex);
- unsubscribe_port(c, aport, agrp, &subs->info, 1);
- kfree(subs);
- snd_seq_port_unlock(aport);
- snd_seq_client_unlock(c);
+ continue;
}
+
+ /* ok we got the connected port */
+ delete_and_unsubscribe_port(c, aport, subs, !is_src, true);
+ kfree(subs);
+ snd_seq_port_unlock(aport);
+ snd_seq_client_unlock(c);
}
}
@@ -262,8 +263,8 @@ static int port_delete(struct snd_seq_client *client,
snd_use_lock_sync(&port->use_lock);
/* clear subscribers info */
- clear_subscriber_list(client, port, &port->c_src, SRC_LIST);
- clear_subscriber_list(client, port, &port->c_dest, DEST_LIST);
+ clear_subscriber_list(client, port, &port->c_src, true);
+ clear_subscriber_list(client, port, &port->c_dest, false);
if (port->private_free)
port->private_free(port->private_data);
@@ -479,85 +480,120 @@ static int match_subs_info(struct snd_seq_port_subscribe *r,
return 0;
}
-
-/* connect two ports */
-int snd_seq_port_connect(struct snd_seq_client *connector,
- struct snd_seq_client *src_client,
- struct snd_seq_client_port *src_port,
- struct snd_seq_client *dest_client,
- struct snd_seq_client_port *dest_port,
- struct snd_seq_port_subscribe *info)
+static int check_and_subscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_subscribers *subs,
+ bool is_src, bool exclusive, bool ack)
{
- struct snd_seq_port_subs_info *src = &src_port->c_src;
- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
- struct snd_seq_subscribers *subs, *s;
- int err, src_called = 0;
- unsigned long flags;
- int exclusive;
+ struct snd_seq_port_subs_info *grp;
+ struct list_head *p;
+ struct snd_seq_subscribers *s;
+ int err;
- subs = kzalloc(sizeof(*subs), GFP_KERNEL);
- if (! subs)
- return -ENOMEM;
-
- subs->info = *info;
- atomic_set(&subs->ref_count, 2);
-
- down_write(&src->list_mutex);
- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
- exclusive = info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE ? 1 : 0;
+ grp = is_src ? &port->c_src : &port->c_dest;
err = -EBUSY;
+ down_write(&grp->list_mutex);
if (exclusive) {
- if (! list_empty(&src->list_head) || ! list_empty(&dest->list_head))
+ if (!list_empty(&grp->list_head))
goto __error;
} else {
- if (src->exclusive || dest->exclusive)
+ if (grp->exclusive)
goto __error;
/* check whether already exists */
- list_for_each_entry(s, &src->list_head, src_list) {
- if (match_subs_info(info, &s->info))
- goto __error;
- }
- list_for_each_entry(s, &dest->list_head, dest_list) {
- if (match_subs_info(info, &s->info))
+ list_for_each(p, &grp->list_head) {
+ s = get_subscriber(p, is_src);
+ if (match_subs_info(&subs->info, &s->info))
goto __error;
}
}
- if ((err = subscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number)) < 0)
- goto __error;
- src_called = 1;
-
- if ((err = subscribe_port(dest_client, dest_port, dest, info,
- connector->number != dest_client->number)) < 0)
+ err = subscribe_port(client, port, grp, &subs->info, ack);
+ if (err < 0) {
+ grp->exclusive = 0;
goto __error;
+ }
/* add to list */
- write_lock_irqsave(&src->list_lock, flags);
- // write_lock(&dest->list_lock); // no other lock yet
- list_add_tail(&subs->src_list, &src->list_head);
- list_add_tail(&subs->dest_list, &dest->list_head);
- // write_unlock(&dest->list_lock); // no other lock yet
- write_unlock_irqrestore(&src->list_lock, flags);
+ write_lock_irq(&grp->list_lock);
+ if (is_src)
+ list_add_tail(&subs->src_list, &grp->list_head);
+ else
+ list_add_tail(&subs->dest_list, &grp->list_head);
+ grp->exclusive = exclusive;
+ atomic_inc(&subs->ref_count);
+ write_unlock_irq(&grp->list_lock);
+ err = 0;
+
+ __error:
+ up_write(&grp->list_mutex);
+ return err;
+}
- src->exclusive = dest->exclusive = exclusive;
+static void delete_and_unsubscribe_port(struct snd_seq_client *client,
+ struct snd_seq_client_port *port,
+ struct snd_seq_subscribers *subs,
+ bool is_src, bool ack)
+{
+ struct snd_seq_port_subs_info *grp;
+
+ grp = is_src ? &port->c_src : &port->c_dest;
+ down_write(&grp->list_mutex);
+ write_lock_irq(&grp->list_lock);
+ if (is_src)
+ list_del(&subs->src_list);
+ else
+ list_del(&subs->dest_list);
+ grp->exclusive = 0;
+ write_unlock_irq(&grp->list_lock);
+ up_write(&grp->list_mutex);
+
+ unsubscribe_port(client, port, grp, &subs->info, ack);
+}
+
+/* connect two ports */
+int snd_seq_port_connect(struct snd_seq_client *connector,
+ struct snd_seq_client *src_client,
+ struct snd_seq_client_port *src_port,
+ struct snd_seq_client *dest_client,
+ struct snd_seq_client_port *dest_port,
+ struct snd_seq_port_subscribe *info)
+{
+ struct snd_seq_subscribers *subs;
+ bool exclusive;
+ int err;
+
+ subs = kzalloc(sizeof(*subs), GFP_KERNEL);
+ if (!subs)
+ return -ENOMEM;
+
+ subs->info = *info;
+ atomic_set(&subs->ref_count, 0);
+ INIT_LIST_HEAD(&subs->src_list);
+ INIT_LIST_HEAD(&subs->dest_list);
+
+ exclusive = !!(info->flags & SNDRV_SEQ_PORT_SUBS_EXCLUSIVE);
+
+ err = check_and_subscribe_port(src_client, src_port, subs, true,
+ exclusive,
+ connector->number != src_client->number);
+ if (err < 0)
+ goto error;
+ err = check_and_subscribe_port(dest_client, dest_port, subs, false,
+ exclusive,
+ connector->number != dest_client->number);
+ if (err < 0)
+ goto error_dest;
- up_write(&dest->list_mutex);
- up_write(&src->list_mutex);
return 0;
- __error:
- if (src_called)
- unsubscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number);
+ error_dest:
+ delete_and_unsubscribe_port(src_client, src_port, subs, true,
+ connector->number != src_client->number);
+ error:
kfree(subs);
- up_write(&dest->list_mutex);
- up_write(&src->list_mutex);
return err;
}
-
/* remove the connection */
int snd_seq_port_disconnect(struct snd_seq_client *connector,
struct snd_seq_client *src_client,
@@ -567,37 +603,28 @@ int snd_seq_port_disconnect(struct snd_seq_client *connector,
struct snd_seq_port_subscribe *info)
{
struct snd_seq_port_subs_info *src = &src_port->c_src;
- struct snd_seq_port_subs_info *dest = &dest_port->c_dest;
struct snd_seq_subscribers *subs;
int err = -ENOENT;
- unsigned long flags;
down_write(&src->list_mutex);
- down_write_nested(&dest->list_mutex, SINGLE_DEPTH_NESTING);
-
/* look for the connection */
list_for_each_entry(subs, &src->list_head, src_list) {
if (match_subs_info(info, &subs->info)) {
- write_lock_irqsave(&src->list_lock, flags);
- // write_lock(&dest->list_lock); // no lock yet
- list_del(&subs->src_list);
- list_del(&subs->dest_list);
- // write_unlock(&dest->list_lock);
- write_unlock_irqrestore(&src->list_lock, flags);
- src->exclusive = dest->exclusive = 0;
- unsubscribe_port(src_client, src_port, src, info,
- connector->number != src_client->number);
- unsubscribe_port(dest_client, dest_port, dest, info,
- connector->number != dest_client->number);
- kfree(subs);
+ atomic_dec(&subs->ref_count); /* mark as not ready */
err = 0;
break;
}
}
-
- up_write(&dest->list_mutex);
up_write(&src->list_mutex);
- return err;
+ if (err < 0)
+ return err;
+
+ delete_and_unsubscribe_port(src_client, src_port, subs, true,
+ connector->number != src_client->number);
+ delete_and_unsubscribe_port(dest_client, dest_port, subs, false,
+ connector->number != dest_client->number);
+ kfree(subs);
+ return 0;
}
diff --git a/sound/core/seq/seq_timer.c b/sound/core/seq/seq_timer.c
index 82b220c76..293104926 100644
--- a/sound/core/seq/seq_timer.c
+++ b/sound/core/seq/seq_timer.c
@@ -90,6 +90,9 @@ void snd_seq_timer_delete(struct snd_seq_timer **tmr)
void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
{
+ unsigned long flags;
+
+ spin_lock_irqsave(&tmr->lock, flags);
/* setup defaults */
tmr->ppq = 96; /* 96 PPQ */
tmr->tempo = 500000; /* 120 BPM */
@@ -105,21 +108,25 @@ void snd_seq_timer_defaults(struct snd_seq_timer * tmr)
tmr->preferred_resolution = seq_default_timer_resolution;
tmr->skew = tmr->skew_base = SKEW_BASE;
+ spin_unlock_irqrestore(&tmr->lock, flags);
}
-void snd_seq_timer_reset(struct snd_seq_timer * tmr)
+static void seq_timer_reset(struct snd_seq_timer *tmr)
{
- unsigned long flags;
-
- spin_lock_irqsave(&tmr->lock, flags);
-
/* reset time & songposition */
tmr->cur_time.tv_sec = 0;
tmr->cur_time.tv_nsec = 0;
tmr->tick.cur_tick = 0;
tmr->tick.fraction = 0;
+}
+
+void snd_seq_timer_reset(struct snd_seq_timer *tmr)
+{
+ unsigned long flags;
+ spin_lock_irqsave(&tmr->lock, flags);
+ seq_timer_reset(tmr);
spin_unlock_irqrestore(&tmr->lock, flags);
}
@@ -138,8 +145,11 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
tmr = q->timer;
if (tmr == NULL)
return;
- if (!tmr->running)
+ spin_lock_irqsave(&tmr->lock, flags);
+ if (!tmr->running) {
+ spin_unlock_irqrestore(&tmr->lock, flags);
return;
+ }
resolution *= ticks;
if (tmr->skew != tmr->skew_base) {
@@ -148,8 +158,6 @@ static void snd_seq_timer_interrupt(struct snd_timer_instance *timeri,
(((resolution & 0xffff) * tmr->skew) >> 16);
}
- spin_lock_irqsave(&tmr->lock, flags);
-
/* update timer */
snd_seq_inc_time_nsec(&tmr->cur_time, resolution);
@@ -296,26 +304,30 @@ int snd_seq_timer_open(struct snd_seq_queue *q)
t->callback = snd_seq_timer_interrupt;
t->callback_data = q;
t->flags |= SNDRV_TIMER_IFLG_AUTO;
+ spin_lock_irq(&tmr->lock);
tmr->timeri = t;
+ spin_unlock_irq(&tmr->lock);
return 0;
}
int snd_seq_timer_close(struct snd_seq_queue *q)
{
struct snd_seq_timer *tmr;
+ struct snd_timer_instance *t;
tmr = q->timer;
if (snd_BUG_ON(!tmr))
return -EINVAL;
- if (tmr->timeri) {
- snd_timer_stop(tmr->timeri);
- snd_timer_close(tmr->timeri);
- tmr->timeri = NULL;
- }
+ spin_lock_irq(&tmr->lock);
+ t = tmr->timeri;
+ tmr->timeri = NULL;
+ spin_unlock_irq(&tmr->lock);
+ if (t)
+ snd_timer_close(t);
return 0;
}
-int snd_seq_timer_stop(struct snd_seq_timer * tmr)
+static int seq_timer_stop(struct snd_seq_timer *tmr)
{
if (! tmr->timeri)
return -EINVAL;
@@ -326,6 +338,17 @@ int snd_seq_timer_stop(struct snd_seq_timer * tmr)
return 0;
}
+int snd_seq_timer_stop(struct snd_seq_timer *tmr)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&tmr->lock, flags);
+ err = seq_timer_stop(tmr);
+ spin_unlock_irqrestore(&tmr->lock, flags);
+ return err;
+}
+
static int initialize_timer(struct snd_seq_timer *tmr)
{
struct snd_timer *t;
@@ -358,13 +381,13 @@ static int initialize_timer(struct snd_seq_timer *tmr)
return 0;
}
-int snd_seq_timer_start(struct snd_seq_timer * tmr)
+static int seq_timer_start(struct snd_seq_timer *tmr)
{
if (! tmr->timeri)
return -EINVAL;
if (tmr->running)
- snd_seq_timer_stop(tmr);
- snd_seq_timer_reset(tmr);
+ seq_timer_stop(tmr);
+ seq_timer_reset(tmr);
if (initialize_timer(tmr) < 0)
return -EINVAL;
snd_timer_start(tmr->timeri, tmr->ticks);
@@ -373,14 +396,25 @@ int snd_seq_timer_start(struct snd_seq_timer * tmr)
return 0;
}
-int snd_seq_timer_continue(struct snd_seq_timer * tmr)
+int snd_seq_timer_start(struct snd_seq_timer *tmr)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&tmr->lock, flags);
+ err = seq_timer_start(tmr);
+ spin_unlock_irqrestore(&tmr->lock, flags);
+ return err;
+}
+
+static int seq_timer_continue(struct snd_seq_timer *tmr)
{
if (! tmr->timeri)
return -EINVAL;
if (tmr->running)
return -EBUSY;
if (! tmr->initialized) {
- snd_seq_timer_reset(tmr);
+ seq_timer_reset(tmr);
if (initialize_timer(tmr) < 0)
return -EINVAL;
}
@@ -390,11 +424,24 @@ int snd_seq_timer_continue(struct snd_seq_timer * tmr)
return 0;
}
+int snd_seq_timer_continue(struct snd_seq_timer *tmr)
+{
+ unsigned long flags;
+ int err;
+
+ spin_lock_irqsave(&tmr->lock, flags);
+ err = seq_timer_continue(tmr);
+ spin_unlock_irqrestore(&tmr->lock, flags);
+ return err;
+}
+
/* return current 'real' time. use timeofday() to get better granularity. */
snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
{
snd_seq_real_time_t cur_time;
+ unsigned long flags;
+ spin_lock_irqsave(&tmr->lock, flags);
cur_time = tmr->cur_time;
if (tmr->running) {
struct timeval tm;
@@ -410,7 +457,7 @@ snd_seq_real_time_t snd_seq_timer_get_cur_time(struct snd_seq_timer *tmr)
}
snd_seq_sanity_real_time(&cur_time);
}
-
+ spin_unlock_irqrestore(&tmr->lock, flags);
return cur_time;
}
diff --git a/sound/core/seq/seq_virmidi.c b/sound/core/seq/seq_virmidi.c
index 56e0f4cd3..81134e067 100644
--- a/sound/core/seq/seq_virmidi.c
+++ b/sound/core/seq/seq_virmidi.c
@@ -155,21 +155,26 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
struct snd_virmidi *vmidi = substream->runtime->private_data;
int count, res;
unsigned char buf[32], *pbuf;
+ unsigned long flags;
if (up) {
vmidi->trigger = 1;
if (vmidi->seq_mode == SNDRV_VIRMIDI_SEQ_DISPATCH &&
!(vmidi->rdev->flags & SNDRV_VIRMIDI_SUBSCRIBE)) {
- snd_rawmidi_transmit_ack(substream, substream->runtime->buffer_size - substream->runtime->avail);
- return; /* ignored */
+ while (snd_rawmidi_transmit(substream, buf,
+ sizeof(buf)) > 0) {
+ /* ignored */
+ }
+ return;
}
if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
return;
vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
}
+ spin_lock_irqsave(&substream->runtime->lock, flags);
while (1) {
- count = snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
+ count = __snd_rawmidi_transmit_peek(substream, buf, sizeof(buf));
if (count <= 0)
break;
pbuf = buf;
@@ -179,16 +184,18 @@ static void snd_virmidi_output_trigger(struct snd_rawmidi_substream *substream,
snd_midi_event_reset_encode(vmidi->parser);
continue;
}
- snd_rawmidi_transmit_ack(substream, res);
+ __snd_rawmidi_transmit_ack(substream, res);
pbuf += res;
count -= res;
if (vmidi->event.type != SNDRV_SEQ_EVENT_NONE) {
if (snd_seq_kernel_client_dispatch(vmidi->client, &vmidi->event, in_atomic(), 0) < 0)
- return;
+ goto out;
vmidi->event.type = SNDRV_SEQ_EVENT_NONE;
}
}
}
+ out:
+ spin_unlock_irqrestore(&substream->runtime->lock, flags);
} else {
vmidi->trigger = 0;
}
@@ -254,9 +261,13 @@ static int snd_virmidi_output_open(struct snd_rawmidi_substream *substream)
*/
static int snd_virmidi_input_close(struct snd_rawmidi_substream *substream)
{
+ struct snd_virmidi_dev *rdev = substream->rmidi->private_data;
struct snd_virmidi *vmidi = substream->runtime->private_data;
- snd_midi_event_free(vmidi->parser);
+
+ write_lock_irq(&rdev->filelist_lock);
list_del(&vmidi->list);
+ write_unlock_irq(&rdev->filelist_lock);
+ snd_midi_event_free(vmidi->parser);
substream->runtime->private_data = NULL;
kfree(vmidi);
return 0;
diff --git a/sound/core/timer.c b/sound/core/timer.c
index 0a049c457..f24c9fccf 100644
--- a/sound/core/timer.c
+++ b/sound/core/timer.c
@@ -305,8 +305,7 @@ int snd_timer_open(struct snd_timer_instance **ti,
return 0;
}
-static int _snd_timer_stop(struct snd_timer_instance *timeri,
- int keep_flag, int event);
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event);
/*
* close a timer instance
@@ -348,7 +347,7 @@ int snd_timer_close(struct snd_timer_instance *timeri)
spin_unlock_irq(&timer->lock);
mutex_lock(&register_mutex);
list_del(&timeri->open_list);
- if (timer && list_empty(&timer->open_list_head) &&
+ if (list_empty(&timer->open_list_head) &&
timer->hw.close)
timer->hw.close(timer);
/* remove slave links */
@@ -423,7 +422,7 @@ static void snd_timer_notify1(struct snd_timer_instance *ti, int event)
spin_lock_irqsave(&timer->lock, flags);
list_for_each_entry(ts, &ti->slave_active_head, active_list)
if (ts->ccallback)
- ts->ccallback(ti, event + 100, &tstamp, resolution);
+ ts->ccallback(ts, event + 100, &tstamp, resolution);
spin_unlock_irqrestore(&timer->lock, flags);
}
@@ -452,6 +451,10 @@ static int snd_timer_start_slave(struct snd_timer_instance *timeri)
unsigned long flags;
spin_lock_irqsave(&slave_active_lock, flags);
+ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+ spin_unlock_irqrestore(&slave_active_lock, flags);
+ return -EBUSY;
+ }
timeri->flags |= SNDRV_TIMER_IFLG_RUNNING;
if (timeri->master && timeri->timer) {
spin_lock(&timeri->timer->lock);
@@ -476,7 +479,8 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
return -EINVAL;
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
result = snd_timer_start_slave(timeri);
- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ if (result >= 0)
+ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
return result;
}
timer = timeri->timer;
@@ -485,16 +489,22 @@ int snd_timer_start(struct snd_timer_instance *timeri, unsigned int ticks)
if (timer->card && timer->card->shutdown)
return -ENODEV;
spin_lock_irqsave(&timer->lock, flags);
+ if (timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+ SNDRV_TIMER_IFLG_START)) {
+ result = -EBUSY;
+ goto unlock;
+ }
timeri->ticks = timeri->cticks = ticks;
timeri->pticks = 0;
result = snd_timer_start1(timer, timeri, ticks);
+ unlock:
spin_unlock_irqrestore(&timer->lock, flags);
- snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
+ if (result >= 0)
+ snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_START);
return result;
}
-static int _snd_timer_stop(struct snd_timer_instance * timeri,
- int keep_flag, int event)
+static int _snd_timer_stop(struct snd_timer_instance *timeri, int event)
{
struct snd_timer *timer;
unsigned long flags;
@@ -503,19 +513,30 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
return -ENXIO;
if (timeri->flags & SNDRV_TIMER_IFLG_SLAVE) {
- if (!keep_flag) {
- spin_lock_irqsave(&slave_active_lock, flags);
- timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
- list_del_init(&timeri->ack_list);
- list_del_init(&timeri->active_list);
+ spin_lock_irqsave(&slave_active_lock, flags);
+ if (!(timeri->flags & SNDRV_TIMER_IFLG_RUNNING)) {
spin_unlock_irqrestore(&slave_active_lock, flags);
+ return -EBUSY;
}
+ if (timeri->timer)
+ spin_lock(&timeri->timer->lock);
+ timeri->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
+ list_del_init(&timeri->ack_list);
+ list_del_init(&timeri->active_list);
+ if (timeri->timer)
+ spin_unlock(&timeri->timer->lock);
+ spin_unlock_irqrestore(&slave_active_lock, flags);
goto __end;
}
timer = timeri->timer;
if (!timer)
return -EINVAL;
spin_lock_irqsave(&timer->lock, flags);
+ if (!(timeri->flags & (SNDRV_TIMER_IFLG_RUNNING |
+ SNDRV_TIMER_IFLG_START))) {
+ spin_unlock_irqrestore(&timer->lock, flags);
+ return -EBUSY;
+ }
list_del_init(&timeri->ack_list);
list_del_init(&timeri->active_list);
if (timer->card && timer->card->shutdown) {
@@ -534,9 +555,7 @@ static int _snd_timer_stop(struct snd_timer_instance * timeri,
}
}
}
- if (!keep_flag)
- timeri->flags &=
- ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
+ timeri->flags &= ~(SNDRV_TIMER_IFLG_RUNNING | SNDRV_TIMER_IFLG_START);
spin_unlock_irqrestore(&timer->lock, flags);
__end:
if (event != SNDRV_TIMER_EVENT_RESOLUTION)
@@ -555,7 +574,7 @@ int snd_timer_stop(struct snd_timer_instance *timeri)
unsigned long flags;
int err;
- err = _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_STOP);
+ err = _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_STOP);
if (err < 0)
return err;
timer = timeri->timer;
@@ -587,10 +606,15 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
if (timer->card && timer->card->shutdown)
return -ENODEV;
spin_lock_irqsave(&timer->lock, flags);
+ if (timeri->flags & SNDRV_TIMER_IFLG_RUNNING) {
+ result = -EBUSY;
+ goto unlock;
+ }
if (!timeri->cticks)
timeri->cticks = 1;
timeri->pticks = 0;
result = snd_timer_start1(timer, timeri, timer->sticks);
+ unlock:
spin_unlock_irqrestore(&timer->lock, flags);
snd_timer_notify1(timeri, SNDRV_TIMER_EVENT_CONTINUE);
return result;
@@ -601,7 +625,7 @@ int snd_timer_continue(struct snd_timer_instance *timeri)
*/
int snd_timer_pause(struct snd_timer_instance * timeri)
{
- return _snd_timer_stop(timeri, 0, SNDRV_TIMER_EVENT_PAUSE);
+ return _snd_timer_stop(timeri, SNDRV_TIMER_EVENT_PAUSE);
}
/*
@@ -724,8 +748,8 @@ void snd_timer_interrupt(struct snd_timer * timer, unsigned long ticks_left)
ti->cticks = ti->ticks;
} else {
ti->flags &= ~SNDRV_TIMER_IFLG_RUNNING;
- if (--timer->running)
- list_del_init(&ti->active_list);
+ --timer->running;
+ list_del_init(&ti->active_list);
}
if ((timer->hw.flags & SNDRV_TIMER_HW_TASKLET) ||
(ti->flags & SNDRV_TIMER_IFLG_FAST))
@@ -1900,6 +1924,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
{
struct snd_timer_user *tu;
long result = 0, unit;
+ int qhead;
int err = 0;
tu = file->private_data;
@@ -1911,7 +1936,7 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
if ((file->f_flags & O_NONBLOCK) != 0 || result > 0) {
err = -EAGAIN;
- break;
+ goto _error;
}
set_current_state(TASK_INTERRUPTIBLE);
@@ -1926,42 +1951,37 @@ static ssize_t snd_timer_user_read(struct file *file, char __user *buffer,
if (tu->disconnected) {
err = -ENODEV;
- break;
+ goto _error;
}
if (signal_pending(current)) {
err = -ERESTARTSYS;
- break;
+ goto _error;
}
}
+ qhead = tu->qhead++;
+ tu->qhead %= tu->queue_size;
spin_unlock_irq(&tu->qlock);
- if (err < 0)
- goto _error;
if (tu->tread) {
- if (copy_to_user(buffer, &tu->tqueue[tu->qhead++],
- sizeof(struct snd_timer_tread))) {
+ if (copy_to_user(buffer, &tu->tqueue[qhead],
+ sizeof(struct snd_timer_tread)))
err = -EFAULT;
- goto _error;
- }
} else {
- if (copy_to_user(buffer, &tu->queue[tu->qhead++],
- sizeof(struct snd_timer_read))) {
+ if (copy_to_user(buffer, &tu->queue[qhead],
+ sizeof(struct snd_timer_read)))
err = -EFAULT;
- goto _error;
- }
}
- tu->qhead %= tu->queue_size;
-
- result += unit;
- buffer += unit;
-
spin_lock_irq(&tu->qlock);
tu->qused--;
+ if (err < 0)
+ goto _error;
+ result += unit;
+ buffer += unit;
}
- spin_unlock_irq(&tu->qlock);
_error:
+ spin_unlock_irq(&tu->qlock);
return result > 0 ? result : err;
}
diff --git a/sound/drivers/dummy.c b/sound/drivers/dummy.c
index 016e451ed..a9f7a7570 100644
--- a/sound/drivers/dummy.c
+++ b/sound/drivers/dummy.c
@@ -109,6 +109,9 @@ struct dummy_timer_ops {
snd_pcm_uframes_t (*pointer)(struct snd_pcm_substream *);
};
+#define get_dummy_ops(substream) \
+ (*(const struct dummy_timer_ops **)(substream)->runtime->private_data)
+
struct dummy_model {
const char *name;
int (*playback_constraints)(struct snd_pcm_runtime *runtime);
@@ -137,7 +140,6 @@ struct snd_dummy {
int iobox;
struct snd_kcontrol *cd_volume_ctl;
struct snd_kcontrol *cd_switch_ctl;
- const struct dummy_timer_ops *timer_ops;
};
/*
@@ -231,6 +233,8 @@ static struct dummy_model *dummy_models[] = {
*/
struct dummy_systimer_pcm {
+ /* ops must be the first item */
+ const struct dummy_timer_ops *timer_ops;
spinlock_t lock;
struct timer_list timer;
unsigned long base_time;
@@ -366,6 +370,8 @@ static struct dummy_timer_ops dummy_systimer_ops = {
*/
struct dummy_hrtimer_pcm {
+ /* ops must be the first item */
+ const struct dummy_timer_ops *timer_ops;
ktime_t base_time;
ktime_t period_time;
atomic_t running;
@@ -492,31 +498,25 @@ static struct dummy_timer_ops dummy_hrtimer_ops = {
static int dummy_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
{
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
switch (cmd) {
case SNDRV_PCM_TRIGGER_START:
case SNDRV_PCM_TRIGGER_RESUME:
- return dummy->timer_ops->start(substream);
+ return get_dummy_ops(substream)->start(substream);
case SNDRV_PCM_TRIGGER_STOP:
case SNDRV_PCM_TRIGGER_SUSPEND:
- return dummy->timer_ops->stop(substream);
+ return get_dummy_ops(substream)->stop(substream);
}
return -EINVAL;
}
static int dummy_pcm_prepare(struct snd_pcm_substream *substream)
{
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
- return dummy->timer_ops->prepare(substream);
+ return get_dummy_ops(substream)->prepare(substream);
}
static snd_pcm_uframes_t dummy_pcm_pointer(struct snd_pcm_substream *substream)
{
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
-
- return dummy->timer_ops->pointer(substream);
+ return get_dummy_ops(substream)->pointer(substream);
}
static struct snd_pcm_hardware dummy_pcm_hardware = {
@@ -562,17 +562,19 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
struct dummy_model *model = dummy->model;
struct snd_pcm_runtime *runtime = substream->runtime;
+ const struct dummy_timer_ops *ops;
int err;
- dummy->timer_ops = &dummy_systimer_ops;
+ ops = &dummy_systimer_ops;
#ifdef CONFIG_HIGH_RES_TIMERS
if (hrtimer)
- dummy->timer_ops = &dummy_hrtimer_ops;
+ ops = &dummy_hrtimer_ops;
#endif
- err = dummy->timer_ops->create(substream);
+ err = ops->create(substream);
if (err < 0)
return err;
+ get_dummy_ops(substream) = ops;
runtime->hw = dummy->pcm_hw;
if (substream->pcm->device & 1) {
@@ -594,7 +596,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
err = model->capture_constraints(substream->runtime);
}
if (err < 0) {
- dummy->timer_ops->free(substream);
+ get_dummy_ops(substream)->free(substream);
return err;
}
return 0;
@@ -602,8 +604,7 @@ static int dummy_pcm_open(struct snd_pcm_substream *substream)
static int dummy_pcm_close(struct snd_pcm_substream *substream)
{
- struct snd_dummy *dummy = snd_pcm_substream_chip(substream);
- dummy->timer_ops->free(substream);
+ get_dummy_ops(substream)->free(substream);
return 0;
}
diff --git a/sound/firewire/bebob/bebob_stream.c b/sound/firewire/bebob/bebob_stream.c
index 926e5dcbb..5022c9b97 100644
--- a/sound/firewire/bebob/bebob_stream.c
+++ b/sound/firewire/bebob/bebob_stream.c
@@ -47,14 +47,16 @@ static const unsigned int bridgeco_freq_table[] = {
[6] = 0x07,
};
-static unsigned int
-get_formation_index(unsigned int rate)
+static int
+get_formation_index(unsigned int rate, unsigned int *index)
{
unsigned int i;
for (i = 0; i < ARRAY_SIZE(snd_bebob_rate_table); i++) {
- if (snd_bebob_rate_table[i] == rate)
- return i;
+ if (snd_bebob_rate_table[i] == rate) {
+ *index = i;
+ return 0;
+ }
}
return -EINVAL;
}
@@ -425,7 +427,9 @@ make_both_connections(struct snd_bebob *bebob, unsigned int rate)
goto end;
/* confirm params for both streams */
- index = get_formation_index(rate);
+ err = get_formation_index(rate, &index);
+ if (err < 0)
+ goto end;
pcm_channels = bebob->tx_stream_formations[index].pcm;
midi_channels = bebob->tx_stream_formations[index].midi;
err = amdtp_am824_set_parameters(&bebob->tx_stream, rate,
diff --git a/sound/isa/Kconfig b/sound/isa/Kconfig
index 403050a1c..b3e1db976 100644
--- a/sound/isa/Kconfig
+++ b/sound/isa/Kconfig
@@ -3,6 +3,7 @@
config SND_WSS_LIB
tristate
select SND_PCM
+ select SND_TIMER
config SND_SB_COMMON
tristate
@@ -42,6 +43,7 @@ config SND_AD1816A
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_TIMER
help
Say Y here to include support for Analog Devices SoundPort
AD1816A or compatible sound chips.
@@ -209,6 +211,7 @@ config SND_GUSCLASSIC
tristate "Gravis UltraSound Classic"
select SND_RAWMIDI
select SND_PCM
+ select SND_TIMER
help
Say Y here to include support for Gravis UltraSound Classic
soundcards.
@@ -221,6 +224,7 @@ config SND_GUSEXTREME
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_PCM
+ select SND_TIMER
help
Say Y here to include support for Gravis UltraSound Extreme
soundcards.
diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig
index 656ce39bd..8f6594a7d 100644
--- a/sound/pci/Kconfig
+++ b/sound/pci/Kconfig
@@ -155,6 +155,7 @@ config SND_AZT3328
select SND_PCM
select SND_RAWMIDI
select SND_AC97_CODEC
+ select SND_TIMER
depends on ZONE_DMA
help
Say Y here to include support for Aztech AZF3328 (PCI168)
@@ -463,6 +464,7 @@ config SND_EMU10K1
select SND_HWDEP
select SND_RAWMIDI
select SND_AC97_CODEC
+ select SND_TIMER
depends on ZONE_DMA
help
Say Y to include support for Sound Blaster PCI 512, Live!,
@@ -889,6 +891,7 @@ config SND_YMFPCI
select SND_OPL3_LIB
select SND_MPU401_UART
select SND_AC97_CODEC
+ select SND_TIMER
help
Say Y here to include support for Yamaha PCI audio chips -
YMF724, YMF724F, YMF740, YMF740C, YMF744, YMF754.
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c
index c6e8a651c..5c4fa8eba 100644
--- a/sound/pci/hda/hda_generic.c
+++ b/sound/pci/hda/hda_generic.c
@@ -771,9 +771,6 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
unsigned int caps;
unsigned int mask, val;
- if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
- return;
-
caps = query_amp_caps(codec, nid, dir);
val = get_amp_val_to_activate(codec, nid, dir, caps, enable);
mask = get_amp_mask_to_modify(codec, nid, dir, idx_to_check, caps);
@@ -784,12 +781,22 @@ static void activate_amp(struct hda_codec *codec, hda_nid_t nid, int dir,
update_amp(codec, nid, dir, idx, mask, val);
}
+static void check_and_activate_amp(struct hda_codec *codec, hda_nid_t nid,
+ int dir, int idx, int idx_to_check,
+ bool enable)
+{
+ /* check whether the given amp is still used by others */
+ if (!enable && is_active_nid(codec, nid, dir, idx_to_check))
+ return;
+ activate_amp(codec, nid, dir, idx, idx_to_check, enable);
+}
+
static void activate_amp_out(struct hda_codec *codec, struct nid_path *path,
int i, bool enable)
{
hda_nid_t nid = path->path[i];
init_amp(codec, nid, HDA_OUTPUT, 0);
- activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
+ check_and_activate_amp(codec, nid, HDA_OUTPUT, 0, 0, enable);
}
static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
@@ -817,9 +824,16 @@ static void activate_amp_in(struct hda_codec *codec, struct nid_path *path,
* when aa-mixer is available, we need to enable the path as well
*/
for (n = 0; n < nums; n++) {
- if (n != idx && (!add_aamix || conn[n] != spec->mixer_merge_nid))
- continue;
- activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
+ if (n != idx) {
+ if (conn[n] != spec->mixer_merge_nid)
+ continue;
+ /* when aamix is disabled, force to off */
+ if (!add_aamix) {
+ activate_amp(codec, nid, HDA_INPUT, n, n, false);
+ continue;
+ }
+ }
+ check_and_activate_amp(codec, nid, HDA_INPUT, n, idx, enable);
}
}
@@ -1580,6 +1594,12 @@ static bool map_singles(struct hda_codec *codec, int outs,
return found;
}
+static inline bool has_aamix_out_paths(struct hda_gen_spec *spec)
+{
+ return spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
+ spec->aamix_out_paths[2];
+}
+
/* create a new path including aamix if available, and return its index */
static int check_aamix_out_path(struct hda_codec *codec, int path_idx)
{
@@ -2422,25 +2442,51 @@ static void update_aamix_paths(struct hda_codec *codec, bool do_mix,
}
}
+/* re-initialize the output paths; only called from loopback_mixing_put() */
+static void update_output_paths(struct hda_codec *codec, int num_outs,
+ const int *paths)
+{
+ struct hda_gen_spec *spec = codec->spec;
+ struct nid_path *path;
+ int i;
+
+ for (i = 0; i < num_outs; i++) {
+ path = snd_hda_get_path_from_idx(codec, paths[i]);
+ if (path)
+ snd_hda_activate_path(codec, path, path->active,
+ spec->aamix_mode);
+ }
+}
+
static int loopback_mixing_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
struct hda_gen_spec *spec = codec->spec;
+ const struct auto_pin_cfg *cfg = &spec->autocfg;
unsigned int val = ucontrol->value.enumerated.item[0];
if (val == spec->aamix_mode)
return 0;
spec->aamix_mode = val;
- update_aamix_paths(codec, val, spec->out_paths[0],
- spec->aamix_out_paths[0],
- spec->autocfg.line_out_type);
- update_aamix_paths(codec, val, spec->hp_paths[0],
- spec->aamix_out_paths[1],
- AUTO_PIN_HP_OUT);
- update_aamix_paths(codec, val, spec->speaker_paths[0],
- spec->aamix_out_paths[2],
- AUTO_PIN_SPEAKER_OUT);
+ if (has_aamix_out_paths(spec)) {
+ update_aamix_paths(codec, val, spec->out_paths[0],
+ spec->aamix_out_paths[0],
+ cfg->line_out_type);
+ update_aamix_paths(codec, val, spec->hp_paths[0],
+ spec->aamix_out_paths[1],
+ AUTO_PIN_HP_OUT);
+ update_aamix_paths(codec, val, spec->speaker_paths[0],
+ spec->aamix_out_paths[2],
+ AUTO_PIN_SPEAKER_OUT);
+ } else {
+ update_output_paths(codec, cfg->line_outs, spec->out_paths);
+ if (cfg->line_out_type != AUTO_PIN_HP_OUT)
+ update_output_paths(codec, cfg->hp_outs, spec->hp_paths);
+ if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT)
+ update_output_paths(codec, cfg->speaker_outs,
+ spec->speaker_paths);
+ }
return 1;
}
@@ -2458,12 +2504,13 @@ static int create_loopback_mixing_ctl(struct hda_codec *codec)
if (!spec->mixer_nid)
return 0;
- if (!(spec->aamix_out_paths[0] || spec->aamix_out_paths[1] ||
- spec->aamix_out_paths[2]))
- return 0;
if (!snd_hda_gen_add_kctl(spec, NULL, &loopback_mixing_enum))
return -ENOMEM;
spec->have_aamix_ctl = 1;
+ /* if no explicit aamix path is present (e.g. for Realtek codecs),
+ * enable aamix as default -- just for compatibility
+ */
+ spec->aamix_mode = !has_aamix_out_paths(spec);
return 0;
}
@@ -3998,9 +4045,9 @@ static void pin_power_callback(struct hda_codec *codec,
struct hda_jack_callback *jack,
bool on)
{
- if (jack && jack->tbl->nid)
+ if (jack && jack->nid)
sync_power_state_change(codec,
- set_pin_power_jack(codec, jack->tbl->nid, on));
+ set_pin_power_jack(codec, jack->nid, on));
}
/* callback only doing power up -- called at first */
@@ -5664,6 +5711,8 @@ static void init_aamix_paths(struct hda_codec *codec)
if (!spec->have_aamix_ctl)
return;
+ if (!has_aamix_out_paths(spec))
+ return;
update_aamix_paths(codec, spec->aamix_mode, spec->out_paths[0],
spec->aamix_out_paths[0],
spec->autocfg.line_out_type);
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c
index 614baff1f..02a86ba5b 100644
--- a/sound/pci/hda/hda_intel.c
+++ b/sound/pci/hda/hda_intel.c
@@ -90,6 +90,8 @@ enum {
#define NVIDIA_HDA_ENABLE_COHBIT 0x01
/* Defines for Intel SCH HDA snoop control */
+#define INTEL_HDA_CGCTL 0x48
+#define INTEL_HDA_CGCTL_MISCBDCGE (0x1 << 6)
#define INTEL_SCH_HDA_DEVC 0x78
#define INTEL_SCH_HDA_DEVC_NOSNOOP (0x1<<11)
@@ -528,10 +530,21 @@ static void hda_intel_init_chip(struct azx *chip, bool full_reset)
{
struct hdac_bus *bus = azx_bus(chip);
struct pci_dev *pci = chip->pci;
+ u32 val;
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_hdac_set_codec_wakeup(bus, true);
+ if (IS_BROXTON(pci)) {
+ pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
+ val = val & ~INTEL_HDA_CGCTL_MISCBDCGE;
+ pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
+ }
azx_init_chip(chip, full_reset);
+ if (IS_BROXTON(pci)) {
+ pci_read_config_dword(pci, INTEL_HDA_CGCTL, &val);
+ val = val | INTEL_HDA_CGCTL_MISCBDCGE;
+ pci_write_config_dword(pci, INTEL_HDA_CGCTL, val);
+ }
if (chip->driver_caps & AZX_DCAPS_I915_POWERWELL)
snd_hdac_set_codec_wakeup(bus, false);
diff --git a/sound/pci/hda/hda_jack.c b/sound/pci/hda/hda_jack.c
index c945e257d..a33234e04 100644
--- a/sound/pci/hda/hda_jack.c
+++ b/sound/pci/hda/hda_jack.c
@@ -259,7 +259,7 @@ snd_hda_jack_detect_enable_callback(struct hda_codec *codec, hda_nid_t nid,
if (!callback)
return ERR_PTR(-ENOMEM);
callback->func = func;
- callback->tbl = jack;
+ callback->nid = jack->nid;
callback->next = jack->callback;
jack->callback = callback;
}
diff --git a/sound/pci/hda/hda_jack.h b/sound/pci/hda/hda_jack.h
index 858708a04..e9814c016 100644
--- a/sound/pci/hda/hda_jack.h
+++ b/sound/pci/hda/hda_jack.h
@@ -21,7 +21,7 @@ struct hda_jack_callback;
typedef void (*hda_jack_callback_fn) (struct hda_codec *, struct hda_jack_callback *);
struct hda_jack_callback {
- struct hda_jack_tbl *tbl;
+ hda_nid_t nid;
hda_jack_callback_fn func;
unsigned int private_data; /* arbitrary data */
struct hda_jack_callback *next;
diff --git a/sound/pci/hda/patch_ca0132.c b/sound/pci/hda/patch_ca0132.c
index 89f48a987..8080bfd82 100644
--- a/sound/pci/hda/patch_ca0132.c
+++ b/sound/pci/hda/patch_ca0132.c
@@ -4427,13 +4427,16 @@ static void ca0132_process_dsp_response(struct hda_codec *codec,
static void hp_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
{
struct ca0132_spec *spec = codec->spec;
+ struct hda_jack_tbl *tbl;
/* Delay enabling the HP amp, to let the mic-detection
* state machine run.
*/
cancel_delayed_work_sync(&spec->unsol_hp_work);
schedule_delayed_work(&spec->unsol_hp_work, msecs_to_jiffies(500));
- cb->tbl->block_report = 1;
+ tbl = snd_hda_jack_tbl_get(codec, cb->nid);
+ if (tbl)
+ tbl->block_report = 1;
}
static void amic_callback(struct hda_codec *codec, struct hda_jack_callback *cb)
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c
index a12ae8ac0..c1c855a6c 100644
--- a/sound/pci/hda/patch_cirrus.c
+++ b/sound/pci/hda/patch_cirrus.c
@@ -614,6 +614,7 @@ enum {
CS4208_MAC_AUTO,
CS4208_MBA6,
CS4208_MBP11,
+ CS4208_MACMINI,
CS4208_GPIO0,
};
@@ -621,6 +622,7 @@ static const struct hda_model_fixup cs4208_models[] = {
{ .id = CS4208_GPIO0, .name = "gpio0" },
{ .id = CS4208_MBA6, .name = "mba6" },
{ .id = CS4208_MBP11, .name = "mbp11" },
+ { .id = CS4208_MACMINI, .name = "macmini" },
{}
};
@@ -632,6 +634,7 @@ static const struct snd_pci_quirk cs4208_fixup_tbl[] = {
/* codec SSID matching */
static const struct snd_pci_quirk cs4208_mac_fixup_tbl[] = {
SND_PCI_QUIRK(0x106b, 0x5e00, "MacBookPro 11,2", CS4208_MBP11),
+ SND_PCI_QUIRK(0x106b, 0x6c00, "MacMini 7,1", CS4208_MACMINI),
SND_PCI_QUIRK(0x106b, 0x7100, "MacBookAir 6,1", CS4208_MBA6),
SND_PCI_QUIRK(0x106b, 0x7200, "MacBookAir 6,2", CS4208_MBA6),
SND_PCI_QUIRK(0x106b, 0x7b00, "MacBookPro 12,1", CS4208_MBP11),
@@ -666,6 +669,24 @@ static void cs4208_fixup_mac(struct hda_codec *codec,
snd_hda_apply_fixup(codec, action);
}
+/* MacMini 7,1 has the inverted jack detection */
+static void cs4208_fixup_macmini(struct hda_codec *codec,
+ const struct hda_fixup *fix, int action)
+{
+ static const struct hda_pintbl pincfgs[] = {
+ { 0x18, 0x00ab9150 }, /* mic (audio-in) jack: disable detect */
+ { 0x21, 0x004be140 }, /* SPDIF: disable detect */
+ { }
+ };
+
+ if (action == HDA_FIXUP_ACT_PRE_PROBE) {
+ /* HP pin (0x10) has an inverted detection */
+ codec->inv_jack_detect = 1;
+ /* disable the bogus Mic and SPDIF jack detections */
+ snd_hda_apply_pincfgs(codec, pincfgs);
+ }
+}
+
static int cs4208_spdif_sw_put(struct snd_kcontrol *kcontrol,
struct snd_ctl_elem_value *ucontrol)
{
@@ -709,6 +730,12 @@ static const struct hda_fixup cs4208_fixups[] = {
.chained = true,
.chain_id = CS4208_GPIO0,
},
+ [CS4208_MACMINI] = {
+ .type = HDA_FIXUP_FUNC,
+ .v.func = cs4208_fixup_macmini,
+ .chained = true,
+ .chain_id = CS4208_GPIO0,
+ },
[CS4208_GPIO0] = {
.type = HDA_FIXUP_FUNC,
.v.func = cs4208_fixup_gpio0,
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c
index 4b6fb668c..70c945603 100644
--- a/sound/pci/hda/patch_hdmi.c
+++ b/sound/pci/hda/patch_hdmi.c
@@ -438,7 +438,8 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol,
eld = &per_pin->sink_eld;
mutex_lock(&per_pin->lock);
- if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data)) {
+ if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) ||
+ eld->eld_size > ELD_MAX_SIZE) {
mutex_unlock(&per_pin->lock);
snd_BUG();
return -EINVAL;
@@ -1183,7 +1184,7 @@ static void check_presence_and_report(struct hda_codec *codec, hda_nid_t nid)
static void jack_callback(struct hda_codec *codec,
struct hda_jack_callback *jack)
{
- check_presence_and_report(codec, jack->tbl->nid);
+ check_presence_and_report(codec, jack->nid);
}
static void hdmi_intrinsic_event(struct hda_codec *codec, unsigned int res)
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index 33753244f..efd4980cf 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -282,7 +282,7 @@ static void alc_update_knob_master(struct hda_codec *codec,
uctl = kzalloc(sizeof(*uctl), GFP_KERNEL);
if (!uctl)
return;
- val = snd_hda_codec_read(codec, jack->tbl->nid, 0,
+ val = snd_hda_codec_read(codec, jack->nid, 0,
AC_VERB_GET_VOLUME_KNOB_CONTROL, 0);
val &= HDA_AMP_VOLMASK;
uctl->value.integer.value[0] = val;
@@ -327,6 +327,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
case 0x10ec0292:
alc_update_coef_idx(codec, 0x4, 1<<15, 0);
break;
+ case 0x10ec0225:
case 0x10ec0233:
case 0x10ec0255:
case 0x10ec0256:
@@ -900,6 +901,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
{ 0x10ec0899, 0x1028, 0, "ALC3861" },
{ 0x10ec0298, 0x1028, 0, "ALC3266" },
{ 0x10ec0256, 0x1028, 0, "ALC3246" },
+ { 0x10ec0225, 0x1028, 0, "ALC3253" },
{ 0x10ec0670, 0x1025, 0, "ALC669X" },
{ 0x10ec0676, 0x1025, 0, "ALC679X" },
{ 0x10ec0282, 0x1043, 0, "ALC3229" },
@@ -1785,7 +1787,6 @@ enum {
ALC882_FIXUP_NO_PRIMARY_HP,
ALC887_FIXUP_ASUS_BASS,
ALC887_FIXUP_BASS_CHMAP,
- ALC882_FIXUP_DISABLE_AAMIX,
};
static void alc889_fixup_coef(struct hda_codec *codec,
@@ -1947,8 +1948,6 @@ static void alc882_fixup_no_primary_hp(struct hda_codec *codec,
static void alc_fixup_bass_chmap(struct hda_codec *codec,
const struct hda_fixup *fix, int action);
-static void alc_fixup_disable_aamix(struct hda_codec *codec,
- const struct hda_fixup *fix, int action);
static const struct hda_fixup alc882_fixups[] = {
[ALC882_FIXUP_ABIT_AW9D_MAX] = {
@@ -2186,10 +2185,6 @@ static const struct hda_fixup alc882_fixups[] = {
.type = HDA_FIXUP_FUNC,
.v.func = alc_fixup_bass_chmap,
},
- [ALC882_FIXUP_DISABLE_AAMIX] = {
- .type = HDA_FIXUP_FUNC,
- .v.func = alc_fixup_disable_aamix,
- },
};
static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2228,6 +2223,7 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x104d, 0x9047, "Sony Vaio TT", ALC889_FIXUP_VAIO_TT),
SND_PCI_QUIRK(0x104d, 0x905a, "Sony Vaio Z", ALC882_FIXUP_NO_PRIMARY_HP),
SND_PCI_QUIRK(0x104d, 0x9043, "Sony Vaio VGC-LN51JGB", ALC882_FIXUP_NO_PRIMARY_HP),
+ SND_PCI_QUIRK(0x104d, 0x9044, "Sony VAIO AiO", ALC882_FIXUP_NO_PRIMARY_HP),
/* All Apple entries are in codec SSIDs */
SND_PCI_QUIRK(0x106b, 0x00a0, "MacBookPro 3,1", ALC889_FIXUP_MBP_VREF),
@@ -2257,7 +2253,6 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
SND_PCI_QUIRK(0x1462, 0x7350, "MSI-7350", ALC889_FIXUP_CD),
SND_PCI_QUIRK_VENDOR(0x1462, "MSI", ALC882_FIXUP_GPIO3),
SND_PCI_QUIRK(0x1458, 0xa002, "Gigabyte EP45-DS3/Z87X-UD3H", ALC889_FIXUP_FRONT_HP_NO_PRESENCE),
- SND_PCI_QUIRK(0x1458, 0xa182, "Gigabyte Z170X-UD3", ALC882_FIXUP_DISABLE_AAMIX),
SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", ALC882_FIXUP_ABIT_AW9D_MAX),
SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
@@ -2651,6 +2646,7 @@ enum {
ALC269_TYPE_ALC298,
ALC269_TYPE_ALC255,
ALC269_TYPE_ALC256,
+ ALC269_TYPE_ALC225,
};
/*
@@ -2680,6 +2676,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec)
case ALC269_TYPE_ALC298:
case ALC269_TYPE_ALC255:
case ALC269_TYPE_ALC256:
+ case ALC269_TYPE_ALC225:
ssids = alc269_ssids;
break;
default:
@@ -3658,6 +3655,16 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
WRITE_COEF(0xb7, 0x802b),
{}
};
+ static struct coef_fw coef0225[] = {
+ UPDATE_COEF(0x4a, 1<<8, 0),
+ UPDATE_COEFEX(0x57, 0x05, 1<<14, 0),
+ UPDATE_COEF(0x63, 3<<14, 3<<14),
+ UPDATE_COEF(0x4a, 3<<4, 2<<4),
+ UPDATE_COEF(0x4a, 3<<10, 3<<10),
+ UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
+ UPDATE_COEF(0x4a, 3<<10, 0),
+ {}
+ };
switch (codec->core.vendor_id) {
case 0x10ec0255:
@@ -3682,6 +3689,9 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
case 0x10ec0668:
alc_process_coef_fw(codec, coef0668);
break;
+ case 0x10ec0225:
+ alc_process_coef_fw(codec, coef0225);
+ break;
}
codec_dbg(codec, "Headset jack set to unplugged mode.\n");
}
@@ -3727,6 +3737,13 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
UPDATE_COEF(0xc3, 0, 1<<12),
{}
};
+ static struct coef_fw coef0225[] = {
+ UPDATE_COEFEX(0x57, 0x05, 1<<14, 1<<14),
+ UPDATE_COEF(0x4a, 3<<4, 2<<4),
+ UPDATE_COEF(0x63, 3<<14, 0),
+ {}
+ };
+
switch (codec->core.vendor_id) {
case 0x10ec0255:
@@ -3772,6 +3789,12 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
alc_process_coef_fw(codec, coef0688);
snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
break;
+ case 0x10ec0225:
+ alc_update_coef_idx(codec, 0x45, 0x3f<<10, 0x31<<10);
+ snd_hda_set_pin_ctl_cache(codec, hp_pin, 0);
+ alc_process_coef_fw(codec, coef0225);
+ snd_hda_set_pin_ctl_cache(codec, mic_pin, PIN_VREF50);
+ break;
}
codec_dbg(codec, "Headset jack set to mic-in mode.\n");
}
@@ -3884,6 +3907,13 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
WRITE_COEF(0xc3, 0x0000),
{}
};
+ static struct coef_fw coef0225[] = {
+ UPDATE_COEF(0x45, 0x3f<<10, 0x35<<10),
+ UPDATE_COEF(0x49, 1<<8, 1<<8),
+ UPDATE_COEF(0x4a, 7<<6, 7<<6),
+ UPDATE_COEF(0x4a, 3<<4, 3<<4),
+ {}
+ };
switch (codec->core.vendor_id) {
case 0x10ec0255:
@@ -3912,6 +3942,9 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
case 0x10ec0668:
alc_process_coef_fw(codec, coef0688);
break;
+ case 0x10ec0225:
+ alc_process_coef_fw(codec, coef0225);
+ break;
}
codec_dbg(codec, "Headset jack set to iPhone-style headset mode.\n");
}
@@ -3955,6 +3988,13 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
WRITE_COEF(0xc3, 0x0000),
{}
};
+ static struct coef_fw coef0225[] = {
+ UPDATE_COEF(0x45, 0x3f<<10, 0x39<<10),
+ UPDATE_COEF(0x49, 1<<8, 1<<8),
+ UPDATE_COEF(0x4a, 7<<6, 7<<6),
+ UPDATE_COEF(0x4a, 3<<4, 3<<4),
+ {}
+ };
switch (codec->core.vendor_id) {
case 0x10ec0255:
@@ -3983,6 +4023,9 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
case 0x10ec0668:
alc_process_coef_fw(codec, coef0688);
break;
+ case 0x10ec0225:
+ alc_process_coef_fw(codec, coef0225);
+ break;
}
codec_dbg(codec, "Headset jack set to Nokia-style headset mode.\n");
}
@@ -4014,6 +4057,11 @@ static void alc_determine_headset_type(struct hda_codec *codec)
WRITE_COEF(0xc3, 0x0c00),
{}
};
+ static struct coef_fw coef0225[] = {
+ UPDATE_COEF(0x45, 0x3f<<10, 0x34<<10),
+ UPDATE_COEF(0x49, 1<<8, 1<<8),
+ {}
+ };
switch (codec->core.vendor_id) {
case 0x10ec0255:
@@ -4058,6 +4106,12 @@ static void alc_determine_headset_type(struct hda_codec *codec)
val = alc_read_coef_idx(codec, 0xbe);
is_ctia = (val & 0x1c02) == 0x1c02;
break;
+ case 0x10ec0225:
+ alc_process_coef_fw(codec, coef0225);
+ msleep(800);
+ val = alc_read_coef_idx(codec, 0x46);
+ is_ctia = (val & 0x00f0) == 0x00f0;
+ break;
}
codec_dbg(codec, "Headset jack detected iPhone-style headset: %s\n",
@@ -5560,6 +5614,9 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{.id = ALC292_FIXUP_TPT440, .name = "tpt440"},
{}
};
+#define ALC225_STANDARD_PINS \
+ {0x12, 0xb7a60130}, \
+ {0x21, 0x04211020}
#define ALC256_STANDARD_PINS \
{0x12, 0x90a60140}, \
@@ -5581,6 +5638,12 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
{0x21, 0x03211020}
static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
+ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC225_STANDARD_PINS,
+ {0x14, 0x901701a0}),
+ SND_HDA_PIN_QUIRK(0x10ec0225, 0x1028, "Dell", ALC269_FIXUP_DELL1_MIC_NO_PRESENCE,
+ ALC225_STANDARD_PINS,
+ {0x14, 0x901701b0}),
SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
{0x14, 0x90170110},
{0x21, 0x02211020}),
@@ -5906,6 +5969,9 @@ static int patch_alc269(struct hda_codec *codec)
spec->gen.mixer_nid = 0; /* ALC256 does not have any loopback mixer path */
alc_update_coef_idx(codec, 0x36, 1 << 13, 1 << 5); /* Switch pcbeep path to Line in path*/
break;
+ case 0x10ec0225:
+ spec->codec_variant = ALC269_TYPE_ALC225;
+ break;
}
if (snd_hda_codec_read(codec, 0x51, 0, AC_VERB_PARAMETERS, 0) == 0x10ec5505) {
@@ -6796,6 +6862,7 @@ static int patch_alc680(struct hda_codec *codec)
*/
static const struct hda_device_id snd_hda_id_realtek[] = {
HDA_CODEC_ENTRY(0x10ec0221, "ALC221", patch_alc269),
+ HDA_CODEC_ENTRY(0x10ec0225, "ALC225", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0231, "ALC231", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 2c7c5eb8b..37b70f8e8 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -493,9 +493,9 @@ static void jack_update_power(struct hda_codec *codec,
if (!spec->num_pwrs)
return;
- if (jack && jack->tbl->nid) {
- stac_toggle_power_map(codec, jack->tbl->nid,
- snd_hda_jack_detect(codec, jack->tbl->nid),
+ if (jack && jack->nid) {
+ stac_toggle_power_map(codec, jack->nid,
+ snd_hda_jack_detect(codec, jack->nid),
true);
return;
}
diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c
index 3e3c7f6be..b74840b5b 100644
--- a/sound/soc/codecs/rt5645.c
+++ b/sound/soc/codecs/rt5645.c
@@ -621,7 +621,7 @@ static const struct snd_kcontrol_new rt5645_snd_controls[] = {
/* IN1/IN2 Control */
SOC_SINGLE_TLV("IN1 Boost", RT5645_IN1_CTRL1,
- RT5645_BST_SFT1, 8, 0, bst_tlv),
+ RT5645_BST_SFT1, 12, 0, bst_tlv),
SOC_SINGLE_TLV("IN2 Boost", RT5645_IN2_CTRL,
RT5645_BST_SFT2, 8, 0, bst_tlv),
diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c
index c86dc96e8..65b936e25 100644
--- a/sound/soc/soc-pcm.c
+++ b/sound/soc/soc-pcm.c
@@ -1743,7 +1743,8 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream)
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PREPARE) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) &&
(be->dpcm[stream].state != SND_SOC_DPCM_STATE_PAUSED) &&
- (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP))
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_STOP) &&
+ (be->dpcm[stream].state != SND_SOC_DPCM_STATE_SUSPEND))
continue;
dev_dbg(be->dev, "ASoC: hw_free BE %s\n",
diff --git a/sound/sparc/Kconfig b/sound/sparc/Kconfig
index d75deba56..dfcd38647 100644
--- a/sound/sparc/Kconfig
+++ b/sound/sparc/Kconfig
@@ -22,6 +22,7 @@ config SND_SUN_AMD7930
config SND_SUN_CS4231
tristate "Sun CS4231"
select SND_PCM
+ select SND_TIMER
help
Say Y here to include support for CS4231 sound device on Sun.
diff --git a/sound/usb/midi.c b/sound/usb/midi.c
index 5b4c58c3e..b21b76690 100644
--- a/sound/usb/midi.c
+++ b/sound/usb/midi.c
@@ -2454,7 +2454,6 @@ int snd_usbmidi_create(struct snd_card *card,
else
err = snd_usbmidi_create_endpoints(umidi, endpoints);
if (err < 0) {
- snd_usbmidi_free(umidi);
return err;
}
diff --git a/sound/usb/quirks.c b/sound/usb/quirks.c
index 23ea6d800..4f6ce1cac 100644
--- a/sound/usb/quirks.c
+++ b/sound/usb/quirks.c
@@ -1121,6 +1121,7 @@ bool snd_usb_get_sample_rate_quirk(struct snd_usb_audio *chip)
switch (chip->usb_id) {
case USB_ID(0x045E, 0x075D): /* MS Lifecam Cinema */
case USB_ID(0x045E, 0x076D): /* MS Lifecam HD-5000 */
+ case USB_ID(0x045E, 0x076F): /* MS Lifecam HD-6000 */
case USB_ID(0x045E, 0x0772): /* MS Lifecam Studio */
case USB_ID(0x045E, 0x0779): /* MS Lifecam HD-3000 */
case USB_ID(0x04D8, 0xFEEA): /* Benchmark DAC1 Pre */
@@ -1205,8 +1206,12 @@ void snd_usb_set_interface_quirk(struct usb_device *dev)
* "Playback Design" products need a 50ms delay after setting the
* USB interface.
*/
- if (le16_to_cpu(dev->descriptor.idVendor) == 0x23ba)
+ switch (le16_to_cpu(dev->descriptor.idVendor)) {
+ case 0x23ba: /* Playback Design */
+ case 0x0644: /* TEAC Corp. */
mdelay(50);
+ break;
+ }
}
void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
@@ -1221,6 +1226,14 @@ void snd_usb_ctl_msg_quirk(struct usb_device *dev, unsigned int pipe,
(requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
mdelay(20);
+ /*
+ * "TEAC Corp." products need a 20ms delay after each
+ * class compliant request
+ */
+ if ((le16_to_cpu(dev->descriptor.idVendor) == 0x0644) &&
+ (requesttype & USB_TYPE_MASK) == USB_TYPE_CLASS)
+ mdelay(20);
+
/* Marantz/Denon devices with USB DAC functionality need a delay
* after each class compliant request
*/
@@ -1269,7 +1282,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case USB_ID(0x20b1, 0x3008): /* iFi Audio micro/nano iDSD */
case USB_ID(0x20b1, 0x2008): /* Matrix Audio X-Sabre */
case USB_ID(0x20b1, 0x300a): /* Matrix Audio Mini-i Pro */
- case USB_ID(0x22d8, 0x0416): /* OPPO HA-1*/
+ case USB_ID(0x22d9, 0x0416): /* OPPO HA-1 */
if (fp->altsetting == 2)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
@@ -1278,6 +1291,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
case USB_ID(0x20b1, 0x2009): /* DIYINHK DSD DXD 384kHz USB to I2S/DSD */
case USB_ID(0x20b1, 0x2023): /* JLsounds I2SoverUSB */
case USB_ID(0x20b1, 0x3023): /* Aune X1S 32BIT/384 DSD DAC */
+ case USB_ID(0x2616, 0x0106): /* PS Audio NuWave DAC */
if (fp->altsetting == 3)
return SNDRV_PCM_FMTBIT_DSD_U32_BE;
break;
diff --git a/tools/testing/selftests/Makefile b/tools/testing/selftests/Makefile
index bf4ece67a..c8edff680 100644
--- a/tools/testing/selftests/Makefile
+++ b/tools/testing/selftests/Makefile
@@ -6,7 +6,6 @@ TARGETS += firmware
TARGETS += ftrace
TARGETS += futex
TARGETS += kcmp
-TARGETS += kdbus
TARGETS += lib
TARGETS += membarrier
TARGETS += memfd
diff --git a/tools/testing/selftests/kdbus/.gitignore b/tools/testing/selftests/kdbus/.gitignore
deleted file mode 100644
index d3ef42f6a..000000000
--- a/tools/testing/selftests/kdbus/.gitignore
+++ /dev/null
@@ -1 +0,0 @@
-kdbus-test
diff --git a/tools/testing/selftests/kdbus/Makefile b/tools/testing/selftests/kdbus/Makefile
deleted file mode 100644
index 8f36cb566..000000000
--- a/tools/testing/selftests/kdbus/Makefile
+++ /dev/null
@@ -1,49 +0,0 @@
-CFLAGS += -I../../../../usr/include/
-CFLAGS += -I../../../../samples/kdbus/
-CFLAGS += -I../../../../include/uapi/
-CFLAGS += -std=gnu99
-CFLAGS += -DKBUILD_MODNAME=\"kdbus\" -D_GNU_SOURCE
-LDLIBS = -pthread -lcap -lm
-
-OBJS= \
- kdbus-enum.o \
- kdbus-util.o \
- kdbus-test.o \
- kdbus-test.o \
- test-activator.o \
- test-benchmark.o \
- test-bus.o \
- test-chat.o \
- test-connection.o \
- test-daemon.o \
- test-endpoint.o \
- test-fd.o \
- test-free.o \
- test-match.o \
- test-message.o \
- test-metadata-ns.o \
- test-monitor.o \
- test-names.o \
- test-policy.o \
- test-policy-ns.o \
- test-policy-priv.o \
- test-sync.o \
- test-timeout.o
-
-all: kdbus-test
-
-include ../lib.mk
-
-%.o: %.c kdbus-enum.h kdbus-test.h kdbus-util.h
- $(CC) $(CFLAGS) -c $< -o $@
-
-kdbus-test: $(OBJS)
- $(CC) $(CFLAGS) $^ $(LDLIBS) -o $@
-
-TEST_PROGS := kdbus-test
-
-run_tests:
- ./kdbus-test --tap
-
-clean:
- rm -f *.o kdbus-test
diff --git a/tools/testing/selftests/kdbus/kdbus-enum.c b/tools/testing/selftests/kdbus/kdbus-enum.c
deleted file mode 100644
index 4f1e57978..000000000
--- a/tools/testing/selftests/kdbus/kdbus-enum.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-struct kdbus_enum_table {
- long long id;
- const char *name;
-};
-
-#define TABLE(what) static struct kdbus_enum_table kdbus_table_##what[]
-#define ENUM(_id) { .id = _id, .name = STRINGIFY(_id) }
-#define LOOKUP(what) \
- const char *enum_##what(long long id) \
- { \
- for (size_t i = 0; i < ELEMENTSOF(kdbus_table_##what); i++) \
- if (id == kdbus_table_##what[i].id) \
- return kdbus_table_##what[i].name; \
- return "UNKNOWN"; \
- }
-
-TABLE(CMD) = {
- ENUM(KDBUS_CMD_BUS_MAKE),
- ENUM(KDBUS_CMD_ENDPOINT_MAKE),
- ENUM(KDBUS_CMD_HELLO),
- ENUM(KDBUS_CMD_SEND),
- ENUM(KDBUS_CMD_RECV),
- ENUM(KDBUS_CMD_LIST),
- ENUM(KDBUS_CMD_NAME_RELEASE),
- ENUM(KDBUS_CMD_CONN_INFO),
- ENUM(KDBUS_CMD_MATCH_ADD),
- ENUM(KDBUS_CMD_MATCH_REMOVE),
-};
-LOOKUP(CMD);
-
-TABLE(MSG) = {
- ENUM(_KDBUS_ITEM_NULL),
- ENUM(KDBUS_ITEM_PAYLOAD_VEC),
- ENUM(KDBUS_ITEM_PAYLOAD_OFF),
- ENUM(KDBUS_ITEM_PAYLOAD_MEMFD),
- ENUM(KDBUS_ITEM_FDS),
- ENUM(KDBUS_ITEM_BLOOM_PARAMETER),
- ENUM(KDBUS_ITEM_BLOOM_FILTER),
- ENUM(KDBUS_ITEM_DST_NAME),
- ENUM(KDBUS_ITEM_MAKE_NAME),
- ENUM(KDBUS_ITEM_ATTACH_FLAGS_SEND),
- ENUM(KDBUS_ITEM_ATTACH_FLAGS_RECV),
- ENUM(KDBUS_ITEM_ID),
- ENUM(KDBUS_ITEM_NAME),
- ENUM(KDBUS_ITEM_TIMESTAMP),
- ENUM(KDBUS_ITEM_CREDS),
- ENUM(KDBUS_ITEM_PIDS),
- ENUM(KDBUS_ITEM_AUXGROUPS),
- ENUM(KDBUS_ITEM_OWNED_NAME),
- ENUM(KDBUS_ITEM_TID_COMM),
- ENUM(KDBUS_ITEM_PID_COMM),
- ENUM(KDBUS_ITEM_EXE),
- ENUM(KDBUS_ITEM_CMDLINE),
- ENUM(KDBUS_ITEM_CGROUP),
- ENUM(KDBUS_ITEM_CAPS),
- ENUM(KDBUS_ITEM_SECLABEL),
- ENUM(KDBUS_ITEM_AUDIT),
- ENUM(KDBUS_ITEM_CONN_DESCRIPTION),
- ENUM(KDBUS_ITEM_NAME_ADD),
- ENUM(KDBUS_ITEM_NAME_REMOVE),
- ENUM(KDBUS_ITEM_NAME_CHANGE),
- ENUM(KDBUS_ITEM_ID_ADD),
- ENUM(KDBUS_ITEM_ID_REMOVE),
- ENUM(KDBUS_ITEM_REPLY_TIMEOUT),
- ENUM(KDBUS_ITEM_REPLY_DEAD),
-};
-LOOKUP(MSG);
-
-TABLE(PAYLOAD) = {
- ENUM(KDBUS_PAYLOAD_KERNEL),
- ENUM(KDBUS_PAYLOAD_DBUS),
-};
-LOOKUP(PAYLOAD);
diff --git a/tools/testing/selftests/kdbus/kdbus-enum.h b/tools/testing/selftests/kdbus/kdbus-enum.h
deleted file mode 100644
index ed28cca26..000000000
--- a/tools/testing/selftests/kdbus/kdbus-enum.h
+++ /dev/null
@@ -1,15 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#pragma once
-
-const char *enum_CMD(long long id);
-const char *enum_MSG(long long id);
-const char *enum_MATCH(long long id);
-const char *enum_PAYLOAD(long long id);
diff --git a/tools/testing/selftests/kdbus/kdbus-test.c b/tools/testing/selftests/kdbus/kdbus-test.c
deleted file mode 100644
index db5738157..000000000
--- a/tools/testing/selftests/kdbus/kdbus-test.c
+++ /dev/null
@@ -1,905 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <time.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <assert.h>
-#include <getopt.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <sys/mount.h>
-#include <sys/prctl.h>
-#include <sys/wait.h>
-#include <sys/syscall.h>
-#include <sys/eventfd.h>
-#include <linux/sched.h>
-
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-enum {
- TEST_CREATE_BUS = 1 << 0,
- TEST_CREATE_CONN = 1 << 1,
-};
-
-struct kdbus_test {
- const char *name;
- const char *desc;
- int (*func)(struct kdbus_test_env *env);
- unsigned int flags;
-};
-
-struct kdbus_test_args {
- bool mntns;
- bool pidns;
- bool userns;
- char *uid_map;
- char *gid_map;
- int loop;
- int wait;
- int fork;
- int tap_output;
- char *module;
- char *root;
- char *test;
- char *busname;
-};
-
-static const struct kdbus_test tests[] = {
- {
- .name = "bus-make",
- .desc = "bus make functions",
- .func = kdbus_test_bus_make,
- .flags = 0,
- },
- {
- .name = "hello",
- .desc = "the HELLO command",
- .func = kdbus_test_hello,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "byebye",
- .desc = "the BYEBYE command",
- .func = kdbus_test_byebye,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "chat",
- .desc = "a chat pattern",
- .func = kdbus_test_chat,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "daemon",
- .desc = "a simple daemon",
- .func = kdbus_test_daemon,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "fd-passing",
- .desc = "file descriptor passing",
- .func = kdbus_test_fd_passing,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "endpoint",
- .desc = "custom endpoint",
- .func = kdbus_test_custom_endpoint,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "monitor",
- .desc = "monitor functionality",
- .func = kdbus_test_monitor,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "name-basics",
- .desc = "basic name registry functions",
- .func = kdbus_test_name_basic,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "name-conflict",
- .desc = "name registry conflict details",
- .func = kdbus_test_name_conflict,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "name-queue",
- .desc = "queuing of names",
- .func = kdbus_test_name_queue,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "name-takeover",
- .desc = "takeover of names",
- .func = kdbus_test_name_takeover,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "message-basic",
- .desc = "basic message handling",
- .func = kdbus_test_message_basic,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "message-prio",
- .desc = "handling of messages with priority",
- .func = kdbus_test_message_prio,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "message-quota",
- .desc = "message quotas are enforced",
- .func = kdbus_test_message_quota,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "memory-access",
- .desc = "memory access",
- .func = kdbus_test_memory_access,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "timeout",
- .desc = "timeout",
- .func = kdbus_test_timeout,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "sync-byebye",
- .desc = "synchronous replies vs. BYEBYE",
- .func = kdbus_test_sync_byebye,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "sync-reply",
- .desc = "synchronous replies",
- .func = kdbus_test_sync_reply,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "message-free",
- .desc = "freeing of memory",
- .func = kdbus_test_free,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "connection-info",
- .desc = "retrieving connection information",
- .func = kdbus_test_conn_info,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "connection-update",
- .desc = "updating connection information",
- .func = kdbus_test_conn_update,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "writable-pool",
- .desc = "verifying pools are never writable",
- .func = kdbus_test_writable_pool,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "policy",
- .desc = "policy",
- .func = kdbus_test_policy,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "policy-priv",
- .desc = "unprivileged bus access",
- .func = kdbus_test_policy_priv,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "policy-ns",
- .desc = "policy in user namespaces",
- .func = kdbus_test_policy_ns,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "metadata-ns",
- .desc = "metadata in different namespaces",
- .func = kdbus_test_metadata_ns,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-id-add",
- .desc = "adding of matches by id",
- .func = kdbus_test_match_id_add,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-id-remove",
- .desc = "removing of matches by id",
- .func = kdbus_test_match_id_remove,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-replace",
- .desc = "replace of matches with the same cookie",
- .func = kdbus_test_match_replace,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-name-add",
- .desc = "adding of matches by name",
- .func = kdbus_test_match_name_add,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-name-remove",
- .desc = "removing of matches by name",
- .func = kdbus_test_match_name_remove,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-name-change",
- .desc = "matching for name changes",
- .func = kdbus_test_match_name_change,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "match-bloom",
- .desc = "matching with bloom filters",
- .func = kdbus_test_match_bloom,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "activator",
- .desc = "activator connections",
- .func = kdbus_test_activator,
- .flags = TEST_CREATE_BUS | TEST_CREATE_CONN,
- },
- {
- .name = "benchmark",
- .desc = "benchmark",
- .func = kdbus_test_benchmark,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "benchmark-nomemfds",
- .desc = "benchmark without using memfds",
- .func = kdbus_test_benchmark_nomemfds,
- .flags = TEST_CREATE_BUS,
- },
- {
- .name = "benchmark-uds",
- .desc = "benchmark comparison to UDS",
- .func = kdbus_test_benchmark_uds,
- .flags = TEST_CREATE_BUS,
- },
-};
-
-#define N_TESTS ((int) (sizeof(tests) / sizeof(tests[0])))
-
-static int test_prepare_env(const struct kdbus_test *t,
- const struct kdbus_test_args *args,
- struct kdbus_test_env *env)
-{
- if (t->flags & TEST_CREATE_BUS) {
- char *s;
- char *n = NULL;
- int ret;
-
- asprintf(&s, "%s/control", args->root);
-
- env->control_fd = open(s, O_RDWR);
- free(s);
- ASSERT_RETURN(env->control_fd >= 0);
-
- if (!args->busname) {
- n = unique_name("test-bus");
- ASSERT_RETURN(n);
- }
-
- ret = kdbus_create_bus(env->control_fd,
- args->busname ?: n,
- _KDBUS_ATTACH_ALL, &s);
- free(n);
- ASSERT_RETURN(ret == 0);
-
- asprintf(&env->buspath, "%s/%s/bus", args->root, s);
- free(s);
- }
-
- if (t->flags & TEST_CREATE_CONN) {
- env->conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(env->conn);
- }
-
- env->root = args->root;
- env->module = args->module;
-
- return 0;
-}
-
-void test_unprepare_env(const struct kdbus_test *t, struct kdbus_test_env *env)
-{
- if (env->conn) {
- kdbus_conn_free(env->conn);
- env->conn = NULL;
- }
-
- if (env->control_fd >= 0) {
- close(env->control_fd);
- env->control_fd = -1;
- }
-
- if (env->buspath) {
- free(env->buspath);
- env->buspath = NULL;
- }
-}
-
-static int test_run(const struct kdbus_test *t,
- const struct kdbus_test_args *kdbus_args,
- int wait)
-{
- int ret;
- struct kdbus_test_env env = {};
-
- ret = test_prepare_env(t, kdbus_args, &env);
- if (ret != TEST_OK)
- return ret;
-
- if (wait > 0) {
- printf("Sleeping %d seconds before running test ...\n", wait);
- sleep(wait);
- }
-
- ret = t->func(&env);
- test_unprepare_env(t, &env);
- return ret;
-}
-
-static int test_run_forked(const struct kdbus_test *t,
- const struct kdbus_test_args *kdbus_args,
- int wait)
-{
- int ret;
- pid_t pid;
-
- pid = fork();
- if (pid < 0) {
- return TEST_ERR;
- } else if (pid == 0) {
- ret = test_run(t, kdbus_args, wait);
- _exit(ret);
- }
-
- pid = waitpid(pid, &ret, 0);
- if (pid <= 0)
- return TEST_ERR;
- else if (!WIFEXITED(ret))
- return TEST_ERR;
- else
- return WEXITSTATUS(ret);
-}
-
-static void print_test_result(int ret)
-{
- switch (ret) {
- case TEST_OK:
- printf("OK");
- break;
- case TEST_SKIP:
- printf("SKIPPED");
- break;
- case TEST_ERR:
- printf("ERROR");
- break;
- }
-}
-
-static int start_all_tests(struct kdbus_test_args *kdbus_args)
-{
- int ret;
- unsigned int fail_cnt = 0;
- unsigned int skip_cnt = 0;
- unsigned int ok_cnt = 0;
- unsigned int i;
-
- if (kdbus_args->tap_output) {
- printf("1..%d\n", N_TESTS);
- fflush(stdout);
- }
-
- kdbus_util_verbose = false;
-
- for (i = 0; i < N_TESTS; i++) {
- const struct kdbus_test *t = tests + i;
-
- if (!kdbus_args->tap_output) {
- unsigned int n;
-
- printf("Testing %s (%s) ", t->desc, t->name);
- for (n = 0; n < 60 - strlen(t->desc) - strlen(t->name); n++)
- printf(".");
- printf(" ");
- }
-
- ret = test_run_forked(t, kdbus_args, 0);
- switch (ret) {
- case TEST_OK:
- ok_cnt++;
- break;
- case TEST_SKIP:
- skip_cnt++;
- break;
- case TEST_ERR:
- fail_cnt++;
- break;
- }
-
- if (kdbus_args->tap_output) {
- printf("%sok %d - %s%s (%s)\n",
- (ret == TEST_ERR) ? "not " : "", i + 1,
- (ret == TEST_SKIP) ? "# SKIP " : "",
- t->desc, t->name);
- fflush(stdout);
- } else {
- print_test_result(ret);
- printf("\n");
- }
- }
-
- if (kdbus_args->tap_output)
- printf("Failed %d/%d tests, %.2f%% okay\n", fail_cnt, N_TESTS,
- 100.0 - (fail_cnt * 100.0) / ((float) N_TESTS));
- else
- printf("\nSUMMARY: %u tests passed, %u skipped, %u failed\n",
- ok_cnt, skip_cnt, fail_cnt);
-
- return fail_cnt > 0 ? TEST_ERR : TEST_OK;
-}
-
-static int start_one_test(struct kdbus_test_args *kdbus_args)
-{
- int i, ret;
- bool test_found = false;
-
- for (i = 0; i < N_TESTS; i++) {
- const struct kdbus_test *t = tests + i;
-
- if (strcmp(t->name, kdbus_args->test))
- continue;
-
- do {
- test_found = true;
- if (kdbus_args->fork)
- ret = test_run_forked(t, kdbus_args,
- kdbus_args->wait);
- else
- ret = test_run(t, kdbus_args,
- kdbus_args->wait);
-
- printf("Testing %s: ", t->desc);
- print_test_result(ret);
- printf("\n");
-
- if (ret != TEST_OK)
- break;
- } while (kdbus_args->loop);
-
- return ret;
- }
-
- if (!test_found) {
- printf("Unknown test-id '%s'\n", kdbus_args->test);
- return TEST_ERR;
- }
-
- return TEST_OK;
-}
-
-static void usage(const char *argv0)
-{
- unsigned int i, j;
-
- printf("Usage: %s [options]\n"
- "Options:\n"
- "\t-a, --tap Output test results in TAP format\n"
- "\t-m, --module <module> Kdbus module name\n"
- "\t-x, --loop Run in a loop\n"
- "\t-f, --fork Fork before running a test\n"
- "\t-h, --help Print this help\n"
- "\t-r, --root <root> Toplevel of the kdbus hierarchy\n"
- "\t-t, --test <test-id> Run one specific test only, in verbose mode\n"
- "\t-b, --bus <busname> Instead of generating a random bus name, take <busname>.\n"
- "\t-w, --wait <secs> Wait <secs> before actually starting test\n"
- "\t --mntns New mount namespace\n"
- "\t --pidns New PID namespace\n"
- "\t --userns New user namespace\n"
- "\t --uidmap uid_map UID map for user namespace\n"
- "\t --gidmap gid_map GID map for user namespace\n"
- "\n", argv0);
-
- printf("By default, all test are run once, and a summary is printed.\n"
- "Available tests for --test:\n\n");
-
- for (i = 0; i < N_TESTS; i++) {
- const struct kdbus_test *t = tests + i;
-
- printf("\t%s", t->name);
-
- for (j = 0; j < 24 - strlen(t->name); j++)
- printf(" ");
-
- printf("Test %s\n", t->desc);
- }
-
- printf("\n");
- printf("Note that some tests may, if run specifically by --test, "
- "behave differently, and not terminate by themselves.\n");
-
- exit(EXIT_FAILURE);
-}
-
-void print_kdbus_test_args(struct kdbus_test_args *args)
-{
- if (args->userns || args->pidns || args->mntns)
- printf("# Starting tests in new %s%s%s namespaces%s\n",
- args->mntns ? "MOUNT " : "",
- args->pidns ? "PID " : "",
- args->userns ? "USER " : "",
- args->mntns ? ", kdbusfs will be remounted" : "");
- else
- printf("# Starting tests in the same namespaces\n");
-}
-
-void print_metadata_support(void)
-{
- bool no_meta_audit, no_meta_cgroups, no_meta_seclabel;
-
- /*
- * KDBUS_ATTACH_CGROUP, KDBUS_ATTACH_AUDIT and
- * KDBUS_ATTACH_SECLABEL
- */
- no_meta_audit = !config_auditsyscall_is_enabled();
- no_meta_cgroups = !config_cgroups_is_enabled();
- no_meta_seclabel = !config_security_is_enabled();
-
- if (no_meta_audit | no_meta_cgroups | no_meta_seclabel)
- printf("# Starting tests without %s%s%s metadata support\n",
- no_meta_audit ? "AUDIT " : "",
- no_meta_cgroups ? "CGROUP " : "",
- no_meta_seclabel ? "SECLABEL " : "");
- else
- printf("# Starting tests with full metadata support\n");
-}
-
-int run_tests(struct kdbus_test_args *kdbus_args)
-{
- int ret;
- static char control[4096];
-
- snprintf(control, sizeof(control), "%s/control", kdbus_args->root);
-
- if (access(control, W_OK) < 0) {
- printf("Unable to locate control node at '%s'.\n",
- control);
- return TEST_ERR;
- }
-
- if (kdbus_args->test) {
- ret = start_one_test(kdbus_args);
- } else {
- do {
- ret = start_all_tests(kdbus_args);
- if (ret != TEST_OK)
- break;
- } while (kdbus_args->loop);
- }
-
- return ret;
-}
-
-static void nop_handler(int sig) {}
-
-static int test_prepare_mounts(struct kdbus_test_args *kdbus_args)
-{
- int ret;
- char kdbusfs[64] = {'\0'};
-
- snprintf(kdbusfs, sizeof(kdbusfs), "%sfs", kdbus_args->module);
-
- /* make current mount slave */
- ret = mount(NULL, "/", NULL, MS_SLAVE|MS_REC, NULL);
- if (ret < 0) {
- ret = -errno;
- printf("error mount() root: %d (%m)\n", ret);
- return ret;
- }
-
- /* Remount procfs since we need it in our tests */
- if (kdbus_args->pidns) {
- ret = mount("proc", "/proc", "proc",
- MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
- if (ret < 0) {
- ret = -errno;
- printf("error mount() /proc : %d (%m)\n", ret);
- return ret;
- }
- }
-
- /* Remount kdbusfs */
- ret = mount(kdbusfs, kdbus_args->root, kdbusfs,
- MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
- if (ret < 0) {
- ret = -errno;
- printf("error mount() %s :%d (%m)\n", kdbusfs, ret);
- return ret;
- }
-
- return 0;
-}
-
-int run_tests_in_namespaces(struct kdbus_test_args *kdbus_args)
-{
- int ret;
- int efd = -1;
- int status;
- pid_t pid, rpid;
- struct sigaction oldsa;
- struct sigaction sa = {
- .sa_handler = nop_handler,
- .sa_flags = SA_NOCLDSTOP,
- };
-
- efd = eventfd(0, EFD_CLOEXEC);
- if (efd < 0) {
- ret = -errno;
- printf("eventfd() failed: %d (%m)\n", ret);
- return TEST_ERR;
- }
-
- ret = sigaction(SIGCHLD, &sa, &oldsa);
- if (ret < 0) {
- ret = -errno;
- printf("sigaction() failed: %d (%m)\n", ret);
- return TEST_ERR;
- }
-
- /* setup namespaces */
- pid = syscall(__NR_clone, SIGCHLD|
- (kdbus_args->userns ? CLONE_NEWUSER : 0) |
- (kdbus_args->mntns ? CLONE_NEWNS : 0) |
- (kdbus_args->pidns ? CLONE_NEWPID : 0), NULL);
- if (pid < 0) {
- printf("clone() failed: %d (%m)\n", -errno);
- return TEST_ERR;
- }
-
- if (pid == 0) {
- eventfd_t event_status = 0;
-
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- if (ret < 0) {
- ret = -errno;
- printf("error prctl(): %d (%m)\n", ret);
- _exit(TEST_ERR);
- }
-
- /* reset sighandlers of childs */
- ret = sigaction(SIGCHLD, &oldsa, NULL);
- if (ret < 0) {
- ret = -errno;
- printf("sigaction() failed: %d (%m)\n", ret);
- _exit(TEST_ERR);
- }
-
- ret = eventfd_read(efd, &event_status);
- if (ret < 0 || event_status != 1) {
- printf("error eventfd_read()\n");
- _exit(TEST_ERR);
- }
-
- if (kdbus_args->mntns) {
- ret = test_prepare_mounts(kdbus_args);
- if (ret < 0) {
- printf("error preparing mounts\n");
- _exit(TEST_ERR);
- }
- }
-
- ret = run_tests(kdbus_args);
- _exit(ret);
- }
-
- /* Setup userns mapping */
- if (kdbus_args->userns) {
- ret = userns_map_uid_gid(pid, kdbus_args->uid_map,
- kdbus_args->gid_map);
- if (ret < 0) {
- printf("error mapping uid and gid in userns\n");
- eventfd_write(efd, 2);
- return TEST_ERR;
- }
- }
-
- ret = eventfd_write(efd, 1);
- if (ret < 0) {
- ret = -errno;
- printf("error eventfd_write(): %d (%m)\n", ret);
- return TEST_ERR;
- }
-
- rpid = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(rpid == pid, TEST_ERR);
-
- close(efd);
-
- if (!WIFEXITED(status) || WEXITSTATUS(status) != 0)
- return TEST_ERR;
-
- return TEST_OK;
-}
-
-int start_tests(struct kdbus_test_args *kdbus_args)
-{
- int ret;
- bool namespaces;
- static char fspath[4096];
-
- namespaces = (kdbus_args->mntns || kdbus_args->pidns ||
- kdbus_args->userns);
-
- /* for pidns we need mntns set */
- if (kdbus_args->pidns && !kdbus_args->mntns) {
- printf("Failed: please set both pid and mnt namesapces\n");
- return TEST_ERR;
- }
-
- if (kdbus_args->userns) {
- if (!config_user_ns_is_enabled()) {
- printf("User namespace not supported\n");
- return TEST_ERR;
- }
-
- if (!kdbus_args->uid_map || !kdbus_args->gid_map) {
- printf("Failed: please specify uid or gid mapping\n");
- return TEST_ERR;
- }
- }
-
- print_kdbus_test_args(kdbus_args);
- print_metadata_support();
-
- /* setup kdbus paths */
- if (!kdbus_args->module)
- kdbus_args->module = "kdbus";
-
- if (!kdbus_args->root) {
- snprintf(fspath, sizeof(fspath), "/sys/fs/%s",
- kdbus_args->module);
- kdbus_args->root = fspath;
- }
-
- /* Start tests */
- if (namespaces)
- ret = run_tests_in_namespaces(kdbus_args);
- else
- ret = run_tests(kdbus_args);
-
- return ret;
-}
-
-int main(int argc, char *argv[])
-{
- int t, ret = 0;
- struct kdbus_test_args *kdbus_args;
- enum {
- ARG_MNTNS = 0x100,
- ARG_PIDNS,
- ARG_USERNS,
- ARG_UIDMAP,
- ARG_GIDMAP,
- };
-
- kdbus_args = malloc(sizeof(*kdbus_args));
- if (!kdbus_args) {
- printf("unable to malloc() kdbus_args\n");
- return EXIT_FAILURE;
- }
-
- memset(kdbus_args, 0, sizeof(*kdbus_args));
-
- static const struct option options[] = {
- { "loop", no_argument, NULL, 'x' },
- { "help", no_argument, NULL, 'h' },
- { "root", required_argument, NULL, 'r' },
- { "test", required_argument, NULL, 't' },
- { "bus", required_argument, NULL, 'b' },
- { "wait", required_argument, NULL, 'w' },
- { "fork", no_argument, NULL, 'f' },
- { "module", required_argument, NULL, 'm' },
- { "tap", no_argument, NULL, 'a' },
- { "mntns", no_argument, NULL, ARG_MNTNS },
- { "pidns", no_argument, NULL, ARG_PIDNS },
- { "userns", no_argument, NULL, ARG_USERNS },
- { "uidmap", required_argument, NULL, ARG_UIDMAP },
- { "gidmap", required_argument, NULL, ARG_GIDMAP },
- {}
- };
-
- srand(time(NULL));
-
- while ((t = getopt_long(argc, argv, "hxfm:r:t:b:w:a", options, NULL)) >= 0) {
- switch (t) {
- case 'x':
- kdbus_args->loop = 1;
- break;
-
- case 'm':
- kdbus_args->module = optarg;
- break;
-
- case 'r':
- kdbus_args->root = optarg;
- break;
-
- case 't':
- kdbus_args->test = optarg;
- break;
-
- case 'b':
- kdbus_args->busname = optarg;
- break;
-
- case 'w':
- kdbus_args->wait = strtol(optarg, NULL, 10);
- break;
-
- case 'f':
- kdbus_args->fork = 1;
- break;
-
- case 'a':
- kdbus_args->tap_output = 1;
- break;
-
- case ARG_MNTNS:
- kdbus_args->mntns = true;
- break;
-
- case ARG_PIDNS:
- kdbus_args->pidns = true;
- break;
-
- case ARG_USERNS:
- kdbus_args->userns = true;
- break;
-
- case ARG_UIDMAP:
- kdbus_args->uid_map = optarg;
- break;
-
- case ARG_GIDMAP:
- kdbus_args->gid_map = optarg;
- break;
-
- default:
- case 'h':
- usage(argv[0]);
- }
- }
-
- ret = start_tests(kdbus_args);
- if (ret == TEST_ERR)
- return EXIT_FAILURE;
-
- free(kdbus_args);
-
- return 0;
-}
diff --git a/tools/testing/selftests/kdbus/kdbus-test.h b/tools/testing/selftests/kdbus/kdbus-test.h
deleted file mode 100644
index ee937f9a8..000000000
--- a/tools/testing/selftests/kdbus/kdbus-test.h
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef _TEST_KDBUS_H_
-#define _TEST_KDBUS_H_
-
-struct kdbus_test_env {
- char *buspath;
- const char *root;
- const char *module;
- int control_fd;
- struct kdbus_conn *conn;
-};
-
-enum {
- TEST_OK,
- TEST_SKIP,
- TEST_ERR,
-};
-
-#define ASSERT_RETURN_VAL(cond, val) \
- if (!(cond)) { \
- fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \
- #cond, __func__, __FILE__, __LINE__); \
- return val; \
- }
-
-#define ASSERT_EXIT_VAL(cond, val) \
- if (!(cond)) { \
- fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \
- #cond, __func__, __FILE__, __LINE__); \
- _exit(val); \
- }
-
-#define ASSERT_BREAK(cond) \
- if (!(cond)) { \
- fprintf(stderr, "Assertion '%s' failed in %s(), %s:%d\n", \
- #cond, __func__, __FILE__, __LINE__); \
- break; \
- }
-
-#define ASSERT_RETURN(cond) \
- ASSERT_RETURN_VAL(cond, TEST_ERR)
-
-#define ASSERT_EXIT(cond) \
- ASSERT_EXIT_VAL(cond, EXIT_FAILURE)
-
-int kdbus_test_activator(struct kdbus_test_env *env);
-int kdbus_test_benchmark(struct kdbus_test_env *env);
-int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env);
-int kdbus_test_benchmark_uds(struct kdbus_test_env *env);
-int kdbus_test_bus_make(struct kdbus_test_env *env);
-int kdbus_test_byebye(struct kdbus_test_env *env);
-int kdbus_test_chat(struct kdbus_test_env *env);
-int kdbus_test_conn_info(struct kdbus_test_env *env);
-int kdbus_test_conn_update(struct kdbus_test_env *env);
-int kdbus_test_daemon(struct kdbus_test_env *env);
-int kdbus_test_custom_endpoint(struct kdbus_test_env *env);
-int kdbus_test_fd_passing(struct kdbus_test_env *env);
-int kdbus_test_free(struct kdbus_test_env *env);
-int kdbus_test_hello(struct kdbus_test_env *env);
-int kdbus_test_match_bloom(struct kdbus_test_env *env);
-int kdbus_test_match_id_add(struct kdbus_test_env *env);
-int kdbus_test_match_id_remove(struct kdbus_test_env *env);
-int kdbus_test_match_replace(struct kdbus_test_env *env);
-int kdbus_test_match_name_add(struct kdbus_test_env *env);
-int kdbus_test_match_name_change(struct kdbus_test_env *env);
-int kdbus_test_match_name_remove(struct kdbus_test_env *env);
-int kdbus_test_message_basic(struct kdbus_test_env *env);
-int kdbus_test_message_prio(struct kdbus_test_env *env);
-int kdbus_test_message_quota(struct kdbus_test_env *env);
-int kdbus_test_memory_access(struct kdbus_test_env *env);
-int kdbus_test_metadata_ns(struct kdbus_test_env *env);
-int kdbus_test_monitor(struct kdbus_test_env *env);
-int kdbus_test_name_basic(struct kdbus_test_env *env);
-int kdbus_test_name_conflict(struct kdbus_test_env *env);
-int kdbus_test_name_queue(struct kdbus_test_env *env);
-int kdbus_test_name_takeover(struct kdbus_test_env *env);
-int kdbus_test_policy(struct kdbus_test_env *env);
-int kdbus_test_policy_ns(struct kdbus_test_env *env);
-int kdbus_test_policy_priv(struct kdbus_test_env *env);
-int kdbus_test_sync_byebye(struct kdbus_test_env *env);
-int kdbus_test_sync_reply(struct kdbus_test_env *env);
-int kdbus_test_timeout(struct kdbus_test_env *env);
-int kdbus_test_writable_pool(struct kdbus_test_env *env);
-
-#endif /* _TEST_KDBUS_H_ */
diff --git a/tools/testing/selftests/kdbus/kdbus-util.c b/tools/testing/selftests/kdbus/kdbus-util.c
deleted file mode 100644
index 82fa89b1a..000000000
--- a/tools/testing/selftests/kdbus/kdbus-util.c
+++ /dev/null
@@ -1,1612 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Daniel Mack
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <stdio.h>
-#include <stdarg.h>
-#include <string.h>
-#include <time.h>
-#include <inttypes.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <grp.h>
-#include <sys/capability.h>
-#include <sys/mman.h>
-#include <sys/stat.h>
-#include <sys/time.h>
-#include <linux/unistd.h>
-#include <linux/memfd.h>
-
-#ifndef __NR_memfd_create
- #ifdef __x86_64__
- #define __NR_memfd_create 319
- #elif defined __arm__
- #define __NR_memfd_create 385
- #else
- #define __NR_memfd_create 356
- #endif
-#endif
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-#ifndef F_ADD_SEALS
-#define F_LINUX_SPECIFIC_BASE 1024
-#define F_ADD_SEALS (F_LINUX_SPECIFIC_BASE + 9)
-#define F_GET_SEALS (F_LINUX_SPECIFIC_BASE + 10)
-
-#define F_SEAL_SEAL 0x0001 /* prevent further seals from being set */
-#define F_SEAL_SHRINK 0x0002 /* prevent file from shrinking */
-#define F_SEAL_GROW 0x0004 /* prevent file from growing */
-#define F_SEAL_WRITE 0x0008 /* prevent writes */
-#endif
-
-int kdbus_util_verbose = true;
-
-int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask)
-{
- int ret;
- FILE *file;
- unsigned long long value;
-
- file = fopen(path, "r");
- if (!file) {
- ret = -errno;
- kdbus_printf("--- error fopen(): %d (%m)\n", ret);
- return ret;
- }
-
- ret = fscanf(file, "%llu", &value);
- if (ret != 1) {
- if (ferror(file))
- ret = -errno;
- else
- ret = -EIO;
-
- kdbus_printf("--- error fscanf(): %d\n", ret);
- fclose(file);
- return ret;
- }
-
- *mask = (uint64_t)value;
-
- fclose(file);
-
- return 0;
-}
-
-int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask)
-{
- int ret;
- FILE *file;
-
- file = fopen(path, "w");
- if (!file) {
- ret = -errno;
- kdbus_printf("--- error open(): %d (%m)\n", ret);
- return ret;
- }
-
- ret = fprintf(file, "%llu", (unsigned long long)mask);
- if (ret <= 0) {
- ret = -EIO;
- kdbus_printf("--- error fprintf(): %d\n", ret);
- }
-
- fclose(file);
-
- return ret > 0 ? 0 : ret;
-}
-
-int kdbus_create_bus(int control_fd, const char *name,
- uint64_t owner_meta, char **path)
-{
- struct {
- struct kdbus_cmd cmd;
-
- /* bloom size item */
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_bloom_parameter bloom;
- } bp;
-
- /* owner metadata items */
- struct {
- uint64_t size;
- uint64_t type;
- uint64_t flags;
- } attach;
-
- /* name item */
- struct {
- uint64_t size;
- uint64_t type;
- char str[64];
- } name;
- } bus_make;
- int ret;
-
- memset(&bus_make, 0, sizeof(bus_make));
- bus_make.bp.size = sizeof(bus_make.bp);
- bus_make.bp.type = KDBUS_ITEM_BLOOM_PARAMETER;
- bus_make.bp.bloom.size = 64;
- bus_make.bp.bloom.n_hash = 1;
-
- snprintf(bus_make.name.str, sizeof(bus_make.name.str),
- "%u-%s", getuid(), name);
-
- bus_make.attach.type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
- bus_make.attach.size = sizeof(bus_make.attach);
- bus_make.attach.flags = owner_meta;
-
- bus_make.name.type = KDBUS_ITEM_MAKE_NAME;
- bus_make.name.size = KDBUS_ITEM_HEADER_SIZE +
- strlen(bus_make.name.str) + 1;
-
- bus_make.cmd.flags = KDBUS_MAKE_ACCESS_WORLD;
- bus_make.cmd.size = sizeof(bus_make.cmd) +
- bus_make.bp.size +
- bus_make.attach.size +
- bus_make.name.size;
-
- kdbus_printf("Creating bus with name >%s< on control fd %d ...\n",
- name, control_fd);
-
- ret = kdbus_cmd_bus_make(control_fd, &bus_make.cmd);
- if (ret < 0) {
- kdbus_printf("--- error when making bus: %d (%m)\n", ret);
- return ret;
- }
-
- if (ret == 0 && path)
- *path = strdup(bus_make.name.str);
-
- return ret;
-}
-
-struct kdbus_conn *
-kdbus_hello(const char *path, uint64_t flags,
- const struct kdbus_item *item, size_t item_size)
-{
- struct kdbus_cmd_free cmd_free = {};
- int fd, ret;
- struct {
- struct kdbus_cmd_hello hello;
-
- struct {
- uint64_t size;
- uint64_t type;
- char str[16];
- } conn_name;
-
- uint8_t extra_items[item_size];
- } h;
- struct kdbus_conn *conn;
-
- memset(&h, 0, sizeof(h));
-
- if (item_size > 0)
- memcpy(h.extra_items, item, item_size);
-
- kdbus_printf("-- opening bus connection %s\n", path);
- fd = open(path, O_RDWR|O_CLOEXEC);
- if (fd < 0) {
- kdbus_printf("--- error %d (%m)\n", fd);
- return NULL;
- }
-
- h.hello.flags = flags | KDBUS_HELLO_ACCEPT_FD;
- h.hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- h.hello.attach_flags_recv = _KDBUS_ATTACH_ALL;
- h.conn_name.type = KDBUS_ITEM_CONN_DESCRIPTION;
- strcpy(h.conn_name.str, "this-is-my-name");
- h.conn_name.size = KDBUS_ITEM_HEADER_SIZE + strlen(h.conn_name.str) + 1;
-
- h.hello.size = sizeof(h);
- h.hello.pool_size = POOL_SIZE;
-
- ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) &h.hello);
- if (ret < 0) {
- kdbus_printf("--- error when saying hello: %d (%m)\n", ret);
- return NULL;
- }
- kdbus_printf("-- Our peer ID for %s: %llu -- bus uuid: '%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x'\n",
- path, (unsigned long long)h.hello.id,
- h.hello.id128[0], h.hello.id128[1], h.hello.id128[2],
- h.hello.id128[3], h.hello.id128[4], h.hello.id128[5],
- h.hello.id128[6], h.hello.id128[7], h.hello.id128[8],
- h.hello.id128[9], h.hello.id128[10], h.hello.id128[11],
- h.hello.id128[12], h.hello.id128[13], h.hello.id128[14],
- h.hello.id128[15]);
-
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = h.hello.offset;
- kdbus_cmd_free(fd, &cmd_free);
-
- conn = malloc(sizeof(*conn));
- if (!conn) {
- kdbus_printf("unable to malloc()!?\n");
- return NULL;
- }
-
- conn->buf = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
- if (conn->buf == MAP_FAILED) {
- free(conn);
- close(fd);
- kdbus_printf("--- error mmap (%m)\n");
- return NULL;
- }
-
- conn->fd = fd;
- conn->id = h.hello.id;
- return conn;
-}
-
-struct kdbus_conn *
-kdbus_hello_registrar(const char *path, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access, uint64_t flags)
-{
- struct kdbus_item *item, *items;
- size_t i, size;
-
- size = KDBUS_ITEM_SIZE(strlen(name) + 1) +
- num_access * KDBUS_ITEM_SIZE(sizeof(*access));
-
- items = alloca(size);
-
- item = items;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- item->type = KDBUS_ITEM_NAME;
- strcpy(item->str, name);
- item = KDBUS_ITEM_NEXT(item);
-
- for (i = 0; i < num_access; i++) {
- item->size = KDBUS_ITEM_HEADER_SIZE +
- sizeof(struct kdbus_policy_access);
- item->type = KDBUS_ITEM_POLICY_ACCESS;
-
- item->policy_access.type = access[i].type;
- item->policy_access.access = access[i].access;
- item->policy_access.id = access[i].id;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- return kdbus_hello(path, flags, items, size);
-}
-
-struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access)
-{
- return kdbus_hello_registrar(path, name, access, num_access,
- KDBUS_HELLO_ACTIVATOR);
-}
-
-bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type)
-{
- const struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, msg, items)
- if (item->type == type)
- return true;
-
- return false;
-}
-
-int kdbus_bus_creator_info(struct kdbus_conn *conn,
- uint64_t flags,
- uint64_t *offset)
-{
- struct kdbus_cmd_info *cmd;
- size_t size = sizeof(*cmd);
- int ret;
-
- cmd = alloca(size);
- memset(cmd, 0, size);
- cmd->size = size;
- cmd->attach_flags = flags;
-
- ret = kdbus_cmd_bus_creator_info(conn->fd, cmd);
- if (ret < 0) {
- kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
- return ret;
- }
-
- if (offset)
- *offset = cmd->offset;
- else
- kdbus_free(conn, cmd->offset);
-
- return 0;
-}
-
-int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
- const char *name, uint64_t flags,
- uint64_t *offset)
-{
- struct kdbus_cmd_info *cmd;
- size_t size = sizeof(*cmd);
- struct kdbus_info *info;
- int ret;
-
- if (name)
- size += KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
-
- cmd = alloca(size);
- memset(cmd, 0, size);
- cmd->size = size;
- cmd->attach_flags = flags;
-
- if (name) {
- cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- cmd->items[0].type = KDBUS_ITEM_NAME;
- strcpy(cmd->items[0].str, name);
- } else {
- cmd->id = id;
- }
-
- ret = kdbus_cmd_conn_info(conn->fd, cmd);
- if (ret < 0) {
- kdbus_printf("--- error when requesting info: %d (%m)\n", ret);
- return ret;
- }
-
- info = (struct kdbus_info *) (conn->buf + cmd->offset);
- if (info->size != cmd->info_size) {
- kdbus_printf("%s(): size mismatch: %d != %d\n", __func__,
- (int) info->size, (int) cmd->info_size);
- return -EIO;
- }
-
- if (offset)
- *offset = cmd->offset;
- else
- kdbus_free(conn, cmd->offset);
-
- return 0;
-}
-
-void kdbus_conn_free(struct kdbus_conn *conn)
-{
- if (!conn)
- return;
-
- if (conn->buf)
- munmap(conn->buf, POOL_SIZE);
-
- if (conn->fd >= 0)
- close(conn->fd);
-
- free(conn);
-}
-
-int sys_memfd_create(const char *name, __u64 size)
-{
- int ret, fd;
-
- fd = syscall(__NR_memfd_create, name, MFD_ALLOW_SEALING);
- if (fd < 0)
- return fd;
-
- ret = ftruncate(fd, size);
- if (ret < 0) {
- close(fd);
- return ret;
- }
-
- return fd;
-}
-
-int sys_memfd_seal_set(int fd)
-{
- return fcntl(fd, F_ADD_SEALS, F_SEAL_SHRINK |
- F_SEAL_GROW | F_SEAL_WRITE | F_SEAL_SEAL);
-}
-
-off_t sys_memfd_get_size(int fd, off_t *size)
-{
- struct stat stat;
- int ret;
-
- ret = fstat(fd, &stat);
- if (ret < 0) {
- kdbus_printf("stat() failed: %m\n");
- return ret;
- }
-
- *size = stat.st_size;
- return 0;
-}
-
-static int __kdbus_msg_send(const struct kdbus_conn *conn,
- const char *name,
- uint64_t cookie,
- uint64_t flags,
- uint64_t timeout,
- int64_t priority,
- uint64_t dst_id,
- uint64_t cmd_flags,
- int cancel_fd)
-{
- struct kdbus_cmd_send *cmd = NULL;
- struct kdbus_msg *msg = NULL;
- const char ref1[1024 * 128 + 3] = "0123456789_0";
- const char ref2[] = "0123456789_1";
- struct kdbus_item *item;
- struct timespec now;
- uint64_t size;
- int memfd = -1;
- int ret;
-
- size = sizeof(*msg) + 3 * KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- if (dst_id == KDBUS_DST_ID_BROADCAST)
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
- else {
- memfd = sys_memfd_create("my-name-is-nice", 1024 * 1024);
- if (memfd < 0) {
- kdbus_printf("failed to create memfd: %m\n");
- return memfd;
- }
-
- if (write(memfd, "kdbus memfd 1234567", 19) != 19) {
- ret = -errno;
- kdbus_printf("writing to memfd failed: %m\n");
- goto out;
- }
-
- ret = sys_memfd_seal_set(memfd);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("memfd sealing failed: %m\n");
- goto out;
- }
-
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
- }
-
- if (name)
- size += KDBUS_ITEM_SIZE(strlen(name) + 1);
-
- msg = malloc(size);
- if (!msg) {
- ret = -errno;
- kdbus_printf("unable to malloc()!?\n");
- goto out;
- }
-
- if (dst_id == KDBUS_DST_ID_BROADCAST)
- flags |= KDBUS_MSG_SIGNAL;
-
- memset(msg, 0, size);
- msg->flags = flags;
- msg->priority = priority;
- msg->size = size;
- msg->src_id = conn->id;
- msg->dst_id = name ? 0 : dst_id;
- msg->cookie = cookie;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- if (timeout) {
- ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
- if (ret < 0)
- goto out;
-
- msg->timeout_ns = now.tv_sec * 1000000000ULL +
- now.tv_nsec + timeout;
- }
-
- item = msg->items;
-
- if (name) {
- item->type = KDBUS_ITEM_DST_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- strcpy(item->str, name);
- item = KDBUS_ITEM_NEXT(item);
- }
-
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)&ref1;
- item->vec.size = sizeof(ref1);
- item = KDBUS_ITEM_NEXT(item);
-
- /* data padding for ref1 */
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)NULL;
- item->vec.size = KDBUS_ALIGN8(sizeof(ref1)) - sizeof(ref1);
- item = KDBUS_ITEM_NEXT(item);
-
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)&ref2;
- item->vec.size = sizeof(ref2);
- item = KDBUS_ITEM_NEXT(item);
-
- if (dst_id == KDBUS_DST_ID_BROADCAST) {
- item->type = KDBUS_ITEM_BLOOM_FILTER;
- item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
- item->bloom_filter.generation = 0;
- } else {
- item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd);
- item->memfd.size = 16;
- item->memfd.fd = memfd;
- }
- item = KDBUS_ITEM_NEXT(item);
-
- size = sizeof(*cmd);
- if (cancel_fd != -1)
- size += KDBUS_ITEM_SIZE(sizeof(cancel_fd));
-
- cmd = malloc(size);
- if (!cmd) {
- ret = -errno;
- kdbus_printf("unable to malloc()!?\n");
- goto out;
- }
-
- cmd->size = size;
- cmd->flags = cmd_flags;
- cmd->msg_address = (uintptr_t)msg;
-
- item = cmd->items;
-
- if (cancel_fd != -1) {
- item->type = KDBUS_ITEM_CANCEL_FD;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(cancel_fd);
- item->fds[0] = cancel_fd;
- item = KDBUS_ITEM_NEXT(item);
- }
-
- ret = kdbus_cmd_send(conn->fd, cmd);
- if (ret < 0) {
- kdbus_printf("error sending message: %d (%m)\n", ret);
- goto out;
- }
-
- if (cmd_flags & KDBUS_SEND_SYNC_REPLY) {
- struct kdbus_msg *reply;
-
- kdbus_printf("SYNC REPLY @offset %llu:\n", cmd->reply.offset);
- reply = (struct kdbus_msg *)(conn->buf + cmd->reply.offset);
- kdbus_msg_dump(conn, reply);
-
- kdbus_msg_free(reply);
-
- ret = kdbus_free(conn, cmd->reply.offset);
- if (ret < 0)
- goto out;
- }
-
-out:
- free(msg);
- free(cmd);
-
- if (memfd >= 0)
- close(memfd);
-
- return ret < 0 ? ret : 0;
-}
-
-int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
- uint64_t cookie, uint64_t flags, uint64_t timeout,
- int64_t priority, uint64_t dst_id)
-{
- return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
- dst_id, 0, -1);
-}
-
-int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name,
- uint64_t cookie, uint64_t flags, uint64_t timeout,
- int64_t priority, uint64_t dst_id, int cancel_fd)
-{
- return __kdbus_msg_send(conn, name, cookie, flags, timeout, priority,
- dst_id, KDBUS_SEND_SYNC_REPLY, cancel_fd);
-}
-
-int kdbus_msg_send_reply(const struct kdbus_conn *conn,
- uint64_t reply_cookie,
- uint64_t dst_id)
-{
- struct kdbus_cmd_send cmd = {};
- struct kdbus_msg *msg;
- const char ref1[1024 * 128 + 3] = "0123456789_0";
- struct kdbus_item *item;
- uint64_t size;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- msg = malloc(size);
- if (!msg) {
- kdbus_printf("unable to malloc()!?\n");
- return -ENOMEM;
- }
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = conn->id;
- msg->dst_id = dst_id;
- msg->cookie_reply = reply_cookie;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- item = msg->items;
-
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)&ref1;
- item->vec.size = sizeof(ref1);
- item = KDBUS_ITEM_NEXT(item);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- if (ret < 0)
- kdbus_printf("error sending message: %d (%m)\n", ret);
-
- free(msg);
-
- return ret;
-}
-
-static char *msg_id(uint64_t id, char *buf)
-{
- if (id == 0)
- return "KERNEL";
- if (id == ~0ULL)
- return "BROADCAST";
- sprintf(buf, "%llu", (unsigned long long)id);
- return buf;
-}
-
-int kdbus_msg_dump(const struct kdbus_conn *conn, const struct kdbus_msg *msg)
-{
- const struct kdbus_item *item = msg->items;
- char buf_src[32];
- char buf_dst[32];
- uint64_t timeout = 0;
- uint64_t cookie_reply = 0;
- int ret = 0;
-
- if (msg->flags & KDBUS_MSG_EXPECT_REPLY)
- timeout = msg->timeout_ns;
- else
- cookie_reply = msg->cookie_reply;
-
- kdbus_printf("MESSAGE: %s (%llu bytes) flags=0x%08llx, %s → %s, "
- "cookie=%llu, timeout=%llu cookie_reply=%llu priority=%lli\n",
- enum_PAYLOAD(msg->payload_type), (unsigned long long)msg->size,
- (unsigned long long)msg->flags,
- msg_id(msg->src_id, buf_src), msg_id(msg->dst_id, buf_dst),
- (unsigned long long)msg->cookie, (unsigned long long)timeout,
- (unsigned long long)cookie_reply, (long long)msg->priority);
-
- KDBUS_ITEM_FOREACH(item, msg, items) {
- if (item->size < KDBUS_ITEM_HEADER_SIZE) {
- kdbus_printf(" +%s (%llu bytes) invalid data record\n",
- enum_MSG(item->type), item->size);
- ret = -EINVAL;
- break;
- }
-
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_OFF: {
- char *s;
-
- if (item->vec.offset == ~0ULL)
- s = "[\\0-bytes]";
- else
- s = (char *)msg + item->vec.offset;
-
- kdbus_printf(" +%s (%llu bytes) off=%llu size=%llu '%s'\n",
- enum_MSG(item->type), item->size,
- (unsigned long long)item->vec.offset,
- (unsigned long long)item->vec.size, s);
- break;
- }
-
- case KDBUS_ITEM_FDS: {
- int i, n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
- sizeof(int);
-
- kdbus_printf(" +%s (%llu bytes, %d fds)\n",
- enum_MSG(item->type), item->size, n);
-
- for (i = 0; i < n; i++)
- kdbus_printf(" fd[%d] = %d\n",
- i, item->fds[i]);
-
- break;
- }
-
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- char *buf;
- off_t size;
-
- buf = mmap(NULL, item->memfd.size, PROT_READ,
- MAP_PRIVATE, item->memfd.fd, 0);
- if (buf == MAP_FAILED) {
- kdbus_printf("mmap() fd=%i size=%llu failed: %m\n",
- item->memfd.fd, item->memfd.size);
- break;
- }
-
- if (sys_memfd_get_size(item->memfd.fd, &size) < 0) {
- kdbus_printf("KDBUS_CMD_MEMFD_SIZE_GET failed: %m\n");
- break;
- }
-
- kdbus_printf(" +%s (%llu bytes) fd=%i size=%llu filesize=%llu '%s'\n",
- enum_MSG(item->type), item->size, item->memfd.fd,
- (unsigned long long)item->memfd.size,
- (unsigned long long)size, buf);
- munmap(buf, item->memfd.size);
- break;
- }
-
- case KDBUS_ITEM_CREDS:
- kdbus_printf(" +%s (%llu bytes) uid=%lld, euid=%lld, suid=%lld, fsuid=%lld, "
- "gid=%lld, egid=%lld, sgid=%lld, fsgid=%lld\n",
- enum_MSG(item->type), item->size,
- item->creds.uid, item->creds.euid,
- item->creds.suid, item->creds.fsuid,
- item->creds.gid, item->creds.egid,
- item->creds.sgid, item->creds.fsgid);
- break;
-
- case KDBUS_ITEM_PIDS:
- kdbus_printf(" +%s (%llu bytes) pid=%lld, tid=%lld, ppid=%lld\n",
- enum_MSG(item->type), item->size,
- item->pids.pid, item->pids.tid,
- item->pids.ppid);
- break;
-
- case KDBUS_ITEM_AUXGROUPS: {
- int i, n;
-
- kdbus_printf(" +%s (%llu bytes)\n",
- enum_MSG(item->type), item->size);
- n = (item->size - KDBUS_ITEM_HEADER_SIZE) /
- sizeof(uint64_t);
-
- for (i = 0; i < n; i++)
- kdbus_printf(" gid[%d] = %lld\n",
- i, item->data64[i]);
- break;
- }
-
- case KDBUS_ITEM_NAME:
- case KDBUS_ITEM_PID_COMM:
- case KDBUS_ITEM_TID_COMM:
- case KDBUS_ITEM_EXE:
- case KDBUS_ITEM_CGROUP:
- case KDBUS_ITEM_SECLABEL:
- case KDBUS_ITEM_DST_NAME:
- case KDBUS_ITEM_CONN_DESCRIPTION:
- kdbus_printf(" +%s (%llu bytes) '%s' (%zu)\n",
- enum_MSG(item->type), item->size,
- item->str, strlen(item->str));
- break;
-
- case KDBUS_ITEM_OWNED_NAME: {
- kdbus_printf(" +%s (%llu bytes) '%s' (%zu) flags=0x%08llx\n",
- enum_MSG(item->type), item->size,
- item->name.name, strlen(item->name.name),
- item->name.flags);
- break;
- }
-
- case KDBUS_ITEM_CMDLINE: {
- size_t size = item->size - KDBUS_ITEM_HEADER_SIZE;
- const char *str = item->str;
- int count = 0;
-
- kdbus_printf(" +%s (%llu bytes) ",
- enum_MSG(item->type), item->size);
- while (size) {
- kdbus_printf("'%s' ", str);
- size -= strlen(str) + 1;
- str += strlen(str) + 1;
- count++;
- }
-
- kdbus_printf("(%d string%s)\n",
- count, (count == 1) ? "" : "s");
- break;
- }
-
- case KDBUS_ITEM_AUDIT:
- kdbus_printf(" +%s (%llu bytes) loginuid=%u sessionid=%u\n",
- enum_MSG(item->type), item->size,
- item->audit.loginuid, item->audit.sessionid);
- break;
-
- case KDBUS_ITEM_CAPS: {
- const uint32_t *cap;
- int n, i;
-
- kdbus_printf(" +%s (%llu bytes) len=%llu bytes, last_cap %d\n",
- enum_MSG(item->type), item->size,
- (unsigned long long)item->size -
- KDBUS_ITEM_HEADER_SIZE,
- (int) item->caps.last_cap);
-
- cap = item->caps.caps;
- n = (item->size - offsetof(struct kdbus_item, caps.caps))
- / 4 / sizeof(uint32_t);
-
- kdbus_printf(" CapInh=");
- for (i = 0; i < n; i++)
- kdbus_printf("%08x", cap[(0 * n) + (n - i - 1)]);
-
- kdbus_printf(" CapPrm=");
- for (i = 0; i < n; i++)
- kdbus_printf("%08x", cap[(1 * n) + (n - i - 1)]);
-
- kdbus_printf(" CapEff=");
- for (i = 0; i < n; i++)
- kdbus_printf("%08x", cap[(2 * n) + (n - i - 1)]);
-
- kdbus_printf(" CapBnd=");
- for (i = 0; i < n; i++)
- kdbus_printf("%08x", cap[(3 * n) + (n - i - 1)]);
- kdbus_printf("\n");
- break;
- }
-
- case KDBUS_ITEM_TIMESTAMP:
- kdbus_printf(" +%s (%llu bytes) seq=%llu realtime=%lluns monotonic=%lluns\n",
- enum_MSG(item->type), item->size,
- (unsigned long long)item->timestamp.seqnum,
- (unsigned long long)item->timestamp.realtime_ns,
- (unsigned long long)item->timestamp.monotonic_ns);
- break;
-
- case KDBUS_ITEM_REPLY_TIMEOUT:
- kdbus_printf(" +%s (%llu bytes) cookie=%llu\n",
- enum_MSG(item->type), item->size,
- msg->cookie_reply);
- break;
-
- case KDBUS_ITEM_NAME_ADD:
- case KDBUS_ITEM_NAME_REMOVE:
- case KDBUS_ITEM_NAME_CHANGE:
- kdbus_printf(" +%s (%llu bytes) '%s', old id=%lld, now id=%lld, old_flags=0x%llx new_flags=0x%llx\n",
- enum_MSG(item->type),
- (unsigned long long) item->size,
- item->name_change.name,
- item->name_change.old_id.id,
- item->name_change.new_id.id,
- item->name_change.old_id.flags,
- item->name_change.new_id.flags);
- break;
-
- case KDBUS_ITEM_ID_ADD:
- case KDBUS_ITEM_ID_REMOVE:
- kdbus_printf(" +%s (%llu bytes) id=%llu flags=%llu\n",
- enum_MSG(item->type),
- (unsigned long long) item->size,
- (unsigned long long) item->id_change.id,
- (unsigned long long) item->id_change.flags);
- break;
-
- default:
- kdbus_printf(" +%s (%llu bytes)\n",
- enum_MSG(item->type), item->size);
- break;
- }
- }
-
- if ((char *)item - ((char *)msg + msg->size) >= 8) {
- kdbus_printf("invalid padding at end of message\n");
- ret = -EINVAL;
- }
-
- kdbus_printf("\n");
-
- return ret;
-}
-
-void kdbus_msg_free(struct kdbus_msg *msg)
-{
- const struct kdbus_item *item;
- int nfds, i;
-
- if (!msg)
- return;
-
- KDBUS_ITEM_FOREACH(item, msg, items) {
- switch (item->type) {
- /* close all memfds */
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- close(item->memfd.fd);
- break;
- case KDBUS_ITEM_FDS:
- nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
- sizeof(int);
-
- for (i = 0; i < nfds; i++)
- close(item->fds[i]);
-
- break;
- }
- }
-}
-
-int kdbus_msg_recv(struct kdbus_conn *conn,
- struct kdbus_msg **msg_out,
- uint64_t *offset)
-{
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_msg *msg;
- int ret;
-
- ret = kdbus_cmd_recv(conn->fd, &recv);
- if (ret < 0)
- return ret;
-
- msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
- ret = kdbus_msg_dump(conn, msg);
- if (ret < 0) {
- kdbus_msg_free(msg);
- return ret;
- }
-
- if (msg_out) {
- *msg_out = msg;
-
- if (offset)
- *offset = recv.msg.offset;
- } else {
- kdbus_msg_free(msg);
-
- ret = kdbus_free(conn, recv.msg.offset);
- if (ret < 0)
- return ret;
- }
-
- return 0;
-}
-
-/*
- * Returns: 0 on success, negative errno on failure.
- *
- * We must return -ETIMEDOUT, -ECONNREST, -EAGAIN and other errors.
- * We must return the result of kdbus_msg_recv()
- */
-int kdbus_msg_recv_poll(struct kdbus_conn *conn,
- int timeout_ms,
- struct kdbus_msg **msg_out,
- uint64_t *offset)
-{
- int ret;
-
- do {
- struct timeval before, after, diff;
- struct pollfd fd;
-
- fd.fd = conn->fd;
- fd.events = POLLIN | POLLPRI | POLLHUP;
- fd.revents = 0;
-
- gettimeofday(&before, NULL);
- ret = poll(&fd, 1, timeout_ms);
- gettimeofday(&after, NULL);
-
- if (ret == 0) {
- ret = -ETIMEDOUT;
- break;
- }
-
- if (ret > 0) {
- if (fd.revents & POLLIN)
- ret = kdbus_msg_recv(conn, msg_out, offset);
-
- if (fd.revents & (POLLHUP | POLLERR))
- ret = -ECONNRESET;
- }
-
- if (ret == 0 || ret != -EAGAIN)
- break;
-
- timersub(&after, &before, &diff);
- timeout_ms -= diff.tv_sec * 1000UL +
- diff.tv_usec / 1000UL;
- } while (timeout_ms > 0);
-
- return ret;
-}
-
-int kdbus_free(const struct kdbus_conn *conn, uint64_t offset)
-{
- struct kdbus_cmd_free cmd_free = {};
- int ret;
-
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = offset;
- cmd_free.flags = 0;
-
- ret = kdbus_cmd_free(conn->fd, &cmd_free);
- if (ret < 0) {
- kdbus_printf("KDBUS_CMD_FREE failed: %d (%m)\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-int kdbus_name_acquire(struct kdbus_conn *conn,
- const char *name, uint64_t *flags)
-{
- struct kdbus_cmd *cmd_name;
- size_t name_len = strlen(name) + 1;
- uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len);
- struct kdbus_item *item;
- int ret;
-
- cmd_name = alloca(size);
-
- memset(cmd_name, 0, size);
-
- item = cmd_name->items;
- item->size = KDBUS_ITEM_HEADER_SIZE + name_len;
- item->type = KDBUS_ITEM_NAME;
- strcpy(item->str, name);
-
- cmd_name->size = size;
- if (flags)
- cmd_name->flags = *flags;
-
- ret = kdbus_cmd_name_acquire(conn->fd, cmd_name);
- if (ret < 0) {
- kdbus_printf("error aquiring name: %s\n", strerror(-ret));
- return ret;
- }
-
- kdbus_printf("%s(): flags after call: 0x%llx\n", __func__,
- cmd_name->return_flags);
-
- if (flags)
- *flags = cmd_name->return_flags;
-
- return 0;
-}
-
-int kdbus_name_release(struct kdbus_conn *conn, const char *name)
-{
- struct kdbus_cmd *cmd_name;
- size_t name_len = strlen(name) + 1;
- uint64_t size = sizeof(*cmd_name) + KDBUS_ITEM_SIZE(name_len);
- struct kdbus_item *item;
- int ret;
-
- cmd_name = alloca(size);
-
- memset(cmd_name, 0, size);
-
- item = cmd_name->items;
- item->size = KDBUS_ITEM_HEADER_SIZE + name_len;
- item->type = KDBUS_ITEM_NAME;
- strcpy(item->str, name);
-
- cmd_name->size = size;
-
- kdbus_printf("conn %lld giving up name '%s'\n",
- (unsigned long long) conn->id, name);
-
- ret = kdbus_cmd_name_release(conn->fd, cmd_name);
- if (ret < 0) {
- kdbus_printf("error releasing name: %s\n", strerror(-ret));
- return ret;
- }
-
- return 0;
-}
-
-int kdbus_list(struct kdbus_conn *conn, uint64_t flags)
-{
- struct kdbus_cmd_list cmd_list = {};
- struct kdbus_info *list, *name;
- int ret;
-
- cmd_list.size = sizeof(cmd_list);
- cmd_list.flags = flags;
-
- ret = kdbus_cmd_list(conn->fd, &cmd_list);
- if (ret < 0) {
- kdbus_printf("error listing names: %d (%m)\n", ret);
- return ret;
- }
-
- kdbus_printf("REGISTRY:\n");
- list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
-
- KDBUS_FOREACH(name, list, cmd_list.list_size) {
- uint64_t flags = 0;
- struct kdbus_item *item;
- const char *n = "MISSING-NAME";
-
- if (name->size == sizeof(struct kdbus_cmd))
- continue;
-
- KDBUS_ITEM_FOREACH(item, name, items)
- if (item->type == KDBUS_ITEM_OWNED_NAME) {
- n = item->name.name;
- flags = item->name.flags;
-
- kdbus_printf("%8llu flags=0x%08llx conn=0x%08llx '%s'\n",
- name->id,
- (unsigned long long) flags,
- name->flags, n);
- }
- }
- kdbus_printf("\n");
-
- ret = kdbus_free(conn, cmd_list.offset);
-
- return ret;
-}
-
-int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
- uint64_t attach_flags_send,
- uint64_t attach_flags_recv)
-{
- int ret;
- size_t size;
- struct kdbus_cmd *update;
- struct kdbus_item *item;
-
- size = sizeof(struct kdbus_cmd);
- size += KDBUS_ITEM_SIZE(sizeof(uint64_t)) * 2;
-
- update = malloc(size);
- if (!update) {
- kdbus_printf("error malloc: %m\n");
- return -ENOMEM;
- }
-
- memset(update, 0, size);
- update->size = size;
-
- item = update->items;
-
- item->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
- item->data64[0] = attach_flags_send;
- item = KDBUS_ITEM_NEXT(item);
-
- item->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(uint64_t);
- item->data64[0] = attach_flags_recv;
- item = KDBUS_ITEM_NEXT(item);
-
- ret = kdbus_cmd_update(conn->fd, update);
- if (ret < 0)
- kdbus_printf("error conn update: %d (%m)\n", ret);
-
- free(update);
-
- return ret;
-}
-
-int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access)
-{
- struct kdbus_cmd *update;
- struct kdbus_item *item;
- size_t i, size;
- int ret;
-
- size = sizeof(struct kdbus_cmd);
- size += KDBUS_ITEM_SIZE(strlen(name) + 1);
- size += num_access * KDBUS_ITEM_SIZE(sizeof(struct kdbus_policy_access));
-
- update = malloc(size);
- if (!update) {
- kdbus_printf("error malloc: %m\n");
- return -ENOMEM;
- }
-
- memset(update, 0, size);
- update->size = size;
-
- item = update->items;
-
- item->type = KDBUS_ITEM_NAME;
- item->size = KDBUS_ITEM_HEADER_SIZE + strlen(name) + 1;
- strcpy(item->str, name);
- item = KDBUS_ITEM_NEXT(item);
-
- for (i = 0; i < num_access; i++) {
- item->size = KDBUS_ITEM_HEADER_SIZE +
- sizeof(struct kdbus_policy_access);
- item->type = KDBUS_ITEM_POLICY_ACCESS;
-
- item->policy_access.type = access[i].type;
- item->policy_access.access = access[i].access;
- item->policy_access.id = access[i].id;
-
- item = KDBUS_ITEM_NEXT(item);
- }
-
- ret = kdbus_cmd_update(conn->fd, update);
- if (ret < 0)
- kdbus_printf("error conn update: %d (%m)\n", ret);
-
- free(update);
-
- return ret;
-}
-
-int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
- uint64_t type, uint64_t id)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_id_change chg;
- } item;
- } buf;
- int ret;
-
- memset(&buf, 0, sizeof(buf));
-
- buf.cmd.size = sizeof(buf);
- buf.cmd.cookie = cookie;
- buf.item.size = sizeof(buf.item);
- buf.item.type = type;
- buf.item.chg.id = id;
-
- ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
- if (ret < 0)
- kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
-
- return ret;
-}
-
-int kdbus_add_match_empty(struct kdbus_conn *conn)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct kdbus_item item;
- } buf;
- int ret;
-
- memset(&buf, 0, sizeof(buf));
-
- buf.item.size = sizeof(uint64_t) * 3;
- buf.item.type = KDBUS_ITEM_ID;
- buf.item.id = KDBUS_MATCH_ID_ANY;
-
- buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
-
- ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
- if (ret < 0)
- kdbus_printf("--- error adding conn match: %d (%m)\n", ret);
-
- return ret;
-}
-
-static int all_ids_are_mapped(const char *path)
-{
- int ret;
- FILE *file;
- uint32_t inside_id, length;
-
- file = fopen(path, "r");
- if (!file) {
- ret = -errno;
- kdbus_printf("error fopen() %s: %d (%m)\n",
- path, ret);
- return ret;
- }
-
- ret = fscanf(file, "%u\t%*u\t%u", &inside_id, &length);
- if (ret != 2) {
- if (ferror(file))
- ret = -errno;
- else
- ret = -EIO;
-
- kdbus_printf("--- error fscanf(): %d\n", ret);
- fclose(file);
- return ret;
- }
-
- fclose(file);
-
- /*
- * If length is 4294967295 which means the invalid uid
- * (uid_t) -1 then we are able to map all uid/gids
- */
- if (inside_id == 0 && length == (uid_t) -1)
- return 1;
-
- return 0;
-}
-
-int all_uids_gids_are_mapped(void)
-{
- int ret;
-
- ret = all_ids_are_mapped("/proc/self/uid_map");
- if (ret <= 0) {
- kdbus_printf("--- error not all uids are mapped\n");
- return 0;
- }
-
- ret = all_ids_are_mapped("/proc/self/gid_map");
- if (ret <= 0) {
- kdbus_printf("--- error not all gids are mapped\n");
- return 0;
- }
-
- return 1;
-}
-
-int drop_privileges(uid_t uid, gid_t gid)
-{
- int ret;
-
- ret = setgroups(0, NULL);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error setgroups: %d (%m)\n", ret);
- return ret;
- }
-
- ret = setresgid(gid, gid, gid);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error setresgid: %d (%m)\n", ret);
- return ret;
- }
-
- ret = setresuid(uid, uid, uid);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error setresuid: %d (%m)\n", ret);
- return ret;
- }
-
- return ret;
-}
-
-uint64_t now(clockid_t clock)
-{
- struct timespec spec;
-
- clock_gettime(clock, &spec);
- return spec.tv_sec * 1000ULL * 1000ULL * 1000ULL + spec.tv_nsec;
-}
-
-char *unique_name(const char *prefix)
-{
- unsigned int i;
- uint64_t u_now;
- char n[17];
- char *str;
- int r;
-
- /*
- * This returns a random string which is guaranteed to be
- * globally unique across all calls to unique_name(). We
- * compose the string as:
- * <prefix>-<random>-<time>
- * With:
- * <prefix>: string provided by the caller
- * <random>: a random alpha string of 16 characters
- * <time>: the current time in micro-seconds since last boot
- *
- * The <random> part makes the string always look vastly different,
- * the <time> part makes sure no two calls return the same string.
- */
-
- u_now = now(CLOCK_MONOTONIC);
-
- for (i = 0; i < sizeof(n) - 1; ++i)
- n[i] = 'a' + (rand() % ('z' - 'a'));
- n[sizeof(n) - 1] = 0;
-
- r = asprintf(&str, "%s-%s-%" PRIu64, prefix, n, u_now);
- if (r < 0)
- return NULL;
-
- return str;
-}
-
-static int do_userns_map_id(pid_t pid,
- const char *map_file,
- const char *map_id)
-{
- int ret;
- int fd;
- char *map;
- unsigned int i;
-
- map = strndupa(map_id, strlen(map_id));
- if (!map) {
- ret = -errno;
- kdbus_printf("error strndupa %s: %d (%m)\n",
- map_file, ret);
- return ret;
- }
-
- for (i = 0; i < strlen(map); i++)
- if (map[i] == ',')
- map[i] = '\n';
-
- fd = open(map_file, O_RDWR);
- if (fd < 0) {
- ret = -errno;
- kdbus_printf("error open %s: %d (%m)\n",
- map_file, ret);
- return ret;
- }
-
- ret = write(fd, map, strlen(map));
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error write to %s: %d (%m)\n",
- map_file, ret);
- goto out;
- }
-
- ret = 0;
-
-out:
- close(fd);
- return ret;
-}
-
-int userns_map_uid_gid(pid_t pid,
- const char *map_uid,
- const char *map_gid)
-{
- int fd, ret;
- char file_id[128] = {'\0'};
-
- snprintf(file_id, sizeof(file_id), "/proc/%ld/uid_map",
- (long) pid);
-
- ret = do_userns_map_id(pid, file_id, map_uid);
- if (ret < 0)
- return ret;
-
- snprintf(file_id, sizeof(file_id), "/proc/%ld/setgroups",
- (long) pid);
-
- fd = open(file_id, O_WRONLY);
- if (fd >= 0) {
- write(fd, "deny\n", 5);
- close(fd);
- }
-
- snprintf(file_id, sizeof(file_id), "/proc/%ld/gid_map",
- (long) pid);
-
- return do_userns_map_id(pid, file_id, map_gid);
-}
-
-static int do_cap_get_flag(cap_t caps, cap_value_t cap)
-{
- int ret;
- cap_flag_value_t flag_set;
-
- ret = cap_get_flag(caps, cap, CAP_EFFECTIVE, &flag_set);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error cap_get_flag(): %d (%m)\n", ret);
- return ret;
- }
-
- return (flag_set == CAP_SET);
-}
-
-/*
- * Returns:
- * 1 in case all the requested effective capabilities are set.
- * 0 in case we do not have the requested capabilities. This value
- * will be used to abort tests with TEST_SKIP
- * Negative errno on failure.
- *
- * Terminate args with a negative value.
- */
-int test_is_capable(int cap, ...)
-{
- int ret;
- va_list ap;
- cap_t caps;
-
- caps = cap_get_proc();
- if (!caps) {
- ret = -errno;
- kdbus_printf("error cap_get_proc(): %d (%m)\n", ret);
- return ret;
- }
-
- ret = do_cap_get_flag(caps, (cap_value_t)cap);
- if (ret <= 0)
- goto out;
-
- va_start(ap, cap);
- while ((cap = va_arg(ap, int)) > 0) {
- ret = do_cap_get_flag(caps, (cap_value_t)cap);
- if (ret <= 0)
- break;
- }
- va_end(ap);
-
-out:
- cap_free(caps);
- return ret;
-}
-
-int config_user_ns_is_enabled(void)
-{
- return (access("/proc/self/uid_map", F_OK) == 0);
-}
-
-int config_auditsyscall_is_enabled(void)
-{
- return (access("/proc/self/loginuid", F_OK) == 0);
-}
-
-int config_cgroups_is_enabled(void)
-{
- return (access("/proc/self/cgroup", F_OK) == 0);
-}
-
-int config_security_is_enabled(void)
-{
- int fd;
- int ret;
- char buf[128];
-
- /* CONFIG_SECURITY is disabled */
- if (access("/proc/self/attr/current", F_OK) != 0)
- return 0;
-
- /*
- * Now only if read() fails with -EINVAL then we assume
- * that SECLABEL and LSM are disabled
- */
- fd = open("/proc/self/attr/current", O_RDONLY|O_CLOEXEC);
- if (fd < 0)
- return 1;
-
- ret = read(fd, buf, sizeof(buf));
- if (ret == -1 && errno == EINVAL)
- ret = 0;
- else
- ret = 1;
-
- close(fd);
-
- return ret;
-}
diff --git a/tools/testing/selftests/kdbus/kdbus-util.h b/tools/testing/selftests/kdbus/kdbus-util.h
deleted file mode 100644
index e1e18b92f..000000000
--- a/tools/testing/selftests/kdbus/kdbus-util.h
+++ /dev/null
@@ -1,218 +0,0 @@
-/*
- * Copyright (C) 2013-2015 Kay Sievers
- * Copyright (C) 2013-2015 Daniel Mack
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#pragma once
-
-#define BIT(X) (1 << (X))
-
-#include <time.h>
-#include <stdbool.h>
-#include <linux/kdbus.h>
-
-#define _STRINGIFY(x) #x
-#define STRINGIFY(x) _STRINGIFY(x)
-#define ELEMENTSOF(x) (sizeof(x)/sizeof((x)[0]))
-
-#define KDBUS_PTR(addr) ((void *)(uintptr_t)(addr))
-
-#define KDBUS_ALIGN8(l) (((l) + 7) & ~7)
-#define KDBUS_ITEM_HEADER_SIZE offsetof(struct kdbus_item, data)
-#define KDBUS_ITEM_SIZE(s) KDBUS_ALIGN8((s) + KDBUS_ITEM_HEADER_SIZE)
-
-#define KDBUS_ITEM_NEXT(item) \
- (typeof(item))((uint8_t *)(item) + KDBUS_ALIGN8((item)->size))
-#define KDBUS_ITEM_FOREACH(item, head, first) \
- for ((item) = (head)->first; \
- ((uint8_t *)(item) < (uint8_t *)(head) + (head)->size) && \
- ((uint8_t *)(item) >= (uint8_t *)(head)); \
- (item) = KDBUS_ITEM_NEXT(item))
-#define KDBUS_FOREACH(iter, first, _size) \
- for ((iter) = (first); \
- ((uint8_t *)(iter) < (uint8_t *)(first) + (_size)) && \
- ((uint8_t *)(iter) >= (uint8_t *)(first)); \
- (iter) = (void *)((uint8_t *)(iter) + KDBUS_ALIGN8((iter)->size)))
-
-#define _KDBUS_ATTACH_BITS_SET_NR (__builtin_popcountll(_KDBUS_ATTACH_ALL))
-
-/* Sum of KDBUS_ITEM_* that reflects _KDBUS_ATTACH_ALL */
-#define KDBUS_ATTACH_ITEMS_TYPE_SUM \
- ((((_KDBUS_ATTACH_BITS_SET_NR - 1) * \
- ((_KDBUS_ATTACH_BITS_SET_NR - 1) + 1)) / 2) + \
- (_KDBUS_ITEM_ATTACH_BASE * _KDBUS_ATTACH_BITS_SET_NR))
-
-#define POOL_SIZE (16 * 1024LU * 1024LU)
-
-#define UNPRIV_UID 65534
-#define UNPRIV_GID 65534
-
-/* Dump as user of process, useful for user namespace testing */
-#define SUID_DUMP_USER 1
-
-extern int kdbus_util_verbose;
-
-#define kdbus_printf(X...) \
- if (kdbus_util_verbose) \
- printf(X)
-
-#define RUN_UNPRIVILEGED(child_uid, child_gid, _child_, _parent_) ({ \
- pid_t pid, rpid; \
- int ret; \
- \
- pid = fork(); \
- if (pid == 0) { \
- ret = drop_privileges(child_uid, child_gid); \
- ASSERT_EXIT_VAL(ret == 0, ret); \
- \
- _child_; \
- _exit(0); \
- } else if (pid > 0) { \
- _parent_; \
- rpid = waitpid(pid, &ret, 0); \
- ASSERT_RETURN(rpid == pid); \
- ASSERT_RETURN(WIFEXITED(ret)); \
- ASSERT_RETURN(WEXITSTATUS(ret) == 0); \
- ret = TEST_OK; \
- } else { \
- ret = pid; \
- } \
- \
- ret; \
- })
-
-#define RUN_UNPRIVILEGED_CONN(_var_, _bus_, _code_) \
- RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({ \
- struct kdbus_conn *_var_; \
- _var_ = kdbus_hello(_bus_, 0, NULL, 0); \
- ASSERT_EXIT(_var_); \
- _code_; \
- kdbus_conn_free(_var_); \
- }), ({ 0; }))
-
-#define RUN_CLONE_CHILD(clone_ret, flags, _setup_, _child_body_, \
- _parent_setup_, _parent_body_) ({ \
- pid_t pid, rpid; \
- int ret; \
- int efd = -1; \
- \
- _setup_; \
- efd = eventfd(0, EFD_CLOEXEC); \
- ASSERT_RETURN(efd >= 0); \
- *(clone_ret) = 0; \
- pid = syscall(__NR_clone, flags, NULL); \
- if (pid == 0) { \
- eventfd_t event_status = 0; \
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL); \
- ASSERT_EXIT(ret == 0); \
- ret = eventfd_read(efd, &event_status); \
- if (ret < 0 || event_status != 1) { \
- kdbus_printf("error eventfd_read()\n"); \
- _exit(EXIT_FAILURE); \
- } \
- _child_body_; \
- _exit(0); \
- } else if (pid > 0) { \
- _parent_setup_; \
- ret = eventfd_write(efd, 1); \
- ASSERT_RETURN(ret >= 0); \
- _parent_body_; \
- rpid = waitpid(pid, &ret, 0); \
- ASSERT_RETURN(rpid == pid); \
- ASSERT_RETURN(WIFEXITED(ret)); \
- ASSERT_RETURN(WEXITSTATUS(ret) == 0); \
- ret = TEST_OK; \
- } else { \
- ret = -errno; \
- *(clone_ret) = -errno; \
- } \
- close(efd); \
- ret; \
-})
-
-/* Enums for parent if it should drop privs or not */
-enum kdbus_drop_parent {
- DO_NOT_DROP,
- DROP_SAME_UNPRIV,
- DROP_OTHER_UNPRIV,
-};
-
-struct kdbus_conn {
- int fd;
- uint64_t id;
- unsigned char *buf;
-};
-
-int kdbus_sysfs_get_parameter_mask(const char *path, uint64_t *mask);
-int kdbus_sysfs_set_parameter_mask(const char *path, uint64_t mask);
-
-int sys_memfd_create(const char *name, __u64 size);
-int sys_memfd_seal_set(int fd);
-off_t sys_memfd_get_size(int fd, off_t *size);
-
-int kdbus_list(struct kdbus_conn *conn, uint64_t flags);
-int kdbus_name_release(struct kdbus_conn *conn, const char *name);
-int kdbus_name_acquire(struct kdbus_conn *conn, const char *name,
- uint64_t *flags);
-void kdbus_msg_free(struct kdbus_msg *msg);
-int kdbus_msg_recv(struct kdbus_conn *conn,
- struct kdbus_msg **msg, uint64_t *offset);
-int kdbus_msg_recv_poll(struct kdbus_conn *conn, int timeout_ms,
- struct kdbus_msg **msg_out, uint64_t *offset);
-int kdbus_free(const struct kdbus_conn *conn, uint64_t offset);
-int kdbus_msg_dump(const struct kdbus_conn *conn,
- const struct kdbus_msg *msg);
-int kdbus_create_bus(int control_fd, const char *name,
- uint64_t owner_meta, char **path);
-int kdbus_msg_send(const struct kdbus_conn *conn, const char *name,
- uint64_t cookie, uint64_t flags, uint64_t timeout,
- int64_t priority, uint64_t dst_id);
-int kdbus_msg_send_sync(const struct kdbus_conn *conn, const char *name,
- uint64_t cookie, uint64_t flags, uint64_t timeout,
- int64_t priority, uint64_t dst_id, int cancel_fd);
-int kdbus_msg_send_reply(const struct kdbus_conn *conn,
- uint64_t reply_cookie,
- uint64_t dst_id);
-struct kdbus_conn *kdbus_hello(const char *path, uint64_t hello_flags,
- const struct kdbus_item *item,
- size_t item_size);
-struct kdbus_conn *kdbus_hello_registrar(const char *path, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access, uint64_t flags);
-struct kdbus_conn *kdbus_hello_activator(const char *path, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access);
-bool kdbus_item_in_message(struct kdbus_msg *msg, uint64_t type);
-int kdbus_bus_creator_info(struct kdbus_conn *conn,
- uint64_t flags,
- uint64_t *offset);
-int kdbus_conn_info(struct kdbus_conn *conn, uint64_t id,
- const char *name, uint64_t flags, uint64_t *offset);
-void kdbus_conn_free(struct kdbus_conn *conn);
-int kdbus_conn_update_attach_flags(struct kdbus_conn *conn,
- uint64_t attach_flags_send,
- uint64_t attach_flags_recv);
-int kdbus_conn_update_policy(struct kdbus_conn *conn, const char *name,
- const struct kdbus_policy_access *access,
- size_t num_access);
-
-int kdbus_add_match_id(struct kdbus_conn *conn, uint64_t cookie,
- uint64_t type, uint64_t id);
-int kdbus_add_match_empty(struct kdbus_conn *conn);
-
-int all_uids_gids_are_mapped(void);
-int drop_privileges(uid_t uid, gid_t gid);
-uint64_t now(clockid_t clock);
-char *unique_name(const char *prefix);
-
-int userns_map_uid_gid(pid_t pid, const char *map_uid, const char *map_gid);
-int test_is_capable(int cap, ...);
-int config_user_ns_is_enabled(void);
-int config_auditsyscall_is_enabled(void);
-int config_cgroups_is_enabled(void);
-int config_security_is_enabled(void);
diff --git a/tools/testing/selftests/kdbus/test-activator.c b/tools/testing/selftests/kdbus/test-activator.c
deleted file mode 100644
index c576a30ad..000000000
--- a/tools/testing/selftests/kdbus/test-activator.c
+++ /dev/null
@@ -1,321 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <sys/capability.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-static int kdbus_starter_poll(struct kdbus_conn *conn)
-{
- int ret;
- struct pollfd fd;
-
- fd.fd = conn->fd;
- fd.events = POLLIN | POLLPRI | POLLHUP;
- fd.revents = 0;
-
- ret = poll(&fd, 1, 100);
- if (ret == 0)
- return -ETIMEDOUT;
- else if (ret > 0) {
- if (fd.revents & POLLIN)
- return 0;
-
- if (fd.revents & (POLLHUP | POLLERR))
- ret = -ECONNRESET;
- }
-
- return ret;
-}
-
-/* Ensure that kdbus activator logic is safe */
-static int kdbus_priv_activator(struct kdbus_test_env *env)
-{
- int ret;
- struct kdbus_msg *msg = NULL;
- uint64_t cookie = 0xdeadbeef;
- uint64_t flags;
- struct kdbus_conn *activator;
- struct kdbus_conn *service;
- struct kdbus_conn *client;
- struct kdbus_conn *holder;
- struct kdbus_policy_access *access;
-
- access = (struct kdbus_policy_access[]){
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = getuid(),
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = getuid(),
- .access = KDBUS_POLICY_TALK,
- },
- };
-
- activator = kdbus_hello_activator(env->buspath, "foo.priv.activator",
- access, 2);
- ASSERT_RETURN(activator);
-
- service = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(service);
-
- client = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(client);
-
- /*
- * Make sure that other users can't TALK to the activator
- */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- /* Try to talk using the ID */
- ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef, 0, 0,
- 0, activator->id);
- ASSERT_EXIT(ret == -ENXIO);
-
- /* Try to talk to the name */
- ret = kdbus_msg_send(unpriv, "foo.priv.activator",
- 0xdeadbeef, 0, 0, 0,
- KDBUS_DST_ID_NAME);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure that we did not receive anything, so the
- * service will not be started automatically
- */
-
- ret = kdbus_starter_poll(activator);
- ASSERT_RETURN(ret == -ETIMEDOUT);
-
- /*
- * Now try to emulate the starter/service logic and
- * acquire the name.
- */
-
- cookie++;
- ret = kdbus_msg_send(service, "foo.priv.activator", cookie,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_starter_poll(activator);
- ASSERT_RETURN(ret == 0);
-
- /* Policies are still checked, access denied */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(unpriv, "foo.priv.activator",
- &flags);
- ASSERT_RETURN(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(service, "foo.priv.activator",
- &flags);
- ASSERT_RETURN(ret == 0);
-
- /* We read our previous starter message */
-
- ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* Try to talk, we still fail */
-
- cookie++;
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- /* Try to talk to the name */
- ret = kdbus_msg_send(unpriv, "foo.priv.activator",
- cookie, 0, 0, 0,
- KDBUS_DST_ID_NAME);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /* Still nothing to read */
-
- ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
- ASSERT_RETURN(ret == -ETIMEDOUT);
-
- /* We receive every thing now */
-
- cookie++;
- ret = kdbus_msg_send(client, "foo.priv.activator", cookie,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- ASSERT_RETURN(ret == 0);
- ret = kdbus_msg_recv_poll(service, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- /* Policies default to deny TALK now */
- kdbus_conn_free(activator);
-
- cookie++;
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- /* Try to talk to the name */
- ret = kdbus_msg_send(unpriv, "foo.priv.activator",
- cookie, 0, 0, 0,
- KDBUS_DST_ID_NAME);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
- ASSERT_RETURN(ret == -ETIMEDOUT);
-
- /* Same user is able to TALK */
- cookie++;
- ret = kdbus_msg_send(client, "foo.priv.activator", cookie,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- ASSERT_RETURN(ret == 0);
- ret = kdbus_msg_recv_poll(service, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- access = (struct kdbus_policy_access []){
- {
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = getuid(),
- .access = KDBUS_POLICY_TALK,
- },
- };
-
- holder = kdbus_hello_registrar(env->buspath, "foo.priv.activator",
- access, 1, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(holder);
-
- /* Now we are able to TALK to the name */
-
- cookie++;
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- /* Try to talk to the name */
- ret = kdbus_msg_send(unpriv, "foo.priv.activator",
- cookie, 0, 0, 0,
- KDBUS_DST_ID_NAME);
- ASSERT_EXIT(ret == 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(service, 100, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(unpriv, "foo.priv.activator",
- &flags);
- ASSERT_RETURN(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- kdbus_conn_free(service);
- kdbus_conn_free(client);
- kdbus_conn_free(holder);
-
- return 0;
-}
-
-int kdbus_test_activator(struct kdbus_test_env *env)
-{
- int ret;
- struct kdbus_conn *activator;
- struct pollfd fds[2];
- bool activator_done = false;
- struct kdbus_policy_access access[2];
-
- access[0].type = KDBUS_POLICY_ACCESS_USER;
- access[0].id = getuid();
- access[0].access = KDBUS_POLICY_OWN;
-
- access[1].type = KDBUS_POLICY_ACCESS_WORLD;
- access[1].access = KDBUS_POLICY_TALK;
-
- activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
- access, 2);
- ASSERT_RETURN(activator);
-
- ret = kdbus_add_match_empty(env->conn);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_list(env->conn, KDBUS_LIST_NAMES |
- KDBUS_LIST_UNIQUE |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_send(env->conn, "foo.test.activator", 0xdeafbeef,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- ASSERT_RETURN(ret == 0);
-
- fds[0].fd = activator->fd;
- fds[1].fd = env->conn->fd;
-
- kdbus_printf("-- entering poll loop ...\n");
-
- for (;;) {
- int i, nfds = sizeof(fds) / sizeof(fds[0]);
-
- for (i = 0; i < nfds; i++) {
- fds[i].events = POLLIN | POLLPRI;
- fds[i].revents = 0;
- }
-
- ret = poll(fds, nfds, 3000);
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_list(env->conn, KDBUS_LIST_NAMES);
- ASSERT_RETURN(ret == 0);
-
- if ((fds[0].revents & POLLIN) && !activator_done) {
- uint64_t flags = KDBUS_NAME_REPLACE_EXISTING;
-
- kdbus_printf("Starter was called back!\n");
-
- ret = kdbus_name_acquire(env->conn,
- "foo.test.activator", &flags);
- ASSERT_RETURN(ret == 0);
-
- activator_done = true;
- }
-
- if (fds[1].revents & POLLIN) {
- kdbus_msg_recv(env->conn, NULL, NULL);
- break;
- }
- }
-
- /* Check if all uids/gids are mapped */
- if (!all_uids_gids_are_mapped())
- return TEST_SKIP;
-
- /* Check now capabilities, so we run the previous tests */
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(ret >= 0);
-
- if (!ret)
- return TEST_SKIP;
-
- ret = kdbus_priv_activator(env);
- ASSERT_RETURN(ret == 0);
-
- kdbus_conn_free(activator);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-benchmark.c b/tools/testing/selftests/kdbus/test-benchmark.c
deleted file mode 100644
index 8a9744b00..000000000
--- a/tools/testing/selftests/kdbus/test-benchmark.c
+++ /dev/null
@@ -1,451 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <locale.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <math.h>
-
-#include "kdbus-api.h"
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-#define SERVICE_NAME "foo.bar.echo"
-
-/*
- * To have a banchmark comparison with unix socket, set:
- * user_memfd = false;
- * compare_uds = true;
- * attach_none = true; do not attached metadata
- */
-
-static bool use_memfd = true; /* transmit memfd? */
-static bool compare_uds = false; /* unix-socket comparison? */
-static bool attach_none = false; /* clear attach-flags? */
-static char stress_payload[8192];
-
-struct stats {
- uint64_t count;
- uint64_t latency_acc;
- uint64_t latency_low;
- uint64_t latency_high;
- uint64_t latency_avg;
- uint64_t latency_ssquares;
-};
-
-static struct stats stats;
-
-static void reset_stats(void)
-{
- stats.count = 0;
- stats.latency_acc = 0;
- stats.latency_low = UINT64_MAX;
- stats.latency_high = 0;
- stats.latency_avg = 0;
- stats.latency_ssquares = 0;
-}
-
-static void dump_stats(bool is_uds)
-{
- if (stats.count > 0) {
- kdbus_printf("stats %s: %'llu packets processed, latency (nsecs) min/max/avg/dev %'7llu // %'7llu // %'7llu // %'7.f\n",
- is_uds ? " (UNIX)" : "(KDBUS)",
- (unsigned long long) stats.count,
- (unsigned long long) stats.latency_low,
- (unsigned long long) stats.latency_high,
- (unsigned long long) stats.latency_avg,
- sqrt(stats.latency_ssquares / stats.count));
- } else {
- kdbus_printf("*** no packets received. bus stuck?\n");
- }
-}
-
-static void add_stats(uint64_t prev)
-{
- uint64_t diff, latency_avg_prev;
-
- diff = now(CLOCK_THREAD_CPUTIME_ID) - prev;
-
- stats.count++;
- stats.latency_acc += diff;
-
- /* see Welford62 */
- latency_avg_prev = stats.latency_avg;
- stats.latency_avg = stats.latency_acc / stats.count;
- stats.latency_ssquares += (diff - latency_avg_prev) * (diff - stats.latency_avg);
-
- if (stats.latency_low > diff)
- stats.latency_low = diff;
-
- if (stats.latency_high < diff)
- stats.latency_high = diff;
-}
-
-static int setup_simple_kdbus_msg(struct kdbus_conn *conn,
- uint64_t dst_id,
- struct kdbus_msg **msg_out)
-{
- struct kdbus_msg *msg;
- struct kdbus_item *item;
- uint64_t size;
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- msg = malloc(size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = conn->id;
- msg->dst_id = dst_id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- item = msg->items;
-
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t) stress_payload;
- item->vec.size = sizeof(stress_payload);
- item = KDBUS_ITEM_NEXT(item);
-
- *msg_out = msg;
-
- return 0;
-}
-
-static int setup_memfd_kdbus_msg(struct kdbus_conn *conn,
- uint64_t dst_id,
- off_t *memfd_item_offset,
- struct kdbus_msg **msg_out)
-{
- struct kdbus_msg *msg;
- struct kdbus_item *item;
- uint64_t size;
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
-
- msg = malloc(size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = conn->id;
- msg->dst_id = dst_id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- item = msg->items;
-
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t) stress_payload;
- item->vec.size = sizeof(stress_payload);
- item = KDBUS_ITEM_NEXT(item);
-
- item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_memfd);
- item->memfd.size = sizeof(uint64_t);
-
- *memfd_item_offset = (unsigned char *)item - (unsigned char *)msg;
- *msg_out = msg;
-
- return 0;
-}
-
-static int
-send_echo_request(struct kdbus_conn *conn, uint64_t dst_id,
- void *kdbus_msg, off_t memfd_item_offset)
-{
- struct kdbus_cmd_send cmd = {};
- int memfd = -1;
- int ret;
-
- if (use_memfd) {
- uint64_t now_ns = now(CLOCK_THREAD_CPUTIME_ID);
- struct kdbus_item *item = memfd_item_offset + kdbus_msg;
- memfd = sys_memfd_create("memfd-name", 0);
- ASSERT_RETURN_VAL(memfd >= 0, memfd);
-
- ret = write(memfd, &now_ns, sizeof(now_ns));
- ASSERT_RETURN_VAL(ret == sizeof(now_ns), -EAGAIN);
-
- ret = sys_memfd_seal_set(memfd);
- ASSERT_RETURN_VAL(ret == 0, -errno);
-
- item->memfd.fd = memfd;
- }
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)kdbus_msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- close(memfd);
-
- return 0;
-}
-
-static int
-handle_echo_reply(struct kdbus_conn *conn, uint64_t send_ns)
-{
- int ret;
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_msg *msg;
- const struct kdbus_item *item;
- bool has_memfd = false;
-
- ret = kdbus_cmd_recv(conn->fd, &recv);
- if (ret == -EAGAIN)
- return ret;
-
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- if (!use_memfd)
- goto out;
-
- msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
-
- KDBUS_ITEM_FOREACH(item, msg, items) {
- switch (item->type) {
- case KDBUS_ITEM_PAYLOAD_MEMFD: {
- char *buf;
-
- buf = mmap(NULL, item->memfd.size, PROT_READ,
- MAP_PRIVATE, item->memfd.fd, 0);
- ASSERT_RETURN_VAL(buf != MAP_FAILED, -EINVAL);
- ASSERT_RETURN_VAL(item->memfd.size == sizeof(uint64_t),
- -EINVAL);
-
- add_stats(*(uint64_t*)buf);
- munmap(buf, item->memfd.size);
- close(item->memfd.fd);
- has_memfd = true;
- break;
- }
-
- case KDBUS_ITEM_PAYLOAD_OFF:
- /* ignore */
- break;
- }
- }
-
-out:
- if (!has_memfd)
- add_stats(send_ns);
-
- ret = kdbus_free(conn, recv.msg.offset);
- ASSERT_RETURN_VAL(ret == 0, -errno);
-
- return 0;
-}
-
-static int benchmark(struct kdbus_test_env *env)
-{
- static char buf[sizeof(stress_payload)];
- struct kdbus_msg *kdbus_msg = NULL;
- off_t memfd_cached_offset = 0;
- int ret;
- struct kdbus_conn *conn_a, *conn_b;
- struct pollfd fds[2];
- uint64_t start, send_ns, now_ns, diff;
- unsigned int i;
- int uds[2];
-
- setlocale(LC_ALL, "");
-
- for (i = 0; i < sizeof(stress_payload); i++)
- stress_payload[i] = i;
-
- /* setup kdbus pair */
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- ret = kdbus_add_match_empty(conn_a);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_empty(conn_b);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(conn_a, SERVICE_NAME, NULL);
- ASSERT_RETURN(ret == 0);
-
- if (attach_none) {
- ret = kdbus_conn_update_attach_flags(conn_a,
- _KDBUS_ATTACH_ALL,
- 0);
- ASSERT_RETURN(ret == 0);
- }
-
- /* setup UDS pair */
-
- ret = socketpair(AF_UNIX, SOCK_SEQPACKET | SOCK_NONBLOCK, 0, uds);
- ASSERT_RETURN(ret == 0);
-
- /* setup a kdbus msg now */
- if (use_memfd) {
- ret = setup_memfd_kdbus_msg(conn_b, conn_a->id,
- &memfd_cached_offset,
- &kdbus_msg);
- ASSERT_RETURN(ret == 0);
- } else {
- ret = setup_simple_kdbus_msg(conn_b, conn_a->id, &kdbus_msg);
- ASSERT_RETURN(ret == 0);
- }
-
- /* start benchmark */
-
- kdbus_printf("-- entering poll loop ...\n");
-
- do {
- /* run kdbus benchmark */
- fds[0].fd = conn_a->fd;
- fds[1].fd = conn_b->fd;
-
- /* cancel any pending message */
- handle_echo_reply(conn_a, 0);
-
- start = now(CLOCK_THREAD_CPUTIME_ID);
- reset_stats();
-
- send_ns = now(CLOCK_THREAD_CPUTIME_ID);
- ret = send_echo_request(conn_b, conn_a->id,
- kdbus_msg, memfd_cached_offset);
- ASSERT_RETURN(ret == 0);
-
- while (1) {
- unsigned int nfds = sizeof(fds) / sizeof(fds[0]);
- unsigned int i;
-
- for (i = 0; i < nfds; i++) {
- fds[i].events = POLLIN | POLLPRI | POLLHUP;
- fds[i].revents = 0;
- }
-
- ret = poll(fds, nfds, 10);
- if (ret < 0)
- break;
-
- if (fds[0].revents & POLLIN) {
- ret = handle_echo_reply(conn_a, send_ns);
- ASSERT_RETURN(ret == 0);
-
- send_ns = now(CLOCK_THREAD_CPUTIME_ID);
- ret = send_echo_request(conn_b, conn_a->id,
- kdbus_msg,
- memfd_cached_offset);
- ASSERT_RETURN(ret == 0);
- }
-
- now_ns = now(CLOCK_THREAD_CPUTIME_ID);
- diff = now_ns - start;
- if (diff > 1000000000ULL) {
- start = now_ns;
-
- dump_stats(false);
- break;
- }
- }
-
- if (!compare_uds)
- continue;
-
- /* run unix-socket benchmark as comparison */
-
- fds[0].fd = uds[0];
- fds[1].fd = uds[1];
-
- /* cancel any pendign message */
- read(uds[1], buf, sizeof(buf));
-
- start = now(CLOCK_THREAD_CPUTIME_ID);
- reset_stats();
-
- send_ns = now(CLOCK_THREAD_CPUTIME_ID);
- ret = write(uds[0], stress_payload, sizeof(stress_payload));
- ASSERT_RETURN(ret == sizeof(stress_payload));
-
- while (1) {
- unsigned int nfds = sizeof(fds) / sizeof(fds[0]);
- unsigned int i;
-
- for (i = 0; i < nfds; i++) {
- fds[i].events = POLLIN | POLLPRI | POLLHUP;
- fds[i].revents = 0;
- }
-
- ret = poll(fds, nfds, 10);
- if (ret < 0)
- break;
-
- if (fds[1].revents & POLLIN) {
- ret = read(uds[1], buf, sizeof(buf));
- ASSERT_RETURN(ret == sizeof(buf));
-
- add_stats(send_ns);
-
- send_ns = now(CLOCK_THREAD_CPUTIME_ID);
- ret = write(uds[0], buf, sizeof(buf));
- ASSERT_RETURN(ret == sizeof(buf));
- }
-
- now_ns = now(CLOCK_THREAD_CPUTIME_ID);
- diff = now_ns - start;
- if (diff > 1000000000ULL) {
- start = now_ns;
-
- dump_stats(true);
- break;
- }
- }
-
- } while (kdbus_util_verbose);
-
- kdbus_printf("-- closing bus connections\n");
-
- free(kdbus_msg);
-
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- return (stats.count > 1) ? TEST_OK : TEST_ERR;
-}
-
-int kdbus_test_benchmark(struct kdbus_test_env *env)
-{
- use_memfd = true;
- attach_none = false;
- compare_uds = false;
- return benchmark(env);
-}
-
-int kdbus_test_benchmark_nomemfds(struct kdbus_test_env *env)
-{
- use_memfd = false;
- attach_none = false;
- compare_uds = false;
- return benchmark(env);
-}
-
-int kdbus_test_benchmark_uds(struct kdbus_test_env *env)
-{
- use_memfd = false;
- attach_none = true;
- compare_uds = true;
- return benchmark(env);
-}
diff --git a/tools/testing/selftests/kdbus/test-bus.c b/tools/testing/selftests/kdbus/test-bus.c
deleted file mode 100644
index 762fb3039..000000000
--- a/tools/testing/selftests/kdbus/test-bus.c
+++ /dev/null
@@ -1,175 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <sys/mman.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-static struct kdbus_item *kdbus_get_item(struct kdbus_info *info,
- uint64_t type)
-{
- struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, info, items)
- if (item->type == type)
- return item;
-
- return NULL;
-}
-
-static int test_bus_creator_info(const char *bus_path)
-{
- int ret;
- uint64_t offset;
- struct kdbus_conn *conn;
- struct kdbus_info *info;
- struct kdbus_item *item;
- char *tmp, *busname;
-
- /* extract the bus-name from @bus_path */
- tmp = strdup(bus_path);
- ASSERT_RETURN(tmp);
- busname = strrchr(tmp, '/');
- ASSERT_RETURN(busname);
- *busname = 0;
- busname = strrchr(tmp, '/');
- ASSERT_RETURN(busname);
- ++busname;
-
- conn = kdbus_hello(bus_path, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- ret = kdbus_bus_creator_info(conn, _KDBUS_ATTACH_ALL, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
-
- item = kdbus_get_item(info, KDBUS_ITEM_MAKE_NAME);
- ASSERT_RETURN(item);
- ASSERT_RETURN(!strcmp(item->str, busname));
-
- ret = kdbus_free(conn, offset);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- free(tmp);
- kdbus_conn_free(conn);
- return 0;
-}
-
-int kdbus_test_bus_make(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd cmd;
-
- /* bloom size item */
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_bloom_parameter bloom;
- } bs;
-
- /* name item */
- uint64_t n_size;
- uint64_t n_type;
- char name[64];
- } bus_make;
- char s[PATH_MAX], *name;
- int ret, control_fd2;
- uid_t uid;
-
- name = unique_name("");
- ASSERT_RETURN(name);
-
- snprintf(s, sizeof(s), "%s/control", env->root);
- env->control_fd = open(s, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(env->control_fd >= 0);
-
- control_fd2 = open(s, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(control_fd2 >= 0);
-
- memset(&bus_make, 0, sizeof(bus_make));
-
- bus_make.bs.size = sizeof(bus_make.bs);
- bus_make.bs.type = KDBUS_ITEM_BLOOM_PARAMETER;
- bus_make.bs.bloom.size = 64;
- bus_make.bs.bloom.n_hash = 1;
-
- bus_make.n_type = KDBUS_ITEM_MAKE_NAME;
-
- uid = getuid();
-
- /* missing uid prefix */
- snprintf(bus_make.name, sizeof(bus_make.name), "foo");
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* non alphanumeric character */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah@123", uid);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* '-' at the end */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-blah-", uid);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* create a new bus */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-1", uid, name);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd);
- ASSERT_RETURN(ret == -EEXIST);
-
- snprintf(s, sizeof(s), "%s/%u-%s-1/bus", env->root, uid, name);
- ASSERT_RETURN(access(s, F_OK) == 0);
-
- ret = test_bus_creator_info(s);
- ASSERT_RETURN(ret == 0);
-
- /* can't use the same fd for bus make twice, even though a different
- * bus name is used
- */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(env->control_fd, &bus_make.cmd);
- ASSERT_RETURN(ret == -EBADFD);
-
- /* create a new bus, with different fd and different bus name */
- snprintf(bus_make.name, sizeof(bus_make.name), "%u-%s-2", uid, name);
- bus_make.n_size = KDBUS_ITEM_HEADER_SIZE + strlen(bus_make.name) + 1;
- bus_make.cmd.size = sizeof(struct kdbus_cmd) +
- sizeof(bus_make.bs) + bus_make.n_size;
- ret = kdbus_cmd_bus_make(control_fd2, &bus_make.cmd);
- ASSERT_RETURN(ret == 0);
-
- close(control_fd2);
- free(name);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-chat.c b/tools/testing/selftests/kdbus/test-chat.c
deleted file mode 100644
index 41e5b53fe..000000000
--- a/tools/testing/selftests/kdbus/test-chat.c
+++ /dev/null
@@ -1,124 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <stdbool.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-int kdbus_test_chat(struct kdbus_test_env *env)
-{
- int ret, cookie;
- struct kdbus_conn *conn_a, *conn_b;
- struct pollfd fds[2];
- uint64_t flags;
- int count;
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- flags = KDBUS_NAME_ALLOW_REPLACEMENT;
- ret = kdbus_name_acquire(conn_a, "foo.bar.test", &flags);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(conn_a, "foo.bar.baz", NULL);
- ASSERT_RETURN(ret == 0);
-
- flags = KDBUS_NAME_QUEUE;
- ret = kdbus_name_acquire(conn_b, "foo.bar.baz", &flags);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(conn_a, "foo.bar.double", NULL);
- ASSERT_RETURN(ret == 0);
-
- flags = 0;
- ret = kdbus_name_acquire(conn_a, "foo.bar.double", &flags);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(!(flags & KDBUS_NAME_ACQUIRED));
-
- ret = kdbus_name_release(conn_a, "foo.bar.double");
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_release(conn_a, "foo.bar.double");
- ASSERT_RETURN(ret == -ESRCH);
-
- ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE |
- KDBUS_LIST_NAMES |
- KDBUS_LIST_QUEUED |
- KDBUS_LIST_ACTIVATORS);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_empty(conn_a);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_empty(conn_b);
- ASSERT_RETURN(ret == 0);
-
- cookie = 0;
- ret = kdbus_msg_send(conn_b, NULL, 0xc0000000 | cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- fds[0].fd = conn_a->fd;
- fds[1].fd = conn_b->fd;
-
- kdbus_printf("-- entering poll loop ...\n");
-
- for (count = 0;; count++) {
- int i, nfds = sizeof(fds) / sizeof(fds[0]);
-
- for (i = 0; i < nfds; i++) {
- fds[i].events = POLLIN | POLLPRI | POLLHUP;
- fds[i].revents = 0;
- }
-
- ret = poll(fds, nfds, 3000);
- ASSERT_RETURN(ret >= 0);
-
- if (fds[0].revents & POLLIN) {
- if (count > 2)
- kdbus_name_release(conn_a, "foo.bar.baz");
-
- ret = kdbus_msg_recv(conn_a, NULL, NULL);
- ASSERT_RETURN(ret == 0);
- ret = kdbus_msg_send(conn_a, NULL,
- 0xc0000000 | cookie++,
- 0, 0, 0, conn_b->id);
- ASSERT_RETURN(ret == 0);
- }
-
- if (fds[1].revents & POLLIN) {
- ret = kdbus_msg_recv(conn_b, NULL, NULL);
- ASSERT_RETURN(ret == 0);
- ret = kdbus_msg_send(conn_b, NULL,
- 0xc0000000 | cookie++,
- 0, 0, 0, conn_a->id);
- ASSERT_RETURN(ret == 0);
- }
-
- ret = kdbus_list(conn_b, KDBUS_LIST_UNIQUE |
- KDBUS_LIST_NAMES |
- KDBUS_LIST_QUEUED |
- KDBUS_LIST_ACTIVATORS);
- ASSERT_RETURN(ret == 0);
-
- if (count > 10)
- break;
- }
-
- kdbus_printf("-- closing bus connections\n");
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-connection.c b/tools/testing/selftests/kdbus/test-connection.c
deleted file mode 100644
index 4688ce8ec..000000000
--- a/tools/testing/selftests/kdbus/test-connection.c
+++ /dev/null
@@ -1,597 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <sys/types.h>
-#include <sys/capability.h>
-#include <sys/mman.h>
-#include <sys/syscall.h>
-#include <sys/wait.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-int kdbus_test_hello(struct kdbus_test_env *env)
-{
- struct kdbus_cmd_free cmd_free = {};
- struct kdbus_cmd_hello hello;
- int fd, ret;
-
- memset(&hello, 0, sizeof(hello));
-
- fd = open(env->buspath, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(fd >= 0);
-
- hello.flags = KDBUS_HELLO_ACCEPT_FD;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- hello.attach_flags_recv = _KDBUS_ATTACH_ALL;
- hello.size = sizeof(struct kdbus_cmd_hello);
- hello.pool_size = POOL_SIZE;
-
- /* an unaligned hello must result in -EFAULT */
- ret = kdbus_cmd_hello(fd, (struct kdbus_cmd_hello *) ((char *) &hello + 1));
- ASSERT_RETURN(ret == -EFAULT);
-
- /* a size of 0 must return EMSGSIZE */
- hello.size = 1;
- hello.flags = KDBUS_HELLO_ACCEPT_FD;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == -EINVAL);
-
- hello.size = sizeof(struct kdbus_cmd_hello);
-
- /* check faulty flags */
- hello.flags = 1ULL << 32;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* check for faulty pool sizes */
- hello.pool_size = 0;
- hello.flags = KDBUS_HELLO_ACCEPT_FD;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == -EINVAL);
-
- hello.pool_size = 4097;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == -EINVAL);
-
- hello.pool_size = POOL_SIZE;
-
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- hello.offset = (__u64)-1;
-
- /* success test */
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == 0);
-
- /* The kernel should have returned some items */
- ASSERT_RETURN(hello.offset != (__u64)-1);
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = hello.offset;
- ret = kdbus_cmd_free(fd, &cmd_free);
- ASSERT_RETURN(ret >= 0);
-
- close(fd);
-
- fd = open(env->buspath, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(fd >= 0);
-
- /* no ACTIVATOR flag without a name */
- hello.flags = KDBUS_HELLO_ACTIVATOR;
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == -EINVAL);
-
- close(fd);
-
- return TEST_OK;
-}
-
-int kdbus_test_byebye(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- struct kdbus_cmd_recv cmd_recv = { .size = sizeof(cmd_recv) };
- struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) };
- int ret;
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- ret = kdbus_add_match_empty(conn);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_empty(env->conn);
- ASSERT_RETURN(ret == 0);
-
- /* send over 1st connection */
- ret = kdbus_msg_send(env->conn, NULL, 0, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- /* say byebye on the 2nd, which must fail */
- ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye);
- ASSERT_RETURN(ret == -EBUSY);
-
- /* receive the message */
- ret = kdbus_cmd_recv(conn->fd, &cmd_recv);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_free(conn, cmd_recv.msg.offset);
- ASSERT_RETURN(ret == 0);
-
- /* and try again */
- ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye);
- ASSERT_RETURN(ret == 0);
-
- /* a 2nd try should result in -ECONNRESET */
- ret = kdbus_cmd_byebye(conn->fd, &cmd_byebye);
- ASSERT_RETURN(ret == -ECONNRESET);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-/* Get only the first item */
-static struct kdbus_item *kdbus_get_item(struct kdbus_info *info,
- uint64_t type)
-{
- struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, info, items)
- if (item->type == type)
- return item;
-
- return NULL;
-}
-
-static unsigned int kdbus_count_item(struct kdbus_info *info,
- uint64_t type)
-{
- unsigned int i = 0;
- const struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, info, items)
- if (item->type == type)
- i++;
-
- return i;
-}
-
-static int kdbus_fuzz_conn_info(struct kdbus_test_env *env, int capable)
-{
- int ret;
- unsigned int cnt = 0;
- uint64_t offset = 0;
- struct kdbus_info *info;
- struct kdbus_conn *conn;
- struct kdbus_conn *privileged;
- const struct kdbus_item *item;
- uint64_t valid_flags = KDBUS_ATTACH_NAMES |
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_CONN_DESCRIPTION;
-
- uint64_t invalid_flags = KDBUS_ATTACH_NAMES |
- KDBUS_ATTACH_CREDS |
- KDBUS_ATTACH_PIDS |
- KDBUS_ATTACH_CAPS |
- KDBUS_ATTACH_CGROUP |
- KDBUS_ATTACH_CONN_DESCRIPTION;
-
- struct kdbus_creds cached_creds;
- uid_t ruid, euid, suid;
- gid_t rgid, egid, sgid;
-
- getresuid(&ruid, &euid, &suid);
- getresgid(&rgid, &egid, &sgid);
-
- cached_creds.uid = ruid;
- cached_creds.euid = euid;
- cached_creds.suid = suid;
- cached_creds.fsuid = ruid;
-
- cached_creds.gid = rgid;
- cached_creds.egid = egid;
- cached_creds.sgid = sgid;
- cached_creds.fsgid = rgid;
-
- struct kdbus_pids cached_pids = {
- .pid = getpid(),
- .tid = syscall(SYS_gettid),
- .ppid = getppid(),
- };
-
- ret = kdbus_conn_info(env->conn, env->conn->id, NULL,
- valid_flags, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(env->conn->buf + offset);
- ASSERT_RETURN(info->id == env->conn->id);
-
- /* We do not have any well-known name */
- item = kdbus_get_item(info, KDBUS_ITEM_NAME);
- ASSERT_RETURN(item == NULL);
-
- item = kdbus_get_item(info, KDBUS_ITEM_CONN_DESCRIPTION);
- if (valid_flags & KDBUS_ATTACH_CONN_DESCRIPTION) {
- ASSERT_RETURN(item);
- } else {
- ASSERT_RETURN(item == NULL);
- }
-
- kdbus_free(env->conn, offset);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- privileged = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(privileged);
-
- ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
- ASSERT_RETURN(info->id == conn->id);
-
- /* We do not have any well-known name */
- item = kdbus_get_item(info, KDBUS_ITEM_NAME);
- ASSERT_RETURN(item == NULL);
-
- cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS);
- if (valid_flags & KDBUS_ATTACH_CREDS) {
- ASSERT_RETURN(cnt == 1);
-
- item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
- ASSERT_RETURN(item);
-
- /* Compare received items with cached creds */
- ASSERT_RETURN(memcmp(&item->creds, &cached_creds,
- sizeof(struct kdbus_creds)) == 0);
- } else {
- ASSERT_RETURN(cnt == 0);
- }
-
- item = kdbus_get_item(info, KDBUS_ITEM_PIDS);
- if (valid_flags & KDBUS_ATTACH_PIDS) {
- ASSERT_RETURN(item);
-
- /* Compare item->pids with cached PIDs */
- ASSERT_RETURN(item->pids.pid == cached_pids.pid &&
- item->pids.tid == cached_pids.tid &&
- item->pids.ppid == cached_pids.ppid);
- } else {
- ASSERT_RETURN(item == NULL);
- }
-
- /* We did not request KDBUS_ITEM_CAPS */
- item = kdbus_get_item(info, KDBUS_ITEM_CAPS);
- ASSERT_RETURN(item == NULL);
-
- kdbus_free(conn, offset);
-
- ret = kdbus_name_acquire(conn, "com.example.a", NULL);
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
- ASSERT_RETURN(info->id == conn->id);
-
- item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME);
- if (valid_flags & KDBUS_ATTACH_NAMES) {
- ASSERT_RETURN(item && !strcmp(item->name.name, "com.example.a"));
- } else {
- ASSERT_RETURN(item == NULL);
- }
-
- kdbus_free(conn, offset);
-
- ret = kdbus_conn_info(conn, 0, "com.example.a", valid_flags, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
- ASSERT_RETURN(info->id == conn->id);
-
- kdbus_free(conn, offset);
-
- /* does not have the necessary caps to drop to unprivileged */
- if (!capable)
- goto continue_test;
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
- ret = kdbus_conn_info(conn, conn->id, NULL,
- valid_flags, &offset);
- ASSERT_EXIT(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
- ASSERT_EXIT(info->id == conn->id);
-
- if (valid_flags & KDBUS_ATTACH_NAMES) {
- item = kdbus_get_item(info, KDBUS_ITEM_OWNED_NAME);
- ASSERT_EXIT(item &&
- strcmp(item->name.name,
- "com.example.a") == 0);
- }
-
- if (valid_flags & KDBUS_ATTACH_CREDS) {
- item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
- ASSERT_EXIT(item);
-
- /* Compare received items with cached creds */
- ASSERT_EXIT(memcmp(&item->creds, &cached_creds,
- sizeof(struct kdbus_creds)) == 0);
- }
-
- if (valid_flags & KDBUS_ATTACH_PIDS) {
- item = kdbus_get_item(info, KDBUS_ITEM_PIDS);
- ASSERT_EXIT(item);
-
- /*
- * Compare item->pids with cached pids of
- * privileged one.
- *
- * cmd_info will always return cached pids.
- */
- ASSERT_EXIT(item->pids.pid == cached_pids.pid &&
- item->pids.tid == cached_pids.tid);
- }
-
- kdbus_free(conn, offset);
-
- /*
- * Use invalid_flags and make sure that userspace
- * do not play with us.
- */
- ret = kdbus_conn_info(conn, conn->id, NULL,
- invalid_flags, &offset);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Make sure that we return only one creds item and
- * it points to the cached creds.
- */
- cnt = kdbus_count_item(info, KDBUS_ITEM_CREDS);
- if (invalid_flags & KDBUS_ATTACH_CREDS) {
- ASSERT_EXIT(cnt == 1);
-
- item = kdbus_get_item(info, KDBUS_ITEM_CREDS);
- ASSERT_EXIT(item);
-
- /* Compare received items with cached creds */
- ASSERT_EXIT(memcmp(&item->creds, &cached_creds,
- sizeof(struct kdbus_creds)) == 0);
- } else {
- ASSERT_EXIT(cnt == 0);
- }
-
- if (invalid_flags & KDBUS_ATTACH_PIDS) {
- cnt = kdbus_count_item(info, KDBUS_ITEM_PIDS);
- ASSERT_EXIT(cnt == 1);
-
- item = kdbus_get_item(info, KDBUS_ITEM_PIDS);
- ASSERT_EXIT(item);
-
- /* Compare item->pids with cached pids */
- ASSERT_EXIT(item->pids.pid == cached_pids.pid &&
- item->pids.tid == cached_pids.tid);
- }
-
- cnt = kdbus_count_item(info, KDBUS_ITEM_CGROUP);
- if (invalid_flags & KDBUS_ATTACH_CGROUP) {
- ASSERT_EXIT(cnt == 1);
- } else {
- ASSERT_EXIT(cnt == 0);
- }
-
- cnt = kdbus_count_item(info, KDBUS_ITEM_CAPS);
- if (invalid_flags & KDBUS_ATTACH_CAPS) {
- ASSERT_EXIT(cnt == 1);
- } else {
- ASSERT_EXIT(cnt == 0);
- }
-
- kdbus_free(conn, offset);
- }),
- ({ 0; }));
- ASSERT_RETURN(ret == 0);
-
-continue_test:
-
- /* A second name */
- ret = kdbus_name_acquire(conn, "com.example.b", NULL);
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_conn_info(conn, conn->id, NULL, valid_flags, &offset);
- ASSERT_RETURN(ret == 0);
-
- info = (struct kdbus_info *)(conn->buf + offset);
- ASSERT_RETURN(info->id == conn->id);
-
- cnt = kdbus_count_item(info, KDBUS_ITEM_OWNED_NAME);
- if (valid_flags & KDBUS_ATTACH_NAMES) {
- ASSERT_RETURN(cnt == 2);
- } else {
- ASSERT_RETURN(cnt == 0);
- }
-
- kdbus_free(conn, offset);
-
- ASSERT_RETURN(ret == 0);
-
- return 0;
-}
-
-int kdbus_test_conn_info(struct kdbus_test_env *env)
-{
- int ret;
- int have_caps;
- struct {
- struct kdbus_cmd_info cmd_info;
-
- struct {
- uint64_t size;
- uint64_t type;
- char str[64];
- } name;
- } buf;
-
- buf.cmd_info.size = sizeof(struct kdbus_cmd_info);
- buf.cmd_info.flags = 0;
- buf.cmd_info.attach_flags = 0;
- buf.cmd_info.id = env->conn->id;
-
- ret = kdbus_conn_info(env->conn, env->conn->id, NULL, 0, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* try to pass a name that is longer than the buffer's size */
- buf.name.size = KDBUS_ITEM_HEADER_SIZE + 1;
- buf.name.type = KDBUS_ITEM_NAME;
- strcpy(buf.name.str, "foo.bar.bla");
-
- buf.cmd_info.id = 0;
- buf.cmd_info.size = sizeof(buf.cmd_info) + buf.name.size;
- ret = kdbus_cmd_conn_info(env->conn->fd, (struct kdbus_cmd_info *) &buf);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* Pass a non existent name */
- ret = kdbus_conn_info(env->conn, 0, "non.existent.name", 0, NULL);
- ASSERT_RETURN(ret == -ESRCH);
-
- if (!all_uids_gids_are_mapped())
- return TEST_SKIP;
-
- /* Test for caps here, so we run the previous test */
- have_caps = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(have_caps >= 0);
-
- ret = kdbus_fuzz_conn_info(env, have_caps);
- ASSERT_RETURN(ret == 0);
-
- /* Now if we have skipped some tests then let the user know */
- if (!have_caps)
- return TEST_SKIP;
-
- return TEST_OK;
-}
-
-int kdbus_test_conn_update(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- int found = 0;
- int ret;
-
- /*
- * kdbus_hello() sets all attach flags. Receive a message by this
- * connection, and make sure a timestamp item (just to pick one) is
- * present.
- */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP);
- ASSERT_RETURN(found == 1);
-
- kdbus_msg_free(msg);
-
- /*
- * Now, modify the attach flags and repeat the action. The item must
- * now be missing.
- */
- found = 0;
-
- ret = kdbus_conn_update_attach_flags(conn,
- _KDBUS_ATTACH_ALL,
- _KDBUS_ATTACH_ALL &
- ~KDBUS_ATTACH_TIMESTAMP);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_send(env->conn, NULL, 0x12345678, 0, 0, 0, conn->id);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- found = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP);
- ASSERT_RETURN(found == 0);
-
- /* Provide a bogus attach_flags value */
- ret = kdbus_conn_update_attach_flags(conn,
- _KDBUS_ATTACH_ALL + 1,
- _KDBUS_ATTACH_ALL);
- ASSERT_RETURN(ret == -EINVAL);
-
- kdbus_msg_free(msg);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-int kdbus_test_writable_pool(struct kdbus_test_env *env)
-{
- struct kdbus_cmd_free cmd_free = {};
- struct kdbus_cmd_hello hello;
- int fd, ret;
- void *map;
-
- fd = open(env->buspath, O_RDWR | O_CLOEXEC);
- ASSERT_RETURN(fd >= 0);
-
- memset(&hello, 0, sizeof(hello));
- hello.flags = KDBUS_HELLO_ACCEPT_FD;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
- hello.attach_flags_recv = _KDBUS_ATTACH_ALL;
- hello.size = sizeof(struct kdbus_cmd_hello);
- hello.pool_size = POOL_SIZE;
- hello.offset = (__u64)-1;
-
- /* success test */
- ret = kdbus_cmd_hello(fd, &hello);
- ASSERT_RETURN(ret == 0);
-
- /* The kernel should have returned some items */
- ASSERT_RETURN(hello.offset != (__u64)-1);
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = hello.offset;
- ret = kdbus_cmd_free(fd, &cmd_free);
- ASSERT_RETURN(ret >= 0);
-
- /* pools cannot be mapped writable */
- map = mmap(NULL, POOL_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
- ASSERT_RETURN(map == MAP_FAILED);
-
- /* pools can always be mapped readable */
- map = mmap(NULL, POOL_SIZE, PROT_READ, MAP_SHARED, fd, 0);
- ASSERT_RETURN(map != MAP_FAILED);
-
- /* make sure we cannot change protection masks to writable */
- ret = mprotect(map, POOL_SIZE, PROT_READ | PROT_WRITE);
- ASSERT_RETURN(ret < 0);
-
- munmap(map, POOL_SIZE);
- close(fd);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-daemon.c b/tools/testing/selftests/kdbus/test-daemon.c
deleted file mode 100644
index 8bc238619..000000000
--- a/tools/testing/selftests/kdbus/test-daemon.c
+++ /dev/null
@@ -1,65 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <stdbool.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-int kdbus_test_daemon(struct kdbus_test_env *env)
-{
- struct pollfd fds[2];
- int count;
- int ret;
-
- /* This test doesn't make any sense in non-interactive mode */
- if (!kdbus_util_verbose)
- return TEST_OK;
-
- printf("Created connection %llu on bus '%s'\n",
- (unsigned long long) env->conn->id, env->buspath);
-
- ret = kdbus_name_acquire(env->conn, "com.example.kdbus-test", NULL);
- ASSERT_RETURN(ret == 0);
- printf(" Aquired name: com.example.kdbus-test\n");
-
- fds[0].fd = env->conn->fd;
- fds[1].fd = STDIN_FILENO;
-
- printf("Monitoring connections:\n");
-
- for (count = 0;; count++) {
- int i, nfds = sizeof(fds) / sizeof(fds[0]);
-
- for (i = 0; i < nfds; i++) {
- fds[i].events = POLLIN | POLLPRI | POLLHUP;
- fds[i].revents = 0;
- }
-
- ret = poll(fds, nfds, -1);
- if (ret <= 0)
- break;
-
- if (fds[0].revents & POLLIN) {
- ret = kdbus_msg_recv(env->conn, NULL, NULL);
- ASSERT_RETURN(ret == 0);
- }
-
- /* stdin */
- if (fds[1].revents & POLLIN)
- break;
- }
-
- printf("Closing bus connection\n");
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-endpoint.c b/tools/testing/selftests/kdbus/test-endpoint.c
deleted file mode 100644
index 34a7be49c..000000000
--- a/tools/testing/selftests/kdbus/test-endpoint.c
+++ /dev/null
@@ -1,352 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <libgen.h>
-#include <sys/capability.h>
-#include <sys/wait.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-#define KDBUS_SYSNAME_MAX_LEN 63
-
-static int install_name_add_match(struct kdbus_conn *conn, const char *name)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_name_change chg;
- } item;
- char name[64];
- } buf;
- int ret;
-
- /* install the match rule */
- memset(&buf, 0, sizeof(buf));
- buf.item.type = KDBUS_ITEM_NAME_ADD;
- buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
- buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
- strncpy(buf.name, name, sizeof(buf.name) - 1);
- buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
- buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
-
- ret = kdbus_cmd_match_add(conn->fd, &buf.cmd);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-static int create_endpoint(const char *buspath, uid_t uid, const char *name,
- uint64_t flags)
-{
- struct {
- struct kdbus_cmd cmd;
-
- /* name item */
- struct {
- uint64_t size;
- uint64_t type;
- /* max should be KDBUS_SYSNAME_MAX_LEN */
- char str[128];
- } name;
- } ep_make;
- int fd, ret;
-
- fd = open(buspath, O_RDWR);
- if (fd < 0)
- return fd;
-
- memset(&ep_make, 0, sizeof(ep_make));
-
- snprintf(ep_make.name.str,
- /* Use the KDBUS_SYSNAME_MAX_LEN or sizeof(str) */
- KDBUS_SYSNAME_MAX_LEN > strlen(name) ?
- KDBUS_SYSNAME_MAX_LEN : sizeof(ep_make.name.str),
- "%u-%s", uid, name);
-
- ep_make.name.type = KDBUS_ITEM_MAKE_NAME;
- ep_make.name.size = KDBUS_ITEM_HEADER_SIZE +
- strlen(ep_make.name.str) + 1;
-
- ep_make.cmd.flags = flags;
- ep_make.cmd.size = sizeof(ep_make.cmd) + ep_make.name.size;
-
- ret = kdbus_cmd_endpoint_make(fd, &ep_make.cmd);
- if (ret < 0) {
- kdbus_printf("error creating endpoint: %d (%m)\n", ret);
- return ret;
- }
-
- return fd;
-}
-
-static int unpriv_test_custom_ep(const char *buspath)
-{
- int ret, ep_fd1, ep_fd2;
- char *ep1, *ep2, *tmp1, *tmp2;
-
- tmp1 = strdup(buspath);
- tmp2 = strdup(buspath);
- ASSERT_RETURN(tmp1 && tmp2);
-
- ret = asprintf(&ep1, "%s/%u-%s", dirname(tmp1), getuid(), "apps1");
- ASSERT_RETURN(ret >= 0);
-
- ret = asprintf(&ep2, "%s/%u-%s", dirname(tmp2), getuid(), "apps2");
- ASSERT_RETURN(ret >= 0);
-
- free(tmp1);
- free(tmp2);
-
- /* endpoint only accessible to current uid */
- ep_fd1 = create_endpoint(buspath, getuid(), "apps1", 0);
- ASSERT_RETURN(ep_fd1 >= 0);
-
- /* endpoint world accessible */
- ep_fd2 = create_endpoint(buspath, getuid(), "apps2",
- KDBUS_MAKE_ACCESS_WORLD);
- ASSERT_RETURN(ep_fd2 >= 0);
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({
- int ep_fd;
- struct kdbus_conn *ep_conn;
-
- /*
- * Make sure that we are not able to create custom
- * endpoints
- */
- ep_fd = create_endpoint(buspath, getuid(),
- "unpriv_costum_ep", 0);
- ASSERT_EXIT(ep_fd == -EPERM);
-
- /*
- * Endpoint "apps1" only accessible to same users,
- * that own the endpoint. Access denied by VFS
- */
- ep_conn = kdbus_hello(ep1, 0, NULL, 0);
- ASSERT_EXIT(!ep_conn && errno == EACCES);
-
- /* Endpoint "apps2" world accessible */
- ep_conn = kdbus_hello(ep2, 0, NULL, 0);
- ASSERT_EXIT(ep_conn);
-
- kdbus_conn_free(ep_conn);
-
- _exit(EXIT_SUCCESS);
- }),
- ({ 0; }));
- ASSERT_RETURN(ret == 0);
-
- close(ep_fd1);
- close(ep_fd2);
- free(ep1);
- free(ep2);
-
- return 0;
-}
-
-static int update_endpoint(int fd, const char *name)
-{
- int len = strlen(name) + 1;
- struct {
- struct kdbus_cmd cmd;
-
- /* name item */
- struct {
- uint64_t size;
- uint64_t type;
- char str[KDBUS_ALIGN8(len)];
- } name;
-
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_policy_access access;
- } access;
- } ep_update;
- int ret;
-
- memset(&ep_update, 0, sizeof(ep_update));
-
- ep_update.name.size = KDBUS_ITEM_HEADER_SIZE + len;
- ep_update.name.type = KDBUS_ITEM_NAME;
- strncpy(ep_update.name.str, name, sizeof(ep_update.name.str) - 1);
-
- ep_update.access.size = sizeof(ep_update.access);
- ep_update.access.type = KDBUS_ITEM_POLICY_ACCESS;
- ep_update.access.access.type = KDBUS_POLICY_ACCESS_WORLD;
- ep_update.access.access.access = KDBUS_POLICY_SEE;
-
- ep_update.cmd.size = sizeof(ep_update);
-
- ret = kdbus_cmd_endpoint_update(fd, &ep_update.cmd);
- if (ret < 0) {
- kdbus_printf("error updating endpoint: %d (%m)\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-int kdbus_test_custom_endpoint(struct kdbus_test_env *env)
-{
- char *ep, *tmp;
- int ret, ep_fd;
- struct kdbus_msg *msg;
- struct kdbus_conn *ep_conn;
- struct kdbus_conn *reader;
- const char *name = "foo.bar.baz";
- const char *epname = "foo";
- char fake_ep[KDBUS_SYSNAME_MAX_LEN + 1] = {'\0'};
-
- memset(fake_ep, 'X', sizeof(fake_ep) - 1);
-
- /* Try to create a custom endpoint with a long name */
- ret = create_endpoint(env->buspath, getuid(), fake_ep, 0);
- ASSERT_RETURN(ret == -ENAMETOOLONG);
-
- /* Try to create a custom endpoint with a different uid */
- ret = create_endpoint(env->buspath, getuid() + 1, "foobar", 0);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* create a custom endpoint, and open a connection on it */
- ep_fd = create_endpoint(env->buspath, getuid(), "foo", 0);
- ASSERT_RETURN(ep_fd >= 0);
-
- tmp = strdup(env->buspath);
- ASSERT_RETURN(tmp);
-
- ret = asprintf(&ep, "%s/%u-%s", dirname(tmp), getuid(), epname);
- free(tmp);
- ASSERT_RETURN(ret >= 0);
-
- /* Register a connection that listen to broadcasts */
- reader = kdbus_hello(ep, 0, NULL, 0);
- ASSERT_RETURN(reader);
-
- /* Register to kernel signals */
- ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- ret = install_name_add_match(reader, name);
- ASSERT_RETURN(ret == 0);
-
- /* Monitor connections are not supported on custom endpoints */
- ep_conn = kdbus_hello(ep, KDBUS_HELLO_MONITOR, NULL, 0);
- ASSERT_RETURN(!ep_conn && errno == EOPNOTSUPP);
-
- ep_conn = kdbus_hello(ep, 0, NULL, 0);
- ASSERT_RETURN(ep_conn);
-
- /* Check that the reader got the IdAdd notification */
- ret = kdbus_msg_recv(reader, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD);
- ASSERT_RETURN(msg->items[0].id_change.id == ep_conn->id);
- kdbus_msg_free(msg);
-
- /*
- * Add a name add match on the endpoint connection, acquire name from
- * the unfiltered connection, and make sure the filtered connection
- * did not get the notification on the name owner change. Also, the
- * endpoint connection may not be able to call conn_info, neither on
- * the name nor on the ID.
- */
- ret = install_name_add_match(ep_conn, name);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(ep_conn, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL);
- ASSERT_RETURN(ret == -ESRCH);
-
- ret = kdbus_conn_info(ep_conn, 0, "random.crappy.name", 0, NULL);
- ASSERT_RETURN(ret == -ESRCH);
-
- ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL);
- ASSERT_RETURN(ret == -ENXIO);
-
- ret = kdbus_conn_info(ep_conn, 0x0fffffffffffffffULL, NULL, 0, NULL);
- ASSERT_RETURN(ret == -ENXIO);
-
- /* Check that the reader did not receive the name notification */
- ret = kdbus_msg_recv(reader, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /*
- * Release the name again, update the custom endpoint policy,
- * and try again. This time, the connection on the custom endpoint
- * should have gotten it.
- */
- ret = kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == 0);
-
- /* Check that the reader did not receive the name notification */
- ret = kdbus_msg_recv(reader, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- ret = update_endpoint(ep_fd, name);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(ep_conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD);
- ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0);
- ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id);
- ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
- kdbus_msg_free(msg);
-
- ret = kdbus_msg_recv(reader, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
-
- kdbus_msg_free(msg);
-
- ret = kdbus_conn_info(ep_conn, 0, name, 0, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_info(ep_conn, env->conn->id, NULL, 0, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* If we have privileges test custom endpoints */
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(ret >= 0);
-
- /*
- * All uids/gids are mapped and we have the necessary caps
- */
- if (ret && all_uids_gids_are_mapped()) {
- ret = unpriv_test_custom_ep(env->buspath);
- ASSERT_RETURN(ret == 0);
- }
-
- kdbus_conn_free(reader);
- kdbus_conn_free(ep_conn);
- close(ep_fd);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-fd.c b/tools/testing/selftests/kdbus/test-fd.c
deleted file mode 100644
index 2ae0f5ae8..000000000
--- a/tools/testing/selftests/kdbus/test-fd.c
+++ /dev/null
@@ -1,789 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdbool.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/mman.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-#include "kdbus-api.h"
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-#define KDBUS_MSG_MAX_ITEMS 128
-#define KDBUS_USER_MAX_CONN 256
-
-/* maximum number of inflight fds in a target queue per user */
-#define KDBUS_CONN_MAX_FDS_PER_USER 16
-
-/* maximum number of memfd items per message */
-#define KDBUS_MSG_MAX_MEMFD_ITEMS 16
-
-static int make_msg_payload_dbus(uint64_t src_id, uint64_t dst_id,
- uint64_t msg_size,
- struct kdbus_msg **msg_dbus)
-{
- struct kdbus_msg *msg;
-
- msg = malloc(msg_size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, msg_size);
- msg->size = msg_size;
- msg->src_id = src_id;
- msg->dst_id = dst_id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- *msg_dbus = msg;
-
- return 0;
-}
-
-static void make_item_memfds(struct kdbus_item *item,
- int *memfds, size_t memfd_size)
-{
- size_t i;
-
- for (i = 0; i < memfd_size; i++) {
- item->type = KDBUS_ITEM_PAYLOAD_MEMFD;
- item->size = KDBUS_ITEM_HEADER_SIZE +
- sizeof(struct kdbus_memfd);
- item->memfd.fd = memfds[i];
- item->memfd.size = sizeof(uint64_t); /* const size */
- item = KDBUS_ITEM_NEXT(item);
- }
-}
-
-static void make_item_fds(struct kdbus_item *item,
- int *fd_array, size_t fd_size)
-{
- size_t i;
- item->type = KDBUS_ITEM_FDS;
- item->size = KDBUS_ITEM_HEADER_SIZE + (sizeof(int) * fd_size);
-
- for (i = 0; i < fd_size; i++)
- item->fds[i] = fd_array[i];
-}
-
-static int memfd_write(const char *name, void *buf, size_t bufsize)
-{
- ssize_t ret;
- int memfd;
-
- memfd = sys_memfd_create(name, 0);
- ASSERT_RETURN_VAL(memfd >= 0, memfd);
-
- ret = write(memfd, buf, bufsize);
- ASSERT_RETURN_VAL(ret == (ssize_t)bufsize, -EAGAIN);
-
- ret = sys_memfd_seal_set(memfd);
- ASSERT_RETURN_VAL(ret == 0, -errno);
-
- return memfd;
-}
-
-static int send_memfds(struct kdbus_conn *conn, uint64_t dst_id,
- int *memfds_array, size_t memfd_count)
-{
- struct kdbus_cmd_send cmd = {};
- struct kdbus_item *item;
- struct kdbus_msg *msg;
- uint64_t size;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
-
- if (dst_id == KDBUS_DST_ID_BROADCAST)
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
-
- ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- item = msg->items;
-
- if (dst_id == KDBUS_DST_ID_BROADCAST) {
- item->type = KDBUS_ITEM_BLOOM_FILTER;
- item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
- item = KDBUS_ITEM_NEXT(item);
-
- msg->flags |= KDBUS_MSG_SIGNAL;
- }
-
- make_item_memfds(item, memfds_array, memfd_count);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- if (ret < 0) {
- kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
- }
-
- free(msg);
- return 0;
-}
-
-static int send_fds(struct kdbus_conn *conn, uint64_t dst_id,
- int *fd_array, size_t fd_count)
-{
- struct kdbus_cmd_send cmd = {};
- struct kdbus_item *item;
- struct kdbus_msg *msg;
- uint64_t size;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count);
-
- if (dst_id == KDBUS_DST_ID_BROADCAST)
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
-
- ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- item = msg->items;
-
- if (dst_id == KDBUS_DST_ID_BROADCAST) {
- item->type = KDBUS_ITEM_BLOOM_FILTER;
- item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + 64;
- item = KDBUS_ITEM_NEXT(item);
-
- msg->flags |= KDBUS_MSG_SIGNAL;
- }
-
- make_item_fds(item, fd_array, fd_count);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- if (ret < 0) {
- kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
- }
-
- free(msg);
- return ret;
-}
-
-static int send_fds_memfds(struct kdbus_conn *conn, uint64_t dst_id,
- int *fds_array, size_t fd_count,
- int *memfds_array, size_t memfd_count)
-{
- struct kdbus_cmd_send cmd = {};
- struct kdbus_item *item;
- struct kdbus_msg *msg;
- uint64_t size;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- size += memfd_count * KDBUS_ITEM_SIZE(sizeof(struct kdbus_memfd));
- size += KDBUS_ITEM_SIZE(sizeof(int) * fd_count);
-
- ret = make_msg_payload_dbus(conn->id, dst_id, size, &msg);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- item = msg->items;
-
- make_item_fds(item, fds_array, fd_count);
- item = KDBUS_ITEM_NEXT(item);
- make_item_memfds(item, memfds_array, memfd_count);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- if (ret < 0) {
- kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
- }
-
- free(msg);
- return ret;
-}
-
-/* Return the number of received fds */
-static unsigned int kdbus_item_get_nfds(struct kdbus_msg *msg)
-{
- unsigned int fds = 0;
- const struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, msg, items) {
- switch (item->type) {
- case KDBUS_ITEM_FDS: {
- fds += (item->size - KDBUS_ITEM_HEADER_SIZE) /
- sizeof(int);
- break;
- }
-
- case KDBUS_ITEM_PAYLOAD_MEMFD:
- fds++;
- break;
-
- default:
- break;
- }
- }
-
- return fds;
-}
-
-static struct kdbus_msg *
-get_kdbus_msg_with_fd(struct kdbus_conn *conn_src,
- uint64_t dst_id, uint64_t cookie, int fd)
-{
- int ret;
- uint64_t size;
- struct kdbus_item *item;
- struct kdbus_msg *msg;
-
- size = sizeof(struct kdbus_msg);
- if (fd >= 0)
- size += KDBUS_ITEM_SIZE(sizeof(int));
-
- ret = make_msg_payload_dbus(conn_src->id, dst_id, size, &msg);
- ASSERT_RETURN_VAL(ret == 0, NULL);
-
- msg->cookie = cookie;
-
- if (fd >= 0) {
- item = msg->items;
-
- make_item_fds(item, (int *)&fd, 1);
- }
-
- return msg;
-}
-
-static int kdbus_test_no_fds(struct kdbus_test_env *env,
- int *fds, int *memfd)
-{
- pid_t pid;
- int ret, status;
- uint64_t cookie;
- int connfd1, connfd2;
- struct kdbus_msg *msg, *msg_sync_reply;
- struct kdbus_cmd_hello hello;
- struct kdbus_conn *conn_src, *conn_dst, *conn_dummy;
- struct kdbus_cmd_send cmd = {};
- struct kdbus_cmd_free cmd_free = {};
-
- conn_src = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_src);
-
- connfd1 = open(env->buspath, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(connfd1 >= 0);
-
- connfd2 = open(env->buspath, O_RDWR|O_CLOEXEC);
- ASSERT_RETURN(connfd2 >= 0);
-
- /*
- * Create connections without KDBUS_HELLO_ACCEPT_FD
- * to test if send fd operations are blocked
- */
- conn_dst = malloc(sizeof(*conn_dst));
- ASSERT_RETURN(conn_dst);
-
- conn_dummy = malloc(sizeof(*conn_dummy));
- ASSERT_RETURN(conn_dummy);
-
- memset(&hello, 0, sizeof(hello));
- hello.size = sizeof(struct kdbus_cmd_hello);
- hello.pool_size = POOL_SIZE;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
-
- ret = kdbus_cmd_hello(connfd1, &hello);
- ASSERT_RETURN(ret == 0);
-
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = hello.offset;
- ret = kdbus_cmd_free(connfd1, &cmd_free);
- ASSERT_RETURN(ret >= 0);
-
- conn_dst->fd = connfd1;
- conn_dst->id = hello.id;
-
- memset(&hello, 0, sizeof(hello));
- hello.size = sizeof(struct kdbus_cmd_hello);
- hello.pool_size = POOL_SIZE;
- hello.attach_flags_send = _KDBUS_ATTACH_ALL;
-
- ret = kdbus_cmd_hello(connfd2, &hello);
- ASSERT_RETURN(ret == 0);
-
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = hello.offset;
- ret = kdbus_cmd_free(connfd2, &cmd_free);
- ASSERT_RETURN(ret >= 0);
-
- conn_dummy->fd = connfd2;
- conn_dummy->id = hello.id;
-
- conn_dst->buf = mmap(NULL, POOL_SIZE, PROT_READ,
- MAP_SHARED, connfd1, 0);
- ASSERT_RETURN(conn_dst->buf != MAP_FAILED);
-
- conn_dummy->buf = mmap(NULL, POOL_SIZE, PROT_READ,
- MAP_SHARED, connfd2, 0);
- ASSERT_RETURN(conn_dummy->buf != MAP_FAILED);
-
- /*
- * Send fds to connection that do not accept fd passing
- */
- ret = send_fds(conn_src, conn_dst->id, fds, 1);
- ASSERT_RETURN(ret == -ECOMM);
-
- /*
- * memfd are kdbus payload
- */
- ret = send_memfds(conn_src, conn_dst->id, memfd, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv_poll(conn_dst, 100, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- cookie = time(NULL);
-
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- struct timespec now;
-
- /*
- * A sync send/reply to a connection that do not
- * accept fds should fail if it contains an fd
- */
- msg_sync_reply = get_kdbus_msg_with_fd(conn_dst,
- conn_dummy->id,
- cookie, fds[0]);
- ASSERT_EXIT(msg_sync_reply);
-
- ret = clock_gettime(CLOCK_MONOTONIC_COARSE, &now);
- ASSERT_EXIT(ret == 0);
-
- msg_sync_reply->timeout_ns = now.tv_sec * 1000000000ULL +
- now.tv_nsec + 100000000ULL;
- msg_sync_reply->flags = KDBUS_MSG_EXPECT_REPLY;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg_sync_reply;
- cmd.flags = KDBUS_SEND_SYNC_REPLY;
-
- ret = kdbus_cmd_send(conn_dst->fd, &cmd);
- ASSERT_EXIT(ret == -ECOMM);
-
- /*
- * Now send a normal message, but the sync reply
- * will fail since it contains an fd that the
- * original sender do not want.
- *
- * The original sender will fail with -ETIMEDOUT
- */
- cookie++;
- ret = kdbus_msg_send_sync(conn_dst, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 5000000000ULL, 0, conn_src->id, -1);
- ASSERT_EXIT(ret == -EREMOTEIO);
-
- cookie++;
- ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL);
- ASSERT_EXIT(ret == 0);
- ASSERT_EXIT(msg->cookie == cookie);
-
- free(msg_sync_reply);
- kdbus_msg_free(msg);
-
- _exit(EXIT_SUCCESS);
- }
-
- ret = kdbus_msg_recv_poll(conn_dummy, 100, NULL, NULL);
- ASSERT_RETURN(ret == -ETIMEDOUT);
-
- cookie++;
- ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- /*
- * Try to reply with a kdbus connection handle, this should
- * fail with -EOPNOTSUPP
- */
- msg_sync_reply = get_kdbus_msg_with_fd(conn_src,
- conn_dst->id,
- cookie, conn_dst->fd);
- ASSERT_RETURN(msg_sync_reply);
-
- msg_sync_reply->cookie_reply = cookie;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg_sync_reply;
-
- ret = kdbus_cmd_send(conn_src->fd, &cmd);
- ASSERT_RETURN(ret == -EOPNOTSUPP);
-
- free(msg_sync_reply);
-
- /*
- * Try to reply with a normal fd, this should fail even
- * if the response is a sync reply
- *
- * From the sender view we fail with -ECOMM
- */
- msg_sync_reply = get_kdbus_msg_with_fd(conn_src,
- conn_dst->id,
- cookie, fds[0]);
- ASSERT_RETURN(msg_sync_reply);
-
- msg_sync_reply->cookie_reply = cookie;
-
- memset(&cmd, 0, sizeof(cmd));
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg_sync_reply;
-
- ret = kdbus_cmd_send(conn_src->fd, &cmd);
- ASSERT_RETURN(ret == -ECOMM);
-
- free(msg_sync_reply);
-
- /*
- * Resend another normal message and check if the queue
- * is clear
- */
- cookie++;
- ret = kdbus_msg_send(conn_src, NULL, cookie, 0, 0, 0,
- conn_dst->id);
- ASSERT_RETURN(ret == 0);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- kdbus_conn_free(conn_dummy);
- kdbus_conn_free(conn_dst);
- kdbus_conn_free(conn_src);
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-static int kdbus_send_multiple_fds(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst)
-{
- int ret, i;
- unsigned int nfds;
- int fds[KDBUS_CONN_MAX_FDS_PER_USER + 1];
- int memfds[KDBUS_MSG_MAX_ITEMS + 1];
- struct kdbus_msg *msg;
- uint64_t dummy_value;
-
- dummy_value = time(NULL);
-
- for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) {
- fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC);
- ASSERT_RETURN_VAL(fds[i] >= 0, -errno);
- }
-
- /* Send KDBUS_CONN_MAX_FDS_PER_USER with one more fd */
- ret = send_fds(conn_src, conn_dst->id, fds,
- KDBUS_CONN_MAX_FDS_PER_USER + 1);
- ASSERT_RETURN(ret == -EMFILE);
-
- /* Retry with the correct KDBUS_CONN_MAX_FDS_PER_USER */
- ret = send_fds(conn_src, conn_dst->id, fds,
- KDBUS_CONN_MAX_FDS_PER_USER);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* Check we got the right number of fds */
- nfds = kdbus_item_get_nfds(msg);
- ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER);
-
- kdbus_msg_free(msg);
-
- for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++, dummy_value++) {
- memfds[i] = memfd_write("memfd-name",
- &dummy_value,
- sizeof(dummy_value));
- ASSERT_RETURN_VAL(memfds[i] >= 0, memfds[i]);
- }
-
- /* Send KDBUS_MSG_MAX_ITEMS with one more memfd */
- ret = send_memfds(conn_src, conn_dst->id,
- memfds, KDBUS_MSG_MAX_ITEMS + 1);
- ASSERT_RETURN(ret == -E2BIG);
-
- ret = send_memfds(conn_src, conn_dst->id,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1);
- ASSERT_RETURN(ret == -E2BIG);
-
- /* Retry with the correct KDBUS_MSG_MAX_ITEMS */
- ret = send_memfds(conn_src, conn_dst->id,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* Check we got the right number of fds */
- nfds = kdbus_item_get_nfds(msg);
- ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS);
-
- kdbus_msg_free(msg);
-
-
- /*
- * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER+1 fds and
- * 10 memfds
- */
- ret = send_fds_memfds(conn_src, conn_dst->id,
- fds, KDBUS_CONN_MAX_FDS_PER_USER + 1,
- memfds, 10);
- ASSERT_RETURN(ret == -EMFILE);
-
- ret = kdbus_msg_recv(conn_dst, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /*
- * Combine multiple KDBUS_CONN_MAX_FDS_PER_USER fds and
- * (128 - 1) + 1 memfds, all fds take one item, while each
- * memfd takes one item
- */
- ret = send_fds_memfds(conn_src, conn_dst->id,
- fds, KDBUS_CONN_MAX_FDS_PER_USER,
- memfds, (KDBUS_MSG_MAX_ITEMS - 1) + 1);
- ASSERT_RETURN(ret == -E2BIG);
-
- ret = send_fds_memfds(conn_src, conn_dst->id,
- fds, KDBUS_CONN_MAX_FDS_PER_USER,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS + 1);
- ASSERT_RETURN(ret == -E2BIG);
-
- ret = kdbus_msg_recv(conn_dst, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /*
- * Send KDBUS_CONN_MAX_FDS_PER_USER fds +
- * KDBUS_MSG_MAX_MEMFD_ITEMS memfds
- */
- ret = send_fds_memfds(conn_src, conn_dst->id,
- fds, KDBUS_CONN_MAX_FDS_PER_USER,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* Check we got the right number of fds */
- nfds = kdbus_item_get_nfds(msg);
- ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER +
- KDBUS_MSG_MAX_MEMFD_ITEMS);
-
- kdbus_msg_free(msg);
-
-
- /*
- * Re-send fds + memfds, close them, but do not receive them
- * and try to queue more
- */
- ret = send_fds_memfds(conn_src, conn_dst->id,
- fds, KDBUS_CONN_MAX_FDS_PER_USER,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS);
- ASSERT_RETURN(ret == 0);
-
- /* close old references and get a new ones */
- for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++) {
- close(fds[i]);
- fds[i] = open("/dev/null", O_RDWR|O_CLOEXEC);
- ASSERT_RETURN_VAL(fds[i] >= 0, -errno);
- }
-
- /* should fail since we have already fds in the queue */
- ret = send_fds(conn_src, conn_dst->id, fds,
- KDBUS_CONN_MAX_FDS_PER_USER);
- ASSERT_RETURN(ret == -EMFILE);
-
- /* This should succeed */
- ret = send_memfds(conn_src, conn_dst->id,
- memfds, KDBUS_MSG_MAX_MEMFD_ITEMS);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- nfds = kdbus_item_get_nfds(msg);
- ASSERT_RETURN(nfds == KDBUS_CONN_MAX_FDS_PER_USER +
- KDBUS_MSG_MAX_MEMFD_ITEMS);
-
- kdbus_msg_free(msg);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- nfds = kdbus_item_get_nfds(msg);
- ASSERT_RETURN(nfds == KDBUS_MSG_MAX_MEMFD_ITEMS);
-
- kdbus_msg_free(msg);
-
- ret = kdbus_msg_recv(conn_dst, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- for (i = 0; i < KDBUS_CONN_MAX_FDS_PER_USER + 1; i++)
- close(fds[i]);
-
- for (i = 0; i < KDBUS_MSG_MAX_ITEMS + 1; i++)
- close(memfds[i]);
-
- return 0;
-}
-
-int kdbus_test_fd_passing(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn_src, *conn_dst;
- const char *str = "stackenblocken";
- const struct kdbus_item *item;
- struct kdbus_msg *msg;
- unsigned int i;
- uint64_t now;
- int fds_conn[2];
- int sock_pair[2];
- int fds[2];
- int memfd;
- int ret;
-
- now = (uint64_t) time(NULL);
-
- /* create two connections */
- conn_src = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_dst = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_src && conn_dst);
-
- fds_conn[0] = conn_src->fd;
- fds_conn[1] = conn_dst->fd;
-
- ret = socketpair(AF_UNIX, SOCK_STREAM, 0, sock_pair);
- ASSERT_RETURN(ret == 0);
-
- /* Setup memfd */
- memfd = memfd_write("memfd-name", &now, sizeof(now));
- ASSERT_RETURN(memfd >= 0);
-
- /* Setup pipes */
- ret = pipe(fds);
- ASSERT_RETURN(ret == 0);
-
- i = write(fds[1], str, strlen(str));
- ASSERT_RETURN(i == strlen(str));
-
- /*
- * Try to ass the handle of a connection as message payload.
- * This must fail.
- */
- ret = send_fds(conn_src, conn_dst->id, fds_conn, 2);
- ASSERT_RETURN(ret == -ENOTSUP);
-
- ret = send_fds(conn_dst, conn_src->id, fds_conn, 2);
- ASSERT_RETURN(ret == -ENOTSUP);
-
- ret = send_fds(conn_src, conn_dst->id, sock_pair, 2);
- ASSERT_RETURN(ret == -ENOTSUP);
-
- /*
- * Send fds and memfds to connection that do not accept fds
- */
- ret = kdbus_test_no_fds(env, fds, (int *)&memfd);
- ASSERT_RETURN(ret == 0);
-
- /* Try to broadcast file descriptors. This must fail. */
- ret = send_fds(conn_src, KDBUS_DST_ID_BROADCAST, fds, 1);
- ASSERT_RETURN(ret == -ENOTUNIQ);
-
- /* Try to broadcast memfd. This must succeed. */
- ret = send_memfds(conn_src, KDBUS_DST_ID_BROADCAST, (int *)&memfd, 1);
- ASSERT_RETURN(ret == 0);
-
- /* Open code this loop */
-loop_send_fds:
-
- /*
- * Send the read end of the pipe and close it.
- */
- ret = send_fds(conn_src, conn_dst->id, fds, 1);
- ASSERT_RETURN(ret == 0);
- close(fds[0]);
-
- ret = kdbus_msg_recv(conn_dst, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- KDBUS_ITEM_FOREACH(item, msg, items) {
- if (item->type == KDBUS_ITEM_FDS) {
- char tmp[14];
- int nfds = (item->size - KDBUS_ITEM_HEADER_SIZE) /
- sizeof(int);
- ASSERT_RETURN(nfds == 1);
-
- i = read(item->fds[0], tmp, sizeof(tmp));
- if (i != 0) {
- ASSERT_RETURN(i == sizeof(tmp));
- ASSERT_RETURN(memcmp(tmp, str, sizeof(tmp)) == 0);
-
- /* Write EOF */
- close(fds[1]);
-
- /*
- * Resend the read end of the pipe,
- * the receiver still holds a reference
- * to it...
- */
- goto loop_send_fds;
- }
-
- /* Got EOF */
-
- /*
- * Close the last reference to the read end
- * of the pipe, other references are
- * automatically closed just after send.
- */
- close(item->fds[0]);
- }
- }
-
- /*
- * Try to resend the read end of the pipe. Must fail with
- * -EBADF since both the sender and receiver closed their
- * references to it. We assume the above since sender and
- * receiver are on the same process.
- */
- ret = send_fds(conn_src, conn_dst->id, fds, 1);
- ASSERT_RETURN(ret == -EBADF);
-
- /* Then we clear out received any data... */
- kdbus_msg_free(msg);
-
- ret = kdbus_send_multiple_fds(conn_src, conn_dst);
- ASSERT_RETURN(ret == 0);
-
- close(sock_pair[0]);
- close(sock_pair[1]);
- close(memfd);
-
- kdbus_conn_free(conn_src);
- kdbus_conn_free(conn_dst);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-free.c b/tools/testing/selftests/kdbus/test-free.c
deleted file mode 100644
index f666da3e8..000000000
--- a/tools/testing/selftests/kdbus/test-free.c
+++ /dev/null
@@ -1,64 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-static int sample_ioctl_call(struct kdbus_test_env *env)
-{
- int ret;
- struct kdbus_cmd_list cmd_list = {
- .flags = KDBUS_LIST_QUEUED,
- .size = sizeof(cmd_list),
- };
-
- ret = kdbus_cmd_list(env->conn->fd, &cmd_list);
- ASSERT_RETURN(ret == 0);
-
- /* DON'T FREE THIS SLICE OF MEMORY! */
-
- return TEST_OK;
-}
-
-int kdbus_test_free(struct kdbus_test_env *env)
-{
- int ret;
- struct kdbus_cmd_free cmd_free = {};
-
- /* free an unallocated buffer */
- cmd_free.size = sizeof(cmd_free);
- cmd_free.flags = 0;
- cmd_free.offset = 0;
- ret = kdbus_cmd_free(env->conn->fd, &cmd_free);
- ASSERT_RETURN(ret == -ENXIO);
-
- /* free a buffer out of the pool's bounds */
- cmd_free.size = sizeof(cmd_free);
- cmd_free.offset = POOL_SIZE + 1;
- ret = kdbus_cmd_free(env->conn->fd, &cmd_free);
- ASSERT_RETURN(ret == -ENXIO);
-
- /*
- * The user application is responsible for freeing the allocated
- * memory with the KDBUS_CMD_FREE ioctl, so let's test what happens
- * if we forget about it.
- */
-
- ret = sample_ioctl_call(env);
- ASSERT_RETURN(ret == 0);
-
- ret = sample_ioctl_call(env);
- ASSERT_RETURN(ret == 0);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-match.c b/tools/testing/selftests/kdbus/test-match.c
deleted file mode 100644
index 2360dc1d7..000000000
--- a/tools/testing/selftests/kdbus/test-match.c
+++ /dev/null
@@ -1,441 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-int kdbus_test_match_id_add(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_id_change chg;
- } item;
- } buf;
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- int ret;
-
- memset(&buf, 0, sizeof(buf));
-
- buf.cmd.size = sizeof(buf);
- buf.cmd.cookie = 0xdeafbeefdeaddead;
- buf.item.size = sizeof(buf.item);
- buf.item.type = KDBUS_ITEM_ID_ADD;
- buf.item.chg.id = KDBUS_MATCH_ID_ANY;
-
- /* match on id add */
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* create 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* 1st connection should have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_ADD);
- ASSERT_RETURN(msg->items[0].id_change.id == conn->id);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-int kdbus_test_match_id_remove(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_id_change chg;
- } item;
- } buf;
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- size_t id;
- int ret;
-
- /* create 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
- id = conn->id;
-
- memset(&buf, 0, sizeof(buf));
- buf.cmd.size = sizeof(buf);
- buf.cmd.cookie = 0xdeafbeefdeaddead;
- buf.item.size = sizeof(buf.item);
- buf.item.type = KDBUS_ITEM_ID_REMOVE;
- buf.item.chg.id = id;
-
- /* register match on 2nd connection */
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* remove 2nd connection again */
- kdbus_conn_free(conn);
-
- /* 1st connection should have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE);
- ASSERT_RETURN(msg->items[0].id_change.id == id);
-
- return TEST_OK;
-}
-
-int kdbus_test_match_replace(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_id_change chg;
- } item;
- } buf;
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- size_t id;
- int ret;
-
- /* add a match to id_add */
- ASSERT_RETURN(kdbus_test_match_id_add(env) == TEST_OK);
-
- /* do a replace of the match from id_add to id_remove */
- memset(&buf, 0, sizeof(buf));
-
- buf.cmd.size = sizeof(buf);
- buf.cmd.cookie = 0xdeafbeefdeaddead;
- buf.cmd.flags = KDBUS_MATCH_REPLACE;
- buf.item.size = sizeof(buf.item);
- buf.item.type = KDBUS_ITEM_ID_REMOVE;
- buf.item.chg.id = KDBUS_MATCH_ID_ANY;
-
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
-
- /* create 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
- id = conn->id;
-
- /* 1st connection should _not_ have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret != 0);
-
- /* remove 2nd connection */
- kdbus_conn_free(conn);
-
- /* 1st connection should _now_ have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_ID_REMOVE);
- ASSERT_RETURN(msg->items[0].id_change.id == id);
-
- return TEST_OK;
-}
-
-int kdbus_test_match_name_add(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_name_change chg;
- } item;
- char name[64];
- } buf;
- struct kdbus_msg *msg;
- char *name;
- int ret;
-
- name = "foo.bla.blaz";
-
- /* install the match rule */
- memset(&buf, 0, sizeof(buf));
- buf.item.type = KDBUS_ITEM_NAME_ADD;
- buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
- buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
- strncpy(buf.name, name, sizeof(buf.name) - 1);
- buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
- buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
-
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* acquire the name */
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* we should have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_ADD);
- ASSERT_RETURN(msg->items[0].name_change.old_id.id == 0);
- ASSERT_RETURN(msg->items[0].name_change.new_id.id == env->conn->id);
- ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
-
- return TEST_OK;
-}
-
-int kdbus_test_match_name_remove(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_name_change chg;
- } item;
- char name[64];
- } buf;
- struct kdbus_msg *msg;
- char *name;
- int ret;
-
- name = "foo.bla.blaz";
-
- /* acquire the name */
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* install the match rule */
- memset(&buf, 0, sizeof(buf));
- buf.item.type = KDBUS_ITEM_NAME_REMOVE;
- buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
- buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
- strncpy(buf.name, name, sizeof(buf.name) - 1);
- buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
- buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
-
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* release the name again */
- kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == 0);
-
- /* we should have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_REMOVE);
- ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id);
- ASSERT_RETURN(msg->items[0].name_change.new_id.id == 0);
- ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
-
- return TEST_OK;
-}
-
-int kdbus_test_match_name_change(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- struct kdbus_notify_name_change chg;
- } item;
- char name[64];
- } buf;
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- uint64_t flags;
- char *name = "foo.bla.baz";
- int ret;
-
- /* acquire the name */
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* install the match rule */
- memset(&buf, 0, sizeof(buf));
- buf.item.type = KDBUS_ITEM_NAME_CHANGE;
- buf.item.chg.old_id.id = KDBUS_MATCH_ID_ANY;
- buf.item.chg.new_id.id = KDBUS_MATCH_ID_ANY;
- strncpy(buf.name, name, sizeof(buf.name) - 1);
- buf.item.size = sizeof(buf.item) + strlen(buf.name) + 1;
- buf.cmd.size = sizeof(buf.cmd) + buf.item.size;
-
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* allow the new connection to own the same name */
- /* queue the 2nd connection as waiting owner */
- flags = KDBUS_NAME_QUEUE;
- ret = kdbus_name_acquire(conn, name, &flags);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE);
-
- /* release name from 1st connection */
- ret = kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == 0);
-
- /* we should have received a notification */
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- ASSERT_RETURN(msg->items[0].type == KDBUS_ITEM_NAME_CHANGE);
- ASSERT_RETURN(msg->items[0].name_change.old_id.id == env->conn->id);
- ASSERT_RETURN(msg->items[0].name_change.new_id.id == conn->id);
- ASSERT_RETURN(strcmp(msg->items[0].name_change.name, name) == 0);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-static int send_bloom_filter(const struct kdbus_conn *conn,
- uint64_t cookie,
- const uint8_t *filter,
- size_t filter_size,
- uint64_t filter_generation)
-{
- struct kdbus_cmd_send cmd = {};
- struct kdbus_msg *msg;
- struct kdbus_item *item;
- uint64_t size;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) + filter_size;
-
- msg = alloca(size);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = conn->id;
- msg->dst_id = KDBUS_DST_ID_BROADCAST;
- msg->flags = KDBUS_MSG_SIGNAL;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
- msg->cookie = cookie;
-
- item = msg->items;
- item->type = KDBUS_ITEM_BLOOM_FILTER;
- item->size = KDBUS_ITEM_SIZE(sizeof(struct kdbus_bloom_filter)) +
- filter_size;
-
- item->bloom_filter.generation = filter_generation;
- memcpy(item->bloom_filter.data, filter, filter_size);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(conn->fd, &cmd);
- if (ret < 0) {
- kdbus_printf("error sending message: %d (%m)\n", ret);
- return ret;
- }
-
- return 0;
-}
-
-int kdbus_test_match_bloom(struct kdbus_test_env *env)
-{
- struct {
- struct kdbus_cmd_match cmd;
- struct {
- uint64_t size;
- uint64_t type;
- uint8_t data_gen0[64];
- uint8_t data_gen1[64];
- } item;
- } buf;
- struct kdbus_conn *conn;
- struct kdbus_msg *msg;
- uint64_t cookie = 0xf000f00f;
- uint8_t filter[64];
- int ret;
-
- /* install the match rule */
- memset(&buf, 0, sizeof(buf));
- buf.cmd.size = sizeof(buf);
-
- buf.item.size = sizeof(buf.item);
- buf.item.type = KDBUS_ITEM_BLOOM_MASK;
- buf.item.data_gen0[0] = 0x55;
- buf.item.data_gen0[63] = 0x80;
-
- buf.item.data_gen1[1] = 0xaa;
- buf.item.data_gen1[9] = 0x02;
-
- ret = kdbus_cmd_match_add(env->conn->fd, &buf.cmd);
- ASSERT_RETURN(ret == 0);
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* a message with a 0'ed out filter must not reach the other peer */
- memset(filter, 0, sizeof(filter));
- ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /* now set the filter to the connection's mask and expect success */
- filter[0] = 0x55;
- filter[63] = 0x80;
- ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- /* broaden the filter and try again. this should also succeed. */
- filter[0] = 0xff;
- filter[8] = 0xff;
- filter[63] = 0xff;
- ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 0);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- /* the same filter must not match against bloom generation 1 */
- ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /* set a different filter and try again */
- filter[1] = 0xaa;
- filter[9] = 0x02;
- ret = send_bloom_filter(conn, ++cookie, filter, sizeof(filter), 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(env->conn, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-message.c b/tools/testing/selftests/kdbus/test-message.c
deleted file mode 100644
index 33d349bb2..000000000
--- a/tools/testing/selftests/kdbus/test-message.c
+++ /dev/null
@@ -1,736 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <time.h>
-#include <stdbool.h>
-#include <sys/eventfd.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-/* maximum number of queued messages from the same individual user */
-#define KDBUS_CONN_MAX_MSGS 256
-
-/* maximum number of queued requests waiting for a reply */
-#define KDBUS_CONN_MAX_REQUESTS_PENDING 128
-
-/* maximum message payload size */
-#define KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE (2 * 1024UL * 1024UL)
-
-int kdbus_test_message_basic(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- struct kdbus_conn *sender;
- struct kdbus_msg *msg;
- uint64_t cookie = 0x1234abcd5678eeff;
- uint64_t offset;
- int ret;
-
- sender = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(sender != NULL);
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- ret = kdbus_add_match_empty(conn);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_empty(sender);
- ASSERT_RETURN(ret == 0);
-
- /* send over 1st connection */
- ret = kdbus_msg_send(sender, NULL, cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- /* Make sure that we do get our own broadcasts */
- ret = kdbus_msg_recv(sender, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- /* ... and receive on the 2nd */
- ret = kdbus_msg_recv_poll(conn, 100, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- /* Msgs that expect a reply must have timeout and cookie */
- ret = kdbus_msg_send(sender, NULL, 0, KDBUS_MSG_EXPECT_REPLY,
- 0, 0, conn->id);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* Faked replies with a valid reply cookie are rejected */
- ret = kdbus_msg_send_reply(conn, time(NULL) ^ cookie, sender->id);
- ASSERT_RETURN(ret == -EBADSLT);
-
- ret = kdbus_free(conn, offset);
- ASSERT_RETURN(ret == 0);
-
- kdbus_conn_free(sender);
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-static int msg_recv_prio(struct kdbus_conn *conn,
- int64_t requested_prio,
- int64_t expected_prio)
-{
- struct kdbus_cmd_recv recv = {
- .size = sizeof(recv),
- .flags = KDBUS_RECV_USE_PRIORITY,
- .priority = requested_prio,
- };
- struct kdbus_msg *msg;
- int ret;
-
- ret = kdbus_cmd_recv(conn->fd, &recv);
- if (ret < 0) {
- kdbus_printf("error receiving message: %d (%m)\n", -errno);
- return ret;
- }
-
- msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
- kdbus_msg_dump(conn, msg);
-
- if (msg->priority != expected_prio) {
- kdbus_printf("expected message prio %lld, got %lld\n",
- (unsigned long long) expected_prio,
- (unsigned long long) msg->priority);
- return -EINVAL;
- }
-
- kdbus_msg_free(msg);
- ret = kdbus_free(conn, recv.msg.offset);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int kdbus_test_message_prio(struct kdbus_test_env *env)
-{
- struct kdbus_conn *a, *b;
- uint64_t cookie = 0;
-
- a = kdbus_hello(env->buspath, 0, NULL, 0);
- b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(a && b);
-
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 25, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -600, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -35, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -100, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 20, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -15, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -150, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, 10, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -800, a->id) == 0);
- ASSERT_RETURN(kdbus_msg_send(b, NULL, ++cookie, 0, 0, -10, a->id) == 0);
-
- ASSERT_RETURN(msg_recv_prio(a, -200, -800) == 0);
- ASSERT_RETURN(msg_recv_prio(a, -100, -800) == 0);
- ASSERT_RETURN(msg_recv_prio(a, -400, -600) == 0);
- ASSERT_RETURN(msg_recv_prio(a, -400, -600) == -EAGAIN);
- ASSERT_RETURN(msg_recv_prio(a, 10, -150) == 0);
- ASSERT_RETURN(msg_recv_prio(a, 10, -100) == 0);
-
- kdbus_printf("--- get priority (all)\n");
- ASSERT_RETURN(kdbus_msg_recv(a, NULL, NULL) == 0);
-
- kdbus_conn_free(a);
- kdbus_conn_free(b);
-
- return TEST_OK;
-}
-
-static int kdbus_test_notify_kernel_quota(struct kdbus_test_env *env)
-{
- int ret;
- unsigned int i;
- struct kdbus_conn *conn;
- struct kdbus_conn *reader;
- struct kdbus_msg *msg = NULL;
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
-
- reader = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(reader);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- /* Register for ID signals */
- ret = kdbus_add_match_id(reader, 0x1, KDBUS_ITEM_ID_ADD,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_id(reader, 0x2, KDBUS_ITEM_ID_REMOVE,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- /* Each iteration two notifications: add and remove ID */
- for (i = 0; i < KDBUS_CONN_MAX_MSGS / 2; i++) {
- struct kdbus_conn *notifier;
-
- notifier = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(notifier);
-
- kdbus_conn_free(notifier);
- }
-
- /*
- * Now the reader queue is full with kernel notfications,
- * but as a user we still have room to push our messages.
- */
- ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0, 0, reader->id);
- ASSERT_RETURN(ret == 0);
-
- /* More ID kernel notifications that will be lost */
- kdbus_conn_free(conn);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- kdbus_conn_free(conn);
-
- /*
- * We lost only 3 packets since only signal msgs are
- * accounted. The connection ID add/remove notification
- */
- ret = kdbus_cmd_recv(reader->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS);
- ASSERT_RETURN(recv.dropped_msgs == 3);
-
- msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
- kdbus_msg_free(msg);
-
- /* Read our queue */
- for (i = 0; i < KDBUS_CONN_MAX_MSGS - 1; i++) {
- memset(&recv, 0, sizeof(recv));
- recv.size = sizeof(recv);
-
- ret = kdbus_cmd_recv(reader->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(!(recv.return_flags &
- KDBUS_RECV_RETURN_DROPPED_MSGS));
-
- msg = (struct kdbus_msg *)(reader->buf + recv.msg.offset);
- kdbus_msg_free(msg);
- }
-
- ret = kdbus_msg_recv(reader, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(reader, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- kdbus_conn_free(reader);
-
- return 0;
-}
-
-/* Return the number of message successfully sent */
-static int kdbus_fill_conn_queue(struct kdbus_conn *conn_src,
- uint64_t dst_id,
- unsigned int max_msgs)
-{
- unsigned int i;
- uint64_t cookie = 0;
- size_t size;
- struct kdbus_cmd_send cmd = {};
- struct kdbus_msg *msg;
- int ret;
-
- size = sizeof(struct kdbus_msg);
- msg = malloc(size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = conn_src->id;
- msg->dst_id = dst_id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- for (i = 0; i < max_msgs; i++) {
- msg->cookie = cookie++;
- ret = kdbus_cmd_send(conn_src->fd, &cmd);
- if (ret < 0)
- break;
- }
-
- free(msg);
-
- return i;
-}
-
-static int kdbus_test_activator_quota(struct kdbus_test_env *env)
-{
- int ret;
- unsigned int i;
- unsigned int activator_msgs_count = 0;
- uint64_t cookie = time(NULL);
- struct kdbus_conn *conn;
- struct kdbus_conn *sender;
- struct kdbus_conn *activator;
- struct kdbus_msg *msg;
- uint64_t flags;
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_policy_access access = {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = geteuid(),
- .access = KDBUS_POLICY_OWN,
- };
-
- activator = kdbus_hello_activator(env->buspath, "foo.test.activator",
- &access, 1);
- ASSERT_RETURN(activator);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- sender = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn || sender);
-
- ret = kdbus_list(sender, KDBUS_LIST_NAMES |
- KDBUS_LIST_UNIQUE |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED);
- ASSERT_RETURN(ret == 0);
-
- for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
- ret = kdbus_msg_send(sender, "foo.test.activator",
- cookie++, 0, 0, 0,
- KDBUS_DST_ID_NAME);
- if (ret < 0)
- break;
- activator_msgs_count++;
- }
-
- /* we must have at least sent one message */
- ASSERT_RETURN_VAL(i > 0, -errno);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- /* Good, activator queue is full now */
-
- /* ENXIO on direct send (activators can never be addressed by ID) */
- ret = kdbus_msg_send(conn, NULL, cookie++, 0, 0, 0, activator->id);
- ASSERT_RETURN(ret == -ENXIO);
-
- /* can't queue more */
- ret = kdbus_msg_send(conn, "foo.test.activator", cookie++,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- /* no match installed, so the broadcast will not inc dropped_msgs */
- ret = kdbus_msg_send(sender, NULL, cookie++, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- /* Check activator queue */
- ret = kdbus_cmd_recv(activator->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv.dropped_msgs == 0);
-
- activator_msgs_count--;
-
- msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
- kdbus_msg_free(msg);
-
-
- /* Stage 1) of test check the pool memory quota */
-
- /* Consume the connection pool memory */
- for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
- ret = kdbus_msg_send(sender, NULL,
- cookie++, 0, 0, 0, conn->id);
- if (ret < 0)
- break;
- }
-
- /* consume one message, so later at least one can be moved */
- memset(&recv, 0, sizeof(recv));
- recv.size = sizeof(recv);
- ret = kdbus_cmd_recv(conn->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv.dropped_msgs == 0);
- msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
- kdbus_msg_free(msg);
-
- /* Try to acquire the name now */
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
- ASSERT_RETURN(ret == 0);
-
- /* try to read messages and see if we have lost some */
- memset(&recv, 0, sizeof(recv));
- recv.size = sizeof(recv);
- ret = kdbus_cmd_recv(conn->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv.dropped_msgs != 0);
-
- /* number of dropped msgs < received ones (at least one was moved) */
- ASSERT_RETURN(recv.dropped_msgs < activator_msgs_count);
-
- /* Deduct the number of dropped msgs from the activator msgs */
- activator_msgs_count -= recv.dropped_msgs;
-
- msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
- kdbus_msg_free(msg);
-
- /*
- * Release the name and hand it back to activator, now
- * we should have 'activator_msgs_count' msgs again in
- * the activator queue
- */
- ret = kdbus_name_release(conn, "foo.test.activator");
- ASSERT_RETURN(ret == 0);
-
- /* make sure that we got our previous activator msgs */
- ret = kdbus_msg_recv(activator, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->src_id == sender->id);
-
- activator_msgs_count--;
-
- kdbus_msg_free(msg);
-
-
- /* Stage 2) of test check max message quota */
-
- /* Empty conn queue */
- for (i = 0; i < KDBUS_CONN_MAX_MSGS; i++) {
- ret = kdbus_msg_recv(conn, NULL, NULL);
- if (ret == -EAGAIN)
- break;
- }
-
- /* fill queue with max msgs quota */
- ret = kdbus_fill_conn_queue(sender, conn->id, KDBUS_CONN_MAX_MSGS);
- ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
-
- /* This one is lost but it is not accounted */
- ret = kdbus_msg_send(sender, NULL,
- cookie++, 0, 0, 0, conn->id);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- /* Acquire the name again */
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(conn, "foo.test.activator", &flags);
- ASSERT_RETURN(ret == 0);
-
- memset(&recv, 0, sizeof(recv));
- recv.size = sizeof(recv);
-
- /*
- * Try to read messages and make sure that we have lost all
- * the activator messages due to quota checks. Our queue is
- * already full.
- */
- ret = kdbus_cmd_recv(conn->fd, &recv);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv.dropped_msgs == activator_msgs_count);
-
- msg = (struct kdbus_msg *)(activator->buf + recv.msg.offset);
- kdbus_msg_free(msg);
-
- kdbus_conn_free(sender);
- kdbus_conn_free(conn);
- kdbus_conn_free(activator);
-
- return 0;
-}
-
-static int kdbus_test_expected_reply_quota(struct kdbus_test_env *env)
-{
- int ret;
- unsigned int i, n;
- unsigned int count;
- uint64_t cookie = 0x1234abcd5678eeff;
- struct kdbus_conn *conn;
- struct kdbus_conn *connections[9];
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- for (i = 0; i < 9; i++) {
- connections[i] = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(connections[i]);
- }
-
- count = 0;
- /* Send 16 messages to 8 different connections */
- for (i = 0; i < 8; i++) {
- for (n = 0; n < 16; n++) {
- ret = kdbus_msg_send(conn, NULL, cookie++,
- KDBUS_MSG_EXPECT_REPLY,
- 100000000ULL, 0,
- connections[i]->id);
- if (ret < 0)
- break;
-
- count++;
- }
- }
-
- /*
- * We should have queued at least
- * KDBUS_CONN_MAX_REQUESTS_PENDING method call
- */
- ASSERT_RETURN(count == KDBUS_CONN_MAX_REQUESTS_PENDING);
-
- /*
- * Now try to send a message to the last connection,
- * if we have reached KDBUS_CONN_MAX_REQUESTS_PENDING
- * no further requests are allowed
- */
- ret = kdbus_msg_send(conn, NULL, cookie++, KDBUS_MSG_EXPECT_REPLY,
- 1000000000ULL, 0, connections[8]->id);
- ASSERT_RETURN(ret == -EMLINK);
-
- for (i = 0; i < 9; i++)
- kdbus_conn_free(connections[i]);
-
- kdbus_conn_free(conn);
-
- return 0;
-}
-
-int kdbus_test_pool_quota(struct kdbus_test_env *env)
-{
- struct kdbus_conn *a, *b, *c;
- struct kdbus_cmd_send cmd = {};
- struct kdbus_item *item;
- struct kdbus_msg *recv_msg;
- struct kdbus_msg *msg;
- uint64_t cookie = time(NULL);
- uint64_t size;
- unsigned int i;
- char *payload;
- int ret;
-
- /* just a guard */
- if (POOL_SIZE <= KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE ||
- POOL_SIZE % KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE != 0)
- return 0;
-
- payload = calloc(KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE, sizeof(char));
- ASSERT_RETURN_VAL(payload, -ENOMEM);
-
- a = kdbus_hello(env->buspath, 0, NULL, 0);
- b = kdbus_hello(env->buspath, 0, NULL, 0);
- c = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(a && b && c);
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- msg = malloc(size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = a->id;
- msg->dst_id = c->id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- item = msg->items;
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = (uintptr_t)payload;
- item->vec.size = KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
- item = KDBUS_ITEM_NEXT(item);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- /*
- * Send 2097248 bytes, a user is only allowed to get 33% of half of
- * the free space of the pool, the already used space is
- * accounted as free space
- */
- size += KDBUS_MSG_MAX_PAYLOAD_VEC_SIZE;
- for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
- msg->cookie = cookie++;
-
- ret = kdbus_cmd_send(a->fd, &cmd);
- ASSERT_RETURN_VAL(ret == 0, ret);
- }
-
- /* Try to get more than 33% */
- msg->cookie = cookie++;
- ret = kdbus_cmd_send(a->fd, &cmd);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- /* We still can pass small messages */
- ret = kdbus_msg_send(b, NULL, cookie++, 0, 0, 0, c->id);
- ASSERT_RETURN(ret == 0);
-
- for (i = size; i < (POOL_SIZE / 2 / 3); i += size) {
- ret = kdbus_msg_recv(c, &recv_msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv_msg->src_id == a->id);
-
- kdbus_msg_free(recv_msg);
- }
-
- ret = kdbus_msg_recv(c, &recv_msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(recv_msg->src_id == b->id);
-
- kdbus_msg_free(recv_msg);
-
- ret = kdbus_msg_recv(c, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- free(msg);
- free(payload);
-
- kdbus_conn_free(c);
- kdbus_conn_free(b);
- kdbus_conn_free(a);
-
- return 0;
-}
-
-int kdbus_test_message_quota(struct kdbus_test_env *env)
-{
- struct kdbus_conn *a, *b;
- uint64_t cookie = 0;
- int ret;
- int i;
-
- ret = kdbus_test_activator_quota(env);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_test_notify_kernel_quota(env);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_test_pool_quota(env);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_test_expected_reply_quota(env);
- ASSERT_RETURN(ret == 0);
-
- a = kdbus_hello(env->buspath, 0, NULL, 0);
- b = kdbus_hello(env->buspath, 0, NULL, 0);
-
- ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS);
- ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
-
- ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- for (i = 0; i < KDBUS_CONN_MAX_MSGS; ++i) {
- ret = kdbus_msg_recv(a, NULL, NULL);
- ASSERT_RETURN(ret == 0);
- }
-
- ret = kdbus_msg_recv(a, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- ret = kdbus_fill_conn_queue(b, a->id, KDBUS_CONN_MAX_MSGS + 1);
- ASSERT_RETURN(ret == KDBUS_CONN_MAX_MSGS);
-
- ret = kdbus_msg_send(b, NULL, ++cookie, 0, 0, 0, a->id);
- ASSERT_RETURN(ret == -ENOBUFS);
-
- kdbus_conn_free(a);
- kdbus_conn_free(b);
-
- return TEST_OK;
-}
-
-int kdbus_test_memory_access(struct kdbus_test_env *env)
-{
- struct kdbus_conn *a, *b;
- struct kdbus_cmd_send cmd = {};
- struct kdbus_item *item;
- struct kdbus_msg *msg;
- uint64_t test_addr = 0;
- char line[256];
- uint64_t size;
- FILE *f;
- int ret;
-
- /*
- * Search in /proc/kallsyms for the address of a kernel symbol that
- * should always be there, regardless of the config. Use that address
- * in a PAYLOAD_VEC item and make sure it's inaccessible.
- */
-
- f = fopen("/proc/kallsyms", "r");
- if (!f)
- return TEST_SKIP;
-
- while (fgets(line, sizeof(line), f)) {
- char *s = line;
-
- if (!strsep(&s, " "))
- continue;
-
- if (!strsep(&s, " "))
- continue;
-
- if (!strncmp(s, "mutex_lock", 10)) {
- test_addr = strtoull(line, NULL, 16);
- break;
- }
- }
-
- fclose(f);
-
- if (!test_addr)
- return TEST_SKIP;
-
- a = kdbus_hello(env->buspath, 0, NULL, 0);
- b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(a && b);
-
- size = sizeof(struct kdbus_msg);
- size += KDBUS_ITEM_SIZE(sizeof(struct kdbus_vec));
-
- msg = alloca(size);
- ASSERT_RETURN_VAL(msg, -ENOMEM);
-
- memset(msg, 0, size);
- msg->size = size;
- msg->src_id = a->id;
- msg->dst_id = b->id;
- msg->payload_type = KDBUS_PAYLOAD_DBUS;
-
- item = msg->items;
- item->type = KDBUS_ITEM_PAYLOAD_VEC;
- item->size = KDBUS_ITEM_HEADER_SIZE + sizeof(struct kdbus_vec);
- item->vec.address = test_addr;
- item->vec.size = sizeof(void*);
- item = KDBUS_ITEM_NEXT(item);
-
- cmd.size = sizeof(cmd);
- cmd.msg_address = (uintptr_t)msg;
-
- ret = kdbus_cmd_send(a->fd, &cmd);
- ASSERT_RETURN(ret == -EFAULT);
-
- kdbus_conn_free(b);
- kdbus_conn_free(a);
-
- return 0;
-}
diff --git a/tools/testing/selftests/kdbus/test-metadata-ns.c b/tools/testing/selftests/kdbus/test-metadata-ns.c
deleted file mode 100644
index 1f6edc090..000000000
--- a/tools/testing/selftests/kdbus/test-metadata-ns.c
+++ /dev/null
@@ -1,500 +0,0 @@
-/*
- * Test metadata in new namespaces. Even if our tests can run
- * in a namespaced setup, this test is necessary so we can inspect
- * metadata on the same kdbusfs but between multiple namespaces
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <sched.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/prctl.h>
-#include <sys/eventfd.h>
-#include <sys/syscall.h>
-#include <sys/capability.h>
-#include <linux/sched.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-static const struct kdbus_creds privileged_creds = {};
-
-static const struct kdbus_creds unmapped_creds = {
- .uid = UNPRIV_UID,
- .euid = UNPRIV_UID,
- .suid = UNPRIV_UID,
- .fsuid = UNPRIV_UID,
- .gid = UNPRIV_GID,
- .egid = UNPRIV_GID,
- .sgid = UNPRIV_GID,
- .fsgid = UNPRIV_GID,
-};
-
-static const struct kdbus_pids unmapped_pids = {};
-
-/* Get only the first item */
-static struct kdbus_item *kdbus_get_item(struct kdbus_msg *msg,
- uint64_t type)
-{
- struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, msg, items)
- if (item->type == type)
- return item;
-
- return NULL;
-}
-
-static int kdbus_match_kdbus_creds(struct kdbus_msg *msg,
- const struct kdbus_creds *expected_creds)
-{
- struct kdbus_item *item;
-
- item = kdbus_get_item(msg, KDBUS_ITEM_CREDS);
- ASSERT_RETURN(item);
-
- ASSERT_RETURN(memcmp(&item->creds, expected_creds,
- sizeof(struct kdbus_creds)) == 0);
-
- return 0;
-}
-
-static int kdbus_match_kdbus_pids(struct kdbus_msg *msg,
- const struct kdbus_pids *expected_pids)
-{
- struct kdbus_item *item;
-
- item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
- ASSERT_RETURN(item);
-
- ASSERT_RETURN(memcmp(&item->pids, expected_pids,
- sizeof(struct kdbus_pids)) == 0);
-
- return 0;
-}
-
-static int __kdbus_clone_userns_test(const char *bus,
- struct kdbus_conn *conn,
- uint64_t grandpa_pid,
- int signal_fd)
-{
- int clone_ret;
- int ret;
- struct kdbus_msg *msg = NULL;
- const struct kdbus_item *item;
- uint64_t cookie = time(NULL) ^ 0xdeadbeef;
- struct kdbus_conn *unpriv_conn = NULL;
- struct kdbus_pids parent_pids = {
- .pid = getppid(),
- .tid = getppid(),
- .ppid = grandpa_pid,
- };
-
- ret = drop_privileges(UNPRIV_UID, UNPRIV_GID);
- ASSERT_EXIT(ret == 0);
-
- unpriv_conn = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(unpriv_conn);
-
- ret = kdbus_add_match_empty(unpriv_conn);
- ASSERT_EXIT(ret == 0);
-
- /*
- * ping privileged connection from this new unprivileged
- * one
- */
-
- ret = kdbus_msg_send(unpriv_conn, NULL, cookie, 0, 0,
- 0, conn->id);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Since we just dropped privileges, the dumpable flag
- * was just cleared which makes the /proc/$clone_child/uid_map
- * to be owned by root, hence any userns uid mapping will fail
- * with -EPERM since the mapping will be done by uid 65534.
- *
- * To avoid this set the dumpable flag again which makes
- * procfs update the /proc/$clone_child/ inodes owner to 65534.
- *
- * Using this we will be able write to /proc/$clone_child/uid_map
- * as uid 65534 and map the uid 65534 to 0 inside the user namespace.
- */
- ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
- ASSERT_EXIT(ret == 0);
-
- /* Make child privileged in its new userns and run tests */
-
- ret = RUN_CLONE_CHILD(&clone_ret,
- SIGCHLD | CLONE_NEWUSER | CLONE_NEWPID,
- ({ 0; /* Clone setup, nothing */ }),
- ({
- eventfd_t event_status = 0;
- struct kdbus_conn *userns_conn;
-
- /* ping connection from the new user namespace */
- userns_conn = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(userns_conn);
-
- ret = kdbus_add_match_empty(userns_conn);
- ASSERT_EXIT(ret == 0);
-
- cookie++;
- ret = kdbus_msg_send(userns_conn, NULL, cookie,
- 0, 0, 0, conn->id);
- ASSERT_EXIT(ret == 0);
-
- /* Parent did send */
- ret = eventfd_read(signal_fd, &event_status);
- ASSERT_RETURN(ret >= 0 && event_status == 1);
-
- /*
- * Receive from privileged connection
- */
- kdbus_printf("Privileged → unprivileged/privileged "
- "in its userns "
- "(different userns and pidns):\n");
- ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL);
- ASSERT_EXIT(ret == 0);
- ASSERT_EXIT(msg->dst_id == userns_conn->id);
-
- item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
- ASSERT_EXIT(item);
-
- /* uid/gid not mapped, so we have unpriv cached creds */
- ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Diffent pid namepsaces. This is the child pidns
- * so it should not see its parent kdbus_pids
- */
- ret = kdbus_match_kdbus_pids(msg, &unmapped_pids);
- ASSERT_EXIT(ret == 0);
-
- kdbus_msg_free(msg);
-
-
- /*
- * Receive broadcast from privileged connection
- */
- kdbus_printf("Privileged → unprivileged/privileged "
- "in its userns "
- "(different userns and pidns):\n");
- ret = kdbus_msg_recv_poll(userns_conn, 300, &msg, NULL);
- ASSERT_EXIT(ret == 0);
- ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST);
-
- item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
- ASSERT_EXIT(item);
-
- /* uid/gid not mapped, so we have unpriv cached creds */
- ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Diffent pid namepsaces. This is the child pidns
- * so it should not see its parent kdbus_pids
- */
- ret = kdbus_match_kdbus_pids(msg, &unmapped_pids);
- ASSERT_EXIT(ret == 0);
-
- kdbus_msg_free(msg);
-
- kdbus_conn_free(userns_conn);
- }),
- ({
- /* Parent setup map child uid/gid */
- ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1");
- ASSERT_EXIT(ret == 0);
- }),
- ({ 0; }));
- /* Unprivileged was not able to create user namespace */
- if (clone_ret == -EPERM) {
- kdbus_printf("-- CLONE_NEWUSER TEST Failed for "
- "uid: %u\n -- Make sure that your kernel "
- "do not allow CLONE_NEWUSER for "
- "unprivileged users\n", UNPRIV_UID);
- ret = 0;
- goto out;
- }
-
- ASSERT_EXIT(ret == 0);
-
-
- /*
- * Receive from privileged connection
- */
- kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n");
- ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL);
-
- ASSERT_EXIT(ret == 0);
- ASSERT_EXIT(msg->dst_id == unpriv_conn->id);
-
- /* will get the privileged creds */
- ret = kdbus_match_kdbus_creds(msg, &privileged_creds);
- ASSERT_EXIT(ret == 0);
-
- /* Same pidns so will get the kdbus_pids */
- ret = kdbus_match_kdbus_pids(msg, &parent_pids);
- ASSERT_RETURN(ret == 0);
-
- kdbus_msg_free(msg);
-
-
- /*
- * Receive broadcast from privileged connection
- */
- kdbus_printf("\nPrivileged → unprivileged (same namespaces):\n");
- ret = kdbus_msg_recv_poll(unpriv_conn, 300, &msg, NULL);
-
- ASSERT_EXIT(ret == 0);
- ASSERT_EXIT(msg->dst_id == KDBUS_DST_ID_BROADCAST);
-
- /* will get the privileged creds */
- ret = kdbus_match_kdbus_creds(msg, &privileged_creds);
- ASSERT_EXIT(ret == 0);
-
- ret = kdbus_match_kdbus_pids(msg, &parent_pids);
- ASSERT_RETURN(ret == 0);
-
- kdbus_msg_free(msg);
-
-out:
- kdbus_conn_free(unpriv_conn);
-
- return ret;
-}
-
-static int kdbus_clone_userns_test(const char *bus,
- struct kdbus_conn *conn)
-{
- int ret, status, efd;
- pid_t pid, ppid;
- uint64_t unpriv_conn_id, userns_conn_id;
- struct kdbus_msg *msg;
- const struct kdbus_item *item;
- struct kdbus_pids expected_pids;
- struct kdbus_conn *monitor;
-
- kdbus_printf("STARTING TEST 'metadata-ns'.\n");
-
- monitor = kdbus_hello(bus, KDBUS_HELLO_MONITOR, NULL, 0);
- ASSERT_EXIT(monitor);
-
- /*
- * parent will signal to child that is in its
- * userns to read its queue
- */
- efd = eventfd(0, EFD_CLOEXEC);
- ASSERT_RETURN_VAL(efd >= 0, efd);
-
- ppid = getppid();
-
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, -errno);
-
- if (pid == 0) {
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- ASSERT_EXIT_VAL(ret == 0, -errno);
-
- ret = __kdbus_clone_userns_test(bus, conn, ppid, efd);
- _exit(ret);
- }
-
-
- /* Phase 1) privileged receives from unprivileged */
-
- /*
- * Receive from the unprivileged child
- */
- kdbus_printf("\nUnprivileged → privileged (same namespaces):\n");
- ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- unpriv_conn_id = msg->src_id;
-
- /* Unprivileged user */
- ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
- ASSERT_RETURN(ret == 0);
-
- /* Set the expected creds_pids */
- expected_pids = (struct kdbus_pids) {
- .pid = pid,
- .tid = pid,
- .ppid = getpid(),
- };
- ret = kdbus_match_kdbus_pids(msg, &expected_pids);
- ASSERT_RETURN(ret == 0);
-
- kdbus_msg_free(msg);
-
-
- /*
- * Receive from the unprivileged that is in his own
- * userns and pidns
- */
-
- kdbus_printf("\nUnprivileged/privileged in its userns → privileged "
- "(different userns and pidns)\n");
- ret = kdbus_msg_recv_poll(conn, 300, &msg, NULL);
- if (ret == -ETIMEDOUT)
- /* perhaps unprivileged userns is not allowed */
- goto wait;
-
- ASSERT_RETURN(ret == 0);
-
- userns_conn_id = msg->src_id;
-
- item = kdbus_get_item(msg, KDBUS_ITEM_CAPS);
- ASSERT_RETURN(item);
-
- /*
- * Compare received items, creds must be translated into
- * the receiver user namespace, so the user is unprivileged
- */
- ret = kdbus_match_kdbus_creds(msg, &unmapped_creds);
- ASSERT_RETURN(ret == 0);
-
- /*
- * We should have the kdbus_pids since we are the parent
- * pidns
- */
- item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
- ASSERT_RETURN(item);
-
- ASSERT_RETURN(memcmp(&item->pids, &unmapped_pids,
- sizeof(struct kdbus_pids)) != 0);
-
- /*
- * Parent pid of the unprivileged/privileged in its userns
- * is the unprivileged child pid that was forked here.
- */
- ASSERT_RETURN((uint64_t)pid == item->pids.ppid);
-
- kdbus_msg_free(msg);
-
-
- /* Phase 2) Privileged connection sends now 3 packets */
-
- /*
- * Sending to unprivileged connections a unicast
- */
- ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
- 0, unpriv_conn_id);
- ASSERT_RETURN(ret == 0);
-
- /* signal to child that is in its userns */
- ret = eventfd_write(efd, 1);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Sending to unprivileged/privilged in its userns
- * connections a unicast
- */
- ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
- 0, userns_conn_id);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Sending to unprivileged connections a broadcast
- */
- ret = kdbus_msg_send(conn, NULL, 0xdeadbeef, 0, 0,
- 0, KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
-
-wait:
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN(ret >= 0);
-
- ASSERT_RETURN(WIFEXITED(status))
- ASSERT_RETURN(!WEXITSTATUS(status));
-
- /* Dump monitor queue */
- kdbus_printf("\n\nMonitor queue:\n");
- for (;;) {
- ret = kdbus_msg_recv_poll(monitor, 100, &msg, NULL);
- if (ret < 0)
- break;
-
- if (msg->payload_type == KDBUS_PAYLOAD_DBUS) {
- /*
- * Parent pidns should see all the
- * pids
- */
- item = kdbus_get_item(msg, KDBUS_ITEM_PIDS);
- ASSERT_RETURN(item);
-
- ASSERT_RETURN(item->pids.pid != 0 &&
- item->pids.tid != 0 &&
- item->pids.ppid != 0);
- }
-
- kdbus_msg_free(msg);
- }
-
- kdbus_conn_free(monitor);
- close(efd);
-
- return 0;
-}
-
-int kdbus_test_metadata_ns(struct kdbus_test_env *env)
-{
- int ret;
- struct kdbus_conn *holder, *conn;
- struct kdbus_policy_access policy_access = {
- /* Allow world so we can inspect metadata in namespace */
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = geteuid(),
- .access = KDBUS_POLICY_TALK,
- };
-
- /*
- * We require user-namespaces and all uids/gids
- * should be mapped (we can just require the necessary ones)
- */
- if (!config_user_ns_is_enabled() ||
- !all_uids_gids_are_mapped())
- return TEST_SKIP;
-
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, CAP_SYS_ADMIN, -1);
- ASSERT_RETURN(ret >= 0);
-
- /* no enough privileges, SKIP test */
- if (!ret)
- return TEST_SKIP;
-
- holder = kdbus_hello_registrar(env->buspath, "com.example.metadata",
- &policy_access, 1,
- KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(holder);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- ret = kdbus_add_match_empty(conn);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(conn, "com.example.metadata", NULL);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_clone_userns_test(env->buspath, conn);
- ASSERT_RETURN(ret == 0);
-
- kdbus_conn_free(holder);
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-monitor.c b/tools/testing/selftests/kdbus/test-monitor.c
deleted file mode 100644
index e00d738a3..000000000
--- a/tools/testing/selftests/kdbus/test-monitor.c
+++ /dev/null
@@ -1,176 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <errno.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/time.h>
-#include <sys/mman.h>
-#include <sys/capability.h>
-#include <sys/wait.h>
-
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-int kdbus_test_monitor(struct kdbus_test_env *env)
-{
- struct kdbus_conn *monitor, *conn;
- unsigned int cookie = 0xdeadbeef;
- struct kdbus_msg *msg;
- uint64_t offset = 0;
- int ret;
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- /* add matches to make sure the monitor do not trigger an item add or
- * remove on connect and disconnect, respectively.
- */
- ret = kdbus_add_match_id(conn, 0x1, KDBUS_ITEM_ID_ADD,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_add_match_id(conn, 0x2, KDBUS_ITEM_ID_REMOVE,
- KDBUS_MATCH_ID_ANY);
- ASSERT_RETURN(ret == 0);
-
- /* register a monitor */
- monitor = kdbus_hello(env->buspath, KDBUS_HELLO_MONITOR, NULL, 0);
- ASSERT_RETURN(monitor);
-
- /* make sure we did not receive a monitor connect notification */
- ret = kdbus_msg_recv(conn, &msg, &offset);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /* check that a monitor cannot acquire a name */
- ret = kdbus_name_acquire(monitor, "foo.bar.baz", NULL);
- ASSERT_RETURN(ret == -EOPNOTSUPP);
-
- ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0, conn->id);
- ASSERT_RETURN(ret == 0);
-
- /* the recipient should have gotten the message */
- ret = kdbus_msg_recv(conn, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
- kdbus_msg_free(msg);
- kdbus_free(conn, offset);
-
- /* and so should the monitor */
- ret = kdbus_msg_recv(monitor, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- kdbus_msg_free(msg);
- kdbus_free(monitor, offset);
-
- /* Installing matches for monitors must fais must fail */
- ret = kdbus_add_match_empty(monitor);
- ASSERT_RETURN(ret == -EOPNOTSUPP);
-
- cookie++;
- ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- /* The monitor should get the message. */
- ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- kdbus_msg_free(msg);
- kdbus_free(monitor, offset);
-
- /*
- * Since we are the only monitor, update the attach flags
- * and tell we are not interessted in attach flags recv
- */
-
- ret = kdbus_conn_update_attach_flags(monitor,
- _KDBUS_ATTACH_ALL,
- 0);
- ASSERT_RETURN(ret == 0);
-
- cookie++;
- ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP);
- ASSERT_RETURN(ret == 0);
-
- kdbus_msg_free(msg);
- kdbus_free(monitor, offset);
-
- /*
- * Now we are interested in KDBUS_ITEM_TIMESTAMP and
- * KDBUS_ITEM_CREDS
- */
- ret = kdbus_conn_update_attach_flags(monitor,
- _KDBUS_ATTACH_ALL,
- KDBUS_ATTACH_TIMESTAMP |
- KDBUS_ATTACH_CREDS);
- ASSERT_RETURN(ret == 0);
-
- cookie++;
- ret = kdbus_msg_send(env->conn, NULL, cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv_poll(monitor, 100, &msg, &offset);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == cookie);
-
- ret = kdbus_item_in_message(msg, KDBUS_ITEM_TIMESTAMP);
- ASSERT_RETURN(ret == 1);
-
- ret = kdbus_item_in_message(msg, KDBUS_ITEM_CREDS);
- ASSERT_RETURN(ret == 1);
-
- /* the KDBUS_ITEM_PID_COMM was not requested */
- ret = kdbus_item_in_message(msg, KDBUS_ITEM_PID_COMM);
- ASSERT_RETURN(ret == 0);
-
- kdbus_msg_free(msg);
- kdbus_free(monitor, offset);
-
- kdbus_conn_free(monitor);
- /* make sure we did not receive a monitor disconnect notification */
- ret = kdbus_msg_recv(conn, &msg, &offset);
- ASSERT_RETURN(ret == -EAGAIN);
-
- kdbus_conn_free(conn);
-
- /* Make sure that monitor as unprivileged is not allowed */
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(ret >= 0);
-
- if (ret && all_uids_gids_are_mapped()) {
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({
- monitor = kdbus_hello(env->buspath,
- KDBUS_HELLO_MONITOR,
- NULL, 0);
- ASSERT_EXIT(!monitor && errno == EPERM);
-
- _exit(EXIT_SUCCESS);
- }),
- ({ 0; }));
- ASSERT_RETURN(ret == 0);
- }
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-names.c b/tools/testing/selftests/kdbus/test-names.c
deleted file mode 100644
index e400dc86a..000000000
--- a/tools/testing/selftests/kdbus/test-names.c
+++ /dev/null
@@ -1,272 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <limits.h>
-#include <getopt.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-#include "kdbus-test.h"
-
-struct test_name {
- const char *name;
- __u64 owner_id;
- __u64 flags;
-};
-
-static bool conn_test_names(const struct kdbus_conn *conn,
- const struct test_name *tests,
- unsigned int n_tests)
-{
- struct kdbus_cmd_list cmd_list = {};
- struct kdbus_info *name, *list;
- unsigned int i;
- int ret;
-
- cmd_list.size = sizeof(cmd_list);
- cmd_list.flags = KDBUS_LIST_NAMES |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED;
-
- ret = kdbus_cmd_list(conn->fd, &cmd_list);
- ASSERT_RETURN(ret == 0);
-
- list = (struct kdbus_info *)(conn->buf + cmd_list.offset);
-
- for (i = 0; i < n_tests; i++) {
- const struct test_name *t = tests + i;
- bool found = false;
-
- KDBUS_FOREACH(name, list, cmd_list.list_size) {
- struct kdbus_item *item;
-
- KDBUS_ITEM_FOREACH(item, name, items) {
- if (item->type != KDBUS_ITEM_OWNED_NAME ||
- strcmp(item->name.name, t->name) != 0)
- continue;
-
- if (t->owner_id == name->id &&
- t->flags == item->name.flags) {
- found = true;
- break;
- }
- }
- }
-
- if (!found)
- return false;
- }
-
- return true;
-}
-
-static bool conn_is_name_primary_owner(const struct kdbus_conn *conn,
- const char *needle)
-{
- struct test_name t = {
- .name = needle,
- .owner_id = conn->id,
- .flags = KDBUS_NAME_PRIMARY,
- };
-
- return conn_test_names(conn, &t, 1);
-}
-
-int kdbus_test_name_basic(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- char *name, *dot_name, *invalid_name, *wildcard_name;
- int ret;
-
- name = "foo.bla.blaz";
- dot_name = ".bla.blaz";
- invalid_name = "foo";
- wildcard_name = "foo.bla.bl.*";
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* acquire name "foo.bar.xxx" name */
- ret = kdbus_name_acquire(conn, "foo.bar.xxx", NULL);
- ASSERT_RETURN(ret == 0);
-
- /* Name is not valid, must fail */
- ret = kdbus_name_acquire(env->conn, dot_name, NULL);
- ASSERT_RETURN(ret == -EINVAL);
-
- ret = kdbus_name_acquire(env->conn, invalid_name, NULL);
- ASSERT_RETURN(ret == -EINVAL);
-
- ret = kdbus_name_acquire(env->conn, wildcard_name, NULL);
- ASSERT_RETURN(ret == -EINVAL);
-
- /* check that we can acquire a name */
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = conn_is_name_primary_owner(env->conn, name);
- ASSERT_RETURN(ret == true);
-
- /* ... and release it again */
- ret = kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == 0);
-
- ret = conn_is_name_primary_owner(env->conn, name);
- ASSERT_RETURN(ret == false);
-
- /* check that we can't release it again */
- ret = kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == -ESRCH);
-
- /* check that we can't release a name that we don't own */
- ret = kdbus_name_release(env->conn, "foo.bar.xxx");
- ASSERT_RETURN(ret == -EADDRINUSE);
-
- /* Name is not valid, must fail */
- ret = kdbus_name_release(env->conn, dot_name);
- ASSERT_RETURN(ret == -ESRCH);
-
- ret = kdbus_name_release(env->conn, invalid_name);
- ASSERT_RETURN(ret == -ESRCH);
-
- ret = kdbus_name_release(env->conn, wildcard_name);
- ASSERT_RETURN(ret == -ESRCH);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-int kdbus_test_name_conflict(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- char *name;
- int ret;
-
- name = "foo.bla.blaz";
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* allow the new connection to own the same name */
- /* acquire name from the 1st connection */
- ret = kdbus_name_acquire(env->conn, name, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = conn_is_name_primary_owner(env->conn, name);
- ASSERT_RETURN(ret == true);
-
- /* check that we also can't acquire it again from the 2nd connection */
- ret = kdbus_name_acquire(conn, name, NULL);
- ASSERT_RETURN(ret == -EEXIST);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-int kdbus_test_name_queue(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- struct test_name t[2];
- const char *name;
- uint64_t flags;
- int ret;
-
- name = "foo.bla.blaz";
-
- flags = 0;
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* allow the new connection to own the same name */
- /* acquire name from the 1st connection */
- ret = kdbus_name_acquire(env->conn, name, &flags);
- ASSERT_RETURN(ret == 0);
-
- ret = conn_is_name_primary_owner(env->conn, name);
- ASSERT_RETURN(ret == true);
-
- /* queue the 2nd connection as waiting owner */
- flags = KDBUS_NAME_QUEUE;
- ret = kdbus_name_acquire(conn, name, &flags);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(flags & KDBUS_NAME_IN_QUEUE);
-
- t[0].name = name;
- t[0].owner_id = env->conn->id;
- t[0].flags = KDBUS_NAME_PRIMARY;
- t[1].name = name;
- t[1].owner_id = conn->id;
- t[1].flags = KDBUS_NAME_QUEUE | KDBUS_NAME_IN_QUEUE;
- ret = conn_test_names(conn, t, 2);
- ASSERT_RETURN(ret == true);
-
- /* release name from 1st connection */
- ret = kdbus_name_release(env->conn, name);
- ASSERT_RETURN(ret == 0);
-
- /* now the name should be owned by the 2nd connection */
- t[0].name = name;
- t[0].owner_id = conn->id;
- t[0].flags = KDBUS_NAME_PRIMARY | KDBUS_NAME_QUEUE;
- ret = conn_test_names(conn, t, 1);
- ASSERT_RETURN(ret == true);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
-
-int kdbus_test_name_takeover(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn;
- struct test_name t;
- const char *name;
- uint64_t flags;
- int ret;
-
- name = "foo.bla.blaz";
-
- flags = KDBUS_NAME_ALLOW_REPLACEMENT;
-
- /* create a 2nd connection */
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn != NULL);
-
- /* acquire name for 1st connection */
- ret = kdbus_name_acquire(env->conn, name, &flags);
- ASSERT_RETURN(ret == 0);
-
- t.name = name;
- t.owner_id = env->conn->id;
- t.flags = KDBUS_NAME_ALLOW_REPLACEMENT | KDBUS_NAME_PRIMARY;
- ret = conn_test_names(conn, &t, 1);
- ASSERT_RETURN(ret == true);
-
- /* now steal name with 2nd connection */
- flags = KDBUS_NAME_REPLACE_EXISTING;
- ret = kdbus_name_acquire(conn, name, &flags);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(flags & KDBUS_NAME_ACQUIRED);
-
- ret = conn_is_name_primary_owner(conn, name);
- ASSERT_RETURN(ret == true);
-
- kdbus_conn_free(conn);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-policy-ns.c b/tools/testing/selftests/kdbus/test-policy-ns.c
deleted file mode 100644
index 3437012f9..000000000
--- a/tools/testing/selftests/kdbus/test-policy-ns.c
+++ /dev/null
@@ -1,632 +0,0 @@
-/*
- * Test metadata and policies in new namespaces. Even if our tests
- * can run in a namespaced setup, this test is necessary so we can
- * inspect policies on the same kdbusfs but between multiple
- * namespaces.
- *
- * Copyright (C) 2014-2015 Djalal Harouni
- *
- * kdbus is free software; you can redistribute it and/or modify it under
- * the terms of the GNU Lesser General Public License as published by the
- * Free Software Foundation; either version 2.1 of the License, or (at
- * your option) any later version.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <pthread.h>
-#include <sched.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <errno.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/prctl.h>
-#include <sys/eventfd.h>
-#include <sys/syscall.h>
-#include <sys/capability.h>
-#include <linux/sched.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-#define MAX_CONN 64
-#define POLICY_NAME "foo.test.policy-test"
-
-#define KDBUS_CONN_MAX_MSGS_PER_USER 16
-
-/**
- * Note: this test can be used to inspect policy_db->talk_access_hash
- *
- * The purpose of these tests:
- * 1) Check KDBUS_POLICY_TALK
- * 2) Check the cache state: kdbus_policy_db->talk_access_hash
- * Should be extended
- */
-
-/**
- * Check a list of connections against conn_db[0]
- * conn_db[0] will own the name "foo.test.policy-test" and the
- * policy holder connection for this name will update the policy
- * entries, so different use cases can be tested.
- */
-static struct kdbus_conn **conn_db;
-
-static void *kdbus_recv_echo(void *ptr)
-{
- int ret;
- struct kdbus_conn *conn = ptr;
-
- ret = kdbus_msg_recv_poll(conn, 200, NULL, NULL);
-
- return (void *)(long)ret;
-}
-
-/* Trigger kdbus_policy_set() */
-static int kdbus_set_policy_talk(struct kdbus_conn *conn,
- const char *name,
- uid_t id, unsigned int type)
-{
- int ret;
- struct kdbus_policy_access access = {
- .type = type,
- .id = id,
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(conn, name, &access, 1);
- ASSERT_RETURN(ret == 0);
-
- return TEST_OK;
-}
-
-/* return TEST_OK or TEST_ERR on failure */
-static int kdbus_register_same_activator(char *bus, const char *name,
- struct kdbus_conn **c)
-{
- int ret;
- struct kdbus_conn *activator;
-
- activator = kdbus_hello_activator(bus, name, NULL, 0);
- if (activator) {
- *c = activator;
- fprintf(stderr, "--- error was able to register name twice '%s'.\n",
- name);
- return TEST_ERR;
- }
-
- ret = -errno;
- /* -EEXIST means test succeeded */
- if (ret == -EEXIST)
- return TEST_OK;
-
- return TEST_ERR;
-}
-
-/* return TEST_OK or TEST_ERR on failure */
-static int kdbus_register_policy_holder(char *bus, const char *name,
- struct kdbus_conn **conn)
-{
- struct kdbus_conn *c;
- struct kdbus_policy_access access[2];
-
- access[0].type = KDBUS_POLICY_ACCESS_USER;
- access[0].access = KDBUS_POLICY_OWN;
- access[0].id = geteuid();
-
- access[1].type = KDBUS_POLICY_ACCESS_WORLD;
- access[1].access = KDBUS_POLICY_TALK;
- access[1].id = geteuid();
-
- c = kdbus_hello_registrar(bus, name, access, 2,
- KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(c);
-
- *conn = c;
-
- return TEST_OK;
-}
-
-/**
- * Create new threads for receiving from multiple senders,
- * The 'conn_db' will be populated by newly created connections.
- * Caller should free all allocated connections.
- *
- * return 0 on success, negative errno on failure.
- */
-static int kdbus_recv_in_threads(const char *bus, const char *name,
- struct kdbus_conn **conn_db)
-{
- int ret;
- bool pool_full = false;
- unsigned int sent_packets = 0;
- unsigned int lost_packets = 0;
- unsigned int i, tid;
- unsigned long dst_id;
- unsigned long cookie = 1;
- unsigned int thread_nr = MAX_CONN - 1;
- pthread_t thread_id[MAX_CONN - 1] = {'\0'};
-
- dst_id = name ? KDBUS_DST_ID_NAME : conn_db[0]->id;
-
- for (tid = 0, i = 1; tid < thread_nr; tid++, i++) {
- ret = pthread_create(&thread_id[tid], NULL,
- kdbus_recv_echo, (void *)conn_db[0]);
- if (ret < 0) {
- ret = -errno;
- kdbus_printf("error pthread_create: %d (%m)\n",
- ret);
- break;
- }
-
- /* just free before re-using */
- kdbus_conn_free(conn_db[i]);
- conn_db[i] = NULL;
-
- /* We need to create connections here */
- conn_db[i] = kdbus_hello(bus, 0, NULL, 0);
- if (!conn_db[i]) {
- ret = -errno;
- break;
- }
-
- ret = kdbus_add_match_empty(conn_db[i]);
- if (ret < 0)
- break;
-
- ret = kdbus_msg_send(conn_db[i], name, cookie++,
- 0, 0, 0, dst_id);
- if (ret < 0) {
- /*
- * Receivers are not reading their messages,
- * not scheduled ?!
- *
- * So set the pool full here, perhaps the
- * connection pool or queue was full, later
- * recheck receivers errors
- */
- if (ret == -ENOBUFS || ret == -EXFULL)
- pool_full = true;
- break;
- }
-
- sent_packets++;
- }
-
- for (tid = 0; tid < thread_nr; tid++) {
- int thread_ret = 0;
-
- if (thread_id[tid]) {
- pthread_join(thread_id[tid], (void *)&thread_ret);
- if (thread_ret < 0) {
- /* Update only if send did not fail */
- if (ret == 0)
- ret = thread_ret;
-
- lost_packets++;
- }
- }
- }
-
- /*
- * When sending if we did fail with -ENOBUFS or -EXFULL
- * then we should have set lost_packet and we should at
- * least have sent_packets set to KDBUS_CONN_MAX_MSGS_PER_USER
- */
- if (pool_full) {
- ASSERT_RETURN(lost_packets > 0);
-
- /*
- * We should at least send KDBUS_CONN_MAX_MSGS_PER_USER
- *
- * For every send operation we create a thread to
- * recv the packet, so we keep the queue clean
- */
- ASSERT_RETURN(sent_packets >= KDBUS_CONN_MAX_MSGS_PER_USER);
-
- /*
- * Set ret to zero since we only failed due to
- * the receiving threads that have not been
- * scheduled
- */
- ret = 0;
- }
-
- return ret;
-}
-
-/* Return: TEST_OK or TEST_ERR on failure */
-static int kdbus_normal_test(const char *bus, const char *name,
- struct kdbus_conn **conn_db)
-{
- int ret;
-
- ret = kdbus_recv_in_threads(bus, name, conn_db);
- ASSERT_RETURN(ret >= 0);
-
- return TEST_OK;
-}
-
-static int kdbus_fork_test_by_id(const char *bus,
- struct kdbus_conn **conn_db,
- int parent_status, int child_status)
-{
- int ret;
- pid_t pid;
- uint64_t cookie = 0x9876ecba;
- struct kdbus_msg *msg = NULL;
- uint64_t offset = 0;
- int status = 0;
-
- /*
- * If the child_status is not EXIT_SUCCESS, then we expect
- * that sending from the child will fail, thus receiving
- * from parent must error with -ETIMEDOUT, and vice versa.
- */
- bool parent_timedout = !!child_status;
- bool child_timedout = !!parent_status;
-
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- struct kdbus_conn *conn_src;
-
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- ASSERT_EXIT(ret == 0);
-
- ret = drop_privileges(65534, 65534);
- ASSERT_EXIT(ret == 0);
-
- conn_src = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(conn_src);
-
- ret = kdbus_add_match_empty(conn_src);
- ASSERT_EXIT(ret == 0);
-
- /*
- * child_status is always checked against send
- * operations, in case it fails always return
- * EXIT_FAILURE.
- */
- ret = kdbus_msg_send(conn_src, NULL, cookie,
- 0, 0, 0, conn_db[0]->id);
- ASSERT_EXIT(ret == child_status);
-
- ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL);
-
- kdbus_conn_free(conn_src);
-
- /*
- * Child kdbus_msg_recv_poll() should timeout since
- * the parent_status was set to a non EXIT_SUCCESS
- * value.
- */
- if (child_timedout)
- _exit(ret == -ETIMEDOUT ? EXIT_SUCCESS : EXIT_FAILURE);
-
- _exit(ret == 0 ? EXIT_SUCCESS : EXIT_FAILURE);
- }
-
- ret = kdbus_msg_recv_poll(conn_db[0], 100, &msg, &offset);
- /*
- * If parent_timedout is set then this should fail with
- * -ETIMEDOUT since the child_status was set to a non
- * EXIT_SUCCESS value. Otherwise, assume
- * that kdbus_msg_recv_poll() has succeeded.
- */
- if (parent_timedout) {
- ASSERT_RETURN_VAL(ret == -ETIMEDOUT, TEST_ERR);
-
- /* timedout no need to continue, we don't have the
- * child connection ID, so just terminate. */
- goto out;
- } else {
- ASSERT_RETURN_VAL(ret == 0, ret);
- }
-
- ret = kdbus_msg_send(conn_db[0], NULL, ++cookie,
- 0, 0, 0, msg->src_id);
- /*
- * parent_status is checked against send operations,
- * on failures always return TEST_ERR.
- */
- ASSERT_RETURN_VAL(ret == parent_status, TEST_ERR);
-
- kdbus_msg_free(msg);
- kdbus_free(conn_db[0], offset);
-
-out:
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-/*
- * Return: TEST_OK, TEST_ERR or TEST_SKIP
- * we return TEST_OK only if the children return with the expected
- * 'expected_status' that is specified as an argument.
- */
-static int kdbus_fork_test(const char *bus, const char *name,
- struct kdbus_conn **conn_db, int expected_status)
-{
- pid_t pid;
- int ret = 0;
- int status = 0;
-
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- ASSERT_EXIT(ret == 0);
-
- ret = drop_privileges(65534, 65534);
- ASSERT_EXIT(ret == 0);
-
- ret = kdbus_recv_in_threads(bus, name, conn_db);
- _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE);
- }
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN(ret >= 0);
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-/* Return EXIT_SUCCESS, EXIT_FAILURE or negative errno */
-static int __kdbus_clone_userns_test(const char *bus,
- const char *name,
- struct kdbus_conn **conn_db,
- int expected_status)
-{
- int efd;
- pid_t pid;
- int ret = 0;
- unsigned int uid = 65534;
- int status;
-
- ret = drop_privileges(uid, uid);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- /*
- * Since we just dropped privileges, the dumpable flag was just
- * cleared which makes the /proc/$clone_child/uid_map to be
- * owned by root, hence any userns uid mapping will fail with
- * -EPERM since the mapping will be done by uid 65534.
- *
- * To avoid this set the dumpable flag again which makes procfs
- * update the /proc/$clone_child/ inodes owner to 65534.
- *
- * Using this we will be able write to /proc/$clone_child/uid_map
- * as uid 65534 and map the uid 65534 to 0 inside the user
- * namespace.
- */
- ret = prctl(PR_SET_DUMPABLE, SUID_DUMP_USER);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- /* sync parent/child */
- efd = eventfd(0, EFD_CLOEXEC);
- ASSERT_RETURN_VAL(efd >= 0, efd);
-
- pid = syscall(__NR_clone, SIGCHLD|CLONE_NEWUSER, NULL);
- if (pid < 0) {
- ret = -errno;
- kdbus_printf("error clone: %d (%m)\n", ret);
- /*
- * Normal user not allowed to create userns,
- * so nothing to worry about ?
- */
- if (ret == -EPERM) {
- kdbus_printf("-- CLONE_NEWUSER TEST Failed for uid: %u\n"
- "-- Make sure that your kernel do not allow "
- "CLONE_NEWUSER for unprivileged users\n"
- "-- Upstream Commit: "
- "https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/?id=5eaf563e\n",
- uid);
- ret = 0;
- }
-
- return ret;
- }
-
- if (pid == 0) {
- struct kdbus_conn *conn_src;
- eventfd_t event_status = 0;
-
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- ASSERT_EXIT(ret == 0);
-
- ret = eventfd_read(efd, &event_status);
- ASSERT_EXIT(ret >= 0 && event_status == 1);
-
- /* ping connection from the new user namespace */
- conn_src = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(conn_src);
-
- ret = kdbus_add_match_empty(conn_src);
- ASSERT_EXIT(ret == 0);
-
- ret = kdbus_msg_send(conn_src, name, 0xabcd1234,
- 0, 0, 0, KDBUS_DST_ID_NAME);
- kdbus_conn_free(conn_src);
-
- _exit(ret == expected_status ? EXIT_SUCCESS : EXIT_FAILURE);
- }
-
- ret = userns_map_uid_gid(pid, "0 65534 1", "0 65534 1");
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- /* Tell child we are ready */
- ret = eventfd_write(efd, 1);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- close(efd);
-
- return status == EXIT_SUCCESS ? TEST_OK : TEST_ERR;
-}
-
-static int kdbus_clone_userns_test(const char *bus,
- const char *name,
- struct kdbus_conn **conn_db,
- int expected_status)
-{
- pid_t pid;
- int ret = 0;
- int status;
-
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, -errno);
-
- if (pid == 0) {
- ret = prctl(PR_SET_PDEATHSIG, SIGKILL);
- if (ret < 0)
- _exit(EXIT_FAILURE);
-
- ret = __kdbus_clone_userns_test(bus, name, conn_db,
- expected_status);
- _exit(ret);
- }
-
- /*
- * Receive in the original (root privileged) user namespace,
- * must fail with -ETIMEDOUT.
- */
- ret = kdbus_msg_recv_poll(conn_db[0], 100, NULL, NULL);
- ASSERT_RETURN_VAL(ret == -ETIMEDOUT, ret);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-int kdbus_test_policy_ns(struct kdbus_test_env *env)
-{
- int i;
- int ret;
- struct kdbus_conn *activator = NULL;
- struct kdbus_conn *policy_holder = NULL;
- char *bus = env->buspath;
-
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(ret >= 0);
-
- /* no enough privileges, SKIP test */
- if (!ret)
- return TEST_SKIP;
-
- /* we require user-namespaces */
- if (access("/proc/self/uid_map", F_OK) != 0)
- return TEST_SKIP;
-
- /* uids/gids must be mapped */
- if (!all_uids_gids_are_mapped())
- return TEST_SKIP;
-
- conn_db = calloc(MAX_CONN, sizeof(struct kdbus_conn *));
- ASSERT_RETURN(conn_db);
-
- memset(conn_db, 0, MAX_CONN * sizeof(struct kdbus_conn *));
-
- conn_db[0] = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_RETURN(conn_db[0]);
-
- ret = kdbus_add_match_empty(conn_db[0]);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
- ASSERT_EXIT(ret == 0);
-
- ret = kdbus_register_policy_holder(bus, POLICY_NAME,
- &policy_holder);
- ASSERT_RETURN(ret == 0);
-
- /* Try to register the same name with an activator */
- ret = kdbus_register_same_activator(bus, POLICY_NAME,
- &activator);
- ASSERT_RETURN(ret == 0);
-
- /* Acquire POLICY_NAME */
- ret = kdbus_name_acquire(conn_db[0], POLICY_NAME, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_normal_test(bus, POLICY_NAME, conn_db);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_list(conn_db[0], KDBUS_LIST_NAMES |
- KDBUS_LIST_UNIQUE |
- KDBUS_LIST_ACTIVATORS |
- KDBUS_LIST_QUEUED);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, EXIT_SUCCESS);
- ASSERT_RETURN(ret == 0);
-
- /*
- * children connections are able to talk to conn_db[0] since
- * current POLICY_NAME TALK type is KDBUS_POLICY_ACCESS_WORLD,
- * so expect EXIT_SUCCESS when sending from child. However,
- * since the child's connection does not own any well-known
- * name, The parent connection conn_db[0] should fail with
- * -EPERM but since it is a privileged bus user the TALK is
- * allowed.
- */
- ret = kdbus_fork_test_by_id(bus, conn_db,
- EXIT_SUCCESS, EXIT_SUCCESS);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Connections that can talk are perhaps being destroyed now.
- * Restrict the policy and purge cache entries where the
- * conn_db[0] is the destination.
- *
- * Now only connections with uid == 0 are allowed to talk.
- */
- ret = kdbus_set_policy_talk(policy_holder, POLICY_NAME,
- geteuid(), KDBUS_POLICY_ACCESS_USER);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Testing connections (FORK+DROP) again:
- * After setting the policy re-check connections
- * we expect the children to fail with -EPERM
- */
- ret = kdbus_fork_test(bus, POLICY_NAME, conn_db, -EPERM);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Now expect that both parent and child to fail.
- *
- * Child should fail with -EPERM since we just restricted
- * the POLICY_NAME TALK to uid 0 and its uid is 65534.
- *
- * Since the parent's connection will timeout when receiving
- * from the child, we never continue. FWIW just put -EPERM.
- */
- ret = kdbus_fork_test_by_id(bus, conn_db, -EPERM, -EPERM);
- ASSERT_EXIT(ret == 0);
-
- /* Check if the name can be reached in a new userns */
- ret = kdbus_clone_userns_test(bus, POLICY_NAME, conn_db, -EPERM);
- ASSERT_RETURN(ret == 0);
-
- for (i = 0; i < MAX_CONN; i++)
- kdbus_conn_free(conn_db[i]);
-
- kdbus_conn_free(activator);
- kdbus_conn_free(policy_holder);
-
- free(conn_db);
-
- return ret;
-}
diff --git a/tools/testing/selftests/kdbus/test-policy-priv.c b/tools/testing/selftests/kdbus/test-policy-priv.c
deleted file mode 100644
index 0208638a7..000000000
--- a/tools/testing/selftests/kdbus/test-policy-priv.c
+++ /dev/null
@@ -1,1285 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
-#include <time.h>
-#include <sys/capability.h>
-#include <sys/eventfd.h>
-#include <sys/wait.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-static int test_policy_priv_by_id(const char *bus,
- struct kdbus_conn *conn_dst,
- bool drop_second_user,
- int parent_status,
- int child_status)
-{
- int ret = 0;
- uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
-
- ASSERT_RETURN(conn_dst);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, bus, ({
- ret = kdbus_msg_send(unpriv, NULL,
- expected_cookie, 0, 0, 0,
- conn_dst->id);
- ASSERT_EXIT(ret == child_status);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_dst, 300, NULL, NULL);
- ASSERT_RETURN(ret == parent_status);
-
- return 0;
-}
-
-static int test_policy_priv_by_broadcast(const char *bus,
- struct kdbus_conn *conn_dst,
- int drop_second_user,
- int parent_status,
- int child_status)
-{
- int efd;
- int ret = 0;
- eventfd_t event_status = 0;
- struct kdbus_msg *msg = NULL;
- uid_t second_uid = UNPRIV_UID;
- gid_t second_gid = UNPRIV_GID;
- struct kdbus_conn *child_2 = conn_dst;
- uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
-
- /* Drop to another unprivileged user other than UNPRIV_UID */
- if (drop_second_user == DROP_OTHER_UNPRIV) {
- second_uid = UNPRIV_UID - 1;
- second_gid = UNPRIV_GID - 1;
- }
-
- /* child will signal parent to send broadcast */
- efd = eventfd(0, EFD_CLOEXEC);
- ASSERT_RETURN_VAL(efd >= 0, efd);
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
- struct kdbus_conn *child;
-
- child = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(child);
-
- ret = kdbus_add_match_empty(child);
- ASSERT_EXIT(ret == 0);
-
- /* signal parent */
- ret = eventfd_write(efd, 1);
- ASSERT_EXIT(ret == 0);
-
- /* Use a little bit high time */
- ret = kdbus_msg_recv_poll(child, 500, &msg, NULL);
- ASSERT_EXIT(ret == child_status);
-
- /*
- * If we expect the child to get the broadcast
- * message, then check the received cookie.
- */
- if (ret == 0) {
- ASSERT_EXIT(expected_cookie == msg->cookie);
- }
-
- /* Use expected_cookie since 'msg' might be NULL */
- ret = kdbus_msg_send(child, NULL, expected_cookie + 1,
- 0, 0, 0, KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == 0);
-
- kdbus_msg_free(msg);
- kdbus_conn_free(child);
- }),
- ({
- if (drop_second_user == DO_NOT_DROP) {
- ASSERT_RETURN(child_2);
-
- ret = eventfd_read(efd, &event_status);
- ASSERT_RETURN(ret >= 0 && event_status == 1);
-
- ret = kdbus_msg_send(child_2, NULL,
- expected_cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- /* drop own broadcast */
- ret = kdbus_msg_recv(child_2, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->src_id == child_2->id);
- kdbus_msg_free(msg);
-
- /* Use a little bit high time */
- ret = kdbus_msg_recv_poll(child_2, 1000,
- &msg, NULL);
- ASSERT_RETURN(ret == parent_status);
-
- /*
- * Check returned cookie in case we expect
- * success.
- */
- if (ret == 0) {
- ASSERT_RETURN(msg->cookie ==
- expected_cookie + 1);
- }
-
- kdbus_msg_free(msg);
- } else {
- /*
- * Two unprivileged users will try to
- * communicate using broadcast.
- */
- ret = RUN_UNPRIVILEGED(second_uid, second_gid, ({
- child_2 = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_EXIT(child_2);
-
- ret = kdbus_add_match_empty(child_2);
- ASSERT_EXIT(ret == 0);
-
- ret = eventfd_read(efd, &event_status);
- ASSERT_EXIT(ret >= 0 && event_status == 1);
-
- ret = kdbus_msg_send(child_2, NULL,
- expected_cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == 0);
-
- /* drop own broadcast */
- ret = kdbus_msg_recv(child_2, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->src_id == child_2->id);
- kdbus_msg_free(msg);
-
- /* Use a little bit high time */
- ret = kdbus_msg_recv_poll(child_2, 1000,
- &msg, NULL);
- ASSERT_EXIT(ret == parent_status);
-
- /*
- * Check returned cookie in case we expect
- * success.
- */
- if (ret == 0) {
- ASSERT_EXIT(msg->cookie ==
- expected_cookie + 1);
- }
-
- kdbus_msg_free(msg);
- kdbus_conn_free(child_2);
- }),
- ({ 0; }));
- ASSERT_RETURN(ret == 0);
- }
- }));
- ASSERT_RETURN(ret == 0);
-
- close(efd);
-
- return ret;
-}
-
-static void nosig(int sig)
-{
-}
-
-static int test_priv_before_policy_upload(struct kdbus_test_env *env)
-{
- int ret = 0;
- struct kdbus_conn *conn;
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- /*
- * Make sure unprivileged bus user cannot acquire names
- * before registring any policy holder.
- */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret < 0);
- }));
- ASSERT_RETURN(ret == 0);
-
- /*
- * Make sure unprivileged bus users cannot talk by default
- * to privileged ones, unless a policy holder that allows
- * this was uploaded.
- */
-
- ret = test_policy_priv_by_id(env->buspath, conn, false,
- -ETIMEDOUT, -EPERM);
- ASSERT_RETURN(ret == 0);
-
- /* Activate matching for a privileged connection */
- ret = kdbus_add_match_empty(conn);
- ASSERT_RETURN(ret == 0);
-
- /*
- * First make sure that BROADCAST with msg flag
- * KDBUS_MSG_EXPECT_REPLY will fail with -ENOTUNIQ
- */
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, NULL, 0xdeadbeef,
- KDBUS_MSG_EXPECT_REPLY,
- 5000000000ULL, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == -ENOTUNIQ);
- }));
- ASSERT_RETURN(ret == 0);
-
- /*
- * Test broadcast with a privileged connection.
- *
- * The first unprivileged receiver should not get the
- * broadcast message sent by the privileged connection,
- * since there is no a TALK policy that allows the
- * unprivileged to TALK to the privileged connection. It
- * will fail with -ETIMEDOUT
- *
- * Then second case:
- * The privileged connection should get the broadcast
- * message from the unprivileged one. Since the receiver is
- * a privileged bus user and it has default TALK access to
- * all connections it will receive those.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, conn,
- DO_NOT_DROP,
- 0, -ETIMEDOUT);
- ASSERT_RETURN(ret == 0);
-
-
- /*
- * Test broadcast with two unprivileged connections running
- * under the same user.
- *
- * Both connections should succeed.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, NULL,
- DROP_SAME_UNPRIV, 0, 0);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Test broadcast with two unprivileged connections running
- * under different users.
- *
- * Both connections will fail with -ETIMEDOUT.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, NULL,
- DROP_OTHER_UNPRIV,
- -ETIMEDOUT, -ETIMEDOUT);
- ASSERT_RETURN(ret == 0);
-
- kdbus_conn_free(conn);
-
- return ret;
-}
-
-static int test_broadcast_after_policy_upload(struct kdbus_test_env *env)
-{
- int ret;
- int efd;
- eventfd_t event_status = 0;
- struct kdbus_msg *msg = NULL;
- struct kdbus_conn *owner_a, *owner_b;
- struct kdbus_conn *holder_a, *holder_b;
- struct kdbus_policy_access access = {};
- uint64_t expected_cookie = time(NULL) ^ 0xdeadbeef;
-
- owner_a = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(owner_a);
-
- ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure unprivileged bus users cannot talk by default
- * to privileged ones, unless a policy holder that allows
- * this was uploaded.
- */
-
- ++expected_cookie;
- ret = test_policy_priv_by_id(env->buspath, owner_a, false,
- -ETIMEDOUT, -EPERM);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Make sure that privileged won't receive broadcasts unless
- * it installs a match. It will fail with -ETIMEDOUT
- *
- * At same time check that the unprivileged connection will
- * not receive the broadcast message from the privileged one
- * since the privileged one owns a name with a restricted
- * policy TALK (actually the TALK policy is still not
- * registered so we fail by default), thus the unprivileged
- * receiver is not able to TALK to that name.
- */
-
- /* Activate matching for a privileged connection */
- ret = kdbus_add_match_empty(owner_a);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Redo the previous test. The privileged conn owner_a is
- * able to TALK to any connection so it will receive the
- * broadcast message now.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, owner_a,
- DO_NOT_DROP,
- 0, -ETIMEDOUT);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Test that broadcast between two unprivileged users running
- * under the same user still succeed.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, NULL,
- DROP_SAME_UNPRIV, 0, 0);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Test broadcast with two unprivileged connections running
- * under different users.
- *
- * Both connections will fail with -ETIMEDOUT.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, NULL,
- DROP_OTHER_UNPRIV,
- -ETIMEDOUT, -ETIMEDOUT);
- ASSERT_RETURN(ret == 0);
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = geteuid(),
- .access = KDBUS_POLICY_OWN,
- };
-
- holder_a = kdbus_hello_registrar(env->buspath,
- "com.example.broadcastA",
- &access, 1,
- KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(holder_a);
-
- holder_b = kdbus_hello_registrar(env->buspath,
- "com.example.broadcastB",
- &access, 1,
- KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(holder_b);
-
- /* Free connections and their received messages and restart */
- kdbus_conn_free(owner_a);
-
- owner_a = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(owner_a);
-
- /* Activate matching for a privileged connection */
- ret = kdbus_add_match_empty(owner_a);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_name_acquire(owner_a, "com.example.broadcastA", NULL);
- ASSERT_EXIT(ret >= 0);
-
- owner_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(owner_b);
-
- ret = kdbus_name_acquire(owner_b, "com.example.broadcastB", NULL);
- ASSERT_EXIT(ret >= 0);
-
- /* Activate matching for a privileged connection */
- ret = kdbus_add_match_empty(owner_b);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Test that even if "com.example.broadcastA" and
- * "com.example.broadcastB" do have a TALK access by default
- * they are able to signal each other using broadcast due to
- * the fact they are privileged connections, they receive
- * all broadcasts if the match allows it.
- */
-
- ++expected_cookie;
- ret = kdbus_msg_send(owner_a, NULL, expected_cookie, 0,
- 0, 0, KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv_poll(owner_a, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- /* Check src ID */
- ASSERT_RETURN(msg->src_id == owner_a->id);
-
- kdbus_msg_free(msg);
-
- ret = kdbus_msg_recv_poll(owner_b, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0);
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- /* Check src ID */
- ASSERT_RETURN(msg->src_id == owner_a->id);
-
- kdbus_msg_free(msg);
-
- /* Release name "com.example.broadcastB" */
-
- ret = kdbus_name_release(owner_b, "com.example.broadcastB");
- ASSERT_EXIT(ret >= 0);
-
- /* KDBUS_POLICY_OWN for unprivileged connections */
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = geteuid(),
- .access = KDBUS_POLICY_OWN,
- };
-
- /* Update the policy so unprivileged will own the name */
-
- ret = kdbus_conn_update_policy(holder_b,
- "com.example.broadcastB",
- &access, 1);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Send broadcasts from an unprivileged connection that
- * owns a name "com.example.broadcastB".
- *
- * We'll have four destinations here:
- *
- * 1) destination owner_a: privileged connection that owns
- * "com.example.broadcastA". It will receive the broadcast
- * since it is a privileged has default TALK access to all
- * connections, and it is subscribed to the match.
- * Will succeed.
- *
- * owner_b: privileged connection (running under a different
- * uid) that do not own names, but with an empty broadcast
- * match, so it will receive broadcasts since it has default
- * TALK access to all connection.
- *
- * unpriv_a: unpriv connection that do not own any name.
- * It will receive the broadcast since it is running under
- * the same user of the one broadcasting and did install
- * matches. It should get the message.
- *
- * unpriv_b: unpriv connection is not interested in broadcast
- * messages, so it did not install broadcast matches. Should
- * fail with -ETIMEDOUT
- */
-
- ++expected_cookie;
- efd = eventfd(0, EFD_CLOEXEC);
- ASSERT_RETURN_VAL(efd >= 0, efd);
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_UID, ({
- struct kdbus_conn *unpriv_owner;
- struct kdbus_conn *unpriv_a, *unpriv_b;
-
- unpriv_owner = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_EXIT(unpriv_owner);
-
- unpriv_a = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_EXIT(unpriv_a);
-
- unpriv_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_EXIT(unpriv_b);
-
- ret = kdbus_name_acquire(unpriv_owner,
- "com.example.broadcastB",
- NULL);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_add_match_empty(unpriv_a);
- ASSERT_EXIT(ret == 0);
-
- /* Signal that we are doing broadcasts */
- ret = eventfd_write(efd, 1);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Do broadcast from a connection that owns the
- * names "com.example.broadcastB".
- */
- ret = kdbus_msg_send(unpriv_owner, NULL,
- expected_cookie,
- 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == 0);
-
- /*
- * Unprivileged connection running under the same
- * user. It should succeed.
- */
- ret = kdbus_msg_recv_poll(unpriv_a, 300, &msg, NULL);
- ASSERT_EXIT(ret == 0 && msg->cookie == expected_cookie);
-
- /*
- * Did not install matches, not interested in
- * broadcasts
- */
- ret = kdbus_msg_recv_poll(unpriv_b, 300, NULL, NULL);
- ASSERT_EXIT(ret == -ETIMEDOUT);
- }),
- ({
- ret = eventfd_read(efd, &event_status);
- ASSERT_RETURN(ret >= 0 && event_status == 1);
-
- /*
- * owner_a must fail with -ETIMEDOUT, since it owns
- * name "com.example.broadcastA" and its TALK
- * access is restriced.
- */
- ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* confirm the received cookie */
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- kdbus_msg_free(msg);
-
- /*
- * owner_b got the broadcast from an unprivileged
- * connection.
- */
- ret = kdbus_msg_recv_poll(owner_b, 300, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* confirm the received cookie */
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- kdbus_msg_free(msg);
-
- }));
- ASSERT_RETURN(ret == 0);
-
- close(efd);
-
- /*
- * Test broadcast with two unprivileged connections running
- * under different users.
- *
- * Both connections will fail with -ETIMEDOUT.
- */
-
- ret = test_policy_priv_by_broadcast(env->buspath, NULL,
- DROP_OTHER_UNPRIV,
- -ETIMEDOUT, -ETIMEDOUT);
- ASSERT_RETURN(ret == 0);
-
- /* Drop received broadcasts by privileged */
- ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL);
- ret = kdbus_msg_recv_poll(owner_a, 100, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(owner_a, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL);
- ret = kdbus_msg_recv_poll(owner_b, 100, NULL, NULL);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_recv(owner_b, NULL, NULL);
- ASSERT_RETURN(ret == -EAGAIN);
-
- /*
- * Perform last tests, allow others to talk to name
- * "com.example.broadcastA". So now receiving broadcasts
- * from it should succeed since the TALK policy allow it.
- */
-
- /* KDBUS_POLICY_OWN for unprivileged connections */
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = geteuid(),
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(holder_a,
- "com.example.broadcastA",
- &access, 1);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Unprivileged is able to TALK to "com.example.broadcastA"
- * now so it will receive its broadcasts
- */
- ret = test_policy_priv_by_broadcast(env->buspath, owner_a,
- DO_NOT_DROP, 0, 0);
- ASSERT_RETURN(ret == 0);
-
- ++expected_cookie;
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.broadcastB",
- NULL);
- ASSERT_EXIT(ret >= 0);
- ret = kdbus_msg_send(unpriv, NULL, expected_cookie,
- 0, 0, 0, KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == 0);
- }));
- ASSERT_RETURN(ret == 0);
-
- /* owner_a is privileged it will get the broadcast now. */
- ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* confirm the received cookie */
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- kdbus_msg_free(msg);
-
- /*
- * owner_a released name "com.example.broadcastA". It should
- * receive broadcasts since it is still privileged and has
- * the right match.
- *
- * Unprivileged connection will own a name and will try to
- * signal to the privileged connection.
- */
-
- ret = kdbus_name_release(owner_a, "com.example.broadcastA");
- ASSERT_EXIT(ret >= 0);
-
- ++expected_cookie;
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.broadcastB",
- NULL);
- ASSERT_EXIT(ret >= 0);
- ret = kdbus_msg_send(unpriv, NULL, expected_cookie,
- 0, 0, 0, KDBUS_DST_ID_BROADCAST);
- ASSERT_EXIT(ret == 0);
- }));
- ASSERT_RETURN(ret == 0);
-
- /* owner_a will get the broadcast now. */
- ret = kdbus_msg_recv_poll(owner_a, 300, &msg, NULL);
- ASSERT_RETURN(ret == 0);
-
- /* confirm the received cookie */
- ASSERT_RETURN(msg->cookie == expected_cookie);
-
- kdbus_msg_free(msg);
-
- kdbus_conn_free(owner_a);
- kdbus_conn_free(owner_b);
- kdbus_conn_free(holder_a);
- kdbus_conn_free(holder_b);
-
- return 0;
-}
-
-static int test_policy_priv(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn_a, *conn_b, *conn, *owner;
- struct kdbus_policy_access access, *acc;
- sigset_t sset;
- size_t num;
- int ret;
-
- /*
- * Make sure we have CAP_SETUID/SETGID so we can drop privileges
- */
-
- ret = test_is_capable(CAP_SETUID, CAP_SETGID, -1);
- ASSERT_RETURN(ret >= 0);
-
- if (!ret)
- return TEST_SKIP;
-
- /* make sure that uids and gids are mapped */
- if (!all_uids_gids_are_mapped())
- return TEST_SKIP;
-
- /*
- * Setup:
- * conn_a: policy holder for com.example.a
- * conn_b: name holder of com.example.b
- */
-
- signal(SIGUSR1, nosig);
- sigemptyset(&sset);
- sigaddset(&sset, SIGUSR1);
- sigprocmask(SIG_BLOCK, &sset, NULL);
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- /*
- * Before registering any policy holder, make sure that the
- * bus is secure by default. This test is necessary, it catches
- * several cases where old D-Bus was vulnerable.
- */
-
- ret = test_priv_before_policy_upload(env);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Make sure unprivileged are not able to register policy
- * holders
- */
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
- struct kdbus_conn *holder;
-
- holder = kdbus_hello_registrar(env->buspath,
- "com.example.a", NULL, 0,
- KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_EXIT(holder == NULL && errno == EPERM);
- }),
- ({ 0; }));
- ASSERT_RETURN(ret == 0);
-
-
- /* Register policy holder */
-
- conn_a = kdbus_hello_registrar(env->buspath, "com.example.a",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn_a);
-
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_b);
-
- ret = kdbus_name_acquire(conn_b, "com.example.b", NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure bus-owners can always acquire names.
- */
- ret = kdbus_name_acquire(conn, "com.example.a", NULL);
- ASSERT_EXIT(ret >= 0);
-
- kdbus_conn_free(conn);
-
- /*
- * Make sure unprivileged users cannot acquire names with default
- * policy assigned.
- */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret < 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged users can acquire names if we make them
- * world-accessible.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_OWN,
- };
-
- /*
- * Make sure unprivileged/normal connections are not able
- * to update policies
- */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_conn_update_policy(unpriv, "com.example.a",
- &access, 1);
- ASSERT_EXIT(ret == -EOPNOTSUPP);
- }));
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged users can acquire names if we make them
- * gid-accessible. But only if the gid matches.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_GROUP,
- .id = UNPRIV_GID,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_GROUP,
- .id = 1,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret < 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged users can acquire names if we make them
- * uid-accessible. But only if the uid matches.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 1,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret < 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged users cannot acquire names if no owner-policy
- * matches, even if SEE/TALK policies match.
- */
-
- num = 4;
- acc = (struct kdbus_policy_access[]){
- {
- .type = KDBUS_POLICY_ACCESS_GROUP,
- .id = UNPRIV_GID,
- .access = KDBUS_POLICY_SEE,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_TALK,
- },
- {
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_TALK,
- },
- {
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_SEE,
- },
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret < 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged users can acquire names if the only matching
- * policy is somewhere in the middle.
- */
-
- num = 5;
- acc = (struct kdbus_policy_access[]){
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 1,
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 2,
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 3,
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 4,
- .access = KDBUS_POLICY_OWN,
- },
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", acc, num);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_name_acquire(unpriv, "com.example.a", NULL);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Clear policies
- */
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", NULL, 0);
- ASSERT_RETURN(ret == 0);
-
- /*
- * Make sure privileged bus users can _always_ talk to others.
- */
-
- conn = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn);
-
- ret = kdbus_msg_send(conn, "com.example.b", 0xdeadbeef, 0, 0, 0, 0);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 300, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- kdbus_conn_free(conn);
-
- /*
- * Make sure unprivileged bus users cannot talk by default.
- */
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged bus users can talk to equals, even without
- * policy.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.c", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- struct kdbus_conn *owner;
-
- owner = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(owner);
-
- ret = kdbus_name_acquire(owner, "com.example.c", NULL);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
- ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- kdbus_conn_free(owner);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged bus users can talk to privileged users if a
- * suitable UID policy is set.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure unprivileged bus users can talk to privileged users if a
- * suitable GID policy is set.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_GROUP,
- .id = UNPRIV_GID,
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure unprivileged bus users can talk to privileged users if a
- * suitable WORLD policy is set.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure unprivileged bus users cannot talk to privileged users if
- * no suitable policy is set.
- */
-
- num = 5;
- acc = (struct kdbus_policy_access[]){
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 0,
- .access = KDBUS_POLICY_OWN,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 1,
- .access = KDBUS_POLICY_TALK,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = UNPRIV_UID,
- .access = KDBUS_POLICY_SEE,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 3,
- .access = KDBUS_POLICY_TALK,
- },
- {
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = 4,
- .access = KDBUS_POLICY_TALK,
- },
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", acc, num);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure unprivileged bus users can talk to privileged users if a
- * suitable OWN privilege overwrites TALK.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_OWN,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
- }));
- ASSERT_RETURN(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- /*
- * Make sure the TALK cache is reset correctly when policies are
- * updated.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_TALK,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = RUN_UNPRIVILEGED_CONN(unpriv, env->buspath, ({
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_msg_recv_poll(conn_b, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.b",
- NULL, 0);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_msg_send(unpriv, "com.example.b", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret == -EPERM);
- }));
- ASSERT_RETURN(ret >= 0);
-
- /*
- * Make sure the TALK cache is reset correctly when policy holders
- * disconnect.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_WORLD,
- .id = 0,
- .access = KDBUS_POLICY_OWN,
- };
-
- conn = kdbus_hello_registrar(env->buspath, "com.example.c",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn);
-
- ret = kdbus_conn_update_policy(conn, "com.example.c", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- owner = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(owner);
-
- ret = kdbus_name_acquire(owner, "com.example.c", NULL);
- ASSERT_RETURN(ret >= 0);
-
- ret = RUN_UNPRIVILEGED(UNPRIV_UID, UNPRIV_GID, ({
- struct kdbus_conn *unpriv;
-
- /* wait for parent to be finished */
- sigemptyset(&sset);
- ret = sigsuspend(&sset);
- ASSERT_RETURN(ret == -1 && errno == EINTR);
-
- unpriv = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(unpriv);
-
- ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret >= 0);
-
- ret = kdbus_msg_recv_poll(owner, 100, NULL, NULL);
- ASSERT_EXIT(ret >= 0);
-
- /* free policy holder */
- kdbus_conn_free(conn);
-
- ret = kdbus_msg_send(unpriv, "com.example.c", 0xdeadbeef, 0, 0,
- 0, 0);
- ASSERT_EXIT(ret == -EPERM);
-
- kdbus_conn_free(unpriv);
- }), ({
- /* make sure policy holder is only valid in child */
- kdbus_conn_free(conn);
- kill(pid, SIGUSR1);
- }));
- ASSERT_RETURN(ret >= 0);
-
-
- /*
- * The following tests are necessary.
- */
-
- ret = test_broadcast_after_policy_upload(env);
- ASSERT_RETURN(ret == 0);
-
- kdbus_conn_free(owner);
-
- /*
- * cleanup resources
- */
-
- kdbus_conn_free(conn_b);
- kdbus_conn_free(conn_a);
-
- return TEST_OK;
-}
-
-int kdbus_test_policy_priv(struct kdbus_test_env *env)
-{
- pid_t pid;
- int ret;
-
- /* make sure to exit() if a child returns from fork() */
- pid = getpid();
- ret = test_policy_priv(env);
- if (pid != getpid())
- exit(1);
-
- return ret;
-}
diff --git a/tools/testing/selftests/kdbus/test-policy.c b/tools/testing/selftests/kdbus/test-policy.c
deleted file mode 100644
index 96d20d5e9..000000000
--- a/tools/testing/selftests/kdbus/test-policy.c
+++ /dev/null
@@ -1,80 +0,0 @@
-#include <errno.h>
-#include <stdio.h>
-#include <string.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stdint.h>
-#include <stdbool.h>
-#include <unistd.h>
-
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-int kdbus_test_policy(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn_a, *conn_b;
- struct kdbus_policy_access access;
- int ret;
-
- /* Invalid name */
- conn_a = kdbus_hello_registrar(env->buspath, ".example.a",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn_a == NULL);
-
- conn_a = kdbus_hello_registrar(env->buspath, "example",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn_a == NULL);
-
- conn_a = kdbus_hello_registrar(env->buspath, "com.example.a",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn_a);
-
- conn_b = kdbus_hello_registrar(env->buspath, "com.example.b",
- NULL, 0, KDBUS_HELLO_POLICY_HOLDER);
- ASSERT_RETURN(conn_b);
-
- /*
- * Verify there cannot be any duplicate entries, except for specific vs.
- * wildcard entries.
- */
-
- access = (struct kdbus_policy_access){
- .type = KDBUS_POLICY_ACCESS_USER,
- .id = geteuid(),
- .access = KDBUS_POLICY_SEE,
- };
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == -EEXIST);
-
- ret = kdbus_conn_update_policy(conn_b, "com.example.a.*", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.a.*", &access, 1);
- ASSERT_RETURN(ret == -EEXIST);
-
- ret = kdbus_conn_update_policy(conn_a, "com.example.*", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_update_policy(conn_b, "com.example.a", &access, 1);
- ASSERT_RETURN(ret == 0);
-
- ret = kdbus_conn_update_policy(conn_b, "com.example.*", &access, 1);
- ASSERT_RETURN(ret == -EEXIST);
-
- /* Invalid name */
- ret = kdbus_conn_update_policy(conn_b, ".example.*", &access, 1);
- ASSERT_RETURN(ret == -EINVAL);
-
- ret = kdbus_conn_update_policy(conn_b, "example", &access, 1);
- ASSERT_RETURN(ret == -EINVAL);
-
- kdbus_conn_free(conn_b);
- kdbus_conn_free(conn_a);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-sync.c b/tools/testing/selftests/kdbus/test-sync.c
deleted file mode 100644
index 0655a545f..000000000
--- a/tools/testing/selftests/kdbus/test-sync.c
+++ /dev/null
@@ -1,369 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <pthread.h>
-#include <stdbool.h>
-#include <signal.h>
-#include <sys/wait.h>
-#include <sys/eventfd.h>
-
-#include "kdbus-api.h"
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-static struct kdbus_conn *conn_a, *conn_b;
-static unsigned int cookie = 0xdeadbeef;
-
-static void nop_handler(int sig) {}
-
-static int interrupt_sync(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst)
-{
- pid_t pid;
- int ret, status;
- struct kdbus_msg *msg = NULL;
- struct sigaction sa = {
- .sa_handler = nop_handler,
- .sa_flags = SA_NOCLDSTOP|SA_RESTART,
- };
-
- cookie++;
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- ret = sigaction(SIGINT, &sa, NULL);
- ASSERT_EXIT(ret == 0);
-
- ret = kdbus_msg_send_sync(conn_dst, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 100000000ULL, 0, conn_src->id, -1);
- ASSERT_EXIT(ret == -ETIMEDOUT);
-
- _exit(EXIT_SUCCESS);
- }
-
- ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- ret = kill(pid, SIGINT);
- ASSERT_RETURN_VAL(ret == 0, ret);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- if (WIFSIGNALED(status))
- return TEST_ERR;
-
- ret = kdbus_msg_recv_poll(conn_src, 100, NULL, NULL);
- ASSERT_RETURN(ret == -ETIMEDOUT);
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-static int close_epipe_sync(const char *bus)
-{
- pid_t pid;
- int ret, status;
- struct kdbus_conn *conn_src;
- struct kdbus_conn *conn_dst;
- struct kdbus_msg *msg = NULL;
-
- conn_src = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_RETURN(conn_src);
-
- ret = kdbus_add_match_empty(conn_src);
- ASSERT_RETURN(ret == 0);
-
- conn_dst = kdbus_hello(bus, 0, NULL, 0);
- ASSERT_RETURN(conn_dst);
-
- cookie++;
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- uint64_t dst_id;
-
- /* close our reference */
- dst_id = conn_dst->id;
- kdbus_conn_free(conn_dst);
-
- ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
- ASSERT_EXIT(ret == 0 && msg->cookie == cookie);
- ASSERT_EXIT(msg->src_id == dst_id);
-
- cookie++;
- ret = kdbus_msg_send_sync(conn_src, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 100000000ULL, 0, dst_id, -1);
- ASSERT_EXIT(ret == -EPIPE);
-
- _exit(EXIT_SUCCESS);
- }
-
- ret = kdbus_msg_send(conn_dst, NULL, cookie, 0, 0, 0,
- KDBUS_DST_ID_BROADCAST);
- ASSERT_RETURN(ret == 0);
-
- cookie++;
- ret = kdbus_msg_recv_poll(conn_dst, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- /* destroy connection */
- kdbus_conn_free(conn_dst);
- kdbus_conn_free(conn_src);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- if (!WIFEXITED(status))
- return TEST_ERR;
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-static int cancel_fd_sync(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst)
-{
- pid_t pid;
- int cancel_fd;
- int ret, status;
- uint64_t counter = 1;
- struct kdbus_msg *msg = NULL;
-
- cancel_fd = eventfd(0, 0);
- ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd);
-
- cookie++;
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- ret = kdbus_msg_send_sync(conn_dst, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 100000000ULL, 0, conn_src->id,
- cancel_fd);
- ASSERT_EXIT(ret == -ECANCELED);
-
- _exit(EXIT_SUCCESS);
- }
-
- ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
- ASSERT_RETURN(ret == 0 && msg->cookie == cookie);
-
- kdbus_msg_free(msg);
-
- ret = write(cancel_fd, &counter, sizeof(counter));
- ASSERT_RETURN(ret == sizeof(counter));
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- if (WIFSIGNALED(status))
- return TEST_ERR;
-
- return (status == EXIT_SUCCESS) ? TEST_OK : TEST_ERR;
-}
-
-static int no_cancel_sync(struct kdbus_conn *conn_src,
- struct kdbus_conn *conn_dst)
-{
- pid_t pid;
- int cancel_fd;
- int ret, status;
- struct kdbus_msg *msg = NULL;
-
- /* pass eventfd, but never signal it so it shouldn't have any effect */
-
- cancel_fd = eventfd(0, 0);
- ASSERT_RETURN_VAL(cancel_fd >= 0, cancel_fd);
-
- cookie++;
- pid = fork();
- ASSERT_RETURN_VAL(pid >= 0, pid);
-
- if (pid == 0) {
- ret = kdbus_msg_send_sync(conn_dst, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 100000000ULL, 0, conn_src->id,
- cancel_fd);
- ASSERT_EXIT(ret == 0);
-
- _exit(EXIT_SUCCESS);
- }
-
- ret = kdbus_msg_recv_poll(conn_src, 100, &msg, NULL);
- ASSERT_RETURN_VAL(ret == 0 && msg->cookie == cookie, -1);
-
- kdbus_msg_free(msg);
-
- ret = kdbus_msg_send_reply(conn_src, cookie, conn_dst->id);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- ret = waitpid(pid, &status, 0);
- ASSERT_RETURN_VAL(ret >= 0, ret);
-
- if (WIFSIGNALED(status))
- return -1;
-
- return (status == EXIT_SUCCESS) ? 0 : -1;
-}
-
-static void *run_thread_reply(void *data)
-{
- int ret;
- unsigned long status = TEST_OK;
-
- ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL);
- if (ret < 0)
- goto exit_thread;
-
- kdbus_printf("Thread received message, sending reply ...\n");
-
- /* using an unknown cookie must fail */
- ret = kdbus_msg_send_reply(conn_a, ~cookie, conn_b->id);
- if (ret != -EBADSLT) {
- status = TEST_ERR;
- goto exit_thread;
- }
-
- ret = kdbus_msg_send_reply(conn_a, cookie, conn_b->id);
- if (ret != 0) {
- status = TEST_ERR;
- goto exit_thread;
- }
-
-exit_thread:
- pthread_exit(NULL);
- return (void *) status;
-}
-
-int kdbus_test_sync_reply(struct kdbus_test_env *env)
-{
- unsigned long status;
- pthread_t thread;
- int ret;
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- pthread_create(&thread, NULL, run_thread_reply, NULL);
-
- ret = kdbus_msg_send_sync(conn_b, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 5000000000ULL, 0, conn_a->id, -1);
-
- pthread_join(thread, (void *) &status);
- ASSERT_RETURN(status == 0);
- ASSERT_RETURN(ret == 0);
-
- ret = interrupt_sync(conn_a, conn_b);
- ASSERT_RETURN(ret == 0);
-
- ret = close_epipe_sync(env->buspath);
- ASSERT_RETURN(ret == 0);
-
- ret = cancel_fd_sync(conn_a, conn_b);
- ASSERT_RETURN(ret == 0);
-
- ret = no_cancel_sync(conn_a, conn_b);
- ASSERT_RETURN(ret == 0);
-
- kdbus_printf("-- closing bus connections\n");
-
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- return TEST_OK;
-}
-
-#define BYEBYE_ME ((void*)0L)
-#define BYEBYE_THEM ((void*)1L)
-
-static void *run_thread_byebye(void *data)
-{
- struct kdbus_cmd cmd_byebye = { .size = sizeof(cmd_byebye) };
- int ret;
-
- ret = kdbus_msg_recv_poll(conn_a, 3000, NULL, NULL);
- if (ret == 0) {
- kdbus_printf("Thread received message, invoking BYEBYE ...\n");
- kdbus_msg_recv(conn_a, NULL, NULL);
- if (data == BYEBYE_ME)
- kdbus_cmd_byebye(conn_b->fd, &cmd_byebye);
- else if (data == BYEBYE_THEM)
- kdbus_cmd_byebye(conn_a->fd, &cmd_byebye);
- }
-
- pthread_exit(NULL);
- return NULL;
-}
-
-int kdbus_test_sync_byebye(struct kdbus_test_env *env)
-{
- pthread_t thread;
- int ret;
-
- /*
- * This sends a synchronous message to a thread, which waits until it
- * received the message and then invokes BYEBYE on the *ORIGINAL*
- * connection. That is, on the same connection that synchronously waits
- * for an reply.
- * This should properly wake the connection up and cause ECONNRESET as
- * the connection is disconnected now.
- *
- * The second time, we do the same but invoke BYEBYE on the *TARGET*
- * connection. This should also wake up the synchronous sender as the
- * reply cannot be sent by a disconnected target.
- */
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_ME);
-
- ret = kdbus_msg_send_sync(conn_b, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 5000000000ULL, 0, conn_a->id, -1);
-
- ASSERT_RETURN(ret == -ECONNRESET);
-
- pthread_join(thread, NULL);
-
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- pthread_create(&thread, NULL, run_thread_byebye, BYEBYE_THEM);
-
- ret = kdbus_msg_send_sync(conn_b, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- 5000000000ULL, 0, conn_a->id, -1);
-
- ASSERT_RETURN(ret == -EPIPE);
-
- pthread_join(thread, NULL);
-
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- return TEST_OK;
-}
diff --git a/tools/testing/selftests/kdbus/test-timeout.c b/tools/testing/selftests/kdbus/test-timeout.c
deleted file mode 100644
index cfd193066..000000000
--- a/tools/testing/selftests/kdbus/test-timeout.c
+++ /dev/null
@@ -1,99 +0,0 @@
-#include <stdio.h>
-#include <string.h>
-#include <time.h>
-#include <fcntl.h>
-#include <stdlib.h>
-#include <stddef.h>
-#include <unistd.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <poll.h>
-#include <stdbool.h>
-
-#include "kdbus-api.h"
-#include "kdbus-test.h"
-#include "kdbus-util.h"
-#include "kdbus-enum.h"
-
-int timeout_msg_recv(struct kdbus_conn *conn, uint64_t *expected)
-{
- struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
- struct kdbus_msg *msg;
- int ret;
-
- ret = kdbus_cmd_recv(conn->fd, &recv);
- if (ret < 0) {
- kdbus_printf("error receiving message: %d (%m)\n", ret);
- return ret;
- }
-
- msg = (struct kdbus_msg *)(conn->buf + recv.msg.offset);
-
- ASSERT_RETURN_VAL(msg->payload_type == KDBUS_PAYLOAD_KERNEL, -EINVAL);
- ASSERT_RETURN_VAL(msg->src_id == KDBUS_SRC_ID_KERNEL, -EINVAL);
- ASSERT_RETURN_VAL(msg->dst_id == conn->id, -EINVAL);
-
- *expected &= ~(1ULL << msg->cookie_reply);
- kdbus_printf("Got message timeout for cookie %llu\n",
- msg->cookie_reply);
-
- ret = kdbus_free(conn, recv.msg.offset);
- if (ret < 0)
- return ret;
-
- return 0;
-}
-
-int kdbus_test_timeout(struct kdbus_test_env *env)
-{
- struct kdbus_conn *conn_a, *conn_b;
- struct pollfd fd;
- int ret, i, n_msgs = 4;
- uint64_t expected = 0;
- uint64_t cookie = 0xdeadbeef;
-
- conn_a = kdbus_hello(env->buspath, 0, NULL, 0);
- conn_b = kdbus_hello(env->buspath, 0, NULL, 0);
- ASSERT_RETURN(conn_a && conn_b);
-
- fd.fd = conn_b->fd;
-
- /*
- * send messages that expect a reply (within 100 msec),
- * but never answer it.
- */
- for (i = 0; i < n_msgs; i++, cookie++) {
- kdbus_printf("Sending message with cookie %llu ...\n",
- (unsigned long long)cookie);
- ASSERT_RETURN(kdbus_msg_send(conn_b, NULL, cookie,
- KDBUS_MSG_EXPECT_REPLY,
- (i + 1) * 100ULL * 1000000ULL, 0,
- conn_a->id) == 0);
- expected |= 1ULL << cookie;
- }
-
- for (;;) {
- fd.events = POLLIN | POLLPRI | POLLHUP;
- fd.revents = 0;
-
- ret = poll(&fd, 1, (n_msgs + 1) * 100);
- if (ret == 0)
- kdbus_printf("--- timeout\n");
- if (ret <= 0)
- break;
-
- if (fd.revents & POLLIN)
- ASSERT_RETURN(!timeout_msg_recv(conn_b, &expected));
-
- if (expected == 0)
- break;
- }
-
- ASSERT_RETURN(expected == 0);
-
- kdbus_conn_free(conn_a);
- kdbus_conn_free(conn_b);
-
- return TEST_OK;
-}