Merge v237 into tizen
authorAdrian Szyndela <adrian.s@samsung.com>
Wed, 26 Feb 2020 13:44:20 +0000 (14:44 +0100)
committerAdrian Szyndela <adrian.s@samsung.com>
Wed, 26 Feb 2020 13:44:20 +0000 (14:44 +0100)
systemd 237

72 files changed:
1  2 
TODO
man/sd_bus_creds_get_pid.xml
man/systemd.exec.xml
meson.build
meson_options.txt
packaging/systemd.spec
rules/50-udev-default.rules.in
src/basic/cgroup-util.c
src/basic/def.h
src/basic/fd-util.c
src/basic/fs-util.c
src/basic/missing.h
src/basic/missing_syscall.h
src/basic/parse-util.c
src/basic/smack-util.c
src/busctl/busctl.c
src/core/cgroup.c
src/core/dbus-execute.c
src/core/dbus-manager.c
src/core/dbus.c
src/core/device.c
src/core/execute.c
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/main.c
src/core/manager.c
src/core/manager.h
src/core/meson.build
src/core/mount-setup.c
src/core/service.c
src/core/socket.c
src/core/timer.c
src/core/unit.c
src/core/unit.h
src/dbus1-generator/dbus1-generator.c
src/libsystemd/meson.build
src/libsystemd/sd-bus/bus-container.c
src/libsystemd/sd-bus/bus-control-kernel.c
src/libsystemd/sd-bus/bus-control-kernel.h
src/libsystemd/sd-bus/bus-control.c
src/libsystemd/sd-bus/bus-control.h
src/libsystemd/sd-bus/bus-convenience.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-kernel.c
src/libsystemd/sd-bus/bus-kernel.h
src/libsystemd/sd-bus/bus-message.c
src/libsystemd/sd-bus/bus-message.h
src/libsystemd/sd-bus/bus-slot.c
src/libsystemd/sd-bus/bus-socket.c
src/libsystemd/sd-bus/sd-bus.c
src/libsystemd/sd-bus/test-bus-benchmark.c
src/libsystemd/sd-bus/test-bus-kernel-bloom.c
src/libsystemd/sd-bus/test-bus-kernel.c
src/libsystemd/sd-bus/test-bus-zero-copy.c
src/login/logind-user.c
src/notify/notify.c
src/nspawn/nspawn-mount.c
src/shared/bus-util.c
src/shared/bus-util.h
src/systemctl/systemctl.c
src/test/meson.build
src/test/test-parse-util.c
src/udev/udev-builtin-net_id.c
test/TEST-20-MAINPIDGAMES/Makefile
test/TEST-20-MAINPIDGAMES/test.sh
test/TEST-20-MAINPIDGAMES/testsuite.sh
test/meson.build
tools/meson-make-symlink.sh
units/debug-shell.service.in
units/meson-add-wants.sh
units/systemd-resolved.service.in
xorg/50-systemd-user.sh

diff --cc TODO
--- 1/TODO
--- 2/TODO
+++ b/TODO
@@@ -480,18 -496,12 +498,16 @@@ Features
  * sd-bus:
    - EBADSLT handling
    - GetAllProperties() on a non-existing object does not result in a failure currently
 +  - kdbus: process fd=-1 for incoming msgs
    - port to sd-resolve for connecting to TCP dbus servers
 +  - kdbus: maybe add controlling tty metadata fields
    - see if we can introduce a new sd_bus_get_owner_machine_id() call to retrieve the machine ID of the machine of the bus itself
 +  - when kdbus does not take our message without memfds, try again with memfds
    - see if we can drop more message validation on the sending side
    - add API to clone sd_bus_message objects
-   - make AddMatch calls on dbus1 transports async?
-   - kdbus: matches against source or destination pids for an "strace -p"-like feel. Problem: The PID info needs to be available in userspace too...
    - longer term: priority inheritance
    - dbus spec updates:
 +       - kdbus mapping
         - NameLost/NameAcquired obsolete
         - GVariant
         - path escaping
Simple merge
Simple merge
diff --cc meson.build
@@@ -530,9 -568,11 +568,11 @@@ foreach prog : prog
          substs.set(name, path)
  endforeach
  
 -if run_command('ln', '--relative', '--help').returncode() != 0
 -        error('ln does not support --relative')
 -endif
+ conf.set_quoted('TELINIT', get_option('telinit-path'))
 +#if run_command('ln', '--relative', '--help').returncode() != 0
 +#        error('ln does not support --relative')
 +#endif
  
  ############################################################
  
@@@ -2696,9 -2829,9 +2842,10 @@@ foreach tuple : 
          ['gnu-efi',          have_gnu_efi],
          ['kmod'],
          ['xkbcommon'],
+         ['pcre2'],
          ['blkid'],
          ['dbus'],
 +        ['kdbus'],
          ['glib'],
          ['nss-myhostname',   conf.get('ENABLE_MYHOSTNAME') == 1],
          ['hwdb'],
Simple merge
index 81d482c,0000000..5128fa2
mode 100644,000000..100644
--- /dev/null
@@@ -1,723 -1,0 +1,723 @@@
- Version:        236
 +# "enable foo" will turn into --enable-foo or --disable-foo
 +# depending "with_foo" macro
 +%define enable() %{expand:%%{?with_%{1}:--enable-%{1}}%%{!?with_%{1}:--disable-%{1}}}
 +
 +%define WITH_RANDOMSEED 0
 +%define WITH_BASH_COMPLETION 0
 +%define WITH_ZSH_COMPLETION 0
 +%define WITH_COREDUMP 0
 +%define WITH_BACKLIGHT 0
 +%define WITH_TIMEDATED 0
 +%define WITH_RFKILL 0
 +%define WITH_MACHINED 0
 +%define WITH_DOC 0
 +%define WITH_HOSTNAMED 0
 +
 +%define build_dir _build
 +%define dbuspolicydir %{_datadir}/dbus-1
 +
 +# The 'meson' macro is defined in rpm macros, but it uses features from rpm 4.15 ({shrink, set_build_flags)
 +# Below is a version suitable for our purposes
 +%define meson \
 +  CFLAGS="${CFLAGS:-%optflags}" \
 +  export CFLAGS \
 +  %{__meson} \\\
 +        --buildtype=plain \\\
 +        --prefix=%{_prefix} \\\
 +        --libdir=%{_libdir} \\\
 +        --libexecdir=%{_libexecdir} \\\
 +        --bindir=%{_bindir} \\\
 +        --sbindir=%{_sbindir} \\\
 +        --includedir=%{_includedir} \\\
 +        --datadir=%{_datadir} \\\
 +        --mandir=%{_mandir} \\\
 +        --infodir=%{_infodir} \\\
 +        --localedir=%{_datadir}/locale \\\
 +        --sysconfdir=%{_sysconfdir} \\\
 +        --localstatedir=%{_localstatedir} \\\
 +        --sharedstatedir=%{_sharedstatedir} \\\
 +        --wrap-mode=%{__meson_wrap_mode} \\\
 +              %{_vpath_builddir}
 +# Ninja macros below are defined for ninja in e.g. fedora distro, but
 +# so far they are not provided by Tizen's ninja package.
 +%define __ninja %{_bindir}/ninja
 +%define __ninja_common_opts -v %{?_smp_flags}
 +%define ninja_build \
 +              %{__ninja} %{__ninja_common_opts}
 +%define ninja_install \
 +              DESTDIR=%{buildroot} %{__ninja} install %{__ninja_common_opts}
 +
 +Name:           systemd
++Version:        237
 +Release:        0%{?release_flags}
 +# For a breakdown of the licensing, see README
 +License:        LGPL-2.1+ and GPL-2.0+
 +Summary:        A System and Service Manager
 +Url:            http://www.freedesktop.org/wiki/Software/systemd
 +Group:          Base/Startup
 +Source0:        https://github.com/systemd/systemd/archive/v%{version}.tar.gz
 +Source1:        pamconsole-tmp.conf
 +Source2:        %{name}-rpmlintrc
 +Source3:        test-runner.c
 +Source4:        wait-default-target.sh
 +Source5:        wait-delayed-target.sh
 +Source6:        org.tizen.system.conf
 +Source7:        sysctl-tizen-override.conf
 +Source1001:     systemd.manifest
 +BuildRequires:  gperf
 +BuildRequires:  intltool >= 0.40.0
 +BuildRequires:  libacl-devel
 +BuildRequires:  libblkid-devel >= 2.20
 +BuildRequires:  libcap-devel
 +BuildRequires:  libgcrypt-devel
 +BuildRequires:  libkmod-devel >= 14
 +%if %{?WITH_DOC}
 +BuildRequires:  xsltproc
 +BuildRequires:  docbook-xsl-stylesheets
 +%endif
 +BuildRequires:  pam-devel
 +BuildRequires:  pkgconfig
 +# BuildRequires:  pkgconfig(dbus-1)     # for remove circular dependency on OBS
 +BuildRequires:  pkgconfig(glib-2.0)
 +BuildRequires:  pkgconfig(liblzma)
 +BuildRequires:  pkgconfig(libkmod)
 +BuildRequires:  pkgconfig(mount)
 +BuildRequires:  meson
 +BuildRequires:  acl
 +BuildRequires:  python
 +# Requires:       dbus                  # for remove circular dependency on OBS
 +Requires:       filesystem
 +Requires(post): coreutils
 +Requires(pre):  coreutils
 +Requires(pre):  /usr/bin/getent
 +Requires(pre):  /usr/sbin/groupadd
 +Requires(post): %{_sbindir}/update-alternatives
 +Requires(preun): %{_sbindir}/update-alternatives
 +
 +Obsoletes:      SysVinit < 2.86-24
 +Obsoletes:      sysvinit < 2.86-24
 +Provides:       SysVinit = 2.86-24
 +Provides:       sysvinit = 2.86-24
 +Provides:       /bin/systemctl
 +Provides:       /sbin/shutdown
 +Provides:       udev = %{version}
 +Obsoletes:      udev < 183
 +
 +%description
 +systemd is a system and service manager for Linux, compatible with
 +SysV and LSB init scripts. systemd provides aggressive parallelization
 +capabilities, uses socket and D-Bus activation for starting services,
 +offers on-demand starting of daemons, keeps track of processes using
 +Linux cgroups, supports snapshotting and restoring of the system
 +state, maintains mount and automount points and implements an
 +elaborate transactional dependency-based service control logic. It can
 +work as a drop-in replacement for sysvinit.
 +
 +%package -n libsystemd
 +License:        LGPL-2.1+
 +Summary:        Systemd libraries
 +Group:          Base/Startup
 +Obsoletes:      libudev < 183
 +Provides:       libudev = %{version}
 +Obsoletes:      systemd < 185-4
 +Conflicts:      systemd < 185-4
 +
 +%description -n libsystemd
 +Libraries for systemd and udev, as well as the systemd PAM module.
 +
 +%package devel
 +License:        LGPL-2.1+
 +Summary:        Development headers for systemd
 +Requires:       %{name} = %{version}
 +Requires:             libsystemd = %{version}
 +Provides:       libudev-devel = %{version}
 +Obsoletes:      libudev-devel < 183
 +
 +%description devel
 +Development headers and auxiliary files for developing applications for systemd.
 +
 +%package analyze
 +License:        LGPL-2.1+
 +Summary:        Tool for processing systemd profiling information
 +Requires:       %{name} = %{version}
 +Obsoletes:      systemd < 38-5
 +
 +%description analyze
 +'systemd-analyze blame' lists which systemd unit needed how much time to finish
 +initialization at boot.
 +'systemd-analyze plot' renders an SVG visualizing the parallel start of units
 +at boot.
 +
 +%package tests
 +License:        LGPL-2.1+ and BSD-2-Clause
 +Summary:        Set of tests for sd-bus component
 +Requires:       %{name} = %{version}
 +
 +%description tests
 +This package is part of 'dbus-integratnion-tests' framework and contains set of tests
 +for sd-bus component (DBUS API C library).
 +
 +%package extension-kdbus
 +Summary:      Extension for systemd to support KDBUS in Tizen
 +Requires:     %{name} = %{version}-%{release}
 +
 +%description extension-kdbus
 +This modifies systemd to support KDBUS in Tizen.
 +
 +%prep
 +%setup -q
 +
 +%build
 +cp %{SOURCE1001} .
 +cp %{SOURCE3} .
 +
 +%define _vpath_srcdir .
 +%define _vpath_builddir %{build_dir}
 +%meson \
 +      -Dkdbus=true \
 +%if ! %{WITH_RANDOMSEED}
 +      -Drandomseed=false \
 +%endif
 +%if ! %{?WITH_COREDUMP}
 +      -Dcoredump=false \
 +%endif
 +%if ! %{?WITH_BACKLIGHT}
 +      -Dbacklight=false \
 +%endif
 +%if ! %{?WITH_TIMEDATED}
 +      -Dtimedated=false \
 +%endif
 +%if ! %{WITH_RFKILL}
 +      -Drfkill=false \
 +%endif
 +        -Dhwdb=false \
 +        -Dsysusers=false \
 +        -Dfirstboot=false \
 +        -Dpolkit=false \
 +        -Dtimesyncd=false \
 +        -Dresolve=false \
 +        -Dnetworkd=false \
 +%if ! %{?WITH_MACHINED}
 +        -Dmachined=false \
 +%endif
 +%if ! %{?WITH_HOSTNAMED}
 +        -Dhostnamed=false \
 +%endif
 +        -Dimportd=false \
 +              -Denvironment-d=false \
 +              -Dnss-systemd=false \
 +        -Dgcrypt=false \
 +%if ! %{?WITH_DOC}
 +        -Dman=false \
 +%endif
 +        -Drpmmacrosdir=%{_sysconfdir}/rpm/ \
 +        -Dsysvinit-path="" \
 +        -Dsysvrcnd-path="" \
 +        -Dsmack-run-label=System::Privileged \
 +              -Dinstall-tests=true \
 +              -Ddefault-hierarchy=legacy \
 +              -Db_pie=true
 +%meson_build
 +
 +# compile test-runner for 'dbus-integration-test' framework
 +%__cc %{_builddir}/%{name}-%{version}/test-runner.c -o %{_builddir}/%{name}-%{version}/systemd-tests
 +
 +%install
 +%meson_install
 +%find_lang %{name}
 +cat <<EOF >> systemd.lang
 +%lang(be) /usr/lib/systemd/catalog/systemd.be.catalog
 +%lang(be) /usr/lib/systemd/catalog/systemd.be@latin.catalog
 +%lang(bg) /usr/lib/systemd/catalog/systemd.bg.catalog
 +%lang(de) /usr/lib/systemd/catalog/systemd.de.catalog
 +%lang(fr) /usr/lib/systemd/catalog/systemd.fr.catalog
 +%lang(it) /usr/lib/systemd/catalog/systemd.it.catalog
 +%lang(pl) /usr/lib/systemd/catalog/systemd.pl.catalog
 +%lang(pt_BR) /usr/lib/systemd/catalog/systemd.pt_BR.catalog
 +%lang(ru) /usr/lib/systemd/catalog/systemd.ru.catalog
 +%lang(zh) /usr/lib/systemd/catalog/systemd.zh_CN.catalog
 +%lang(zh) /usr/lib/systemd/catalog/systemd.zh_TW.catalog
 +EOF
 +
 +# udev links
 +/usr/bin/mkdir -p %{buildroot}/%{_sbindir}
 +/usr/bin/ln -sf ../bin/udevadm %{buildroot}%{_sbindir}/udevadm
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/firmware/updates
 +
 +# Create SysV compatibility symlinks. systemctl/systemd are smart
 +# enough to detect in which way they are called.
 +/usr/bin/ln -s ../lib/systemd/systemd %{buildroot}%{_sbindir}/init
 +/usr/bin/ln -s ../lib/systemd/systemd %{buildroot}%{_bindir}/systemd
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/reboot
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/halt
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/poweroff
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/shutdown
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/telinit
 +/usr/bin/ln -s ../bin/systemctl %{buildroot}%{_sbindir}/runlevel
 +
 +# legacy links
 +/usr/bin/ln -s loginctl %{buildroot}%{_bindir}/systemd-loginctl
 +
 +# We create all wants links manually at installation time to make sure
 +# they are not owned and hence overriden by rpm after the used deleted
 +# them.
 +/usr/bin/rm -r %{buildroot}%{_sysconfdir}/systemd/system/*.target.wants
 +
 +# Make sure these directories are properly owned
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/basic.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/default.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/dbus.target.wants
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system/syslog.target.wants
 +
 +# Make sure the user generators dir exists too
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-generators
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-generators
 +
 +# Create new-style configuration files so that we can ghost-own them
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/hostname
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/vconsole.conf
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/locale.conf
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/machine-id
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/machine-info
 +/usr/bin/touch %{buildroot}%{_sysconfdir}/timezone
 +
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-preset/
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/user-preset/
 +
 +# Make sure the shutdown/sleep drop-in dirs exist
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-shutdown/
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/system-sleep/
 +
 +# Make sure the NTP units dir exists
 +/usr/bin/mkdir -p %{buildroot}%{_prefix}/lib/systemd/ntp-units.d/
 +
 +# Install modprobe fragment
 +/usr/bin/mkdir -p %{buildroot}%{_sysconfdir}/modprobe.d/
 +
 +# Fix the dangling /var/lock -> /run/lock symlink
 +install -Dm644 tmpfiles.d/legacy.conf %{buildroot}%{_prefix}/lib/tmpfiles.d/legacy.conf
 +
 +install -m644 %{SOURCE1} %{buildroot}%{_prefix}/lib/tmpfiles.d/
 +
 +install -m 755 -d %{buildroot}/%{_prefix}/lib/systemd/system
 +
 +rm -rf %{buildroot}/%{_docdir}/%{name}
 +
 +# Allow replacing systemd-shutdown with tizen-specific variant
 +mv %{buildroot}%{_prefix}/lib/systemd/systemd-shutdown %{buildroot}%{_prefix}/lib/systemd/systemd-shutdown-original
 +
 +# Disable some useless services in Tizen
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/dev-hugepages.mount
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/sys-fs-fuse-connections.mount
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-binfmt.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-modules-load.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/sysinit.target.wants/systemd-ask-password-console.path
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/multi-user.target.wants/systemd-ask-password-wall.path
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/systemd-tmpfiles-clean.timer
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/systemd-tmpfiles-clean.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/system/timers.target.wants/systemd-tmpfiles-clean.timer
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-clean.timer
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-clean.service
 +rm -rf %{buildroot}/%{_prefix}/lib/systemd/user/systemd-tmpfiles-setup.service
 +
 +# Exclude ELF binaries
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-debug-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-efi-boot-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-gpt-auto-generator
 +rm -f %{buildroot}/%{_prefix}/lib/systemd/system-generators/systemd-hibernate-resume-generator
 +
 +# Marker file for kdbus
 +touch %{buildroot}/%{_sysconfdir}/systemd/extension-kdbus
 +
 +# Prepare tests for 'dbus-integration-test' framework
 +install -D -m 755 %{_builddir}/%{name}-%{version}/systemd-tests %{buildroot}%{_prefix}/lib/dbus-tests/runner/systemd-tests
 +mkdir -p %{buildroot}%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +mv %{buildroot}%{_prefix}/lib/systemd/tests/test-bus-* %{buildroot}%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +
 +# Shell Completion
 +%if ! %{?WITH_BASH_COMPLETION}
 +rm -rf %{buildroot}/%{_datadir}/bash-completion/*
 +%endif
 +%if ! %{?WITH_ZSH_COMPLETION}
 +rm -rf %{buildroot}/%{_datadir}/zsh/site-functions/*
 +%endif
 +
 +mkdir -p %{buildroot}/%{_localstatedir}/log/journal
 +
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-daemon.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-id128.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-journal.pc
 +ln -sf ./libsystemd.pc %{buildroot}%{_libdir}/pkgconfig/libsystemd-login.pc
 +
 +# Delayed target
 +install -m 0755 %{SOURCE4} %{buildroot}%{_bindir}/wait-default-target.sh
 +install -m 0755 %{SOURCE5} %{buildroot}%{_bindir}/wait-delayed-target.sh
 +install -m 0755 %{SOURCE6} %{buildroot}%{dbuspolicydir}/system.d/org.tizen.system.conf
 +
 +# Tizen sysctl values overriding default systemd values
 +install -m 0644 %{SOURCE7} %{buildroot}%{_sysconfdir}/sysctl.d/
 +
 +# end of install
 +%pre
 +/usr/bin/getent group cdrom >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 11 cdrom >/dev/null 2>&1 || :
 +/usr/bin/getent group tape >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 33 tape >/dev/null 2>&1 || :
 +/usr/bin/getent group dialout >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 18 dialout >/dev/null 2>&1 || :
 +/usr/bin/getent group floppy >/dev/null 2>&1 || /usr/sbin/groupadd -r -g 19 floppy >/dev/null 2>&1 || :
 +/usr/bin/systemctl stop systemd-udevd-control.socket systemd-udevd-kernel.socket systemd-udevd.service >/dev/null 2>&1 || :
 +
 +# Rename configuration files that changed their names
 +/usr/bin/mv -n %{_sysconfdir}/systemd/systemd-logind.conf %{_sysconfdir}/systemd/logind.conf >/dev/null 2>&1 || :
 +/usr/bin/mv -n %{_sysconfdir}/systemd/systemd-journald.conf %{_sysconfdir}/systemd/journald.conf >/dev/null 2>&1 || :
 +
 +%post
 +/usr/bin/systemd-machine-id-setup > /dev/null 2>&1 || :
 +%if %{WITH_RANDOMSEED}
 +/usr/lib/systemd/systemd-random-seed save > /dev/null 2>&1 || :
 +%endif
 +/usr/bin/systemctl daemon-reexec > /dev/null 2>&1 || :
 +/usr/bin/systemctl start systemd-udevd.service >/dev/null 2>&1 || :
 +/usr/bin/mkdir -p /etc/systemd/network
 +/usr/bin/ln -sf /dev/null /etc/systemd/network/99-default.link
 +
 +# Set the smack label of executable binary tools
 +chsmack %{_bindir}/bootctl -a "System::Tools"
 +chsmack %{_bindir}/busctl -a "System::Tools"
 +chsmack %{_bindir}/kernel-install -a "System::Tools"
 +%if %{?WITH_MACHINED}
 +chsmack %{_bindir}/machinectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/systemd-run -a "System::Tools"
 +%if %{?WITH_HOSTNAMED}
 +chsmack %{_bindir}/hostnamectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/localectl -a "System::Tools"
 +%if %{?WITH_COREDUMP}
 +chsmack %{_bindir}/coredumpctl -a "System::Tools"
 +%endif
 +%if %{?WITH_TIMEDATED}
 +chsmack %{_bindir}/timedatectl -a "System::Tools"
 +%endif
 +chsmack %{_bindir}/systemd -a "System::Tools"
 +chsmack %{_bindir}/systemctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-notify -a "System::Tools"
 +chsmack %{_bindir}/systemd-ask-password -a "System::Tools"
 +chsmack %{_bindir}/systemd-tty-ask-password-agent -a "System::Tools"
 +chsmack %{_bindir}/systemd-machine-id-setup -a "System::Tools"
 +chsmack %{_bindir}/systemd-socket-activate -a "System::Tools"
 +chsmack %{_bindir}/loginctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-loginctl -a "System::Tools"
 +chsmack %{_bindir}/journalctl -a "System::Tools"
 +chsmack %{_bindir}/systemd-tmpfiles -a "System::Tools"
 +chsmack %{_bindir}/systemd-nspawn -a "System::Tools"
 +chsmack %{_bindir}/systemd-stdio-bridge -a "System::Tools"
 +chsmack %{_bindir}/systemd-cat -a "System::Tools"
 +chsmack %{_bindir}/systemd-cgls -a "System::Tools"
 +chsmack %{_bindir}/systemd-cgtop -a "System::Tools"
 +chsmack %{_bindir}/systemd-delta -a "System::Tools"
 +chsmack %{_bindir}/systemd-detect-virt -a "System::Tools"
 +chsmack %{_bindir}/systemd-inhibit -a "System::Tools"
 +chsmack %{_bindir}/udevadm -a "System::Tools"
 +chsmack %{_bindir}/systemd-escape -a "System::Tools"
 +chsmack %{_bindir}/systemd-path -a "System::Tools"
 +chsmack %{_prefix}/lib/systemd/* -a "System::Tools"
 +
 +%postun
 +if [ $1 -ge 1 ] ; then
 +        /usr/bin/systemctl daemon-reload > /dev/null 2>&1 || :
 +        /usr/bin/systemctl try-restart systemd-logind.service >/dev/null 2>&1 || :
 +fi
 +
 +%preun
 +if [ $1 -eq 0 ] ; then
 +        /usr/bin/systemctl disable \
 +                getty@.service \
 +                remote-fs.target \
 +                systemd-readahead-replay.service \
 +                systemd-readahead-collect.service >/dev/null 2>&1 || :
 +
 +        update-alternatives --remove systemd-shutdown %{_prefix}/lib/systemd/systemd-shutdown-original
 +fi
 +
 +%posttrans
 +# Update alternatives after the whole transaction is completed - this is
 +# necessary due to RPM ordering, which removes files from old package not
 +# provided by new package after regular post scripts are run.  Please refer
 +# to following guideliness for explanation:
 +#   https://fedoraproject.org/wiki/Packaging:Scriptlets#Ordering
 +if [ $1 -eq 0 ]; then
 +    update-alternatives --install %{_prefix}/lib/systemd/systemd-shutdown systemd-shutdown %{_prefix}/lib/systemd/systemd-shutdown-original 100 || :
 +fi
 +
 +%post -n libsystemd -p /sbin/ldconfig
 +%postun -n libsystemd  -p /sbin/ldconfig
 +
 +%lang_package
 +
 +%files
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1  LICENSE.GPL2
 +%config %{_sysconfdir}/pam.d/systemd-user
 +%{_bindir}/bootctl
 +%{_bindir}/busctl
 +%{_bindir}/kernel-install
 +%if %{?WITH_MACHINED}
 +%{_bindir}/machinectl
 +%endif
 +%{_bindir}/systemd-run
 +%dir %{_prefix}/lib/kernel
 +%dir %{_prefix}/lib/kernel/install.d
 +%{_prefix}/lib/kernel/install.d/50-depmod.install
 +%{_prefix}/lib/kernel/install.d/90-loaderentry.install
 +%if %{?WITH_HOSTNAMED}
 +%{_bindir}/hostnamectl
 +%endif
 +%{_bindir}/localectl
 +%if %{?WITH_COREDUMP}
 +%{_bindir}/coredumpctl
 +%endif
 +%if %{?WITH_TIMEDATED}
 +%{_bindir}/timedatectl
 +%endif
 +%dir %{_sysconfdir}/systemd
 +%dir %{_sysconfdir}/systemd/system
 +%dir %{_sysconfdir}/systemd/user
 +%dir %{_sysconfdir}/tmpfiles.d
 +%dir %{_sysconfdir}/sysctl.d
 +%dir %{_sysconfdir}/modules-load.d
 +%dir %{_sysconfdir}/binfmt.d
 +%if %{?WITH_BASH_COMPLETION}
 +%{_datadir}/bash-completion/*
 +%endif
 +%if %{?WITH_ZSH_COMPLETION}
 +%dir %{_datadir}/zsh/site-functions
 +%{_datadir}/zsh/site-functions/*
 +%endif
 +%dir %{_sysconfdir}/udev
 +%dir %{_sysconfdir}/udev/rules.d
 +%dir %{_prefix}/lib/systemd
 +%dir %{_prefix}/lib/systemd/system
 +%dir %{_prefix}/lib/systemd/system-generators
 +%dir %{_prefix}/lib/systemd/user-generators
 +%dir %{_prefix}/lib/systemd/system-preset
 +%dir %{_prefix}/lib/systemd/user-preset
 +%dir %{_prefix}/lib/systemd/system-shutdown
 +%dir %{_prefix}/lib/systemd/system-sleep
 +%dir %{_prefix}/lib/tmpfiles.d
 +%dir %{_prefix}/lib/sysctl.d
 +%dir %{_prefix}/lib/modules-load.d
 +%dir %{_prefix}/lib/binfmt.d
 +%dir %{_prefix}/lib/firmware
 +%dir %{_prefix}/lib/firmware/updates
 +%dir %{_datadir}/systemd
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.systemd1.conf
 +%if %{?WITH_HOSTNAMED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.hostname1.conf
 +%endif
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.login1.conf
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.locale1.conf
 +%if %{?WITH_TIMEDATED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.timedate1.conf
 +%endif
 +%if %{?WITH_MACHINED}
 +%config(noreplace) %{dbuspolicydir}/system.d/org.freedesktop.machine1.conf
 +%endif
 +%if %{?WITH_COREDUMP}
 +%config(noreplace) %{_sysconfdir}/systemd/coredump.conf
 +%else
 +%exclude %{_sysconfdir}/systemd/coredump.conf
 +%endif
 +%config(noreplace) %{_sysconfdir}/systemd/system.conf
 +%config(noreplace) %{_sysconfdir}/systemd/user.conf
 +%config(noreplace) %{_sysconfdir}/systemd/logind.conf
 +%config(noreplace) %{_sysconfdir}/systemd/journald.conf
 +%config(noreplace) %{_sysconfdir}/udev/udev.conf
 +%config(noreplace) %{_sysconfdir}/sysctl.d/sysctl-tizen-override.conf
 +%{_sysconfdir}/xdg/systemd
 +%ghost %config(noreplace) %{_sysconfdir}/hostname
 +%ghost %config(noreplace) %{_sysconfdir}/vconsole.conf
 +%ghost %config(noreplace) %{_sysconfdir}/locale.conf
 +%ghost %config(noreplace) %{_sysconfdir}/machine-id
 +%ghost %config(noreplace) %{_sysconfdir}/machine-info
 +%ghost %config(noreplace) %{_sysconfdir}/timezone
 +%exclude %{_sysconfdir}/X11/xinit/xinitrc.d/50-systemd-user.sh
 +%{_bindir}/systemd
 +%{_bindir}/systemctl
 +%{_bindir}/systemd-notify
 +%{_bindir}/systemd-ask-password
 +%{_bindir}/systemd-tty-ask-password-agent
 +%{_bindir}/systemd-machine-id-setup
 +%{_bindir}/systemd-socket-activate
 +%{_bindir}/loginctl
 +%{_bindir}/systemd-loginctl
 +%{_bindir}/journalctl
 +%{_bindir}/systemd-tmpfiles
 +%{_bindir}/systemd-nspawn
 +%{_bindir}/systemd-stdio-bridge
 +%{_bindir}/systemd-cat
 +%{_bindir}/systemd-cgls
 +%{_bindir}/systemd-cgtop
 +%{_bindir}/systemd-delta
 +%{_bindir}/systemd-detect-virt
 +%{_bindir}/systemd-inhibit
 +%{_bindir}/udevadm
 +%{_bindir}/systemd-escape
 +%{_bindir}/systemd-path
 +%{_bindir}/systemd-mount
 +%{_bindir}/systemd-umount
 +%{_prefix}/lib/sysctl.d/*.conf
 +%{_prefix}/lib/systemd/systemd
 +%{_prefix}/lib/systemd/system
 +
 +%dir %{_prefix}/lib/systemd/system/basic.target.wants
 +%dir %{_prefix}/lib/systemd/user
 +%dir %{_prefix}/lib/systemd/network
 +%dir %{_prefix}/lib/systemd/user/default.target.wants
 +%{_prefix}/lib/systemd/user/basic.target
 +%{_prefix}/lib/systemd/user/exit.target
 +%{_prefix}/lib/systemd/user/printer.target
 +%{_prefix}/lib/systemd/user/shutdown.target
 +%{_prefix}/lib/systemd/user/sockets.target
 +%{_prefix}/lib/systemd/user/sound.target
 +%{_prefix}/lib/systemd/user/systemd-exit.service
 +%{_prefix}/lib/systemd/user/paths.target
 +%{_prefix}/lib/systemd/user/smartcard.target
 +%{_prefix}/lib/systemd/user/timers.target
 +%{_prefix}/lib/systemd/user/default.target
 +%exclude %{_prefix}/lib/systemd/user/graphical-session.target
 +%exclude %{_prefix}/lib/systemd/user/graphical-session-pre.target
 +%{_prefix}/lib/systemd/network/99-default.link
 +%exclude %{_prefix}/lib/systemd/system-preset/90-systemd.preset
 +%exclude %{_prefix}/lib/systemd/user-preset/90-systemd.preset
 +%{_prefix}/lib/systemd/user/delayed.target
 +%{_prefix}/lib/systemd/user/user-delayed-target-trigger.service
 +%{_prefix}/lib/systemd/user/default.target.wants/user-delayed-target-trigger.service
 +%{_prefix}/lib/systemd/user/user-default-target-done.service
 +%{_prefix}/lib/systemd/user/default.target.wants/user-default-target-done.service
 +%{_prefix}/lib/systemd/user/user-delayed-target-done.service
 +%{_prefix}/lib/systemd/user/delayed.target.wants/user-delayed-target-done.service
 +%{dbuspolicydir}/system.d/org.tizen.system.conf
 +%exclude %{_prefix}/lib/modprobe.d/systemd.conf
 +
 +%{_prefix}/lib/systemd/libsystemd-shared-%{version}.so
 +%{_prefix}/lib/systemd/systemd-*
 +%dir %{_prefix}/lib/systemd/catalog
 +%{_prefix}/lib/systemd/catalog/systemd.catalog
 +%{_prefix}/lib/udev
 +%{_prefix}/lib/systemd/system-generators/systemd-getty-generator
 +%{_prefix}/lib/systemd/system-generators/systemd-fstab-generator
 +%{_prefix}/lib/systemd/system-generators/systemd-system-update-generator
 +%{_prefix}/lib/tmpfiles.d/home.conf
 +%{_prefix}/lib/tmpfiles.d/journal-nocow.conf
 +%{_prefix}/lib/tmpfiles.d/legacy.conf
 +%{_prefix}/lib/tmpfiles.d/pamconsole-tmp.conf
 +%{_prefix}/lib/tmpfiles.d/systemd.conf
 +%{_prefix}/lib/tmpfiles.d/systemd-nologin.conf
 +%{_prefix}/lib/tmpfiles.d/systemd-nspawn.conf
 +%{_prefix}/lib/tmpfiles.d/tmp.conf
 +%{_prefix}/lib/tmpfiles.d/var.conf
 +%{_prefix}/lib/tmpfiles.d/x11.conf
 +%{_sbindir}/init
 +%{_sbindir}/reboot
 +%{_sbindir}/halt
 +%{_sbindir}/poweroff
 +%{_sbindir}/shutdown
 +%{_sbindir}/telinit
 +%{_sbindir}/runlevel
 +%{_sbindir}/udevadm
 +%{_datadir}/systemd/graphinfo.gvpr
 +%{_datadir}/systemd/kbd-model-map
 +%{_datadir}/systemd/language-fallback-map
 +%{_datadir}/dbus-1/services/org.freedesktop.systemd1.service
 +%{_datadir}/dbus-1/system-services/org.freedesktop.systemd1.service
 +%if %{?WITH_HOSTNAMED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.hostname1.service
 +%endif
 +%{_datadir}/dbus-1/system-services/org.freedesktop.login1.service
 +%{_datadir}/dbus-1/system-services/org.freedesktop.locale1.service
 +%if %{?WITH_TIMEDATED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.timedate1.service
 +%endif
 +%if %{?WITH_MACHINED}
 +%{_datadir}/dbus-1/system-services/org.freedesktop.machine1.service
 +%endif
 +%dir %{_datadir}/factory/
 +%dir %{_datadir}/factory/etc
 +%dir %{_datadir}/factory/etc/pam.d
 +%{_datadir}/factory/etc/nsswitch.conf
 +%{_datadir}/factory/etc/pam.d/other
 +%{_datadir}/factory/etc/pam.d/system-auth
 +
 +%{_localstatedir}/log/journal
 +
 +%{_bindir}/wait-default-target.sh
 +%{_bindir}/wait-delayed-target.sh
 +%exclude %{_prefix}/lib/systemd/system/runlevel0.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel1.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel2.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel3.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel4.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel5.target
 +%exclude %{_prefix}/lib/systemd/system/runlevel6.target
 +
 +%files -n libsystemd
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1
 +%{_libdir}/security/pam_systemd.so
 +%{_libdir}/libsystemd.so.*
 +%{_libdir}/libudev.so.*
 +%{_libdir}/libnss_myhostname.so.2
 +%if %{?WITH_MACHINED}
 +%{_libdir}/libnss_mymachines.so.2
 +%endif
 +
 +%files extension-kdbus
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1  LICENSE.GPL2
 +%{_sysconfdir}/systemd/extension-kdbus
 +%{_prefix}/lib/systemd/user/busnames.target
 +%{_prefix}/lib/systemd/system-generators/systemd-dbus1-generator
 +%{_prefix}/lib/systemd/user-generators/systemd-dbus1-generator
 +
 +%files devel
 +%manifest %{name}.manifest
 +%{_libdir}/libudev.so
 +%{_libdir}/libsystemd.so
 +%dir %{_includedir}/systemd
 +%{_includedir}/systemd/sd-bus.h
 +%{_includedir}/systemd/sd-bus-protocol.h
 +%{_includedir}/systemd/sd-bus-vtable.h
 +%{_includedir}/systemd/sd-event.h
 +%{_includedir}/systemd/_sd-common.h
 +%{_includedir}/systemd/sd-daemon.h
 +%{_includedir}/systemd/sd-id128.h
 +%{_includedir}/systemd/sd-journal.h
 +%{_includedir}/systemd/sd-login.h
 +%{_includedir}/systemd/sd-messages.h
 +%{_includedir}/libudev.h
 +%{_libdir}/pkgconfig/libudev.pc
 +%{_libdir}/pkgconfig/libsystemd.pc
 +%{_datadir}/pkgconfig/systemd.pc
 +%{_datadir}/pkgconfig/udev.pc
 +%{_libdir}/pkgconfig/libsystemd-daemon.pc
 +%{_libdir}/pkgconfig/libsystemd-id128.pc
 +%{_libdir}/pkgconfig/libsystemd-journal.pc
 +%{_libdir}/pkgconfig/libsystemd-login.pc
 +%{_sysconfdir}/rpm/macros.systemd
 +
 +%files analyze
 +%manifest %{name}.manifest
 +%license LICENSE.LGPL2.1
 +%{_bindir}/systemd-analyze
 +
 +%files tests
 +%manifest %{name}.manifest
 +%{_prefix}/lib/dbus-tests/test-suites/systemd-tests/
 +%{_prefix}/lib/dbus-tests/runner/systemd-tests
 +%{_prefix}/lib/systemd/tests/
 +
 +%if %{?WITH_DOC}
 +%docs_package
 +%else
 +%exclude %{_docdir}
 +%exclude %{_datadir}/doc/systemd
 +%endif
Simple merge
Simple merge
diff --cc src/basic/def.h
          "/usr/lib/kbd/keymaps/\0"
  #endif
  
- #define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/var/run/dbus/system_bus_socket"
+ /* Note that we use the new /run prefix here (instead of /var/run) since we require them to be aliases and that way we
+  * become independent of /var being mounted */
 -#define DEFAULT_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket"
 -#define DEFAULT_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
++#define UNIX_SYSTEM_BUS_ADDRESS "unix:path=/run/dbus/system_bus_socket"
 +#define KERNEL_SYSTEM_BUS_ADDRESS "kernel:path=/sys/fs/kdbus/0-system/bus"
 +#define DEFAULT_SYSTEM_BUS_ADDRESS KERNEL_SYSTEM_BUS_ADDRESS ";" UNIX_SYSTEM_BUS_ADDRESS
 +#define UNIX_USER_BUS_ADDRESS_FMT "unix:path=%s/bus"
 +#define KERNEL_USER_BUS_ADDRESS_FMT "kernel:path=/sys/fs/kdbus/"UID_FMT"-user/bus"
++#define DEFAULT_USER_BUS_ADDRESS_FMT KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT
  
  #define PLYMOUTH_SOCKET {                                       \
                  .un.sun_family = AF_UNIX,                       \
Simple merge
@@@ -639,22 -660,28 +660,32 @@@ int chase_symlinks(const char *path, co
           * function what to do when encountering a symlink with an absolute path as directory: prefix it by the
           * specified path. */
  
+         /* A root directory of "/" or "" is identical to none */
+         if (isempty(original_root) || path_equal(original_root, "/"))
+                 original_root = NULL;
          if (original_root) {
 -                r = path_make_absolute_cwd(original_root, &root);
 -                if (r < 0)
 -                        return r;
 +                int res = path_make_absolute_cwd(original_root, &root);
 +                if (res != 0)
 +                        return res;
 +                if (root == NULL)
 +                        return -ENOENT;
  
-                 if (flags & CHASE_PREFIX_ROOT)
+                 if (flags & CHASE_PREFIX_ROOT) {
+                         /* We don't support relative paths in combination with a root directory */
+                         if (!path_is_absolute(path))
+                                 return -EINVAL;
                          path = prefix_roota(root, path);
+                 }
          }
  
 -        r = path_make_absolute_cwd(path, &buffer);
 -        if (r < 0)
 -                return r;
 +        int res = path_make_absolute_cwd(path, &buffer);
 +        if (res != 0)
 +                return res;
 +        if (buffer == NULL)
 +                return -ENOENT;
  
          fd = open("/", O_CLOEXEC|O_NOFOLLOW|O_PATH);
          if (fd < 0)
                                  if (fd < 0)
                                          return -errno;
  
+                                 if (flags & CHASE_SAFE) {
+                                         if (fstat(fd, &st) < 0)
+                                                 return -errno;
+                                         if (!safe_transition(&previous_stat, &st))
+                                                 return -EPERM;
+                                         previous_stat = st;
+                                 }
                                  free(done);
  
 +                                if (flags & CHASE_SAFE) {
 +                                        if (fstat(fd, &st) < 0)
 +                                                return -errno;
 +
 +                                        if (!safe_transition(&previous_stat, &st))
 +                                                return -EPERM;
 +
 +                                        previous_stat = st;
 +                                }
 +
                                  /* Note that we do not revalidate the root, we take it as is. */
                                  if (isempty(root))
                                          done = NULL;
@@@ -975,6 -1047,6 +1047,10 @@@ struct input_mask 
  #define RTA_PREF 20
  #endif
  
++#ifndef RTAX_QUICKACK
++#define RTAX_QUICKACK 15
++#endif
++
  #ifndef IPV6_UNICAST_IF
  #define IPV6_UNICAST_IF 76
  #endif
Simple merge
@@@ -529,34 -531,10 +531,34 @@@ int safe_atoi16(const char *s, int16_t 
          return 0;
  }
  
 +int safe_atoux16(const char *s, uint16_t *ret) {
 +        char *x = NULL;
 +        unsigned long l;
 +
 +        assert(s);
 +        assert(ret);
 +
 +        s += strspn(s, WHITESPACE);
 +
 +        errno = 0;
 +        l = strtoul(s, &x, 16);
 +        if (errno > 0)
 +                return -errno;
 +        if (!x || x == s || *x != 0)
 +                return -EINVAL;
 +        if (s[0] == '-')
 +                return -ERANGE;
 +        if ((unsigned long) (uint16_t) l != l)
 +                return -ERANGE;
 +
 +        *ret = (uint16_t) l;
 +        return 0;
 +}
 +
  int safe_atod(const char *s, double *ret_d) {
+         _cleanup_(freelocalep) locale_t loc = (locale_t) 0;
          char *x = NULL;
          double d = 0;
-         locale_t loc;
  
          assert(s);
          assert(ret_d);
Simple merge
@@@ -65,13 -62,8 +65,14 @@@ static bool arg_expect_reply = true
  static bool arg_auto_start = true;
  static bool arg_allow_interactive_authorization = true;
  static bool arg_augment_creds = true;
+ static bool arg_watch_bind = false;
  static usec_t arg_timeout = 0;
 +static int arg_sender_pid = 0;
 +static int arg_receiver_pid = 0;
 +static bool arg_pid = false;
 +static bool arg_dot = false;
 +static bool monitor_run_condi = true;
 +static bool arg_well_known_names;
  
  #define NAME_IS_ACQUIRED INT_TO_PTR(1)
  #define NAME_IS_ACTIVATABLE INT_TO_PTR(2)
@@@ -1912,14 -1736,9 +1913,17 @@@ static int help(void) 
                 "     --allow-interactive-authorization=BOOL\n"
                 "                          Allow interactive authorization for operation\n"
                 "     --timeout=SECS       Maximum time to wait for method call completion\n"
-                "     --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n\n"
+                "     --augment-creds=BOOL Extend credential data with data read from /proc/$PID\n"
+                "     --watch-bind=BOOL    Wait for bus AF_UNIX socket to be bound in the file\n"
+                "                          system\n\n"
++               "\n"
 +               "     --pid=PID            Only show messages with pid equals PID\n"
 +               "     --sender-pid=SENDER_PID\n"
 +               "                          Only show message with sender pid equals SENDER_PID\n"
 +               "     --receiver-pid=RECEIVER_PID\n"
 +               "                          Only show message with receiver pid equals RECEIVER_PID\n"
 +               "     --well-known-names=BOOL \n"
 +               "                          Show well know names connected to unique names on graph\n"
                 "Commands:\n"
                 "  list                    List bus names\n"
                 "  status [SERVICE]        Show bus service, process or bus owner credentials\n"
@@@ -1983,10 -1780,7 +1987,11 @@@ static int parse_argv(int argc, char *a
                  ARG_ALLOW_INTERACTIVE_AUTHORIZATION,
                  ARG_TIMEOUT,
                  ARG_AUGMENT_CREDS,
+                 ARG_WATCH_BIND,
 +                ARG_PID,
 +                ARG_SENDER_PID,
 +                ARG_RECEIVER_PID,
 +                ARG_WELL_KNOWN_NAMES,
          };
  
          static const struct option options[] = {
                  { "allow-interactive-authorization", required_argument, NULL, ARG_ALLOW_INTERACTIVE_AUTHORIZATION },
                  { "timeout",      required_argument, NULL, ARG_TIMEOUT      },
                  { "augment-creds",required_argument, NULL, ARG_AUGMENT_CREDS},
+                 { "watch-bind",   required_argument, NULL, ARG_WATCH_BIND   },
 +                { "pid",          required_argument, NULL, ARG_PID},
 +                { "sender-pid", required_argument, NULL, ARG_SENDER_PID},
 +                { "receiver-pid", required_argument, NULL, ARG_RECEIVER_PID},
 +                { "well-known-names", required_argument, NULL, ARG_WELL_KNOWN_NAMES},
                  {},
          };
  
                          arg_augment_creds = !!r;
                          break;
  
+                 case ARG_WATCH_BIND:
+                         r = parse_boolean(optarg);
+                         if (r < 0) {
+                                 log_error("Failed to parse --watch-bind= parameter.");
+                                 return r;
+                         }
+                         arg_watch_bind = !!r;
+                         break;
 +                case ARG_PID:
 +                        arg_pid = true;
 +                        r = arg_parse_pid(optarg, true, true);
 +                        if (r < 0)
 +                                return r;
 +                        break;
 +
 +                case ARG_SENDER_PID:
 +                        r = arg_parse_pid(optarg, true, false);
 +                        if (r < 0)
 +                                return 0;
 +                        break;
 +
 +                case ARG_RECEIVER_PID:
 +                        r = arg_parse_pid(optarg, false, true);
 +                        if (r < 0)
 +                                return 0;
 +                        break;
 +
 +                case ARG_WELL_KNOWN_NAMES:
 +                        arg_well_known_names = parse_boolean(optarg);
 +                        break;
 +
                  case '?':
                          return -EINVAL;
  
@@@ -989,9 -997,8 +999,10 @@@ static void cgroup_context_apply
                          NULSTR_FOREACH_PAIR(x, y, auto_devices)
                                  whitelist_device(path, x, y);
  
+                         /* PTS (/dev/pts) devices may not be duplicated, but accessed */
                          whitelist_major(path, "pts", 'c', "rw");
 +                        whitelist_major(path, "kdbus", 'c', "rw");
 +                        whitelist_major(path, "kdbus/*", 'c', "rw");
                  }
  
                  LIST_FOREACH(device_allow, a, c->device_allow) {
Simple merge
Simple merge
diff --cc src/core/dbus.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/core/main.c
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
diff --cc src/core/unit.c
Simple merge
diff --cc src/core/unit.h
Simple merge
index a1eb37d,0000000..1bed18c
mode 100755,000000..100755
--- /dev/null
@@@ -1,363 -1,0 +1,364 @@@
-         log_set_target(LOG_TARGET_SAFE);
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  systemd 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.
 +
 +  systemd is distributed in the hope that it will be useful, but
 +  WITHOUT ANY WARRANTY; without even the implied warranty of
 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 +  Lesser General Public License for more details.
 +
 +  You should have received a copy of the GNU Lesser General Public License
 +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 +***/
 +
 +#include "alloc-util.h"
 +#include "bus-internal.h"
 +#include "bus-util.h"
 +#include "cgroup-util.h"
 +#include "conf-parser.h"
 +#include "dirent-util.h"
 +#include "fd-util.h"
 +#include "fileio.h"
 +#include "mkdir.h"
 +#include "special.h"
 +#include "unit-name.h"
 +#include "util.h"
 +
 +static const char *arg_dest_late = "/tmp", *arg_dest = "/tmp";
 +
 +static int create_dbus_files(
 +                const char *path,
 +                const char *name,
 +                const char *service,
 +                const char *exec,
 +                const char *user,
 +                const char *type) {
 +
 +        _cleanup_free_ char *b = NULL, *s = NULL, *lnk = NULL;
 +        _cleanup_fclose_ FILE *f = NULL;
 +        int r;
 +
 +        assert(path);
 +        assert(name);
 +        assert(service || exec);
 +
 +        if (!service) {
 +                _cleanup_free_ char *a = NULL;
 +
 +                s = strjoin("dbus-", name, ".service", NULL);
 +                if (!s)
 +                        return log_oom();
 +
 +                a = strjoin(arg_dest_late, "/", s, NULL);
 +                if (!a)
 +                        return log_oom();
 +
 +                f = fopen(a, "wxe");
 +                if (!f)
 +                        return log_error_errno(errno, "Failed to create %s: %m", a);
 +
 +                fprintf(f,
 +                        "# Automatically generated by systemd-dbus1-generator\n\n"
 +                        "[Unit]\n"
 +                        "SourcePath=%s\n"
 +                        "Description=DBUS1: %s\n"
 +                        "Documentation=man:systemd-dbus1-generator(8)\n\n"
 +                        "[Service]\n"
 +                        "ExecStart=%s\n"
 +                        "Type=dbus\n"
 +                        "BusName=%s\n",
 +                        path,
 +                        name,
 +                        exec,
 +                        name);
 +
 +                if (user)
 +                        fprintf(f, "User=%s\n", user);
 +
 +
 +                if (type) {
 +                        fprintf(f, "Environment=DBUS_STARTER_BUS_TYPE=%s\n", type);
 +
 +                        if (streq(type, "system"))
 +                                fprintf(f, "Environment=DBUS_STARTER_ADDRESS=" DEFAULT_SYSTEM_BUS_ADDRESS "\n");
 +                        else if (streq(type, "session")) {
 +                                char *run;
 +
 +                                run = getenv("XDG_RUNTIME_DIR");
 +                                if (!run) {
 +                                        log_error("XDG_RUNTIME_DIR not set.");
 +                                        return -EINVAL;
 +                                }
 +
 +                                fprintf(f, "Environment=DBUS_STARTER_ADDRESS="KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT "\n",
 +                                        getuid(), run);
 +                        }
 +                }
 +
 +                r = fflush_and_check(f);
 +                if (r < 0)
 +                        return log_error_errno(r, "Failed to write %s: %m", a);
 +
 +                f = safe_fclose(f);
 +
 +                service = s;
 +        }
 +
 +        b = strjoin(arg_dest_late, "/", name, ".busname", NULL);
 +        if (!b)
 +                return log_oom();
 +
 +        f = fopen(b, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", b);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "SourcePath=%s\n"
 +                "Description=DBUS1: %s\n"
 +                "Documentation=man:systemd-dbus1-generator(8)\n\n"
 +                "[BusName]\n"
 +                "Name=%s\n"
 +                "Service=%s\n"
 +                "AllowWorld=talk\n",
 +                path,
 +                name,
 +                name,
 +                service);
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", b);
 +
 +        lnk = strjoin(arg_dest_late, "/" SPECIAL_BUSNAMES_TARGET ".wants/", name, ".busname", NULL);
 +        if (!lnk)
 +                return log_oom();
 +
 +        mkdir_parents_label(lnk, 0755);
 +        if (symlink(b, lnk))
 +                return log_error_errno(errno, "Failed to create symlink %s: %m", lnk);
 +
 +        return 0;
 +}
 +
 +static int add_dbus(const char *path, const char *fname, const char *type) {
 +        _cleanup_free_ char *name = NULL, *exec = NULL, *user = NULL, *service = NULL;
 +
 +        const ConfigTableItem table[] = {
 +                { "D-BUS Service", "Name", config_parse_string, 0, &name },
 +                { "D-BUS Service", "Exec", config_parse_string, 0, &exec },
 +                { "D-BUS Service", "User", config_parse_string, 0, &user },
 +                { "D-BUS Service", "SystemdService", config_parse_string, 0, &service },
 +                { },
 +        };
 +
 +        char *p;
 +        int r;
 +
 +        assert(path);
 +        assert(fname);
 +
 +        p = strjoina(path, "/", fname);
 +        r = config_parse(NULL, p, NULL,
 +                         "D-BUS Service\0",
 +                         config_item_table_lookup, table,
 +                         CONFIG_PARSE_RELAXED|CONFIG_PARSE_WARN, NULL);
 +        if (r < 0)
 +                return r;
 +
 +        if (!name) {
 +                log_warning("Activation file %s lacks name setting, ignoring.", p);
 +                return 0;
 +        }
 +
 +        if (!service_name_is_valid(name)) {
 +                log_warning("Bus service name %s is not valid, ignoring.", name);
 +                return 0;
 +        }
 +
 +        if (streq(name, "org.freedesktop.systemd1")) {
 +                log_debug("Skipping %s, identified as systemd.", p);
 +                return 0;
 +        }
 +
 +        if (service) {
 +                if (!unit_name_is_valid(service, UNIT_NAME_PLAIN|UNIT_NAME_INSTANCE)) {
 +                        log_warning("Unit name %s is not valid, ignoring.", service);
 +                        return 0;
 +                }
 +                if (!endswith(service, ".service")) {
 +                        log_warning("Bus names can only activate services, ignoring %s.", p);
 +                        return 0;
 +                }
 +        } else {
 +                if (!exec || streq(exec, "/bin/false")) {
 +                        log_warning("Neither service name nor binary path specified, ignoring %s.", p);
 +                        return 0;
 +                }
 +
 +                if (exec[0] != '/') {
 +                        log_warning("Exec= in %s does not start with an absolute path, ignoring.", p);
 +                        return 0;
 +                }
 +        }
 +
 +        return create_dbus_files(p, name, service, exec, user, type);
 +}
 +
 +static int parse_dbus_fragments(const char *path, const char *type) {
 +        _cleanup_closedir_ DIR *d = NULL;
 +        struct dirent *de;
 +        int r;
 +
 +        assert(path);
 +        assert(type);
 +
 +        d = opendir(path);
 +        if (!d) {
 +                if (errno == -ENOENT)
 +                        return 0;
 +
 +                return log_error_errno(errno, "Failed to enumerate D-Bus activated services: %m");
 +        }
 +
 +        r = 0;
 +        FOREACH_DIRENT(de, d, goto fail) {
 +                int q;
 +
 +                if (!endswith(de->d_name, ".service"))
 +                        continue;
 +
 +                q = add_dbus(path, de->d_name, type);
 +                if (q < 0)
 +                        r = q;
 +        }
 +
 +        return r;
 +
 +fail:
 +        return log_error_errno(errno, "Failed to read D-Bus services directory: %m");
 +}
 +
 +static int link_busnames_target(const char *units) {
 +        const char *f, *t;
 +
 +        f = strjoina(units, "/" SPECIAL_BUSNAMES_TARGET);
 +        t = strjoina(arg_dest, "/" SPECIAL_BASIC_TARGET ".wants/" SPECIAL_BUSNAMES_TARGET);
 +
 +        mkdir_parents_label(t, 0755);
 +        if (symlink(f, t) < 0)
 +                return log_error_errno(errno, "Failed to create symlink %s: %m", t);
 +
 +        return 0;
 +}
 +
 +static int create_compatibility(const char *units, const char *type) {
 +        const char *t;
 +        _cleanup_fclose_ FILE *f = NULL;
 +        int r;
 +
 +        t = strjoina(arg_dest, "/" SPECIAL_DBUS_SERVICE);
 +        if (!t)
 +                return log_oom();
 +
 +        f = fopen(t, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", t);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "Description=DBUS1: dbus.service for kdbus compatibility\n"
 +                "[Service]\n"
 +                "ExecStart=/bin/true\n"
 +                "RemainAfterExit=yes\n");
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", t);
 +
 +        f = safe_fclose(f);
 +
 +
 +        t = strjoina(arg_dest, "/" SPECIAL_DBUS_SOCKET);
 +        if (!t)
 +                return log_oom();
 +
 +        f = fopen(t, "wxe");
 +        if (!f)
 +                return log_error_errno(errno, "Failed to create %s: %m", t);
 +
 +        fprintf(f,
 +                "# Automatically generated by systemd-dbus1-generator\n\n"
 +                "[Unit]\n"
 +                "Description=DBUS1: dbus.socket for kdbus compatibility\n"
 +                "[Socket]\n"
 +                "SmackLabelIPIn=^\n"
 +                "ListenStream=@/tmp/.kdbus_bus_%s_%d\n", type, getuid());
 +
 +
 +        r = fflush_and_check(f);
 +        if (r < 0)
 +                return log_error_errno(r, "Failed to write %s: %m", t);
 +
 +        f = safe_fclose(f);
 +
 +        return 0;
 +}
 +
 +int main(int argc, char *argv[]) {
 +        const char *path, *type, *units;
 +        int r, q;
 +
 +        if (argc > 1 && argc != 4) {
 +                log_error("This program takes three or no arguments.");
 +                return EXIT_FAILURE;
 +        }
 +
 +        if (argc > 1) {
 +                arg_dest = argv[1];
 +                arg_dest_late = argv[3];
 +        }
 +
++        log_set_prohibit_ipc(true);
++        log_set_target(LOG_TARGET_AUTO);
 +        log_parse_environment();
 +        log_open();
 +
 +        umask(0022);
 +
 +        if (!is_kdbus_available())
 +                return 0;
 +
 +        r = cg_pid_get_owner_uid(0, NULL);
 +        if (r >= 0) {
 +                path = "/usr/share/dbus-1/services";
 +                type = "session";
 +                units = USER_DATA_UNIT_PATH;
 +        } else if (r == -ENXIO) {
 +                path = "/usr/share/dbus-1/system-services";
 +                type = "system";
 +                units = SYSTEM_DATA_UNIT_PATH;
 +        } else
 +                return log_error_errno(r, "Failed to determine whether we are running as user or system instance: %m");
 +
 +        r = parse_dbus_fragments(path, type);
 +
 +        /* FIXME: One day this should just be pulled in statically from basic.target */
 +        q = link_busnames_target(units);
 +        if (q < 0)
 +                r = q;
 +
 +        q = create_compatibility(units, type);
 +        if (q < 0)
 +                r = q;
 +
 +        return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS;
 +}
@@@ -26,6 -24,6 +24,8 @@@ libsystemd_sources = files(''
          sd-bus/bus-container.h
          sd-bus/bus-control.c
          sd-bus/bus-control.h
++        sd-bus/bus-control-kernel.c
++        sd-bus/bus-control-kernel.h
          sd-bus/bus-convenience.c
          sd-bus/bus-creds.c
          sd-bus/bus-creds.h
@@@ -133,146 -129,5 +129,140 @@@ int bus_container_connect_socket(sd_bu
                          return -error_buf;
          }
  
-         if (si.si_code != CLD_EXITED)
-                 return -EIO;
-         if (si.si_status != EXIT_SUCCESS)
-                 return -EIO;
          return bus_socket_start_auth(b);
  }
 +
 +int bus_container_connect_kernel(sd_bus *b) {
 +        _cleanup_close_pair_ int pair[2] = { -1, -1 };
 +        _cleanup_close_ int pidnsfd = -1, mntnsfd = -1, usernsfd = -1, rootfd = -1;
 +        union {
 +                struct cmsghdr cmsghdr;
 +                uint8_t buf[CMSG_SPACE(sizeof(int))];
 +        } control = {};
 +        int error_buf = 0;
 +        struct iovec iov = {
 +                .iov_base = &error_buf,
 +                .iov_len = sizeof(error_buf),
 +        };
 +        struct msghdr mh = {
 +                .msg_control = &control,
 +                .msg_controllen = sizeof(control),
 +                .msg_iov = &iov,
 +                .msg_iovlen = 1,
 +        };
 +        struct cmsghdr *cmsg;
 +        pid_t child;
 +        siginfo_t si;
 +        int r, fd = -1;
 +        ssize_t n;
 +
 +        assert(b);
 +        assert(b->input_fd < 0);
 +        assert(b->output_fd < 0);
 +        assert(b->nspid > 0 || b->machine);
 +
 +        if (b->nspid <= 0) {
 +                r = container_get_leader(b->machine, &b->nspid);
 +                if (r < 0)
 +                        return r;
 +        }
 +
 +        r = namespace_open(b->nspid, &pidnsfd, &mntnsfd, NULL, &usernsfd, &rootfd);
 +        if (r < 0)
 +                return r;
 +
 +        if (socketpair(AF_UNIX, SOCK_SEQPACKET, 0, pair) < 0)
 +                return -errno;
 +
 +        child = fork();
 +        if (child < 0)
 +                return -errno;
 +
 +        if (child == 0) {
 +                pid_t grandchild;
 +
 +                pair[0] = safe_close(pair[0]);
 +
 +                r = namespace_enter(pidnsfd, mntnsfd, -1, usernsfd, rootfd);
 +                if (r < 0)
 +                        _exit(EXIT_FAILURE);
 +
 +                /* We just changed PID namespace, however it will only
 +                 * take effect on the children we now fork. Hence,
 +                 * let's fork another time, and connect from this
 +                 * grandchild, so that kdbus only sees the credentials
 +                 * of this process which comes from within the
 +                 * container, and not outside of it */
 +
 +                grandchild = fork();
 +                if (grandchild < 0)
 +                        _exit(EXIT_FAILURE);
 +
 +                if (grandchild == 0) {
 +                        fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
 +                        if (fd < 0) {
 +                                /* Try to send error up */
 +                                error_buf = errno;
 +                                (void) write(pair[1], &error_buf, sizeof(error_buf));
 +                                _exit(EXIT_FAILURE);
 +                        }
 +
 +                        r = send_one_fd(pair[1], fd, 0);
 +                        if (r < 0)
 +                                _exit(EXIT_FAILURE);
 +
 +                        _exit(EXIT_SUCCESS);
 +                }
 +
 +                r = wait_for_terminate(grandchild, &si);
 +                if (r < 0)
 +                        _exit(EXIT_FAILURE);
 +
 +                if (si.si_code != CLD_EXITED)
 +                        _exit(EXIT_FAILURE);
 +
 +                _exit(si.si_status);
 +        }
 +
 +        pair[1] = safe_close(pair[1]);
 +
 +        r = wait_for_terminate(child, &si);
 +        if (r < 0)
 +                return r;
 +
 +        n = recvmsg(pair[0], &mh, MSG_NOSIGNAL|MSG_CMSG_CLOEXEC);
 +        if (n < 0)
 +                return -errno;
 +
 +        CMSG_FOREACH(cmsg, &mh) {
 +                if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
 +                        int *fds;
 +                        unsigned n_fds;
 +
 +                        assert(fd < 0);
 +
 +                        fds = (int*) CMSG_DATA(cmsg);
 +                        n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
 +
 +                        if (n_fds != 1) {
 +                                close_many(fds, n_fds);
 +                                return -EIO;
 +                        }
 +
 +                        fd = fds[0];
 +                }
 +        }
 +
 +        /* If there's an fd passed, we are good. */
 +        if (fd >= 0) {
 +                b->input_fd = b->output_fd = fd;
 +                return bus_kernel_take_fd(b);
 +        }
 +
 +        /* If there's an error passed, use it */
 +        if (n == sizeof(error_buf) && error_buf > 0)
 +                return -error_buf;
 +
 +        /* Otherwise, we have no clue */
 +        return -EIO;
 +}
index 0000000,0000000..5508c58
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,1047 @@@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++/***
++  This file is part of systemd.
++
++  Copyright 2013 Lennart Poettering
++
++  systemd 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.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  Lesser General Public License for more details.
++
++  You should have received a copy of the GNU Lesser General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++#if HAVE_VALGRIND_MEMCHECK_H
++#include <valgrind/memcheck.h>
++#endif
++
++#include <errno.h>
++#include <stddef.h>
++
++#include "sd-bus.h"
++
++#include "alloc-util.h"
++//#include "bus-bloom.h"
++#include "bus-control-kernel.h"
++#include "bus-internal.h"
++#include "bus-message.h"
++#include "bus-util.h"
++#include "capability-util.h"
++#include "process-util.h"
++#include "stdio-util.h"
++#include "string-util.h"
++#include "strv.h"
++#include "user-util.h"
++
++int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags) {
++        struct kdbus_cmd *n;
++        size_t size, l;
++        int r;
++
++        assert(bus);
++        assert(name);
++
++        l = strlen(name) + 1;
++        size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
++        n = alloca0_align(size, 8);
++        n->size = size;
++        n->flags = request_name_flags_to_kdbus(flags);
++
++        n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
++        n->items[0].type = KDBUS_ITEM_NAME;
++        memcpy(n->items[0].str, name, l);
++
++#if HAVE_VALGRIND_MEMCHECK_H
++        VALGRIND_MAKE_MEM_DEFINED(n, n->size);
++#endif
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n);
++        if (r < 0)
++                return -errno;
++
++        if (n->return_flags & KDBUS_NAME_IN_QUEUE)
++                return 0;
++
++        return 1;
++}
++
++int bus_release_name_kernel(sd_bus *bus, const char *name) {
++        struct kdbus_cmd *n;
++        size_t size, l;
++        int r;
++
++        assert(bus);
++        assert(name);
++
++        l = strlen(name) + 1;
++        size = offsetof(struct kdbus_cmd, items) + KDBUS_ITEM_SIZE(l);
++        n = alloca0_align(size, 8);
++        n->size = size;
++
++        n->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
++        n->items[0].type = KDBUS_ITEM_NAME;
++        memcpy(n->items[0].str, name, l);
++
++#if HAVE_VALGRIND_MEMCHECK_H
++        VALGRIND_MAKE_MEM_DEFINED(n, n->size);
++#endif
++        r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n);
++        if (r < 0)
++                return -errno;
++
++        return 0;
++}
++
++static int kernel_get_list(sd_bus *bus, uint64_t flags, char ***x) {
++        struct kdbus_cmd_list cmd = {
++                .size = sizeof(cmd),
++                .flags = flags,
++        };
++        struct kdbus_info *name_list, *name;
++        uint64_t previous_id = 0;
++        int r;
++
++        /* Caller will free half-constructed list on failure... */
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_LIST, &cmd);
++        if (r < 0)
++                return -errno;
++
++        name_list = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
++
++        KDBUS_FOREACH(name, name_list, cmd.list_size) {
++                struct kdbus_item *item;
++
++                if ((flags & KDBUS_LIST_UNIQUE) && name->id != previous_id && !(name->flags & KDBUS_HELLO_ACTIVATOR)) {
++                        char *n;
++
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wformat"
++                        if (asprintf(&n, ":1.%llu", name->id) < 0) {
++                                r = -ENOMEM;
++                                goto fail;
++                        }
++#pragma GCC diagnostic pop
++
++                        r = strv_consume(x, n);
++                        if (r < 0)
++                                goto fail;
++
++                        previous_id = name->id;
++                }
++
++                KDBUS_ITEM_FOREACH(item, name, items) {
++                        if (item->type == KDBUS_ITEM_OWNED_NAME) {
++                                if (service_name_is_valid(item->name.name)) {
++                                        r = strv_extend(x, item->name.name);
++                                        if (r < 0) {
++                                                r = -ENOMEM;
++                                                goto fail;
++                                        }
++                                }
++                        }
++                }
++        }
++
++        r = 0;
++
++fail:
++        bus_kernel_cmd_free(bus, cmd.offset);
++        return r;
++}
++
++int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable) {
++        _cleanup_strv_free_ char **x = NULL, **y = NULL;
++        int r;
++
++        if (acquired) {
++                r = kernel_get_list(bus, KDBUS_LIST_UNIQUE | KDBUS_LIST_NAMES, &x);
++                if (r < 0)
++                        return r;
++        }
++
++        if (activatable) {
++                r = kernel_get_list(bus, KDBUS_LIST_ACTIVATORS, &y);
++                if (r < 0)
++                        return r;
++
++                *activatable = y;
++                y = NULL;
++        }
++
++        if (acquired) {
++                *acquired = x;
++                x = NULL;
++        }
++
++        return 0;
++}
++
++static int bus_populate_creds_from_items(
++                sd_bus *bus,
++                struct kdbus_info *info,
++                uint64_t mask,
++                sd_bus_creds *c) {
++
++        struct kdbus_item *item;
++        uint64_t m;
++        int r;
++
++        assert(bus);
++        assert(info);
++        assert(c);
++
++        KDBUS_ITEM_FOREACH(item, info, items) {
++
++                switch (item->type) {
++
++                case KDBUS_ITEM_PIDS:
++
++                        if (mask & SD_BUS_CREDS_PID && item->pids.pid > 0) {
++                                c->pid = (pid_t) item->pids.pid;
++                                c->mask |= SD_BUS_CREDS_PID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_TID && item->pids.tid > 0) {
++                                c->tid = (pid_t) item->pids.tid;
++                                c->mask |= SD_BUS_CREDS_TID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_PPID) {
++                                if (item->pids.ppid > 0) {
++                                        c->ppid = (pid_t) item->pids.ppid;
++                                        c->mask |= SD_BUS_CREDS_PPID;
++                                } else if (item->pids.pid == 1) {
++                                        /* The structure doesn't
++                                         * really distinguish the case
++                                         * where a process has no
++                                         * parent and where we don't
++                                         * know it because it could
++                                         * not be translated due to
++                                         * namespaces. However, we
++                                         * know that PID 1 has no
++                                         * parent process, hence let's
++                                         * patch that in, manually. */
++                                        c->ppid = 0;
++                                        c->mask |= SD_BUS_CREDS_PPID;
++                                }
++                        }
++
++                        break;
++
++                case KDBUS_ITEM_CREDS:
++
++                        if (mask & SD_BUS_CREDS_UID && (uid_t) item->creds.uid != UID_INVALID) {
++                                c->uid = (uid_t) item->creds.uid;
++                                c->mask |= SD_BUS_CREDS_UID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_EUID && (uid_t) item->creds.euid != UID_INVALID) {
++                                c->euid = (uid_t) item->creds.euid;
++                                c->mask |= SD_BUS_CREDS_EUID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_SUID && (uid_t) item->creds.suid != UID_INVALID) {
++                                c->suid = (uid_t) item->creds.suid;
++                                c->mask |= SD_BUS_CREDS_SUID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_FSUID && (uid_t) item->creds.fsuid != UID_INVALID) {
++                                c->fsuid = (uid_t) item->creds.fsuid;
++                                c->mask |= SD_BUS_CREDS_FSUID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_GID && (gid_t) item->creds.gid != GID_INVALID) {
++                                c->gid = (gid_t) item->creds.gid;
++                                c->mask |= SD_BUS_CREDS_GID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_EGID && (gid_t) item->creds.egid != GID_INVALID) {
++                                c->egid = (gid_t) item->creds.egid;
++                                c->mask |= SD_BUS_CREDS_EGID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_SGID && (gid_t) item->creds.sgid != GID_INVALID) {
++                                c->sgid = (gid_t) item->creds.sgid;
++                                c->mask |= SD_BUS_CREDS_SGID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_FSGID && (gid_t) item->creds.fsgid != GID_INVALID) {
++                                c->fsgid = (gid_t) item->creds.fsgid;
++                                c->mask |= SD_BUS_CREDS_FSGID;
++                        }
++
++                        break;
++
++                case KDBUS_ITEM_PID_COMM:
++                        if (mask & SD_BUS_CREDS_COMM) {
++                                r = free_and_strdup(&c->comm, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_COMM;
++                        }
++                        break;
++
++                case KDBUS_ITEM_TID_COMM:
++                        if (mask & SD_BUS_CREDS_TID_COMM) {
++                                r = free_and_strdup(&c->tid_comm, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_TID_COMM;
++                        }
++                        break;
++
++                case KDBUS_ITEM_EXE:
++                        if (mask & SD_BUS_CREDS_EXE) {
++                                r = free_and_strdup(&c->exe, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_EXE;
++                        }
++                        break;
++
++                case KDBUS_ITEM_CMDLINE:
++                        if (mask & SD_BUS_CREDS_CMDLINE) {
++                                c->cmdline_size = item->size - offsetof(struct kdbus_item, data);
++                                c->cmdline = memdup(item->data, c->cmdline_size);
++                                if (!c->cmdline)
++                                        return -ENOMEM;
++
++                                c->mask |= SD_BUS_CREDS_CMDLINE;
++                        }
++                        break;
++
++                case KDBUS_ITEM_CGROUP:
++                        m = (SD_BUS_CREDS_CGROUP | SD_BUS_CREDS_UNIT |
++                             SD_BUS_CREDS_USER_UNIT | SD_BUS_CREDS_SLICE |
++                             SD_BUS_CREDS_SESSION | SD_BUS_CREDS_OWNER_UID) & mask;
++
++                        if (m) {
++                                r = free_and_strdup(&c->cgroup, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                r = bus_get_root_path(bus);
++                                if (r < 0)
++                                        return r;
++
++                                r = free_and_strdup(&c->cgroup_root, bus->cgroup_root);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= m;
++                        }
++                        break;
++
++                case KDBUS_ITEM_CAPS:
++                        m = (SD_BUS_CREDS_EFFECTIVE_CAPS | SD_BUS_CREDS_PERMITTED_CAPS |
++                             SD_BUS_CREDS_INHERITABLE_CAPS | SD_BUS_CREDS_BOUNDING_CAPS) & mask;
++
++                        if (m) {
++                                if (item->caps.last_cap != cap_last_cap() ||
++                                    item->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(item->caps.last_cap, 32U) * 4 * 4)
++                                        return -EBADMSG;
++
++                                c->capability = memdup(item->caps.caps, item->size - offsetof(struct kdbus_item, caps.caps));
++                                if (!c->capability)
++                                        return -ENOMEM;
++
++                                c->mask |= m;
++                        }
++                        break;
++
++                case KDBUS_ITEM_SECLABEL:
++                        if (mask & SD_BUS_CREDS_SELINUX_CONTEXT) {
++                                r = free_and_strdup(&c->label, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_SELINUX_CONTEXT;
++                        }
++                        break;
++
++                case KDBUS_ITEM_AUDIT:
++                        if (mask & SD_BUS_CREDS_AUDIT_SESSION_ID) {
++                                c->audit_session_id = (uint32_t) item->audit.sessionid;
++                                c->mask |= SD_BUS_CREDS_AUDIT_SESSION_ID;
++                        }
++
++                        if (mask & SD_BUS_CREDS_AUDIT_LOGIN_UID) {
++                                c->audit_login_uid = (uid_t) item->audit.loginuid;
++                                c->mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID;
++                        }
++                        break;
++
++                case KDBUS_ITEM_OWNED_NAME:
++                        if ((mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) && service_name_is_valid(item->name.name)) {
++                                r = strv_extend(&c->well_known_names, item->name.name);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
++                        }
++                        break;
++
++                case KDBUS_ITEM_CONN_DESCRIPTION:
++                        if (mask & SD_BUS_CREDS_DESCRIPTION) {
++                                r = free_and_strdup(&c->description, item->str);
++                                if (r < 0)
++                                        return r;
++
++                                c->mask |= SD_BUS_CREDS_DESCRIPTION;
++                        }
++                        break;
++
++                case KDBUS_ITEM_AUXGROUPS:
++                        if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
++                                size_t i, n;
++                                uid_t *g;
++
++                                n = (item->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
++                                g = new(gid_t, n);
++                                if (!g)
++                                        return -ENOMEM;
++
++                                for (i = 0; i < n; i++)
++                                        g[i] = item->data64[i];
++
++                                free(c->supplementary_gids);
++                                c->supplementary_gids = g;
++                                c->n_supplementary_gids = n;
++
++                                c->mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
++                        }
++                        break;
++                }
++        }
++
++        return 0;
++}
++
++static uint64_t attach_flags_to_kdbus(uint64_t mask) {
++        uint64_t m = 0;
++
++        if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
++                    SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
++                m |= KDBUS_ATTACH_CREDS;
++
++        if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
++                m |= KDBUS_ATTACH_PIDS;
++
++        if (mask & SD_BUS_CREDS_COMM)
++                m |= KDBUS_ATTACH_PID_COMM;
++
++        if (mask & SD_BUS_CREDS_TID_COMM)
++                m |= KDBUS_ATTACH_TID_COMM;
++
++        if (mask & SD_BUS_CREDS_EXE)
++                m |= KDBUS_ATTACH_EXE;
++
++        if (mask & SD_BUS_CREDS_CMDLINE)
++                m |= KDBUS_ATTACH_CMDLINE;
++
++        if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
++                m |= KDBUS_ATTACH_CGROUP;
++
++        if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
++                m |= KDBUS_ATTACH_CAPS;
++
++        if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
++                m |= KDBUS_ATTACH_SECLABEL;
++
++        if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
++                m |= KDBUS_ATTACH_AUDIT;
++
++        if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
++                m |= KDBUS_ATTACH_NAMES;
++
++        if (mask & SD_BUS_CREDS_DESCRIPTION)
++                m |= KDBUS_ATTACH_CONN_DESCRIPTION;
++
++        if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
++                m |= KDBUS_ATTACH_AUXGROUPS;
++
++        return m;
++}
++
++int bus_get_name_creds_kdbus(
++                sd_bus *bus,
++                const char *name,
++                uint64_t mask,
++                bool allow_activator,
++                sd_bus_creds **creds) {
++
++        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
++        struct kdbus_cmd_info *cmd;
++        struct kdbus_info *conn_info;
++        size_t size, l;
++        uint64_t id;
++        int r;
++
++        if (streq(name, "org.freedesktop.DBus"))
++                return -EOPNOTSUPP;
++
++        r = bus_kernel_parse_unique_name(name, &id);
++        if (r < 0)
++                return r;
++        if (r > 0) {
++                size = offsetof(struct kdbus_cmd_info, items);
++                cmd = alloca0_align(size, 8);
++                cmd->id = id;
++        } else {
++                l = strlen(name) + 1;
++                size = offsetof(struct kdbus_cmd_info, items) + KDBUS_ITEM_SIZE(l);
++                cmd = alloca0_align(size, 8);
++                cmd->items[0].size = KDBUS_ITEM_HEADER_SIZE + l;
++                cmd->items[0].type = KDBUS_ITEM_NAME;
++                memcpy(cmd->items[0].str, name, l);
++        }
++
++        /* If augmentation is on, and the bus didn't provide us
++         * the bits we want, then ask for the PID/TID so that we
++         * can read the rest from /proc. */
++        if ((mask & SD_BUS_CREDS_AUGMENT) &&
++            (mask & (SD_BUS_CREDS_PPID|
++                     SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
++                     SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
++                     SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
++                     SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
++                     SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
++                     SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
++                     SD_BUS_CREDS_SELINUX_CONTEXT|
++                     SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
++                mask |= SD_BUS_CREDS_PID;
++
++        cmd->size = size;
++        cmd->attach_flags = attach_flags_to_kdbus(mask);
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_CONN_INFO, cmd);
++        if (r < 0)
++                return -errno;
++
++        conn_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd->offset);
++
++        /* Non-activated names are considered not available */
++        if (!allow_activator && (conn_info->flags & KDBUS_HELLO_ACTIVATOR)) {
++                if (name[0] == ':')
++                        r = -ENXIO;
++                else
++                        r = -ESRCH;
++                goto fail;
++        }
++
++        c = bus_creds_new();
++        if (!c) {
++                r = -ENOMEM;
++                goto fail;
++        }
++
++        if (mask & SD_BUS_CREDS_UNIQUE_NAME) {
++#pragma GCC diagnostic push
++#pragma GCC diagnostic ignored "-Wformat"
++                if (asprintf(&c->unique_name, ":1.%llu", conn_info->id) < 0) {
++                        r = -ENOMEM;
++                        goto fail;
++                }
++#pragma GCC diagnostic pop
++
++                c->mask |= SD_BUS_CREDS_UNIQUE_NAME;
++        }
++
++        /* If KDBUS_ITEM_OWNED_NAME is requested then we'll get 0 of
++           them in case the service has no names. This does not mean
++           however that the list of owned names could not be
++           acquired. Hence, let's explicitly clarify that the data is
++           complete. */
++        c->mask |= mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
++
++        r = bus_populate_creds_from_items(bus, conn_info, mask, c);
++        if (r < 0)
++                goto fail;
++
++        r = bus_creds_add_more(c, mask, 0, 0);
++        if (r < 0)
++                goto fail;
++
++        if (creds) {
++                *creds = c;
++                c = NULL;
++        }
++
++        r = 0;
++
++fail:
++        bus_kernel_cmd_free(bus, cmd->offset);
++        return r;
++}
++
++int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
++        _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
++        struct kdbus_cmd_info cmd = {
++                .size = sizeof(struct kdbus_cmd_info),
++        };
++        struct kdbus_info *creator_info;
++        pid_t pid = 0;
++        int r;
++
++        c = bus_creds_new();
++        if (!c)
++                return -ENOMEM;
++
++        /* If augmentation is on, and the bus doesn't didn't allow us
++         * to get the bits we want, then ask for the PID/TID so that we
++         * can read the rest from /proc. */
++        if ((mask & SD_BUS_CREDS_AUGMENT) &&
++            (mask & (SD_BUS_CREDS_PPID|
++                     SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
++                     SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
++                     SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
++                     SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
++                     SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
++                     SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
++                     SD_BUS_CREDS_SELINUX_CONTEXT|
++                     SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
++                mask |= SD_BUS_CREDS_PID;
++
++        cmd.attach_flags = attach_flags_to_kdbus(mask);
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
++        if (r < 0)
++                return -errno;
++
++        creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
++
++        r = bus_populate_creds_from_items(bus, creator_info, mask, c);
++        bus_kernel_cmd_free(bus, cmd.offset);
++        if (r < 0)
++                return r;
++
++        r = bus_creds_add_more(c, mask, pid, 0);
++        if (r < 0)
++                return r;
++
++        *ret = c;
++        c = NULL;
++        return 0;
++}
++
++static int add_name_change_match(sd_bus *bus,
++                                 uint64_t cookie,
++                                 const char *name,
++                                 const char *old_owner,
++                                 const char *new_owner) {
++
++        uint64_t name_id = KDBUS_MATCH_ID_ANY, old_owner_id = 0, new_owner_id = 0;
++        int is_name_id = -1, r;
++        struct kdbus_item *item;
++
++        assert(bus);
++
++        /* If we encounter a match that could match against
++         * NameOwnerChanged messages, then we need to create
++         * KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE} and
++         * KDBUS_ITEM_ID_{ADD,REMOVE} matches for it, possibly
++         * multiple if the match is underspecified.
++         *
++         * The NameOwnerChanged signals take three parameters with
++         * unique or well-known names, but only some forms actually
++         * exist:
++         *
++         * WELLKNOWN, "", UNIQUE       â†’ KDBUS_ITEM_NAME_ADD
++         * WELLKNOWN, UNIQUE, ""       â†’ KDBUS_ITEM_NAME_REMOVE
++         * WELLKNOWN, UNIQUE, UNIQUE   â†’ KDBUS_ITEM_NAME_CHANGE
++         * UNIQUE, "", UNIQUE          â†’ KDBUS_ITEM_ID_ADD
++         * UNIQUE, UNIQUE, ""          â†’ KDBUS_ITEM_ID_REMOVE
++         *
++         * For the latter two the two unique names must be identical.
++         *
++         * */
++
++        if (name) {
++                is_name_id = bus_kernel_parse_unique_name(name, &name_id);
++                if (is_name_id < 0)
++                        return 0;
++        }
++
++        if (!isempty(old_owner)) {
++                r = bus_kernel_parse_unique_name(old_owner, &old_owner_id);
++                if (r < 0)
++                        return 0;
++                if (r == 0)
++                        return 0;
++                if (is_name_id > 0 && old_owner_id != name_id)
++                        return 0;
++        } else
++                old_owner_id = KDBUS_MATCH_ID_ANY;
++
++        if (!isempty(new_owner)) {
++                r = bus_kernel_parse_unique_name(new_owner, &new_owner_id);
++                if (r < 0)
++                        return r;
++                if (r == 0)
++                        return 0;
++                if (is_name_id > 0 && new_owner_id != name_id)
++                        return 0;
++        } else
++                new_owner_id = KDBUS_MATCH_ID_ANY;
++
++        if (is_name_id <= 0) {
++                struct kdbus_cmd_match *m;
++                size_t sz, l;
++
++                /* If the name argument is missing or is a well-known
++                 * name, then add KDBUS_ITEM_NAME_{ADD,REMOVE,CHANGE}
++                 * matches for it */
++
++                l = name ? strlen(name) + 1 : 0;
++
++                sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
++                            offsetof(struct kdbus_item, name_change) +
++                            offsetof(struct kdbus_notify_name_change, name) +
++                            l);
++
++                m = alloca0_align(sz, 8);
++                m->size = sz;
++                m->cookie = cookie;
++
++                item = m->items;
++                item->size =
++                        offsetof(struct kdbus_item, name_change) +
++                        offsetof(struct kdbus_notify_name_change, name) +
++                        l;
++
++                item->name_change.old_id.id = old_owner_id;
++                item->name_change.new_id.id = new_owner_id;
++
++                memcpy_safe(item->name_change.name, name, l);
++
++                /* If the old name is unset or empty, then
++                 * this can match against added names */
++                if (isempty(old_owner)) {
++                        item->type = KDBUS_ITEM_NAME_ADD;
++
++                        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++                        if (r < 0)
++                                return -errno;
++                }
++
++                /* If the new name is unset or empty, then
++                 * this can match against removed names */
++                if (isempty(new_owner)) {
++                        item->type = KDBUS_ITEM_NAME_REMOVE;
++
++                        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++                        if (r < 0)
++                                return -errno;
++                }
++
++                /* The CHANGE match we need in either case, because
++                 * what is reported as a name change by the kernel
++                 * might just be an owner change between starter and
++                 * normal clients. For userspace such a change should
++                 * be considered a removal/addition, hence let's
++                 * subscribe to this unconditionally. */
++                item->type = KDBUS_ITEM_NAME_CHANGE;
++                r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++                if (r < 0)
++                        return -errno;
++        }
++
++        if (is_name_id != 0) {
++                struct kdbus_cmd_match *m;
++                uint64_t sz;
++
++                /* If the name argument is missing or is a unique
++                 * name, then add KDBUS_ITEM_ID_{ADD,REMOVE} matches
++                 * for it */
++
++                sz = ALIGN8(offsetof(struct kdbus_cmd_match, items) +
++                            offsetof(struct kdbus_item, id_change) +
++                            sizeof(struct kdbus_notify_id_change));
++
++                m = alloca0_align(sz, 8);
++                m->size = sz;
++                m->cookie = cookie;
++
++                item = m->items;
++                item->size =
++                        offsetof(struct kdbus_item, id_change) +
++                        sizeof(struct kdbus_notify_id_change);
++                item->id_change.id = name_id;
++
++                /* If the old name is unset or empty, then this can
++                 * match against added ids */
++                if (isempty(old_owner)) {
++                        item->type = KDBUS_ITEM_ID_ADD;
++                        if (!isempty(new_owner))
++                                item->id_change.id = new_owner_id;
++
++                        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++                        if (r < 0)
++                                return -errno;
++                }
++
++                /* If thew new name is unset or empty, then this can
++                 * match against removed ids */
++                if (isempty(new_owner)) {
++                        item->type = KDBUS_ITEM_ID_REMOVE;
++                        if (!isempty(old_owner))
++                                item->id_change.id = old_owner_id;
++
++                        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++                        if (r < 0)
++                                return -errno;
++                }
++        }
++
++        return 0;
++}
++
++int bus_add_match_internal_kernel(
++                sd_bus *bus,
++                struct bus_match_component *components,
++                unsigned n_components,
++                uint64_t cookie) {
++
++        struct kdbus_cmd_match *m;
++        struct kdbus_item *item;
++        uint64_t *bloom;
++        size_t sz;
++        const char *sender = NULL;
++        size_t sender_length = 0;
++        uint64_t src_id = KDBUS_MATCH_ID_ANY, dst_id = KDBUS_MATCH_ID_ANY;
++        bool using_bloom = false;
++        unsigned i;
++        bool matches_name_change = true;
++        const char *name_change_arg[3] = {};
++        int r;
++
++        assert(bus);
++
++        /* Monitor streams don't support matches, make this a NOP */
++        //if (bus->hello_flags & KDBUS_HELLO_MONITOR)
++                //return 0;
++
++        bloom = alloca0(bus->bloom_size);
++
++        sz = ALIGN8(offsetof(struct kdbus_cmd_match, items));
++
++        for (i = 0; i < n_components; i++) {
++                struct bus_match_component *c = &components[i];
++
++                switch (c->type) {
++
++                case BUS_MATCH_SENDER:
++                        if (!streq(c->value_str, "org.freedesktop.DBus"))
++                                matches_name_change = false;
++
++                        r = bus_kernel_parse_unique_name(c->value_str, &src_id);
++                        if (r < 0)
++                                return r;
++                        else if (r > 0)
++                                sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
++                        else  {
++                                sender = c->value_str;
++                                sender_length = strlen(sender);
++                                sz += ALIGN8(offsetof(struct kdbus_item, str) + sender_length + 1);
++                        }
++
++                        break;
++
++                case BUS_MATCH_MESSAGE_TYPE:
++                        if (c->value_u8 != SD_BUS_MESSAGE_SIGNAL)
++                                matches_name_change = false;
++
++//                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "message-type", bus_message_type_to_string(c->value_u8));
++                        using_bloom = true;
++                        break;
++
++                case BUS_MATCH_INTERFACE:
++                        if (!streq(c->value_str, "org.freedesktop.DBus"))
++                                matches_name_change = false;
++
++//                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "interface", c->value_str);
++                        using_bloom = true;
++                        break;
++
++                case BUS_MATCH_MEMBER:
++                        if (!streq(c->value_str, "NameOwnerChanged"))
++                                matches_name_change = false;
++
++//                        bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "member", c->value_str);
++                        using_bloom = true;
++                        break;
++
++                case BUS_MATCH_PATH:
++                        if (!streq(c->value_str, "/org/freedesktop/DBus"))
++                                matches_name_change = false;
++
++                        //bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path", c->value_str);
++                        using_bloom = true;
++                        break;
++
++                case BUS_MATCH_PATH_NAMESPACE:
++                        //bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, "path-slash-prefix", c->value_str);
++                        using_bloom = true;
++                        break;
++
++                case BUS_MATCH_ARG...BUS_MATCH_ARG_LAST: {
++                        char buf[sizeof("arg")-1 + 2 + 1];
++
++                        if (c->type - BUS_MATCH_ARG < 3)
++                                name_change_arg[c->type - BUS_MATCH_ARG] = c->value_str;
++
++                        xsprintf(buf, "arg%i", c->type - BUS_MATCH_ARG);
++                        //bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
++                        using_bloom = true;
++                        break;
++                }
++
++                case BUS_MATCH_ARG_HAS...BUS_MATCH_ARG_HAS_LAST: {
++                        char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
++
++                        xsprintf(buf, "arg%i-has", c->type - BUS_MATCH_ARG_HAS);
++                        //bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
++                        using_bloom = true;
++                        break;
++                }
++
++                case BUS_MATCH_ARG_PATH...BUS_MATCH_ARG_PATH_LAST:
++                        /*
++                         * XXX: DBus spec defines arg[0..63]path= matching to be
++                         * a two-way glob. That is, if either string is a prefix
++                         * of the other, it matches.
++                         * This is really hard to realize in bloom-filters, as
++                         * we would have to create a bloom-match for each prefix
++                         * of @c->value_str. This is excessive, hence we just
++                         * ignore all those matches and accept everything from
++                         * the kernel. People should really avoid those matches.
++                         * If they're used in real-life some day, we will have
++                         * to properly support multiple-matches here.
++                         */
++                        break;
++
++                case BUS_MATCH_ARG_NAMESPACE...BUS_MATCH_ARG_NAMESPACE_LAST: {
++                        char buf[sizeof("arg")-1 + 2 + sizeof("-dot-prefix")];
++
++                        xsprintf(buf, "arg%i-dot-prefix", c->type - BUS_MATCH_ARG_NAMESPACE);
++                        //bloom_add_pair(bloom, bus->bloom_size, bus->bloom_n_hash, buf, c->value_str);
++                        using_bloom = true;
++                        break;
++                }
++
++                case BUS_MATCH_DESTINATION:
++                        /*
++                         * Kernel only supports matching on destination IDs, but
++                         * not on destination names. So just skip the
++                         * destination name restriction and verify it in
++                         * user-space on retrieval.
++                         */
++                        r = bus_kernel_parse_unique_name(c->value_str, &dst_id);
++                        if (r < 0)
++                                return r;
++                        else if (r > 0)
++                                sz += ALIGN8(offsetof(struct kdbus_item, id) + sizeof(uint64_t));
++
++                        /* if not a broadcast, it cannot be a name-change */
++                        if (r <= 0 || dst_id != KDBUS_DST_ID_BROADCAST)
++                                matches_name_change = false;
++
++                        break;
++
++                case BUS_MATCH_ROOT:
++                case BUS_MATCH_VALUE:
++                case BUS_MATCH_LEAF:
++                case _BUS_MATCH_NODE_TYPE_MAX:
++                case _BUS_MATCH_NODE_TYPE_INVALID:
++                        assert_not_reached("Invalid match type?");
++                }
++        }
++
++        if (using_bloom)
++                sz += ALIGN8(offsetof(struct kdbus_item, data64) + bus->bloom_size);
++
++        m = alloca0_align(sz, 8);
++        m->size = sz;
++        m->cookie = cookie;
++
++        item = m->items;
++
++        if (src_id != KDBUS_MATCH_ID_ANY) {
++                item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
++                item->type = KDBUS_ITEM_ID;
++                item->id = src_id;
++                item = KDBUS_ITEM_NEXT(item);
++        }
++
++        if (dst_id != KDBUS_MATCH_ID_ANY) {
++                item->size = offsetof(struct kdbus_item, id) + sizeof(uint64_t);
++                item->type = KDBUS_ITEM_DST_ID;
++                item->id = dst_id;
++                item = KDBUS_ITEM_NEXT(item);
++        }
++
++        if (using_bloom) {
++                item->size = offsetof(struct kdbus_item, data64) + bus->bloom_size;
++                item->type = KDBUS_ITEM_BLOOM_MASK;
++                memcpy(item->data64, bloom, bus->bloom_size);
++                item = KDBUS_ITEM_NEXT(item);
++        }
++
++        if (sender) {
++                item->size = offsetof(struct kdbus_item, str) + sender_length + 1;
++                item->type = KDBUS_ITEM_NAME;
++                memcpy(item->str, sender, sender_length + 1);
++        }
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_ADD, m);
++        if (r < 0)
++                return -errno;
++
++        if (matches_name_change) {
++
++                /* If this match could theoretically match
++                 * NameOwnerChanged messages, we need to
++                 * install a second non-bloom filter explitly
++                 * for it */
++
++                r = add_name_change_match(bus, cookie, name_change_arg[0], name_change_arg[1], name_change_arg[2]);
++                if (r < 0)
++                        return r;
++        }
++
++        return 0;
++}
++
++int bus_remove_match_internal_kernel(
++                sd_bus *bus,
++                uint64_t cookie) {
++
++        struct kdbus_cmd_match m = {
++                .size = offsetof(struct kdbus_cmd_match, items),
++                .cookie = cookie,
++        };
++        int r;
++
++        assert(bus);
++
++        /* Monitor streams don't support matches, make this a NOP */
++        //if (bus->hello_flags & KDBUS_HELLO_MONITOR)
++                //return 0;
++
++        r = ioctl(bus->input_fd, KDBUS_CMD_MATCH_REMOVE, &m);
++        if (r < 0)
++                return -errno;
++
++        return 0;
++}
index 0000000,0000000..db98e11
new file mode 100644 (file)
--- /dev/null
--- /dev/null
@@@ -1,0 -1,0 +1,43 @@@
++/* SPDX-License-Identifier: LGPL-2.1+ */
++#pragma once
++
++/***
++  This file is part of systemd.
++
++  Copyright 2013 Lennart Poettering
++
++  systemd 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.
++
++  systemd is distributed in the hope that it will be useful, but
++  WITHOUT ANY WARRANTY; without even the implied warranty of
++  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++  Lesser General Public License for more details.
++
++  You should have received a copy of the GNU Lesser General Public License
++  along with systemd; If not, see <http://www.gnu.org/licenses/>.
++***/
++
++#include "sd-bus.h"
++#include "bus-match.h"
++
++int bus_request_name_kernel(sd_bus *bus, const char *name, uint64_t flags);
++int bus_release_name_kernel(sd_bus *bus, const char *name);
++int bus_list_names_kernel(sd_bus *bus, char ***acquired, char ***activatable);
++int bus_get_name_creds_kdbus(
++                sd_bus *bus,
++                const char *name,
++                uint64_t mask,
++                bool allow_activator,
++                sd_bus_creds **creds);
++int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret);
++int bus_add_match_internal_kernel(
++                sd_bus *bus,
++                struct bus_match_component *components,
++                unsigned n_components,
++                uint64_t cookie);
++int bus_remove_match_internal_kernel(
++                sd_bus *bus,
++                uint64_t cookie);
@@@ -28,8 -28,7 +28,8 @@@
  #include "sd-bus.h"
  
  #include "alloc-util.h"
- #include "bus-bloom.h"
  #include "bus-control.h"
++#include "bus-control-kernel.h"
  #include "bus-internal.h"
  #include "bus-message.h"
  #include "bus-util.h"
@@@ -94,16 -105,15 +106,18 @@@ _public_ int sd_bus_request_name
          uint32_t ret, param = 0;
          int r;
  
-         assert(bus);
-         assert(name);
+         assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
+         assert_return(name, -EINVAL);
+         assert_return(!bus_pid_changed(bus), -ECHILD);
  
-         if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
-                 param |= BUS_NAME_ALLOW_REPLACEMENT;
-         if (flags & SD_BUS_NAME_REPLACE_EXISTING)
-                 param |= BUS_NAME_REPLACE_EXISTING;
-         if (!(flags & SD_BUS_NAME_QUEUE))
-                 param |= BUS_NAME_DO_NOT_QUEUE;
+         r = validate_request_name_parameters(bus, name, flags, &param);
+         if (r < 0)
+                 return r;
++        if (bus->is_kernel)
++                return bus_request_name_kernel(bus, name, flags);
 +
          r = sd_bus_call_method(
                          bus,
                          "org.freedesktop.DBus",
@@@ -190,9 -263,15 +267,18 @@@ _public_ int sd_bus_release_name
          uint32_t ret;
          int r;
  
-         assert(bus);
-         assert(name);
+         assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
+         assert_return(name, -EINVAL);
+         assert_return(!bus_pid_changed(bus), -ECHILD);
+         r = validate_release_name_parameters(bus, name);
+         if (r < 0)
+                 return r;
++        if (bus->is_kernel)
++                return bus_release_name_kernel(bus, name);
 +
          r = sd_bus_call_method(
                          bus,
                          "org.freedesktop.DBus",
@@@ -332,6 -383,17 +390,20 @@@ _public_ int sd_bus_list_names(sd_bus *
          _cleanup_strv_free_ char **x = NULL, **y = NULL;
          int r;
  
+         assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
+         assert_return(acquired || activatable, -EINVAL);
+         assert_return(!bus_pid_changed(bus), -ECHILD);
+         if (!bus->bus_client)
+                 return -EINVAL;
+         if (!BUS_IS_OPEN(bus->state))
+                 return -ENOTCONN;
++        if (bus->is_kernel)
++                return bus_list_names_kernel(bus, acquired, activatable);
++
          if (acquired) {
                  r = sd_bus_call_method(
                                  bus,
@@@ -765,6 -455,31 +465,34 @@@ _public_ int sd_bus_get_name_creds
          pid_t pid = 0;
          int r;
  
+         assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
+         assert_return(name, -EINVAL);
+         assert_return((mask & ~SD_BUS_CREDS_AUGMENT) <= _SD_BUS_CREDS_ALL, -EOPNOTSUPP);
+         assert_return(mask == 0 || creds, -EINVAL);
+         assert_return(!bus_pid_changed(bus), -ECHILD);
+         assert_return(service_name_is_valid(name), -EINVAL);
+         if (!bus->bus_client)
+                 return -EINVAL;
+         /* Turn off augmenting if this isn't a local connection. If the connection is not local, then /proc is not
+          * going to match. */
+         if (!bus->is_local)
+                 mask &= ~SD_BUS_CREDS_AUGMENT;
+         if (streq(name, "org.freedesktop.DBus.Local"))
+                 return -EINVAL;
+         if (streq(name, "org.freedesktop.DBus"))
+                 return sd_bus_get_owner_creds(bus, mask, creds);
+         if (!BUS_IS_OPEN(bus->state))
+                 return -ENOTCONN;
++        if (bus->is_kernel)
++                return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
++
          /* Only query the owner if the caller wants to know it or if
           * the caller just wants to check whether a name exists */
          if ((mask & SD_BUS_CREDS_UNIQUE_NAME) || mask == 0) {
@@@ -1046,85 -760,11 +773,14 @@@ _public_ int sd_bus_get_owner_creds(sd_
          if (!bus->is_local)
                  mask &= ~SD_BUS_CREDS_AUGMENT;
  
-         if (streq(name, "org.freedesktop.DBus.Local"))
-                 return -EINVAL;
-         if (streq(name, "org.freedesktop.DBus"))
-                 return sd_bus_get_owner_creds(bus, mask, creds);
-         if (!BUS_IS_OPEN(bus->state))
-                 return -ENOTCONN;
 +        if (bus->is_kernel)
-                 return bus_get_name_creds_kdbus(bus, name, mask, false, creds);
-         else
-                 return bus_get_name_creds_dbus1(bus, name, mask, creds);
- }
- static int bus_get_owner_creds_kdbus(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
-         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
-         struct kdbus_cmd_info cmd = {
-                 .size = sizeof(struct kdbus_cmd_info),
-         };
-         struct kdbus_info *creator_info;
-         pid_t pid = 0;
-         int r;
-         c = bus_creds_new();
-         if (!c)
-                 return -ENOMEM;
-         /* If augmentation is on, and the bus doesn't didn't allow us
-          * to get the bits we want, then ask for the PID/TID so that we
-          * can read the rest from /proc. */
-         if ((mask & SD_BUS_CREDS_AUGMENT) &&
-             (mask & (SD_BUS_CREDS_PPID|
-                      SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
-                      SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID|
-                      SD_BUS_CREDS_SUPPLEMENTARY_GIDS|
-                      SD_BUS_CREDS_COMM|SD_BUS_CREDS_TID_COMM|SD_BUS_CREDS_EXE|SD_BUS_CREDS_CMDLINE|
-                      SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID|
-                      SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS|
-                      SD_BUS_CREDS_SELINUX_CONTEXT|
-                      SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID)))
-                 mask |= SD_BUS_CREDS_PID;
-         cmd.attach_flags = attach_flags_to_kdbus(mask);
-         r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
-         if (r < 0)
-                 return -errno;
-         creator_info = (struct kdbus_info *) ((uint8_t *) bus->kdbus_buffer + cmd.offset);
-         r = bus_populate_creds_from_items(bus, creator_info, mask, c);
-         bus_kernel_cmd_free(bus, cmd.offset);
-         if (r < 0)
-                 return r;
-         r = bus_creds_add_more(c, mask, pid, 0);
-         if (r < 0)
-                 return r;
-         *ret = c;
-         c = NULL;
-         return 0;
- }
- static int bus_get_owner_creds_dbus1(sd_bus *bus, uint64_t mask, sd_bus_creds **ret) {
-         _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *c = NULL;
-         pid_t pid = 0;
-         bool do_label;
-         int r;
-         assert(bus);
++                return bus_get_owner_creds_kdbus(bus, mask, ret);
 +
          do_label = bus->label && (mask & SD_BUS_CREDS_SELINUX_CONTEXT);
+         do_groups = bus->n_groups != (size_t) -1 && (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS);
  
          /* Avoid allocating anything if we have no chance of returning useful data */
-         if (!bus->ucred_valid && !do_label)
+         if (!bus->ucred_valid && !do_label && !do_groups)
                  return -ENODATA;
  
          c = bus_creds_new();
           ? (isempty(m) ? "eavesdrop='true'" : strjoina((m), ",eavesdrop='true'")) \
           : (m))
  
static int bus_add_match_internal_dbus1(
int bus_add_match_internal(
                  sd_bus *bus,
--                const char *match) {
++                const char *match,
++                uint64_t cookie) {
  
          const char *e;
  
          assert(bus);
-         assert(match);
  
-         e = internal_match(bus, match);
+         if (!bus->bus_client)
+                 return -EINVAL;
++        if (bus->is_kernel)
++                return bus_add_match_internal_kernel(bus, NULL, 0, cookie);
++
+         e = append_eavesdrop(bus, match);
  
          return sd_bus_call_method(
                          bus,
@@@ -1665,18 -875,31 +895,35 @@@ int bus_add_match_internal_async
  
  int bus_remove_match_internal(
                  sd_bus *bus,
 -                const char *match) {
 +                const char *match,
 +                uint64_t cookie) {
  
+         const char *e;
          assert(bus);
+         assert(match);
  
          if (!bus->bus_client)
                  return -EINVAL;
  
-         else
-                 return bus_remove_match_internal_dbus1(bus, match);
 +        if (bus->is_kernel)
 +                return bus_remove_match_internal_kernel(bus, cookie);
++
+         e = append_eavesdrop(bus, match);
+         /* Fire and forget */
+         return sd_bus_call_method_async(
+                         bus,
+                         NULL,
+                         "org.freedesktop.DBus",
+                         "/org/freedesktop/DBus",
+                         "org.freedesktop.DBus",
+                         "RemoveMatch",
+                         NULL,
+                         NULL,
+                         "s",
+                         e);
  }
  
  _public_ int sd_bus_get_name_machine_id(sd_bus *bus, const char *name, sd_id128_t *machine) {
  
  #include "sd-bus.h"
  
- #include "bus-match.h"
- int bus_add_match_internal(sd_bus *bus, const char *match, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
 -int bus_add_match_internal(sd_bus *bus, const char *match);
++int bus_add_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
+ int bus_add_match_internal_async(sd_bus *bus, sd_bus_slot **ret, const char *match, sd_bus_message_handler_t callback, void *userdata);
 -
 -int bus_remove_match_internal(sd_bus *bus, const char *match);
 +int bus_remove_match_internal(sd_bus *bus, const char *match, uint64_t cookie);
- int bus_add_match_internal_kernel(sd_bus *bus, struct bus_match_component *components, unsigned n_components, uint64_t cookie);
- int bus_remove_match_internal_kernel(sd_bus *bus, uint64_t cookie);
- int bus_get_name_creds_kdbus(sd_bus *bus, const char *name, uint64_t mask, bool allow_activator, sd_bus_creds **creds);
@@@ -54,8 -53,10 +54,11 @@@ struct filter_callback 
  
  struct match_callback {
          sd_bus_message_handler_t callback;
+         sd_bus_message_handler_t install_callback;
+         sd_bus_slot *install_slot; /* The AddMatch() call */
  
 +        uint64_t cookie;
          unsigned last_iteration;
  
          char *match_string;
@@@ -292,11 -297,6 +305,8 @@@ struct sd_bus 
  
          pid_t original_pid;
  
-         uint64_t hello_flags;
-         uint64_t attach_flags;
 +        uint64_t match_cookie;
 +
          sd_event_source *input_io_event_source;
          sd_event_source *output_io_event_source;
          sd_event_source *time_event_source;
          char *cgroup_root;
  
          char *description;
+         char *patch_sender;
  
 +        size_t bloom_size;
 +        unsigned bloom_n_hash;
 +
          sd_bus_track *track_queue;
  
          LIST_HEAD(sd_bus_slot, slots);
  #include "user-util.h"
  #include "util.h"
  
 -void close_and_munmap(int fd, void *address, size_t size) {
 +#pragma GCC diagnostic ignored "-Wformat"
 +
 +#define UNIQUE_NAME_MAX (3+DECIMAL_STR_MAX(uint64_t))
 +
 +int bus_kernel_parse_unique_name(const char *s, uint64_t *id) {
 +        int r;
 +
 +        assert(s);
 +        assert(id);
 +
 +        if (!startswith(s, ":1."))
 +                return 0;
 +
 +        r = safe_atou64(s + 3, id);
 +        if (r < 0)
 +                return r;
 +
 +        return 1;
 +}
 +
 +static void append_payload_vec(struct kdbus_item **d, const void *p, size_t sz) {
 +        assert(d);
 +        assert(sz > 0);
 +
 +        *d = ALIGN8_PTR(*d);
 +
 +        /* Note that p can be NULL, which encodes a region full of
 +         * zeroes, which is useful to optimize certain padding
 +         * conditions */
 +
 +        (*d)->size = offsetof(struct kdbus_item, vec) + sizeof(struct kdbus_vec);
 +        (*d)->type = KDBUS_ITEM_PAYLOAD_VEC;
 +        (*d)->vec.address = PTR_TO_UINT64(p);
 +        (*d)->vec.size = sz;
 +
 +        *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
 +}
 +
 +static void append_payload_memfd(struct kdbus_item **d, int memfd, size_t start, size_t sz) {
 +        assert(d);
 +        assert(memfd >= 0);
 +        assert(sz > 0);
 +
 +        *d = ALIGN8_PTR(*d);
 +        (*d)->size = offsetof(struct kdbus_item, memfd) + sizeof(struct kdbus_memfd);
 +        (*d)->type = KDBUS_ITEM_PAYLOAD_MEMFD;
 +        (*d)->memfd.fd = memfd;
 +        (*d)->memfd.start = start;
 +        (*d)->memfd.size = sz;
 +
 +        *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
 +}
 +
 +static void append_destination(struct kdbus_item **d, const char *s, size_t length) {
 +        assert(d);
 +        assert(s);
 +
 +        *d = ALIGN8_PTR(*d);
 +
 +        (*d)->size = offsetof(struct kdbus_item, str) + length + 1;
 +        (*d)->type = KDBUS_ITEM_DST_NAME;
 +        memcpy((*d)->str, s, length + 1);
 +
 +        *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
 +}
 +
 +static struct kdbus_bloom_filter *append_bloom(struct kdbus_item **d, size_t length) {
 +        struct kdbus_item *i;
 +
 +        assert(d);
 +
 +        i = ALIGN8_PTR(*d);
 +
 +        i->size = offsetof(struct kdbus_item, bloom_filter) +
 +                  offsetof(struct kdbus_bloom_filter, data) +
 +                  length;
 +        i->type = KDBUS_ITEM_BLOOM_FILTER;
 +
 +        *d = (struct kdbus_item *) ((uint8_t*) i + i->size);
 +
 +        return &i->bloom_filter;
 +}
 +
 +static void append_fds(struct kdbus_item **d, const int fds[], unsigned n_fds) {
 +        assert(d);
 +        assert(fds);
 +        assert(n_fds > 0);
 +
 +        *d = ALIGN8_PTR(*d);
 +        (*d)->size = offsetof(struct kdbus_item, fds) + sizeof(int) * n_fds;
 +        (*d)->type = KDBUS_ITEM_FDS;
 +        memcpy((*d)->fds, fds, sizeof(int) * n_fds);
 +
 +        *d = (struct kdbus_item *) ((uint8_t*) *d + (*d)->size);
 +}
 +
 +static void add_bloom_arg(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
 +        char buf[sizeof("arg")-1 + 2 + sizeof("-slash-prefix")];
 +        char *e;
 +
 +        assert(data);
 +        assert(size > 0);
 +        assert(i < 64);
 +        assert(t);
 +
 +        e = stpcpy(buf, "arg");
 +        if (i < 10)
 +                *(e++) = '0' + (char) i;
 +        else {
 +                *(e++) = '0' + (char) (i / 10);
 +                *(e++) = '0' + (char) (i % 10);
 +        }
 +
 +        *e = 0;
-         bloom_add_pair(data, size, n_hash, buf, t);
++        //bloom_add_pair(data, size, n_hash, buf, t);
 +
 +        strcpy(e, "-dot-prefix");
-         bloom_add_prefixes(data, size, n_hash, buf, t, '.');
++        //bloom_add_prefixes(data, size, n_hash, buf, t, '.');
 +        strcpy(e, "-slash-prefix");
-         bloom_add_prefixes(data, size, n_hash, buf, t, '/');
++        //bloom_add_prefixes(data, size, n_hash, buf, t, '/');
 +}
 +
 +static void add_bloom_arg_has(void *data, size_t size, unsigned n_hash, unsigned i, const char *t) {
 +        char buf[sizeof("arg")-1 + 2 + sizeof("-has")];
 +        char *e;
 +
 +        assert(data);
 +        assert(size > 0);
 +        assert(i < 64);
 +        assert(t);
 +
 +        e = stpcpy(buf, "arg");
 +        if (i < 10)
 +                *(e++) = '0' + (char) i;
 +        else {
 +                *(e++) = '0' + (char) (i / 10);
 +                *(e++) = '0' + (char) (i % 10);
 +        }
 +
 +        strcpy(e, "-has");
-         bloom_add_pair(data, size, n_hash, buf, t);
++        //bloom_add_pair(data, size, n_hash, buf, t);
 +}
 +
 +static int bus_message_setup_bloom(sd_bus_message *m, struct kdbus_bloom_filter *bloom) {
 +        void *data;
 +        unsigned i;
 +        int r;
 +
 +        assert(m);
 +        assert(bloom);
 +
 +        data = bloom->data;
 +        memzero(data, m->bus->bloom_size);
 +        bloom->generation = 0;
 +
-         bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
++        //bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "message-type", bus_message_type_to_string(m->header->type));
 +
-         if (m->interface)
-                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
-         if (m->member)
-                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
-         if (m->path) {
-                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
-                 bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
-                 bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
-         }
++        //if (m->interface)
++                //bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "interface", m->interface);
++        //if (m->member)
++                //bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "member", m->member);
++        //if (m->path) {
++                //bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path", m->path);
++                //bloom_add_pair(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path);
++                //bloom_add_prefixes(data, m->bus->bloom_size, m->bus->bloom_n_hash, "path-slash-prefix", m->path, '/');
++        //}
 +
 +        r = sd_bus_message_rewind(m, true);
 +        if (r < 0)
 +                return r;
 +
 +        for (i = 0; i < 64; i++) {
 +                const char *t, *contents;
 +                char type;
 +
 +                r = sd_bus_message_peek_type(m, &type, &contents);
 +                if (r < 0)
 +                        return r;
 +
 +                if (IN_SET(type, SD_BUS_TYPE_STRING, SD_BUS_TYPE_OBJECT_PATH, SD_BUS_TYPE_SIGNATURE)) {
 +
 +                        /* The bloom filter includes simple strings of any kind */
 +                        r = sd_bus_message_read_basic(m, type, &t);
 +                        if (r < 0)
 +                                return r;
 +
 +                        add_bloom_arg(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
 +                }
 +
 +                if (type == SD_BUS_TYPE_ARRAY && STR_IN_SET(contents, "s", "o", "g")) {
 +
 +                        /* As well as array of simple strings of any kinds */
 +                        r = sd_bus_message_enter_container(m, type, contents);
 +                        if (r < 0)
 +                                return r;
 +
 +                        while ((r = sd_bus_message_read_basic(m, contents[0], &t)) > 0)
 +                                add_bloom_arg_has(data, m->bus->bloom_size, m->bus->bloom_n_hash, i, t);
 +                        if (r < 0)
 +                                return r;
 +
 +                        r = sd_bus_message_exit_container(m);
 +                        if (r < 0)
 +                                return r;
 +
 +                } else
 +                        /* Stop adding to bloom filter as soon as we
 +                         * run into the first argument we cannot add
 +                         * to it. */
 +                        break;
 +        }
 +
 +        return 0;
 +}
 +
 +static int bus_message_setup_kmsg(sd_bus *b, sd_bus_message *m) {
 +        struct bus_body_part *part;
 +        struct kdbus_item *d;
 +        const char *destination;
 +        bool well_known = false;
 +        uint64_t dst_id;
 +        size_t sz, dl;
 +        unsigned i;
 +        int r;
 +
 +        assert(b);
 +        assert(m);
 +        assert(m->sealed);
 +
 +        /* We put this together only once, if this message is reused
 +         * we reuse the earlier-built version */
 +        if (m->kdbus)
 +                return 0;
 +
-         destination = m->destination ?: m->destination_ptr;
++        //destination = m->destination ?: m->destination_ptr;
 +
 +        if (destination) {
 +                r = bus_kernel_parse_unique_name(destination, &dst_id);
 +                if (r < 0)
 +                        return r;
 +                if (r == 0) {
 +                        well_known = true;
 +
 +                        /* verify_destination_id will usually be 0, which makes the kernel
 +                         * driver only look at the provided well-known name. Otherwise,
 +                         * the kernel will make sure the provided destination id matches
 +                         * the owner of the provided well-known-name, and fail if they
 +                         * differ. Currently, this is only needed for bus-proxyd. */
 +                        dst_id = m->verify_destination_id;
 +                }
 +        } else
 +                dst_id = KDBUS_DST_ID_BROADCAST;
 +
 +        sz = offsetof(struct kdbus_msg, items);
 +
 +        /* Add in fixed header, fields header and payload */
 +        sz += (1 + m->n_body_parts) * ALIGN8(offsetof(struct kdbus_item, vec) +
 +                                             MAX(sizeof(struct kdbus_vec),
 +                                                 sizeof(struct kdbus_memfd)));
 +
 +        /* Add space for bloom filter */
 +        sz += ALIGN8(offsetof(struct kdbus_item, bloom_filter) +
 +                     offsetof(struct kdbus_bloom_filter, data) +
 +                     m->bus->bloom_size);
 +
 +        /* Add in well-known destination header */
 +        if (well_known) {
 +                dl = strlen(destination);
 +                sz += ALIGN8(offsetof(struct kdbus_item, str) + dl + 1);
 +        }
 +
 +        /* Add space for unix fds */
 +        if (m->n_fds > 0)
 +                sz += ALIGN8(offsetof(struct kdbus_item, fds) + sizeof(int)*m->n_fds);
 +
 +        m->kdbus = memalign(8, sz);
 +        if (!m->kdbus) {
 +                r = -ENOMEM;
 +                goto fail;
 +        }
 +
 +        m->free_kdbus = true;
 +        memzero(m->kdbus, sz);
 +
 +        m->kdbus->flags =
 +                ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) ? 0 : KDBUS_MSG_EXPECT_REPLY) |
 +                ((m->header->flags & BUS_MESSAGE_NO_AUTO_START) ? KDBUS_MSG_NO_AUTO_START : 0) |
 +                ((m->header->type == SD_BUS_MESSAGE_SIGNAL) ? KDBUS_MSG_SIGNAL : 0);
 +
 +        m->kdbus->dst_id = dst_id;
 +        m->kdbus->payload_type = KDBUS_PAYLOAD_DBUS;
 +        m->kdbus->cookie = m->header->dbus2.cookie;
 +        m->kdbus->priority = m->priority;
 +
 +        if (m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED)
 +                m->kdbus->cookie_reply = m->reply_cookie;
 +        else {
 +                struct timespec now;
 +
 +                assert_se(clock_gettime(CLOCK_MONOTONIC_COARSE, &now) == 0);
 +                m->kdbus->timeout_ns = now.tv_sec * NSEC_PER_SEC + now.tv_nsec +
 +                                       m->timeout * NSEC_PER_USEC;
 +        }
 +
 +        d = m->kdbus->items;
 +
 +        if (well_known)
 +                append_destination(&d, destination, dl);
 +
 +        append_payload_vec(&d, m->header, BUS_MESSAGE_BODY_BEGIN(m));
 +
 +        MESSAGE_FOREACH_PART(part, i, m) {
 +                if (part->is_zero) {
 +                        /* If this is padding then simply send a
 +                         * vector with a NULL data pointer which the
 +                         * kernel will just pass through. This is the
 +                         * most efficient way to encode zeroes */
 +
 +                        append_payload_vec(&d, NULL, part->size);
 +                        continue;
 +                }
 +
 +                if (part->memfd >= 0 && part->sealed && destination) {
 +                        /* Try to send a memfd, if the part is
 +                         * sealed and this is not a broadcast. Since we can only  */
 +
 +                        append_payload_memfd(&d, part->memfd, part->memfd_offset, part->size);
 +                        continue;
 +                }
 +
 +                /* Otherwise, let's send a vector to the actual data.
 +                 * For that, we need to map it first. */
 +                r = bus_body_part_map(part);
 +                if (r < 0)
 +                        goto fail;
 +
 +                append_payload_vec(&d, part->data, part->size);
 +        }
 +
 +        if (m->header->type == SD_BUS_MESSAGE_SIGNAL) {
 +                struct kdbus_bloom_filter *bloom;
 +
 +                bloom = append_bloom(&d, m->bus->bloom_size);
 +                r = bus_message_setup_bloom(m, bloom);
 +                if (r < 0)
 +                        goto fail;
 +        }
 +
 +        if (m->n_fds > 0)
 +                append_fds(&d, m->fds, m->n_fds);
 +
 +        m->kdbus->size = (uint8_t*) d - (uint8_t*) m->kdbus;
 +        assert(m->kdbus->size <= sz);
 +
 +        return 0;
 +
 +fail:
 +        m->poisoned = true;
 +        return r;
 +}
 +
 +static void unset_memfds(struct sd_bus_message *m) {
 +        struct bus_body_part *part;
 +        unsigned i;
 +
 +        assert(m);
 +
 +        /* Make sure the memfds are not freed twice */
 +        MESSAGE_FOREACH_PART(part, i, m)
 +                if (part->memfd >= 0)
 +                        part->memfd = -1;
 +}
 +
 +static void message_set_timestamp(sd_bus *bus, sd_bus_message *m, const struct kdbus_timestamp *ts) {
 +        assert(bus);
 +        assert(m);
 +
 +        if (!ts)
 +                return;
 +
-         if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
-                 return;
++        //if (!(bus->attach_flags & KDBUS_ATTACH_TIMESTAMP))
++                //return;
 +
 +        m->realtime = ts->realtime_ns / NSEC_PER_USEC;
 +        m->monotonic = ts->monotonic_ns / NSEC_PER_USEC;
 +        m->seqnum = ts->seqnum;
 +}
 +
 +static int bus_kernel_make_message(sd_bus *bus, struct kdbus_msg *k) {
 +        sd_bus_message *m = NULL;
 +        struct kdbus_item *d;
 +        unsigned n_fds = 0;
 +        _cleanup_free_ int *fds = NULL;
 +        struct bus_header *header = NULL;
 +        void *footer = NULL;
 +        size_t header_size = 0, footer_size = 0;
 +        size_t n_bytes = 0, idx = 0;
 +        const char *destination = NULL, *seclabel = NULL;
 +        bool last_was_memfd = false;
 +        int r;
 +
 +        assert(bus);
 +        assert(k);
 +        assert(k->payload_type == KDBUS_PAYLOAD_DBUS);
 +
 +        KDBUS_ITEM_FOREACH(d, k, items) {
 +                size_t l;
 +
 +                l = d->size - offsetof(struct kdbus_item, data);
 +
 +                switch (d->type) {
 +
 +                case KDBUS_ITEM_PAYLOAD_OFF:
 +                        if (!header) {
 +                                header = (struct bus_header*)((uint8_t*) k + d->vec.offset);
 +                                header_size = d->vec.size;
 +                        }
 +
 +                        footer = (uint8_t*) k + d->vec.offset;
 +                        footer_size = d->vec.size;
 +
 +                        n_bytes += d->vec.size;
 +                        last_was_memfd = false;
 +                        break;
 +
 +                case KDBUS_ITEM_PAYLOAD_MEMFD:
 +                        if (!header) /* memfd cannot be first part */
 +                                return -EBADMSG;
 +
 +                        n_bytes += d->memfd.size;
 +                        last_was_memfd = true;
 +                        break;
 +
 +                case KDBUS_ITEM_FDS: {
 +                        int *f;
 +                        unsigned j;
 +
 +                        j = l / sizeof(int);
 +                        f = realloc(fds, sizeof(int) * (n_fds + j));
 +                        if (!f)
 +                                return -ENOMEM;
 +
 +                        fds = f;
 +                        memcpy(fds + n_fds, d->fds, sizeof(int) * j);
 +                        n_fds += j;
 +                        break;
 +                }
 +
 +                case KDBUS_ITEM_SECLABEL:
 +                        seclabel = d->str;
 +                        break;
 +                }
 +        }
 +
 +        if (last_was_memfd) /* memfd cannot be last part */
 +                return -EBADMSG;
 +
 +        if (!header)
 +                return -EBADMSG;
 +
 +        if (header_size < sizeof(struct bus_header))
 +                return -EBADMSG;
 +
 +        /* on kdbus we only speak native endian gvariant, never dbus1
 +         * marshalling or reverse endian */
 +        if (header->version != 2 ||
 +            header->endian != BUS_NATIVE_ENDIAN)
 +                return -EPROTOTYPE;
 +
 +        r = bus_message_from_header(
 +                        bus,
 +                        header, header_size,
 +                        footer, footer_size,
 +                        n_bytes,
 +                        fds, n_fds,
 +                        seclabel, 0, &m);
 +        if (r < 0)
 +                return r;
 +
 +        /* The well-known names list is different from the other
 +        credentials. If we asked for it, but nothing is there, this
 +        means that the list of well-known names is simply empty, not
 +        that we lack any data */
 +
 +        m->creds.mask |= (SD_BUS_CREDS_UNIQUE_NAME|SD_BUS_CREDS_WELL_KNOWN_NAMES) & bus->creds_mask;
 +
 +        KDBUS_ITEM_FOREACH(d, k, items) {
 +                size_t l;
 +
 +                l = d->size - offsetof(struct kdbus_item, data);
 +
 +                switch (d->type) {
 +
 +                case KDBUS_ITEM_PAYLOAD_OFF: {
 +                        size_t begin_body;
 +
 +                        begin_body = BUS_MESSAGE_BODY_BEGIN(m);
 +
 +                        if (idx + d->vec.size > begin_body) {
 +                                struct bus_body_part *part;
 +
 +                                /* Contains body material */
 +
 +                                part = message_append_part(m);
 +                                if (!part) {
 +                                        r = -ENOMEM;
 +                                        goto fail;
 +                                }
 +
 +                                /* A -1 offset is NUL padding. */
 +                                part->is_zero = d->vec.offset == ~0ULL;
 +
 +                                if (idx >= begin_body) {
 +                                        if (!part->is_zero)
 +                                                part->data = (uint8_t* )k + d->vec.offset;
 +                                        part->size = d->vec.size;
 +                                } else {
 +                                        if (!part->is_zero)
 +                                                part->data = (uint8_t*) k + d->vec.offset + (begin_body - idx);
 +                                        part->size = d->vec.size - (begin_body - idx);
 +                                }
 +
 +                                part->sealed = true;
 +                        }
 +
 +                        idx += d->vec.size;
 +                        break;
 +                }
 +
 +                case KDBUS_ITEM_PAYLOAD_MEMFD: {
 +                        struct bus_body_part *part;
 +
 +                        if (idx < BUS_MESSAGE_BODY_BEGIN(m)) {
 +                                r = -EBADMSG;
 +                                goto fail;
 +                        }
 +
 +                        part = message_append_part(m);
 +                        if (!part) {
 +                                r = -ENOMEM;
 +                                goto fail;
 +                        }
 +
 +                        part->memfd = d->memfd.fd;
 +                        part->memfd_offset = d->memfd.start;
 +                        part->size = d->memfd.size;
 +                        part->sealed = true;
 +
 +                        idx += d->memfd.size;
 +                        break;
 +                }
 +
 +                case KDBUS_ITEM_PIDS:
 +
 +                        /* The PID/TID might be missing, when the data
 +                         * is faked by a bus proxy and it lacks that
 +                         * information about the real client (since
 +                         * SO_PEERCRED is used for that). Also kernel
 +                         * namespacing might make some of this data
 +                         * unavailable when untranslatable. */
 +
 +                        if (d->pids.pid > 0) {
 +                                m->creds.pid = (pid_t) d->pids.pid;
 +                                m->creds.mask |= SD_BUS_CREDS_PID & bus->creds_mask;
 +                        }
 +
 +                        if (d->pids.tid > 0) {
 +                                m->creds.tid = (pid_t) d->pids.tid;
 +                                m->creds.mask |= SD_BUS_CREDS_TID & bus->creds_mask;
 +                        }
 +
 +                        if (d->pids.ppid > 0) {
 +                                m->creds.ppid = (pid_t) d->pids.ppid;
 +                                m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
 +                        } else if (d->pids.pid == 1) {
 +                                m->creds.ppid = 0;
 +                                m->creds.mask |= SD_BUS_CREDS_PPID & bus->creds_mask;
 +                        }
 +
 +                        break;
 +
 +                case KDBUS_ITEM_CREDS:
 +
 +                        /* EUID/SUID/FSUID/EGID/SGID/FSGID might be
 +                         * missing too (see above). */
 +
 +                        if ((uid_t) d->creds.uid != UID_INVALID) {
 +                                m->creds.uid = (uid_t) d->creds.uid;
 +                                m->creds.mask |= SD_BUS_CREDS_UID & bus->creds_mask;
 +                        }
 +
 +                        if ((uid_t) d->creds.euid != UID_INVALID) {
 +                                m->creds.euid = (uid_t) d->creds.euid;
 +                                m->creds.mask |= SD_BUS_CREDS_EUID & bus->creds_mask;
 +                        }
 +
 +                        if ((uid_t) d->creds.suid != UID_INVALID) {
 +                                m->creds.suid = (uid_t) d->creds.suid;
 +                                m->creds.mask |= SD_BUS_CREDS_SUID & bus->creds_mask;
 +                        }
 +
 +                        if ((uid_t) d->creds.fsuid != UID_INVALID) {
 +                                m->creds.fsuid = (uid_t) d->creds.fsuid;
 +                                m->creds.mask |= SD_BUS_CREDS_FSUID & bus->creds_mask;
 +                        }
 +
 +                        if ((gid_t) d->creds.gid != GID_INVALID) {
 +                                m->creds.gid = (gid_t) d->creds.gid;
 +                                m->creds.mask |= SD_BUS_CREDS_GID & bus->creds_mask;
 +                        }
 +
 +                        if ((gid_t) d->creds.egid != GID_INVALID) {
 +                                m->creds.egid = (gid_t) d->creds.egid;
 +                                m->creds.mask |= SD_BUS_CREDS_EGID & bus->creds_mask;
 +                        }
 +
 +                        if ((gid_t) d->creds.sgid != GID_INVALID) {
 +                                m->creds.sgid = (gid_t) d->creds.sgid;
 +                                m->creds.mask |= SD_BUS_CREDS_SGID & bus->creds_mask;
 +                        }
 +
 +                        if ((gid_t) d->creds.fsgid != GID_INVALID) {
 +                                m->creds.fsgid = (gid_t) d->creds.fsgid;
 +                                m->creds.mask |= SD_BUS_CREDS_FSGID & bus->creds_mask;
 +                        }
 +
 +                        break;
 +
 +                case KDBUS_ITEM_TIMESTAMP:
 +                        message_set_timestamp(bus, m, &d->timestamp);
 +                        break;
 +
 +                case KDBUS_ITEM_PID_COMM:
 +                        m->creds.comm = d->str;
 +                        m->creds.mask |= SD_BUS_CREDS_COMM & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_TID_COMM:
 +                        m->creds.tid_comm = d->str;
 +                        m->creds.mask |= SD_BUS_CREDS_TID_COMM & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_EXE:
 +                        m->creds.exe = d->str;
 +                        m->creds.mask |= SD_BUS_CREDS_EXE & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_CMDLINE:
 +                        m->creds.cmdline = d->str;
 +                        m->creds.cmdline_size = l;
 +                        m->creds.mask |= SD_BUS_CREDS_CMDLINE & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_CGROUP:
 +                        m->creds.cgroup = d->str;
 +                        m->creds.mask |= (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID) & bus->creds_mask;
 +
 +                        r = bus_get_root_path(bus);
 +                        if (r < 0)
 +                                goto fail;
 +
 +                        m->creds.cgroup_root = bus->cgroup_root;
 +                        break;
 +
 +                case KDBUS_ITEM_AUDIT:
 +                        m->creds.audit_session_id = (uint32_t) d->audit.sessionid;
 +                        m->creds.mask |= SD_BUS_CREDS_AUDIT_SESSION_ID & bus->creds_mask;
 +
 +                        m->creds.audit_login_uid = (uid_t) d->audit.loginuid;
 +                        m->creds.mask |= SD_BUS_CREDS_AUDIT_LOGIN_UID & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_CAPS:
 +                        if (d->caps.last_cap != cap_last_cap() ||
 +                            d->size - offsetof(struct kdbus_item, caps.caps) < DIV_ROUND_UP(d->caps.last_cap, 32U) * 4 * 4) {
 +                                r = -EBADMSG;
 +                                goto fail;
 +                        }
 +
 +                        m->creds.capability = d->caps.caps;
 +                        m->creds.mask |= (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS) & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_DST_NAME:
 +                        if (!service_name_is_valid(d->str)) {
 +                                r = -EBADMSG;
 +                                goto fail;
 +                        }
 +
 +                        destination = d->str;
 +                        break;
 +
 +                case KDBUS_ITEM_OWNED_NAME:
 +                        if (!service_name_is_valid(d->name.name)) {
 +                                r = -EBADMSG;
 +                                goto fail;
 +                        }
 +
 +                        if (bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES) {
 +                                char **wkn;
 +                                size_t n;
 +
 +                                /* We just extend the array here, but
 +                                 * do not allocate the strings inside
 +                                 * of it, instead we just point to our
 +                                 * buffer directly. */
 +                                n = strv_length(m->creds.well_known_names);
 +                                wkn = realloc(m->creds.well_known_names, (n + 2) * sizeof(char*));
 +                                if (!wkn) {
 +                                        r = -ENOMEM;
 +                                        goto fail;
 +                                }
 +
 +                                wkn[n] = d->name.name;
 +                                wkn[n+1] = NULL;
 +                                m->creds.well_known_names = wkn;
 +
 +                                m->creds.mask |= SD_BUS_CREDS_WELL_KNOWN_NAMES;
 +                        }
 +                        break;
 +
 +                case KDBUS_ITEM_CONN_DESCRIPTION:
 +                        m->creds.description = d->str;
 +                        m->creds.mask |= SD_BUS_CREDS_DESCRIPTION & bus->creds_mask;
 +                        break;
 +
 +                case KDBUS_ITEM_AUXGROUPS:
 +
 +                        if (bus->creds_mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS) {
 +                                size_t i, n;
 +                                gid_t *g;
 +
 +                                n = (d->size - offsetof(struct kdbus_item, data64)) / sizeof(uint64_t);
 +                                g = new(gid_t, n);
 +                                if (!g) {
 +                                        r = -ENOMEM;
 +                                        goto fail;
 +                                }
 +
 +                                for (i = 0; i < n; i++)
 +                                        g[i] = d->data64[i];
 +
 +                                m->creds.supplementary_gids = g;
 +                                m->creds.n_supplementary_gids = n;
 +                                m->creds.mask |= SD_BUS_CREDS_SUPPLEMENTARY_GIDS;
 +                        }
 +
 +                        break;
 +
 +                case KDBUS_ITEM_FDS:
 +                case KDBUS_ITEM_SECLABEL:
 +                case KDBUS_ITEM_BLOOM_FILTER:
 +                        break;
 +
 +                default:
 +                        log_debug("Got unknown field from kernel %llu", d->type);
 +                }
 +        }
 +
 +        /* If we requested the list of well-known names to be appended
 +         * and the sender had none no item for it will be
 +         * attached. However, this does *not* mean that the kernel
 +         * didn't want to provide this information to us. Hence, let's
 +         * explicitly mark this information as available if it was
 +         * requested. */
 +        m->creds.mask |= bus->creds_mask & SD_BUS_CREDS_WELL_KNOWN_NAMES;
 +
 +        r = bus_message_parse_fields(m);
 +        if (r < 0)
 +                goto fail;
 +
 +        /* Refuse messages if kdbus and dbus1 cookie doesn't match up */
 +        if ((uint64_t) m->header->dbus2.cookie != k->cookie) {
 +                r = -EBADMSG;
 +                goto fail;
 +        }
 +
 +        /* Refuse messages where the reply flag doesn't match up */
 +        if (!(m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) != !!(k->flags & KDBUS_MSG_EXPECT_REPLY)) {
 +                r = -EBADMSG;
 +                goto fail;
 +        }
 +
 +        /* Refuse reply messages where the reply cookie doesn't match up */
 +        if ((m->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) && m->reply_cookie != k->cookie_reply) {
 +                r = -EBADMSG;
 +                goto fail;
 +        }
 +
 +        /* Refuse messages where the autostart flag doesn't match up */
 +        if (!(m->header->flags & BUS_MESSAGE_NO_AUTO_START) != !(k->flags & KDBUS_MSG_NO_AUTO_START)) {
 +                r = -EBADMSG;
 +                goto fail;
 +        }
 +
 +        /* Override information from the user header with data from the kernel */
 +        if (k->src_id == KDBUS_SRC_ID_KERNEL)
 +                bus_message_set_sender_driver(bus, m);
 +        else {
-                 xsprintf(m->sender_buffer, ":1.%llu", k->src_id);
-                 m->sender = m->creds.unique_name = m->sender_buffer;
++                //xsprintf(m->sender_buffer, ":1.%llu", k->src_id);
++                //m->sender = m->creds.unique_name = m->sender_buffer;
 +        }
 +
 +        if (destination)
 +                m->destination = destination;
 +        else if (k->dst_id == KDBUS_DST_ID_BROADCAST)
 +                m->destination = NULL;
 +        else if (k->dst_id == KDBUS_DST_ID_NAME)
 +                m->destination = bus->unique_name; /* fill in unique name if the well-known name is missing */
 +        else {
-                 xsprintf(m->destination_buffer, ":1.%llu", k->dst_id);
-                 m->destination = m->destination_buffer;
++                //xsprintf(m->destination_buffer, ":1.%llu", k->dst_id);
++                //m->destination = m->destination_buffer;
 +        }
 +
 +        /* We take possession of the kmsg struct now */
 +        m->kdbus = k;
 +        m->release_kdbus = true;
 +        m->free_fds = true;
 +        fds = NULL;
 +
 +        bus->rqueue[bus->rqueue_size++] = m;
 +
 +        return 1;
 +
 +fail:
 +        unset_memfds(m);
 +        sd_bus_message_unref(m);
 +
 +        return r;
 +}
 +
 +int bus_kernel_take_fd(sd_bus *b) {
 +        struct kdbus_bloom_parameter *bloom = NULL;
 +        struct kdbus_item *items, *item;
 +        struct kdbus_cmd_hello *hello;
 +        _cleanup_free_ char *g = NULL;
 +        const char *name;
 +        size_t l = 0, m = 0, sz;
 +        int r;
 +
 +        assert(b);
 +
 +        if (b->is_server)
 +                return -EINVAL;
 +
 +        b->use_memfd = 1;
 +
 +        if (b->description) {
 +                g = bus_label_escape(b->description);
 +                if (!g)
 +                        return -ENOMEM;
 +
 +                name = g;
 +        } else {
 +                char pr[17] = {};
 +
 +                /* If no name is explicitly set, we'll include a hint
 +                 * indicating the library implementation, a hint which
 +                 * kind of bus this is and the thread name */
 +
 +                assert_se(prctl(PR_GET_NAME, (unsigned long) pr) >= 0);
 +
 +                if (isempty(pr)) {
 +                        name = b->is_system ? "sd-system" :
 +                                b->is_user ? "sd-user" : "sd";
 +                } else {
 +                        _cleanup_free_ char *e = NULL;
 +
 +                        e = bus_label_escape(pr);
 +                        if (!e)
 +                                return -ENOMEM;
 +
 +                        g = strappend(b->is_system ? "sd-system-" :
 +                                      b->is_user ? "sd-user-" : "sd-",
 +                                      e);
 +                        if (!g)
 +                                return -ENOMEM;
 +
 +                        name = g;
 +                }
 +
 +                b->description = bus_label_unescape(name);
 +                if (!b->description)
 +                        return -ENOMEM;
 +        }
 +
 +        m = strlen(name);
 +
 +        sz = ALIGN8(offsetof(struct kdbus_cmd_hello, items)) +
 +                ALIGN8(offsetof(struct kdbus_item, str) + m + 1);
 +
 +        if (b->fake_creds_valid)
 +                sz += ALIGN8(offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds));
 +
 +        if (b->fake_pids_valid)
 +                sz += ALIGN8(offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids));
 +
 +        if (b->fake_label) {
 +                l = strlen(b->fake_label);
 +                sz += ALIGN8(offsetof(struct kdbus_item, str) + l + 1);
 +        }
 +
 +        hello = alloca0_align(sz, 8);
 +        hello->size = sz;
-         hello->flags = b->hello_flags;
++        //hello->flags = b->hello_flags;
 +        hello->attach_flags_send = _KDBUS_ATTACH_ANY;
-         hello->attach_flags_recv = b->attach_flags;
++        //hello->attach_flags_recv = b->attach_flags;
 +        hello->pool_size = KDBUS_POOL_SIZE;
 +
 +        item = hello->items;
 +
 +        item->size = offsetof(struct kdbus_item, str) + m + 1;
 +        item->type = KDBUS_ITEM_CONN_DESCRIPTION;
 +        memcpy(item->str, name, m + 1);
 +        item = KDBUS_ITEM_NEXT(item);
 +
 +        if (b->fake_creds_valid) {
 +                item->size = offsetof(struct kdbus_item, creds) + sizeof(struct kdbus_creds);
 +                item->type = KDBUS_ITEM_CREDS;
 +                item->creds = b->fake_creds;
 +
 +                item = KDBUS_ITEM_NEXT(item);
 +        }
 +
 +        if (b->fake_pids_valid) {
 +                item->size = offsetof(struct kdbus_item, pids) + sizeof(struct kdbus_pids);
 +                item->type = KDBUS_ITEM_PIDS;
 +                item->pids = b->fake_pids;
 +
 +                item = KDBUS_ITEM_NEXT(item);
 +        }
 +
 +        if (b->fake_label) {
 +                item->size = offsetof(struct kdbus_item, str) + l + 1;
 +                item->type = KDBUS_ITEM_SECLABEL;
 +                memcpy(item->str, b->fake_label, l+1);
 +        }
 +
 +        r = ioctl(b->input_fd, KDBUS_CMD_HELLO, hello);
 +        if (r < 0) {
 +                if (errno == ENOTTY)
 +                        /* If the ioctl is not supported we assume that the
 +                         * API version changed in a major incompatible way,
 +                         * let's indicate an API incompatibility in this
 +                         * case. */
 +                        return -ESOCKTNOSUPPORT;
 +
 +                return -errno;
 +        }
 +
 +        if (!b->kdbus_buffer) {
 +                b->kdbus_buffer = mmap(NULL, KDBUS_POOL_SIZE, PROT_READ, MAP_SHARED, b->input_fd, 0);
 +                if (b->kdbus_buffer == MAP_FAILED) {
 +                        b->kdbus_buffer = NULL;
 +                        r = -errno;
 +                        goto fail;
 +                }
 +        }
 +
 +        /* The higher 32bit of the bus_flags fields are considered
 +         * 'incompatible flags'. Refuse them all for now. */
 +        if (hello->bus_flags > 0xFFFFFFFFULL) {
 +                r = -ESOCKTNOSUPPORT;
 +                goto fail;
 +        }
 +
 +        /* extract bloom parameters from items */
 +        items = (void*)((uint8_t*)b->kdbus_buffer + hello->offset);
 +        KDBUS_FOREACH(item, items, hello->items_size) {
 +                switch (item->type) {
 +                case KDBUS_ITEM_BLOOM_PARAMETER:
 +                        bloom = &item->bloom_parameter;
 +                        break;
 +                }
 +        }
 +
-         if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
-                 r = -EOPNOTSUPP;
-                 goto fail;
-         }
++        //if (!bloom || !bloom_validate_parameters((size_t) bloom->size, (unsigned) bloom->n_hash)) {
++                //r = -EOPNOTSUPP;
++                //goto fail;
++        //}
 +
 +        b->bloom_size = (size_t) bloom->size;
 +        b->bloom_n_hash = (unsigned) bloom->n_hash;
 +
 +        if (asprintf(&b->unique_name, ":1.%llu", hello->id) < 0) {
 +                r = -ENOMEM;
 +                goto fail;
 +        }
 +
 +        b->unique_id = hello->id;
 +
 +        b->is_kernel = true;
 +        b->bus_client = true;
 +        b->can_fds = !!(hello->flags & KDBUS_HELLO_ACCEPT_FD);
 +        b->message_version = 2;
 +        b->message_endian = BUS_NATIVE_ENDIAN;
 +
 +        /* the kernel told us the UUID of the underlying bus */
 +        memcpy(b->server_id.bytes, hello->id128, sizeof(b->server_id.bytes));
 +
 +        /* free returned items */
 +        (void) bus_kernel_cmd_free(b, hello->offset);
 +        return bus_start_running(b);
 +
 +fail:
 +        (void) bus_kernel_cmd_free(b, hello->offset);
 +        return r;
 +}
 +
 +int bus_kernel_connect(sd_bus *b) {
 +        assert(b);
 +        assert(b->input_fd < 0);
 +        assert(b->output_fd < 0);
 +        assert(b->kernel);
 +
 +        if (b->is_server)
 +                return -EINVAL;
 +
 +        b->input_fd = open(b->kernel, O_RDWR|O_NOCTTY|O_CLOEXEC);
 +        if (b->input_fd < 0)
 +                return -errno;
 +
 +        b->output_fd = b->input_fd;
 +
 +        return bus_kernel_take_fd(b);
 +}
 +
 +int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset) {
 +        struct kdbus_cmd_free cmd = {
 +                .size = sizeof(cmd),
 +                .offset = offset,
 +        };
 +        int r;
 +
 +        assert(bus);
 +        assert(bus->is_kernel);
 +
 +        r = ioctl(bus->input_fd, KDBUS_CMD_FREE, &cmd);
 +        if (r < 0)
 +                return -errno;
 +
 +        return 0;
 +}
 +
 +static void close_kdbus_msg(sd_bus *bus, struct kdbus_msg *k) {
 +        struct kdbus_item *d;
 +
 +        assert(bus);
 +        assert(k);
 +
 +        KDBUS_ITEM_FOREACH(d, k, items) {
 +                if (d->type == KDBUS_ITEM_FDS)
 +                        close_many(d->fds, (d->size - offsetof(struct kdbus_item, fds)) / sizeof(int));
 +                else if (d->type == KDBUS_ITEM_PAYLOAD_MEMFD)
 +                        safe_close(d->memfd.fd);
 +        }
 +
 +        bus_kernel_cmd_free(bus, (uint8_t*) k - (uint8_t*) bus->kdbus_buffer);
 +}
 +
 +int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call) {
 +        struct kdbus_cmd_send cmd = { };
 +        int r;
 +
 +        assert(bus);
 +        assert(m);
 +        assert(bus->state == BUS_RUNNING);
 +
 +        /* If we can't deliver, we want room for the error message */
 +        r = bus_rqueue_make_room(bus);
 +        if (r < 0)
 +                return r;
 +
 +        r = bus_message_setup_kmsg(bus, m);
 +        if (r < 0)
 +                return r;
 +
 +        cmd.size = sizeof(cmd);
 +        cmd.msg_address = (uintptr_t)m->kdbus;
 +
 +        /* If this is a synchronous method call, then let's tell the
 +         * kernel, so that it can pass CPU time/scheduling to the
 +         * destination for the time, if it wants to. If we
 +         * synchronously wait for the result anyway, we won't need CPU
 +         * anyway. */
 +        if (hint_sync_call) {
 +                m->kdbus->flags |= KDBUS_MSG_EXPECT_REPLY;
 +                cmd.flags |= KDBUS_SEND_SYNC_REPLY;
 +        }
 +
 +        r = ioctl(bus->output_fd, KDBUS_CMD_SEND, &cmd);
 +        if (r < 0) {
 +                _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 +                sd_bus_message *reply;
 +
 +                if (errno == EAGAIN || errno == EINTR)
 +                        return 0;
 +                else if (errno == ENXIO || errno == ESRCH) {
 +
 +                        /* ENXIO: unique name not known
 +                         * ESRCH: well-known name not known */
 +
 +                        if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
 +                                sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Destination %s not known", m->destination);
 +                        else {
 +                                log_debug("Could not deliver message to %s as destination is not known. Ignoring.", m->destination);
 +                                return 0;
 +                        }
 +
 +                } else if (errno == EADDRNOTAVAIL) {
 +
 +                        /* EADDRNOTAVAIL: activation is possible, but turned off in request flags */
 +
 +                        if (m->header->type == SD_BUS_MESSAGE_METHOD_CALL)
 +                                sd_bus_error_setf(&error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Activation of %s not requested", m->destination);
 +                        else {
 +                                log_debug("Could not deliver message to %s as destination is not activated. Ignoring.", m->destination);
 +                                return 0;
 +                        }
 +                } else
 +                        return -errno;
 +
 +                r = bus_message_new_synthetic_error(
 +                                bus,
 +                                BUS_MESSAGE_COOKIE(m),
 +                                &error,
 +                                &reply);
 +
 +                if (r < 0)
 +                        return r;
 +
 +                r = bus_seal_synthetic_message(bus, reply);
 +                if (r < 0)
 +                        return r;
 +
 +                bus->rqueue[bus->rqueue_size++] = reply;
 +
 +        } else if (hint_sync_call) {
 +                struct kdbus_msg *k;
 +
 +                k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + cmd.reply.offset);
 +                assert(k);
 +
 +                if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
 +
 +                        r = bus_kernel_make_message(bus, k);
 +                        if (r < 0) {
 +                                close_kdbus_msg(bus, k);
 +
 +                                /* Anybody can send us invalid messages, let's just drop them. */
 +                                if (r == -EBADMSG || r == -EPROTOTYPE)
 +                                        log_debug_errno(r, "Ignoring invalid synchronous reply: %m");
 +                                else
 +                                        return r;
 +                        }
 +                } else {
 +                        log_debug("Ignoring message with unknown payload type %llu.", k->payload_type);
 +                        close_kdbus_msg(bus, k);
 +                }
 +        }
 +
 +        return 1;
 +}
 +
 +static int push_name_owner_changed(
 +                sd_bus *bus,
 +                const char *name,
 +                const char *old_owner,
 +                const char *new_owner,
 +                const struct kdbus_timestamp *ts) {
 +
 +        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 +        int r;
 +
 +        assert(bus);
 +
 +        r = sd_bus_message_new_signal(
 +                        bus,
 +                        &m,
 +                        "/org/freedesktop/DBus",
 +                        "org.freedesktop.DBus",
 +                        "NameOwnerChanged");
 +        if (r < 0)
 +                return r;
 +
 +        r = sd_bus_message_append(m, "sss", name, old_owner, new_owner);
 +        if (r < 0)
 +                return r;
 +
 +        bus_message_set_sender_driver(bus, m);
 +        message_set_timestamp(bus, m, ts);
 +
 +        r = bus_seal_synthetic_message(bus, m);
 +        if (r < 0)
 +                return r;
 +
 +        bus->rqueue[bus->rqueue_size++] = m;
 +        m = NULL;
 +
 +        return 1;
 +}
 +
 +static int translate_name_change(
 +                sd_bus *bus,
 +                const struct kdbus_msg *k,
 +                const struct kdbus_item *d,
 +                const struct kdbus_timestamp *ts) {
 +
 +        char new_owner[UNIQUE_NAME_MAX], old_owner[UNIQUE_NAME_MAX];
 +
 +        assert(bus);
 +        assert(k);
 +        assert(d);
 +
 +        if (d->type == KDBUS_ITEM_NAME_ADD || (d->name_change.old_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR)))
 +                old_owner[0] = 0;
 +        else
 +                sprintf(old_owner, ":1.%llu", d->name_change.old_id.id);
 +
 +        if (d->type == KDBUS_ITEM_NAME_REMOVE || (d->name_change.new_id.flags & (KDBUS_NAME_IN_QUEUE|KDBUS_NAME_ACTIVATOR))) {
 +
 +                if (isempty(old_owner))
 +                        return 0;
 +
 +                new_owner[0] = 0;
 +        } else
 +                sprintf(new_owner, ":1.%llu", d->name_change.new_id.id);
 +
 +        return push_name_owner_changed(bus, d->name_change.name, old_owner, new_owner, ts);
 +}
 +
 +static int translate_id_change(
 +                sd_bus *bus,
 +                const struct kdbus_msg *k,
 +                const struct kdbus_item *d,
 +                const struct kdbus_timestamp *ts) {
 +
 +        char owner[UNIQUE_NAME_MAX];
 +
 +        assert(bus);
 +        assert(k);
 +        assert(d);
 +
 +        sprintf(owner, ":1.%llu", d->id_change.id);
 +
 +        return push_name_owner_changed(
 +                        bus, owner,
 +                        d->type == KDBUS_ITEM_ID_ADD ? NULL : owner,
 +                        d->type == KDBUS_ITEM_ID_ADD ? owner : NULL,
 +                        ts);
 +}
 +
 +static int translate_reply(
 +                sd_bus *bus,
 +                const struct kdbus_msg *k,
 +                const struct kdbus_item *d,
 +                const struct kdbus_timestamp *ts) {
 +
 +        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 +        int r;
 +
 +        assert(bus);
 +        assert(k);
 +        assert(d);
 +
 +        r = bus_message_new_synthetic_error(
 +                        bus,
 +                        k->cookie_reply,
 +                        d->type == KDBUS_ITEM_REPLY_TIMEOUT ?
 +                        &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call timed out") :
 +                        &SD_BUS_ERROR_MAKE_CONST(SD_BUS_ERROR_NO_REPLY, "Method call peer died"),
 +                        &m);
 +        if (r < 0)
 +                return r;
 +
 +        message_set_timestamp(bus, m, ts);
 +
 +        r = bus_seal_synthetic_message(bus, m);
 +        if (r < 0)
 +                return r;
 +
 +        bus->rqueue[bus->rqueue_size++] = m;
 +        m = NULL;
 +
 +        return 1;
 +}
 +
 +static int bus_kernel_translate_message(sd_bus *bus, struct kdbus_msg *k) {
 +        static int (* const translate[])(sd_bus *bus, const struct kdbus_msg *k, const struct kdbus_item *d, const struct kdbus_timestamp *ts) = {
 +                [KDBUS_ITEM_NAME_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
 +                [KDBUS_ITEM_NAME_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
 +                [KDBUS_ITEM_NAME_CHANGE - _KDBUS_ITEM_KERNEL_BASE] = translate_name_change,
 +
 +                [KDBUS_ITEM_ID_ADD - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
 +                [KDBUS_ITEM_ID_REMOVE - _KDBUS_ITEM_KERNEL_BASE] = translate_id_change,
 +
 +                [KDBUS_ITEM_REPLY_TIMEOUT - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
 +                [KDBUS_ITEM_REPLY_DEAD - _KDBUS_ITEM_KERNEL_BASE] = translate_reply,
 +        };
 +
 +        struct kdbus_item *d, *found = NULL;
 +        struct kdbus_timestamp *ts = NULL;
 +
 +        assert(bus);
 +        assert(k);
 +        assert(k->payload_type == KDBUS_PAYLOAD_KERNEL);
 +
 +        KDBUS_ITEM_FOREACH(d, k, items) {
 +                if (d->type == KDBUS_ITEM_TIMESTAMP)
 +                        ts = &d->timestamp;
 +                else if (d->type >= _KDBUS_ITEM_KERNEL_BASE && d->type < _KDBUS_ITEM_KERNEL_BASE + ELEMENTSOF(translate)) {
 +                        if (found)
 +                                return -EBADMSG;
 +                        found = d;
 +                } else
 +                        log_debug("Got unknown field from kernel %llu", d->type);
 +        }
 +
 +        if (!found) {
 +                log_debug("Didn't find a kernel message to translate.");
 +                return 0;
 +        }
 +
 +        return translate[found->type - _KDBUS_ITEM_KERNEL_BASE](bus, k, found, ts);
 +}
 +
 +int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority) {
 +        struct kdbus_cmd_recv recv = { .size = sizeof(recv) };
 +        struct kdbus_msg *k;
 +        int r;
 +
 +        assert(bus);
 +
 +        r = bus_rqueue_make_room(bus);
 +        if (r < 0)
 +                return r;
 +
 +        if (hint_priority) {
 +                recv.flags |= KDBUS_RECV_USE_PRIORITY;
 +                recv.priority = priority;
 +        }
 +
 +        r = ioctl(bus->input_fd, KDBUS_CMD_RECV, &recv);
 +        if (recv.return_flags & KDBUS_RECV_RETURN_DROPPED_MSGS)
 +                log_debug("%s: kdbus reports %" PRIu64 " dropped broadcast messages, ignoring.", strna(bus->description), (uint64_t) recv.dropped_msgs);
 +        if (r < 0) {
 +                if (errno == EAGAIN)
 +                        return 0;
 +
 +                return -errno;
 +        }
 +
 +        k = (struct kdbus_msg *)((uint8_t *)bus->kdbus_buffer + recv.msg.offset);
 +        if (k->payload_type == KDBUS_PAYLOAD_DBUS) {
 +                r = bus_kernel_make_message(bus, k);
 +
 +                /* Anybody can send us invalid messages, let's just drop them. */
 +                if (r == -EBADMSG || r == -EPROTOTYPE) {
 +                        log_debug_errno(r, "Ignoring invalid message: %m");
 +                        r = 0;
 +                }
 +
 +                if (r <= 0)
 +                        close_kdbus_msg(bus, k);
 +        } else if (k->payload_type == KDBUS_PAYLOAD_KERNEL) {
 +                r = bus_kernel_translate_message(bus, k);
 +                close_kdbus_msg(bus, k);
 +        } else {
 +                log_debug("Ignoring message with unknown payload type %llu.", k->payload_type);
 +                r = 0;
 +                close_kdbus_msg(bus, k);
 +        }
 +
 +        return r < 0 ? r : 1;
 +}
 +
 +int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated) {
 +        struct memfd_cache *c;
 +        int fd;
 +
 +        assert(address);
 +        assert(mapped);
 +        assert(allocated);
 +
 +        if (!bus || !bus->is_kernel)
 +                return -EOPNOTSUPP;
 +
 +        assert_se(pthread_mutex_lock(&bus->memfd_cache_mutex) == 0);
 +
 +        if (bus->n_memfd_cache <= 0) {
 +                int r;
 +
 +                assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
 +
 +                r = memfd_new(bus->description);
 +                if (r < 0)
 +                        return r;
 +
 +                *address = NULL;
 +                *mapped = 0;
 +                *allocated = 0;
 +                return r;
 +        }
 +
 +        c = &bus->memfd_cache[--bus->n_memfd_cache];
 +
 +        assert(c->fd >= 0);
 +        assert(c->mapped == 0 || c->address);
 +
 +        *address = c->address;
 +        *mapped = c->mapped;
 +        *allocated = c->allocated;
 +        fd = c->fd;
 +
 +        assert_se(pthread_mutex_unlock(&bus->memfd_cache_mutex) == 0);
 +
 +        return fd;
 +}
 +
 +static void close_and_munmap(int fd, void *address, size_t size) {
          if (size > 0)
                  assert_se(munmap(address, PAGE_ALIGN(size)) >= 0);
  
@@@ -1524,260 -66,3 +1523,214 @@@ void bus_kernel_flush_memfd(sd_bus *b) 
          for (i = 0; i < b->n_memfd_cache; i++)
                  close_and_munmap(b->memfd_cache[i].fd, b->memfd_cache[i].address, b->memfd_cache[i].mapped);
  }
- uint64_t attach_flags_to_kdbus(uint64_t mask) {
-         uint64_t m = 0;
-         if (mask & (SD_BUS_CREDS_UID|SD_BUS_CREDS_EUID|SD_BUS_CREDS_SUID|SD_BUS_CREDS_FSUID|
-                     SD_BUS_CREDS_GID|SD_BUS_CREDS_EGID|SD_BUS_CREDS_SGID|SD_BUS_CREDS_FSGID))
-                 m |= KDBUS_ATTACH_CREDS;
-         if (mask & (SD_BUS_CREDS_PID|SD_BUS_CREDS_TID|SD_BUS_CREDS_PPID))
-                 m |= KDBUS_ATTACH_PIDS;
-         if (mask & SD_BUS_CREDS_COMM)
-                 m |= KDBUS_ATTACH_PID_COMM;
-         if (mask & SD_BUS_CREDS_TID_COMM)
-                 m |= KDBUS_ATTACH_TID_COMM;
-         if (mask & SD_BUS_CREDS_EXE)
-                 m |= KDBUS_ATTACH_EXE;
-         if (mask & SD_BUS_CREDS_CMDLINE)
-                 m |= KDBUS_ATTACH_CMDLINE;
-         if (mask & (SD_BUS_CREDS_CGROUP|SD_BUS_CREDS_UNIT|SD_BUS_CREDS_USER_UNIT|SD_BUS_CREDS_SLICE|SD_BUS_CREDS_SESSION|SD_BUS_CREDS_OWNER_UID))
-                 m |= KDBUS_ATTACH_CGROUP;
-         if (mask & (SD_BUS_CREDS_EFFECTIVE_CAPS|SD_BUS_CREDS_PERMITTED_CAPS|SD_BUS_CREDS_INHERITABLE_CAPS|SD_BUS_CREDS_BOUNDING_CAPS))
-                 m |= KDBUS_ATTACH_CAPS;
-         if (mask & SD_BUS_CREDS_SELINUX_CONTEXT)
-                 m |= KDBUS_ATTACH_SECLABEL;
-         if (mask & (SD_BUS_CREDS_AUDIT_SESSION_ID|SD_BUS_CREDS_AUDIT_LOGIN_UID))
-                 m |= KDBUS_ATTACH_AUDIT;
-         if (mask & SD_BUS_CREDS_WELL_KNOWN_NAMES)
-                 m |= KDBUS_ATTACH_NAMES;
-         if (mask & SD_BUS_CREDS_DESCRIPTION)
-                 m |= KDBUS_ATTACH_CONN_DESCRIPTION;
-         if (mask & SD_BUS_CREDS_SUPPLEMENTARY_GIDS)
-                 m |= KDBUS_ATTACH_AUXGROUPS;
-         return m;
- }
 +
 +uint64_t request_name_flags_to_kdbus(uint64_t flags) {
 +        uint64_t f = 0;
 +
 +        if (flags & SD_BUS_NAME_ALLOW_REPLACEMENT)
 +                f |= KDBUS_NAME_ALLOW_REPLACEMENT;
 +
 +        if (flags & SD_BUS_NAME_REPLACE_EXISTING)
 +                f |= KDBUS_NAME_REPLACE_EXISTING;
 +
 +        if (flags & SD_BUS_NAME_QUEUE)
 +                f |= KDBUS_NAME_QUEUE;
 +
 +        return f;
 +}
 +
-         n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
-         n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
 +int bus_kernel_create_bus(const char *name, bool world, char **s) {
 +        struct kdbus_cmd *make;
 +        struct kdbus_item *n;
 +        size_t l;
 +        int fd;
 +
 +        assert(name);
 +        assert(s);
 +
 +        fd = open("/sys/fs/kdbus/control", O_RDWR|O_NOCTTY|O_CLOEXEC);
 +        if (fd < 0)
 +                return -errno;
 +
 +        l = strlen(name);
 +        make = alloca0_align(offsetof(struct kdbus_cmd, items) +
 +                             ALIGN8(offsetof(struct kdbus_item, bloom_parameter) + sizeof(struct kdbus_bloom_parameter)) +
 +                             ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)) +
 +                             ALIGN8(offsetof(struct kdbus_item, str) + DECIMAL_STR_MAX(uid_t) + 1 + l + 1),
 +                             8);
 +
 +        make->size = offsetof(struct kdbus_cmd, items);
 +
 +        /* Set the bloom parameters */
 +        n = make->items;
 +        n->size = offsetof(struct kdbus_item, bloom_parameter) +
 +                  sizeof(struct kdbus_bloom_parameter);
 +        n->type = KDBUS_ITEM_BLOOM_PARAMETER;
-         assert_cc(DEFAULT_BLOOM_SIZE > 0);
-         assert_cc(DEFAULT_BLOOM_N_HASH > 0);
++        //n->bloom_parameter.size = DEFAULT_BLOOM_SIZE;
++        //n->bloom_parameter.n_hash = DEFAULT_BLOOM_N_HASH;
 +
-         n->data64[0] = bus->attach_flags;
++        //assert_cc(DEFAULT_BLOOM_SIZE > 0);
++        //assert_cc(DEFAULT_BLOOM_N_HASH > 0);
 +
 +        make->size += ALIGN8(n->size);
 +
 +        /* Provide all metadata via bus-owner queries */
 +        n = KDBUS_ITEM_NEXT(n);
 +        n->type = KDBUS_ITEM_ATTACH_FLAGS_SEND;
 +        n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
 +        n->data64[0] = _KDBUS_ATTACH_ANY;
 +        make->size += ALIGN8(n->size);
 +
 +        /* Set the a good name */
 +        n = KDBUS_ITEM_NEXT(n);
 +        sprintf(n->str, UID_FMT "-%s", getuid(), name);
 +        n->size = offsetof(struct kdbus_item, str) + strlen(n->str) + 1;
 +        n->type = KDBUS_ITEM_MAKE_NAME;
 +        make->size += ALIGN8(n->size);
 +
 +        make->flags = world ? KDBUS_MAKE_ACCESS_WORLD : 0;
 +
 +        if (ioctl(fd, KDBUS_CMD_BUS_MAKE, make) < 0) {
 +                safe_close(fd);
 +
 +                /* Major API change? then the ioctls got shuffled around. */
 +                if (errno == ENOTTY)
 +                        return -ESOCKTNOSUPPORT;
 +
 +                return -errno;
 +        }
 +
 +        if (s) {
 +                char *p;
 +
 +                p = strjoin("/sys/fs/kdbus/", n->str, "/bus");
 +                if (!p) {
 +                        safe_close(fd);
 +                        return -ENOMEM;
 +                }
 +
 +                *s = p;
 +        }
 +
 +        return fd;
 +}
 +
 +int bus_kernel_open_bus_fd(const char *bus, char **path) {
 +        char *p;
 +        int fd;
 +        size_t len;
 +
 +        assert(bus);
 +
 +        len = strlen("/sys/fs/kdbus/") + DECIMAL_STR_MAX(uid_t) + 1 + strlen(bus) + strlen("/bus") + 1;
 +
 +        if (path) {
 +                p = new(char, len);
 +                if (!p)
 +                        return -ENOMEM;
 +        } else
 +                p = newa(char, len);
 +
 +        sprintf(p, "/sys/fs/kdbus/" UID_FMT "-%s/bus", getuid(), bus);
 +
 +        fd = open(p, O_RDWR|O_NOCTTY|O_CLOEXEC);
 +        if (fd < 0) {
 +                if (path)
 +                        free(p);
 +
 +                return -errno;
 +        }
 +
 +        if (path)
 +                *path = p;
 +
 +        return fd;
 +}
 +
 +int bus_kernel_try_close(sd_bus *bus) {
 +        struct kdbus_cmd byebye = { .size = sizeof(byebye) };
 +
 +        assert(bus);
 +        assert(bus->is_kernel);
 +
 +        if (ioctl(bus->input_fd, KDBUS_CMD_BYEBYE, &byebye) < 0)
 +                return -errno;
 +
 +        return 0;
 +}
 +
 +int bus_kernel_drop_one(int fd) {
 +        struct kdbus_cmd_recv recv = {
 +                .size = sizeof(recv),
 +                .flags = KDBUS_RECV_DROP,
 +        };
 +
 +        assert(fd >= 0);
 +
 +        if (ioctl(fd, KDBUS_CMD_RECV, &recv) < 0)
 +                return -errno;
 +
 +        return 0;
 +}
 +
 +int bus_kernel_realize_attach_flags(sd_bus *bus) {
 +        struct kdbus_cmd *update;
 +        struct kdbus_item *n;
 +
 +        assert(bus);
 +        assert(bus->is_kernel);
 +
 +        update = alloca0_align(offsetof(struct kdbus_cmd, items) +
 +                               ALIGN8(offsetof(struct kdbus_item, data64) + sizeof(uint64_t)),
 +                               8);
 +
 +        n = update->items;
 +        n->type = KDBUS_ITEM_ATTACH_FLAGS_RECV;
 +        n->size = offsetof(struct kdbus_item, data64) + sizeof(uint64_t);
++        //n->data64[0] = bus->attach_flags;
 +
 +        update->size =
 +                offsetof(struct kdbus_cmd, items) +
 +                ALIGN8(n->size);
 +
 +        if (ioctl(bus->input_fd, KDBUS_CMD_UPDATE, update) < 0)
 +                return -errno;
 +
 +        return 0;
 +}
 +
 +int bus_kernel_get_bus_name(sd_bus *bus, char **name) {
 +        struct kdbus_cmd_info cmd = {
 +                .size = sizeof(struct kdbus_cmd_info),
 +        };
 +        struct kdbus_info *info;
 +        struct kdbus_item *item;
 +        char *n = NULL;
 +        int r;
 +
 +        assert(bus);
 +        assert(name);
 +        assert(bus->is_kernel);
 +
 +        r = ioctl(bus->input_fd, KDBUS_CMD_BUS_CREATOR_INFO, &cmd);
 +        if (r < 0)
 +                return -errno;
 +
 +        info = (struct kdbus_info*) ((uint8_t*) bus->kdbus_buffer + cmd.offset);
 +
 +        KDBUS_ITEM_FOREACH(item, info, items)
 +                if (item->type == KDBUS_ITEM_MAKE_NAME) {
 +                        r = free_and_strdup(&n, item->str);
 +                        break;
 +                }
 +
 +        bus_kernel_cmd_free(bus, cmd.offset);
 +
 +        if (r < 0)
 +                return r;
 +        if (!n)
 +                return -EIO;
 +
 +        *name = n;
 +        return 0;
 +}
@@@ -62,33 -39,5 +62,32 @@@ struct memfd_cache 
          size_t allocated;
  };
  
 -void close_and_munmap(int fd, void *address, size_t size);
 -void bus_flush_memfd(sd_bus *bus);
 +int bus_kernel_connect(sd_bus *b);
 +int bus_kernel_take_fd(sd_bus *b);
 +
 +int bus_kernel_write_message(sd_bus *bus, sd_bus_message *m, bool hint_sync_call);
 +int bus_kernel_read_message(sd_bus *bus, bool hint_priority, int64_t priority);
 +
 +int bus_kernel_open_bus_fd(const char *bus, char **path);
 +
 +int bus_kernel_create_bus(const char *name, bool world, char **s);
 +int bus_kernel_create_endpoint(const char *bus_name, const char *ep_name, char **path);
 +
 +int bus_kernel_pop_memfd(sd_bus *bus, void **address, size_t *mapped, size_t *allocated);
 +void bus_kernel_push_memfd(sd_bus *bus, int fd, void *address, size_t mapped, size_t allocated);
 +
 +void bus_kernel_flush_memfd(sd_bus *bus);
 +
 +int bus_kernel_parse_unique_name(const char *s, uint64_t *id);
 +
 +uint64_t request_name_flags_to_kdbus(uint64_t sd_bus_flags);
- uint64_t attach_flags_to_kdbus(uint64_t sd_bus_flags);
 +
 +int bus_kernel_try_close(sd_bus *bus);
 +
 +int bus_kernel_drop_one(int fd);
 +
 +int bus_kernel_realize_attach_flags(sd_bus *bus);
 +
 +int bus_kernel_get_bus_name(sd_bus *bus, char **name);
 +
 +int bus_kernel_cmd_free(sd_bus *bus, uint64_t offset);
Simple merge
Simple merge
@@@ -94,7 -94,12 +94,12 @@@ void bus_slot_disconnect(sd_bus_slot *s
          case BUS_MATCH_CALLBACK:
  
                  if (slot->match_added)
-                         bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
 -                        (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string);
++                        (void) bus_remove_match_internal(slot->bus, slot->match_callback.match_string, slot->match_callback.cookie);
+                 if (slot->match_callback.install_slot) {
+                         bus_slot_disconnect(slot->match_callback.install_slot);
+                         slot->match_callback.install_slot = sd_bus_slot_unref(slot->match_callback.install_slot);
+                 }
  
                  slot->bus->match_callbacks_modified = true;
                  bus_match_remove(&slot->bus->match_callbacks, &slot->match_callback);
@@@ -592,10 -596,9 +596,10 @@@ void bus_socket_setup(sd_bus *b) 
          assert(b);
  
          /* Increase the buffers to 8 MB */
-         fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
-         fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
+         (void) fd_inc_rcvbuf(b->input_fd, SNDBUF_SIZE);
+         (void) fd_inc_sndbuf(b->output_fd, SNDBUF_SIZE);
  
 +        b->is_kernel = false;
          b->message_version = 1;
          b->message_endian = 0;
  }
@@@ -131,21 -201,19 +201,24 @@@ static void bus_free(sd_bus *b) 
          if (b->default_bus_ptr)
                  *b->default_bus_ptr = NULL;
  
-         bus_close_fds(b);
+         bus_close_io_fds(b);
+         bus_close_inotify_fd(b);
  
 +        if (b->kdbus_buffer)
 +                munmap(b->kdbus_buffer, KDBUS_POOL_SIZE);
 +
          free(b->label);
+         free(b->groups);
          free(b->rbuffer);
          free(b->unique_name);
          free(b->auth_buffer);
          free(b->address);
 +        free(b->kernel);
          free(b->machine);
 +        free(b->fake_label);
          free(b->cgroup_root);
          free(b->description);
+         free(b->patch_sender);
  
          free(b->exec_path);
          strv_free(b->exec_argv);
@@@ -439,10 -613,28 +618,28 @@@ static int bus_send_hello(sd_bus *bus) 
  }
  
  int bus_start_running(sd_bus *bus) {
+         struct reply_callback *c;
+         Iterator i;
+         usec_t n;
+         int r;
          assert(bus);
+         assert(bus->state < BUS_HELLO);
+         /* We start all method call timeouts when we enter BUS_HELLO or BUS_RUNNING mode. At this point let's convert
+          * all relative to absolute timestamps. Note that we do not reshuffle the reply callback priority queue since
+          * adding a fixed value to all entries should not alter the internal order. */
+         n = now(CLOCK_MONOTONIC);
+         ORDERED_HASHMAP_FOREACH(c, bus->reply_callbacks, i) {
+                 if (c->timeout_usec == 0)
+                         continue;
+                 c->timeout_usec = usec_add(n, c->timeout_usec);
+         }
  
 -        if (bus->bus_client) {
 +        if (bus->bus_client && !bus->is_kernel) {
-                 bus->state = BUS_HELLO;
+                 bus_set_state(bus, BUS_HELLO);
                  return 1;
          }
  
@@@ -1024,56 -1105,39 +1227,65 @@@ static int bus_start_address(sd_bus *b
          assert(b);
  
          for (;;) {
-                 bus_close_fds(b);
 +                bool skipped = false;
 +
+                 bus_close_io_fds(b);
+                 bus_close_inotify_fd(b);
  
 -                /* If you provide multiple different bus-addresses, we
 -                 * try all of them in order and use the first one that
 -                 * succeeds. */
 +                /*
 +                 * Usually, if you provide multiple different bus-addresses, we
 +                 * try all of them in order. We use the first one that
 +                 * succeeds. However, if you mix kernel and unix addresses, we
 +                 * never try unix-addresses if a previous kernel address was
 +                 * tried and kdbus was available. This is required to prevent
 +                 * clients to fallback to the bus-proxy if kdbus is available
 +                 * but failed (eg., too many connections).
 +                 */
  
                  if (b->exec_path)
                          r = bus_socket_exec(b);
 -                else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC)
 -                        r = bus_container_connect_socket(b);
 -                else if (b->sockaddr.sa.sa_family != AF_UNSPEC)
 -                        r = bus_socket_connect(b);
 -                else
 -                        goto next;
 +                else if ((b->nspid > 0 || b->machine) && b->kernel) {
 +                        r = bus_container_connect_kernel(b);
 +                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
 +                                container_kdbus_available = true;
 +
 +                } else if ((b->nspid > 0 || b->machine) && b->sockaddr.sa.sa_family != AF_UNSPEC) {
 +                        if (!container_kdbus_available)
 +                                r = bus_container_connect_socket(b);
 +                        else
 +                                skipped = true;
  
 -                if (r >= 0) {
 -                        int q;
 +                } else if (b->kernel) {
 +                        r = bus_kernel_connect(b);
 +                        if (r < 0 && !IN_SET(r, -ENOENT, -ESOCKTNOSUPPORT))
 +                                kdbus_available = true;
  
 -                        q = bus_attach_io_events(b);
 -                        if (q < 0)
 -                                return q;
 +                } else if (b->sockaddr.sa.sa_family != AF_UNSPEC) {
 +                        if (!kdbus_available)
 +                                r = bus_socket_connect(b);
 +                        else
 +                                skipped = true;
 +                } else
 +                        skipped = true;
  
 -                        q = bus_attach_inotify_event(b);
 -                        if (q < 0)
 -                                return q;
 +                if (!skipped) {
 +                        if (r >= 0) {
-                                 r = attach_io_events(b);
-                                 if (r >= 0)
-                                         return r;
++                                int q;
 -                        return r;
 -                }
++                                q = bus_attach_io_events(b);
++                                if (q < 0)
++                                        return q;
 -                b->last_connect_error = -r;
++                                q = bus_attach_inotify_event(b);
++                                if (q < 0)
++                                        return q;
++
++                                return r;
 +                        }
 +
 +                        b->last_connect_error = -r;
 +                }
  
 -        next:
                  r = bus_parse_next_address(b);
                  if (r < 0)
                          return r;
@@@ -1265,24 -1324,19 +1476,24 @@@ int bus_set_address_user(sd_bus *b) 
          if (e)
                  return sd_bus_set_address(b, e);
  
 +        r = cg_pid_get_owner_uid(0, &uid);
 +        if (r < 0)
 +                uid = getuid();
 +
          e = secure_getenv("XDG_RUNTIME_DIR");
 -        if (!e)
 -                return -ENOENT;
 +        if (e) {
 +                _cleanup_free_ char *ee = NULL;
  
 -        ee = bus_address_escape(e);
 -        if (!ee)
 -                return -ENOMEM;
 +                ee = bus_address_escape(e);
 +                if (!ee)
 +                        return -ENOMEM;
  
-                 (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT ";" UNIX_USER_BUS_ADDRESS_FMT, uid, ee);
 -        if (asprintf(&s, DEFAULT_USER_BUS_ADDRESS_FMT, ee) < 0)
 -                return -ENOMEM;
++                (void) asprintf(&b->address, DEFAULT_USER_BUS_ADDRESS_FMT, uid, ee);
 +        } else
 +                (void) asprintf(&b->address, KERNEL_USER_BUS_ADDRESS_FMT, uid);
  
 -        b->address = s;
 -        s = NULL;
 +        if (!b->address)
 +                return -ENOMEM;
  
          return 0;
  }
@@@ -1460,13 -1514,8 +1671,15 @@@ _public_ void sd_bus_close(sd_bus *bus
           * the bus object and the bus may be freed */
          bus_reset_queues(bus);
  
 -        bus_close_io_fds(bus);
 +        if (!bus->is_kernel)
-                 bus_close_fds(bus);
++                bus_close_io_fds(bus);
 +
 +        /* We'll leave the fd open in case this is a kernel bus, since
 +         * there might still be memblocks around that reference this
 +         * bus, and they might need to invoke the KDBUS_CMD_FREE
 +         * ioctl on the fd when they are freed. */
++
+         bus_close_inotify_fd(bus);
  }
  
  _public_ sd_bus* sd_bus_flush_close_unref(sd_bus *bus) {
@@@ -1632,16 -1692,12 +1864,16 @@@ static int bus_write_message(sd_bus *bu
          assert(bus);
          assert(m);
  
-         if (bus->is_kernel)
-                 r = bus_kernel_write_message(bus, m, hint_sync_call);
-         else
 -        r = bus_socket_write_message(bus, m, idx);
++        //if (bus->is_kernel)
++                //r = bus_kernel_write_message(bus, m, hint_sync_call);
++        //else
 +                r = bus_socket_write_message(bus, m, idx);
 +
          if (r <= 0)
                  return r;
  
 -        if (*idx >= BUS_MESSAGE_SIZE(m))
 +        if (bus->is_kernel || *idx >= BUS_MESSAGE_SIZE(m))
-                 log_debug("Sent message type=%s sender=%s destination=%s object=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " error-name=%s error-message=%s",
+                 log_debug("Sent message type=%s sender=%s destination=%s path=%s interface=%s member=%s cookie=%" PRIu64 " reply_cookie=%" PRIu64 " signature=%s error-name=%s error-message=%s",
                            bus_message_type_to_string(m->header->type),
                            strna(sd_bus_message_get_sender(m)),
                            strna(sd_bus_message_get_destination(m)),
@@@ -1756,7 -1810,6 +1989,7 @@@ _public_ int sd_bus_send(sd_bus *bus, s
                  bus = m->bus;
  
          assert_return(!bus_pid_changed(bus), -ECHILD);
-         assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
++        //assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
  
          if (!BUS_IS_OPEN(bus->state))
                  return -ENOTCONN;
@@@ -1908,7 -1965,6 +2145,7 @@@ _public_ int sd_bus_call_async
                  bus = m->bus;
  
          assert_return(!bus_pid_changed(bus), -ECHILD);
-         assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
++        //assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS);
  
          if (!BUS_IS_OPEN(bus->state))
                  return -ENOTCONN;
@@@ -2009,7 -2071,6 +2252,7 @@@ _public_ int sd_bus_call
                  bus = m->bus;
  
          bus_assert_return(!bus_pid_changed(bus), -ECHILD, error);
-         bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
++        //bus_assert_return(!bus->is_kernel || !(bus->hello_flags & KDBUS_HELLO_MONITOR), -EROFS, error);
  
          if (!BUS_IS_OPEN(bus->state)) {
                  r = -ENOTCONN;
@@@ -2326,9 -2432,6 +2614,9 @@@ static int process_reply(sd_bus *bus, s
          if (!IN_SET(m->header->type, SD_BUS_MESSAGE_METHOD_RETURN, SD_BUS_MESSAGE_METHOD_ERROR))
                  return 0;
  
-         if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR))
-                 return 0;
++        //if (bus->is_kernel && (bus->hello_flags & KDBUS_HELLO_MONITOR))
++                //return 0;
 +
          if (m->destination && bus->unique_name && !streq_ptr(m->destination, bus->unique_name))
                  return 0;
  
@@@ -3042,31 -3231,32 +3416,35 @@@ static int bus_add_match_full
          }
  
          s->match_callback.callback = callback;
+         s->match_callback.install_callback = install_callback;
 +        s->match_callback.cookie = ++bus->match_cookie;
  
          if (bus->bus_client) {
                  enum bus_match_scope scope;
  
                  scope = bus_match_get_scope(components, n_components);
  
-                 /* Do not install server-side matches for matches
-                  * against the local service, interface or bus
-                  * path. */
+                 /* Do not install server-side matches for matches against the local service, interface or bus path. */
                  if (scope != BUS_MATCH_LOCAL) {
  
 -                        /* We store the original match string, so that we can use it to remove the match again. */
 +                        if (!bus->is_kernel) {
-                                 /* When this is not a kernel transport, we
-                                  * store the original match string, so that we
-                                  * can use it to remove the match again */
++                                /* When this is not a kernel transport we store the original match string, so that we can use it to remove the match again. */
  
 -                        s->match_callback.match_string = strdup(match);
 -                        if (!s->match_callback.match_string) {
 -                                r = -ENOMEM;
 -                                goto finish;
 +                                s->match_callback.match_string = strdup(match);
 +                                if (!s->match_callback.match_string) {
 +                                        r = -ENOMEM;
 +                                        goto finish;
 +                                }
                          }
  
-                         r = bus_add_match_internal(bus, s->match_callback.match_string, components, n_components, s->match_callback.cookie);
+                         if (asynchronous)
+                                 r = bus_add_match_internal_async(bus,
+                                                                  &s->match_callback.install_slot,
+                                                                  s->match_callback.match_string,
+                                                                  add_match_callback,
+                                                                  s);
+                         else
 -                                r = bus_add_match_internal(bus, s->match_callback.match_string);
++                                r = bus_add_match_internal(bus, s->match_callback.match_string, s->match_callback.cookie);
                          if (r < 0)
                                  goto finish;
  
@@@ -3679,29 -3888,11 +4076,30 @@@ _public_ int sd_bus_path_decode_many(co
  }
  
  _public_ int sd_bus_try_close(sd_bus *bus) {
 +        int r;
 +
          assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
          assert_return(!bus_pid_changed(bus), -ECHILD);
  
 -        return -EOPNOTSUPP;
 +        if (!bus->is_kernel)
 +                return -EOPNOTSUPP;
 +
 +        if (!BUS_IS_OPEN(bus->state))
 +                return -ENOTCONN;
 +
 +        if (bus->rqueue_size > 0)
 +                return -EBUSY;
 +
 +        if (bus->wqueue_size > 0)
 +                return -EBUSY;
 +
 +        r = bus_kernel_try_close(bus);
 +        if (r < 0)
 +                return r;
 +
 +        sd_bus_close(bus);
 +        return 0;
  }
  
  _public_ int sd_bus_get_description(sd_bus *bus, const char **description) {
@@@ -3733,9 -3925,8 +4132,10 @@@ int bus_get_root_path(sd_bus *bus) 
  }
  
  _public_ int sd_bus_get_scope(sd_bus *bus, const char **scope) {
 +        int r;
 +
          assert_return(bus, -EINVAL);
+         assert_return(bus = bus_resolve(bus), -ENOPKG);
          assert_return(scope, -EINVAL);
          assert_return(!bus_pid_changed(bus), -ECHILD);
  
@@@ -28,6 -28,6 +28,7 @@@
  #include "bus-util.h"
  #include "def.h"
  #include "fd-util.h"
++#include "process-util.h"
  #include "time-util.h"
  #include "util.h"
  
index 03d6f27,0000000..0117786
mode 100644,000000..100644
--- /dev/null
@@@ -1,141 -1,0 +1,142 @@@
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  systemd 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.
 +
 +  systemd is distributed in the hope that it will be useful, but
 +  WITHOUT ANY WARRANTY; without even the implied warranty of
 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 +  Lesser General Public License for more details.
 +
 +  You should have received a copy of the GNU Lesser General Public License
 +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 +***/
 +
 +#include "sd-bus.h"
 +
 +#include "alloc-util.h"
 +#include "bus-kernel.h"
 +#include "bus-util.h"
 +#include "fd-util.h"
 +#include "log.h"
++#include "process-util.h"
 +#include "util.h"
 +
 +static int test_match(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
 +        int *found = userdata;
 +
 +        *found = 1;
 +
 +        return 0;
 +}
 +
 +static void test_one(
 +                const char *path,
 +                const char *interface,
 +                const char *member,
 +                bool as_list,
 +                const char *arg0,
 +                const char *match,
 +                bool good) {
 +
 +        _cleanup_close_ int bus_ref = -1;
 +        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
 +        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 +        sd_bus *a, *b;
 +        int r, found = 0;
 +
 +        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid_cached()) >= 0);
 +
 +        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
 +        if (bus_ref == -ENOENT)
 +                exit(EXIT_TEST_SKIP);
 +
 +        assert_se(bus_ref >= 0);
 +
 +        address = strappend("kernel:path=", bus_name);
 +        assert_se(address);
 +
 +        r = sd_bus_new(&a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_new(&b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(a, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(b, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(b);
 +        assert_se(r >= 0);
 +
 +        log_debug("match");
 +        r = sd_bus_add_match(b, NULL, match, test_match, &found);
 +        assert_se(r >= 0);
 +
 +        log_debug("signal");
 +
 +        if (as_list)
 +                r = sd_bus_emit_signal(a, path, interface, member, "as", 1, arg0);
 +        else
 +                r = sd_bus_emit_signal(a, path, interface, member, "s", arg0);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_process(b, &m);
 +        assert_se(r >= 0 && good == !!found);
 +
 +        sd_bus_unref(a);
 +        sd_bus_unref(b);
 +}
 +
 +int main(int argc, char *argv[]) {
 +        log_set_max_level(LOG_DEBUG);
 +
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/tuut'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "interface='waldo.com'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Piep'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "member='Pi_ep'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foobar'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "arg0='foo_bar'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foobar'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0='foo_bar'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foobar'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", true, "foobar", "arg0has='foo_bar'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo',interface='waldo.com',member='Piep',arg0='foobar2'", false);
 +
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/quux'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/quux'", false);
 +        test_one("/", "waldo.com", "Piep", false, "foobar", "path_namespace='/'", true);
 +
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/bar/waldo/'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path='/foo/'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/bar/waldo/'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "foobar", "path_namespace='/foo/'", true);
 +
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/bar/waldo", "arg0path='/foo/'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo'", true);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo", "arg0path='/foo/bar/waldo'", false);
 +        test_one("/foo/bar/waldo", "waldo.com", "Piep", false, "/foo/", "arg0path='/foo/bar/waldo'", true);
 +
 +        return 0;
 +}
index 2fc2288,0000000..0f31e0e
mode 100644,000000..100644
--- /dev/null
@@@ -1,190 -1,0 +1,191 @@@
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  systemd 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.
 +
 +  systemd is distributed in the hope that it will be useful, but
 +  WITHOUT ANY WARRANTY; without even the implied warranty of
 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 +  Lesser General Public License for more details.
 +
 +  You should have received a copy of the GNU Lesser General Public License
 +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 +***/
 +
 +#include <fcntl.h>
 +
 +#include "sd-bus.h"
 +
 +#include "alloc-util.h"
 +#include "bus-dump.h"
 +#include "bus-kernel.h"
 +#include "bus-util.h"
 +#include "fd-util.h"
 +#include "log.h"
++#include "process-util.h"
 +#include "util.h"
 +
 +int main(int argc, char *argv[]) {
 +        _cleanup_close_ int bus_ref = -1;
 +        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL, *bname = NULL;
 +        _cleanup_(sd_bus_message_unrefp) sd_bus_message *m = NULL;
 +        _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
 +        const char *ua = NULL, *ub = NULL, *the_string = NULL;
 +        sd_bus *a, *b;
 +        int r, pipe_fds[2];
 +        const char *nn;
 +
 +        log_set_max_level(LOG_DEBUG);
 +
 +        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid_cached()) >= 0);
 +
 +        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
 +        if (bus_ref == -ENOENT)
 +                return EXIT_TEST_SKIP;
 +
 +        assert_se(bus_ref >= 0);
 +
 +        address = strappend("kernel:path=", bus_name);
 +        assert_se(address);
 +
 +        r = sd_bus_new(&a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_new(&b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_description(a, "a");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(a, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(b, address);
 +        assert_se(r >= 0);
 +
 +        assert_se(sd_bus_negotiate_timestamp(a, 1) >= 0);
 +        assert_se(sd_bus_negotiate_creds(a, true, _SD_BUS_CREDS_ALL) >= 0);
 +
 +        assert_se(sd_bus_negotiate_timestamp(b, 0) >= 0);
 +        assert_se(sd_bus_negotiate_creds(b, true, 0) >= 0);
 +
 +        r = sd_bus_start(a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(b);
 +        assert_se(r >= 0);
 +
 +        assert_se(sd_bus_negotiate_timestamp(b, 1) >= 0);
 +        assert_se(sd_bus_negotiate_creds(b, true, _SD_BUS_CREDS_ALL) >= 0);
 +
 +        r = sd_bus_get_unique_name(a, &ua);
 +        assert_se(r >= 0);
 +        printf("unique a: %s\n", ua);
 +
 +        r = sd_bus_get_description(a, &nn);
 +        assert_se(r >= 0);
 +        printf("name of a: %s\n", nn);
 +
 +        r = sd_bus_get_unique_name(b, &ub);
 +        assert_se(r >= 0);
 +        printf("unique b: %s\n", ub);
 +
 +        r = sd_bus_get_description(b, &nn);
 +        assert_se(r >= 0);
 +        printf("name of b: %s\n", nn);
 +
 +        assert_se(bus_kernel_get_bus_name(b, &bname) >= 0);
 +        assert_se(endswith(bname, name));
 +
 +        r = sd_bus_call_method(a, "this.doesnt.exist", "/foo", "meh.mah", "muh", &error, NULL, "s", "yayayay");
 +        assert_se(sd_bus_error_has_name(&error, SD_BUS_ERROR_SERVICE_UNKNOWN));
 +        assert_se(r == -EHOSTUNREACH);
 +
 +        r = sd_bus_add_match(b, NULL, "interface='waldo.com',member='Piep'", NULL, NULL);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_emit_signal(a, "/foo/bar/waldo", "waldo.com", "Piep", "sss", "I am a string", "/this/is/a/path", "and.this.a.domain.name");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_try_close(b);
 +        assert_se(r == -EBUSY);
 +
 +        r = sd_bus_process_priority(b, -10, &m);
 +        assert_se(r == 0);
 +
 +        r = sd_bus_process(b, &m);
 +        assert_se(r > 0);
 +        assert_se(m);
 +
 +        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +        assert_se(sd_bus_message_rewind(m, true) >= 0);
 +
 +        r = sd_bus_message_read(m, "s", &the_string);
 +        assert_se(r >= 0);
 +        assert_se(streq(the_string, "I am a string"));
 +
 +        sd_bus_message_unref(m);
 +        m = NULL;
 +
 +        r = sd_bus_request_name(a, "net.x0pointer.foobar", 0);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_new_method_call(b, &m, "net.x0pointer.foobar", "/a/path", "an.inter.face", "AMethod");
 +        assert_se(r >= 0);
 +
 +        assert_se(pipe2(pipe_fds, O_CLOEXEC) >= 0);
 +
 +        assert_se(write(pipe_fds[1], "x", 1) == 1);
 +
 +        pipe_fds[1] = safe_close(pipe_fds[1]);
 +
 +        r = sd_bus_message_append(m, "h", pipe_fds[0]);
 +        assert_se(r >= 0);
 +
 +        pipe_fds[0] = safe_close(pipe_fds[0]);
 +
 +        r = sd_bus_send(b, m, NULL);
 +        assert_se(r >= 0);
 +
 +        for (;;) {
 +                sd_bus_message_unref(m);
 +                m = NULL;
 +                r = sd_bus_process(a, &m);
 +                assert_se(r > 0);
 +                assert_se(m);
 +
 +                bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +                assert_se(sd_bus_message_rewind(m, true) >= 0);
 +
 +                if (sd_bus_message_is_method_call(m, "an.inter.face", "AMethod")) {
 +                        int fd;
 +                        char x;
 +
 +                        r = sd_bus_message_read(m, "h", &fd);
 +                        assert_se(r >= 0);
 +
 +                        assert_se(read(fd, &x, 1) == 1);
 +                        assert_se(x == 'x');
 +                        break;
 +                }
 +        }
 +
 +        r = sd_bus_release_name(a, "net.x0pointer.foobar");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_release_name(a, "net.x0pointer.foobar");
 +        assert_se(r == -ESRCH);
 +
 +        r = sd_bus_try_close(a);
 +        assert_se(r >= 0);
 +
 +        sd_bus_unref(a);
 +        sd_bus_unref(b);
 +
 +        return 0;
 +}
index 7f6d7f4,0000000..5bb023c
mode 100644,000000..100644
--- /dev/null
@@@ -1,210 -1,0 +1,211 @@@
 +/***
 +  This file is part of systemd.
 +
 +  Copyright 2013 Lennart Poettering
 +
 +  systemd 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.
 +
 +  systemd is distributed in the hope that it will be useful, but
 +  WITHOUT ANY WARRANTY; without even the implied warranty of
 +  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 +  Lesser General Public License for more details.
 +
 +  You should have received a copy of the GNU Lesser General Public License
 +  along with systemd; If not, see <http://www.gnu.org/licenses/>.
 +***/
 +
 +#include <sys/mman.h>
 +
 +#include "sd-bus.h"
 +
 +#include "alloc-util.h"
 +#include "bus-dump.h"
 +#include "bus-kernel.h"
 +#include "bus-message.h"
 +#include "fd-util.h"
 +#include "log.h"
 +#include "memfd-util.h"
++#include "process-util.h"
 +#include "string-util.h"
 +#include "util.h"
 +
 +#define FIRST_ARRAY 17
 +#define SECOND_ARRAY 33
 +
 +#define STRING_SIZE 123
 +
 +int main(int argc, char *argv[]) {
 +        _cleanup_free_ char *name = NULL, *bus_name = NULL, *address = NULL;
 +        const char *unique;
 +        uint8_t *p;
 +        sd_bus *a, *b;
 +        int r, bus_ref;
 +        sd_bus_message *m;
 +        int f;
 +        uint64_t sz;
 +        uint32_t u32;
 +        size_t i, l;
 +        char *s;
 +        _cleanup_close_ int sfd = -1;
 +
 +        log_set_max_level(LOG_DEBUG);
 +
 +        assert_se(asprintf(&name, "deine-mutter-%u", (unsigned) getpid_cached()) >= 0);
 +
 +        bus_ref = bus_kernel_create_bus(name, false, &bus_name);
 +        if (bus_ref == -ENOENT)
 +                return EXIT_TEST_SKIP;
 +
 +        assert_se(bus_ref >= 0);
 +
 +        address = strappend("kernel:path=", bus_name);
 +        assert_se(address);
 +
 +        r = sd_bus_new(&a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_new(&b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(a, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_set_address(b, address);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(a);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_start(b);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_get_unique_name(a, &unique);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_new_method_call(b, &m, unique, "/a/path", "an.inter.face", "AMethod");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_open_container(m, 'r', "aysay");
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_append_array_space(m, 'y', FIRST_ARRAY, (void**) &p);
 +        assert_se(r >= 0);
 +
 +        p[0] = '<';
 +        memset(p+1, 'L', FIRST_ARRAY-2);
 +        p[FIRST_ARRAY-1] = '>';
 +
 +        f = memfd_new_and_map(NULL, STRING_SIZE, (void**) &s);
 +        assert_se(f >= 0);
 +
 +        s[0] = '<';
 +        for (i = 1; i < STRING_SIZE-2; i++)
 +                s[i] = '0' + (i % 10);
 +        s[STRING_SIZE-2] = '>';
 +        s[STRING_SIZE-1] = 0;
 +        munmap(s, STRING_SIZE);
 +
 +        r = memfd_get_size(f, &sz);
 +        assert_se(r >= 0);
 +        assert_se(sz == STRING_SIZE);
 +
 +        r = sd_bus_message_append_string_memfd(m, f, 0, (uint64_t) -1);
 +        assert_se(r >= 0);
 +
 +        close(f);
 +
 +        f = memfd_new_and_map(NULL, SECOND_ARRAY, (void**) &p);
 +        assert_se(f >= 0);
 +
 +        p[0] = '<';
 +        memset(p+1, 'P', SECOND_ARRAY-2);
 +        p[SECOND_ARRAY-1] = '>';
 +        munmap(p, SECOND_ARRAY);
 +
 +        r = memfd_get_size(f, &sz);
 +        assert_se(r >= 0);
 +        assert_se(sz == SECOND_ARRAY);
 +
 +        r = sd_bus_message_append_array_memfd(m, 'y', f, 0, (uint64_t) -1);
 +        assert_se(r >= 0);
 +
 +        close(f);
 +
 +        r = sd_bus_message_close_container(m);
 +        assert_se(r >= 0);
 +
 +        r = sd_bus_message_append(m, "u", 4711);
 +        assert_se(r >= 0);
 +
 +        assert_se((sfd = memfd_new_and_map(NULL, 6, (void**) &p)) >= 0);
 +        memcpy(p, "abcd\0", 6);
 +        munmap(p, 6);
 +        assert_se(sd_bus_message_append_string_memfd(m, sfd, 1, 4) >= 0);
 +
 +        r = sd_bus_message_seal(m, 55, 99*USEC_PER_SEC);
 +        assert_se(r >= 0);
 +
 +        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +
 +        r = sd_bus_send(b, m, NULL);
 +        assert_se(r >= 0);
 +
 +        sd_bus_message_unref(m);
 +
 +        r = sd_bus_process(a, &m);
 +        assert_se(r > 0);
 +
 +        bus_message_dump(m, stdout, BUS_MESSAGE_DUMP_WITH_HEADER);
 +        sd_bus_message_rewind(m, true);
 +
 +        r = sd_bus_message_enter_container(m, 'r', "aysay");
 +        assert_se(r > 0);
 +
 +        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
 +        assert_se(r > 0);
 +        assert_se(l == FIRST_ARRAY);
 +
 +        assert_se(p[0] == '<');
 +        for (i = 1; i < l-1; i++)
 +                assert_se(p[i] == 'L');
 +        assert_se(p[l-1] == '>');
 +
 +        r = sd_bus_message_read(m, "s", &s);
 +        assert_se(r > 0);
 +
 +        assert_se(s[0] == '<');
 +        for (i = 1; i < STRING_SIZE-2; i++)
 +                assert_se(s[i] == (char) ('0' + (i % 10)));
 +        assert_se(s[STRING_SIZE-2] == '>');
 +        assert_se(s[STRING_SIZE-1] == 0);
 +
 +        r = sd_bus_message_read_array(m, 'y', (const void**) &p, &l);
 +        assert_se(r > 0);
 +        assert_se(l == SECOND_ARRAY);
 +
 +        assert_se(p[0] == '<');
 +        for (i = 1; i < l-1; i++)
 +                assert_se(p[i] == 'P');
 +        assert_se(p[l-1] == '>');
 +
 +        r = sd_bus_message_exit_container(m);
 +        assert_se(r > 0);
 +
 +        r = sd_bus_message_read(m, "u", &u32);
 +        assert_se(r > 0);
 +        assert_se(u32 == 4711);
 +
 +        r = sd_bus_message_read(m, "s", &s);
 +        assert_se(r > 0);
 +        assert_se(streq_ptr(s, "bcd"));
 +
 +        sd_bus_message_unref(m);
 +
 +        sd_bus_unref(a);
 +        sd_bus_unref(b);
 +
 +        return 0;
 +}
@@@ -377,18 -344,15 +377,15 @@@ static int user_mkdir_runtime_path(Use
          if (path_is_mount_point(u->runtime_path, NULL, 0) <= 0) {
                  _cleanup_free_ char *t = NULL;
  
-                 (void) mkdir_label(u->runtime_path, 0700);
+                 r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu%s",
+                              u->uid, u->gid, u->manager->runtime_dir_size,
+                              mac_smack_use() ? ",smackfsroot=*" : "");
+                 if (r < 0)
+                         return log_oom();
  
-                 if (mac_smack_use())
-                         r = asprintf(&t, "mode=0700,smackfsroot=*,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
-                 else
-                         r = asprintf(&t, "mode=0700,uid=" UID_FMT ",gid=" GID_FMT ",size=%zu", u->uid, u->gid, u->manager->runtime_dir_size);
-                 if (r < 0) {
-                         r = log_oom();
-                         goto fail;
-                 }
+                 (void) mkdir_label(u->runtime_path, 0700);
  
 -                r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID, t);
 +                r = mount("tmpfs", u->runtime_path, "tmpfs", MS_NODEV|MS_NOSUID|MS_NOEXEC, t);
                  if (r < 0) {
                          if (!IN_SET(errno, EPERM, EACCES)) {
                                  r = log_error_errno(errno, "Failed to mount per-user tmpfs directory %s: %m", u->runtime_path);
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
Simple merge
index e28368c,34d7cc6..e9f93b1
mode 100644,100644..120000
@@@ -1,1 -1,4 +1,1 @@@
- ../TEST-01-BASIC/Makefile
 -BUILD_DIR=$(shell ../../tools/find-build-dir.sh)
 -
 -all setup clean run:
 -      @basedir=../.. TEST_BASE_DIR=../ BUILD_DIR=$(BUILD_DIR) ./test.sh --$@
++../TEST-01-BASIC/Makefile
index d9e20b7,b14083a..066a623
mode 100644,100755..100644
@@@ -72,11 -39,4 +73,10 @@@ EO
      umount $TESTDIR/root
  }
  
 +test_cleanup() {
 +    umount $TESTDIR/root 2>/dev/null
 +    [[ $LOOPDEV ]] && losetup -d $LOOPDEV
 +    return 0
 +}
 +
  do_test "$@"
Simple merge
@@@ -1,10 -1,6 +1,11 @@@
- #!/bin/sh -eu
+ #!/bin/sh
+ set -eu
  
 +relpath() {
 +        python -c 'import os.path, sys;\
 +                   print os.path.relpath(sys.argv[1],sys.argv[2])' "$1" "${2-$PWD}"
 +}
 +
  # this is needed mostly because $DESTDIR is provided as a variable,
  # and we need to create the target directory...
  
Simple merge
Simple merge
@@@ -13,15 -13,12 +13,17 @@@ Documentation=man:systemd-resolved.serv
  Documentation=https://www.freedesktop.org/wiki/Software/systemd/resolved
  Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-network-configuration-managers
  Documentation=https://www.freedesktop.org/wiki/Software/systemd/writing-resolver-clients
- After=systemd-networkd.service network.target
- Before=network-online.target nss-lookup.target
+ DefaultDependencies=no
+ After=systemd-sysusers.service systemd-networkd.service
+ Before=network.target nss-lookup.target shutdown.target
+ Conflicts=shutdown.target
  Wants=nss-lookup.target
  
 +# On kdbus systems we pull in the busname explicitly, because it
 +# carries policy that allows the daemon to acquire its name.
 +Wants=org.freedesktop.resolve1.busname
 +After=org.freedesktop.resolve1.busname
 +
  [Service]
  Type=notify
  Restart=always
@@@ -1,9 -1,7 +1,9 @@@
  #!/bin/sh
  
 +PATH=/bin:/usr/bin:/sbin:/usr/sbin
 +
  systemctl --user import-environment DISPLAY XAUTHORITY
  
- if which dbus-update-activation-environment >/dev/null 2>&1; then
+ if command -v dbus-update-activation-environment >/dev/null 2>&1; then
          dbus-update-activation-environment DISPLAY XAUTHORITY
  fi