diff options
Diffstat (limited to 'meta-app-framework')
113 files changed, 9909 insertions, 102 deletions
diff --git a/meta-app-framework/conf/include/agl-appfw-smack.inc b/meta-app-framework/conf/include/agl-appfw-smack.inc index 139722402..831368a31 100644 --- a/meta-app-framework/conf/include/agl-appfw-smack.inc +++ b/meta-app-framework/conf/include/agl-appfw-smack.inc @@ -3,6 +3,8 @@ OVERRIDES .= ":with-lsm-smack" DISTRO_FEATURES_append = " smack xattr" DISTRO_FEATURES_NATIVE_append = " smack xattr" +APPFW_ENABLED = "1" + # use tar-native to support SMACK extended attributes independently of host config IMAGE_CMD_TAR = "tar --xattrs --xattrs-include='*'" do_image_tar[depends] += "tar-replacement-native:do_populate_sysroot" @@ -17,3 +19,6 @@ PACKAGECONFIG_append_pn-shadow-native = " attr" # set the home directory for root ROOT_HOME = "/home/0" + +# include devel wgts in images +IMAGE_FEATURES_append = " agl-devel-wgt" diff --git a/meta-app-framework/conf/include/agl-sign-wgts.inc b/meta-app-framework/conf/include/agl-sign-wgts.inc new file mode 100644 index 000000000..d56c01288 --- /dev/null +++ b/meta-app-framework/conf/include/agl-sign-wgts.inc @@ -0,0 +1,3 @@ +# allows insertion of code or items specific to developement +OVERRIDES .= ":agl-sign-wgts" +AGL_FEATURES_append = " agl-sign-wgts" diff --git a/meta-app-framework/conf/layer.conf b/meta-app-framework/conf/layer.conf index 21b8ee530..77701bb57 100644 --- a/meta-app-framework/conf/layer.conf +++ b/meta-app-framework/conf/layer.conf @@ -10,3 +10,24 @@ BBFILE_PATTERN_app-framework = "^${LAYERDIR}/" BBFILE_PRIORITY_app-framework = "70" LAYERSERIES_COMPAT_app-framework = "dunfell" + +# dependency: meta-oe +LAYERDEPENDS_app-framework = "openembedded-layer" +# dependency: meta-security +LAYERDEPENDS_app-framework += "security" + +# AGL core layer is an optional requirement +LAYERRECOMMENDS_app-framework += "aglcore" +LAYERRECOMMENDS_app-framework += "qt5-layer" + +BBFILES_DYNAMIC += " \ + qt5-layer:${LAYERDIR}/dynamic-layers/meta-qt5/*/*/*.bb \ + qt5-layer:${LAYERDIR}/dynamic-layers/meta-qt5/*/*/*.bbappend \ + aglcore:${LAYERDIR}/dynamic-layers/meta-agl-core/*/*/*.bb \ + aglcore:${LAYERDIR}/dynamic-layers/meta-agl-core/*/*/*.bbappend \ +" + + +# bug in meta-security +BBMASK += "packagegroup-core-security-ptest\.bb" +#BBMASK += "meta-security/recipes-mac/smack/smack-test_1.0.bb diff --git a/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-core-security.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-core-security.bbappend new file mode 100644 index 000000000..048154e04 --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-core-security.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', '${PN}_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-core-security.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-core-security_appfw.inc index 8445a9edd..423f15fdb 100644 --- a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-core-security.bbappend +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-core-security_appfw.inc @@ -1,4 +1,4 @@ -RDEPENDS_${PN} += "\ +RDEPENDS_${PN}_append = "\ smack-system-setup \ xmlsec1 \ cynagora \ @@ -6,4 +6,3 @@ RDEPENDS_${PN} += "\ security-manager-policy \ agl-users \ " - diff --git a/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-boot.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-boot.bbappend new file mode 100644 index 000000000..514dde79b --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-boot.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'packagegroup-agl-image-boot_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-image-boot.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-boot_appfw.inc index ad09e5ddf..b3383f114 100644 --- a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-image-boot.bbappend +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-boot_appfw.inc @@ -1,3 +1,3 @@ -RDEPENDS_${PN} += "\ +RDEPENDS_${PN}_append = "\ packagegroup-agl-app-framework \ " diff --git a/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-minimal.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-minimal.bbappend new file mode 100644 index 000000000..5f890bf06 --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-minimal.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'packagegroup-agl-image-minimal_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-image-minimal.bbappend b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-minimal_appfw.inc index ad09e5ddf..b3383f114 100644 --- a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-image-minimal.bbappend +++ b/meta-app-framework/dynamic-layers/meta-agl-core/recipes-platform/packagegroups/packagegroup-agl-image-minimal_appfw.inc @@ -1,3 +1,3 @@ -RDEPENDS_${PN} += "\ +RDEPENDS_${PN}_append = "\ packagegroup-agl-app-framework \ " diff --git a/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libafb-helpers-qt/libafb-helpers-qt_git.bb b/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libafb-helpers-qt/libafb-helpers-qt_git.bb new file mode 100644 index 000000000..802167b2d --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libafb-helpers-qt/libafb-helpers-qt_git.bb @@ -0,0 +1,11 @@ +require recipes-devtools/libafb-helpers/libafb-helpers_git.inc + +DEPENDS_append = " qtwebsockets" +RDEPENDS_${PN}_append = " af-binder" + +inherit cmake_qt5 + +EXTRA_OECMAKE_append = " -DAFB_HELPERS_QT=ON -DAFB_HELPERS=OFF" + +ALLOW_EMPTY_${PN} = "1" + diff --git a/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libqtappfw/libqtappfw_git.bb b/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libqtappfw/libqtappfw_git.bb new file mode 100644 index 000000000..dd270d048 --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-qt5/recipes-devtools/libqtappfw/libqtappfw_git.bb @@ -0,0 +1,20 @@ +SUMMARY = "AGL Qt AppFW Library" +DESCRIPTION = "libqtappfw" +HOMEPAGE = "http://docs.automotivelinux.org" +LICENSE = "Apache-2.0" +SECTION = "libs" + +BBCLASSEXTEND = "nativesdk" + +LIC_FILES_CHKSUM = "file://LICENSE;md5=ae6497158920d9524cf208c09cc4c984" + +DEPENDS += "qtbase qtdeclarative qtwebsockets" + +inherit cmake_qt5 + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/libqtappfw;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "fe20f1b029f67dee1f790ade7a9114086f2abd38" +S = "${WORKDIR}/git/" + +# PV needs to be modified with SRCPV to work AUTOREV correctly +PV = "0.0+git${SRCPV}" diff --git a/meta-app-framework/dynamic-layers/meta-qt5/recipes-platform/packagegroups/packagegroup-agl-appfw-qt5.bb b/meta-app-framework/dynamic-layers/meta-qt5/recipes-platform/packagegroups/packagegroup-agl-appfw-qt5.bb new file mode 100644 index 000000000..2f0f01fec --- /dev/null +++ b/meta-app-framework/dynamic-layers/meta-qt5/recipes-platform/packagegroups/packagegroup-agl-appfw-qt5.bb @@ -0,0 +1,16 @@ +SUMMARY = "The software for application framework of AGL IVI profile" +DESCRIPTION = "A set of packages belong to AGL application framework" + +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-appfw-qt5 \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + packagegroup-agl-appfw-native \ +"
\ No newline at end of file diff --git a/meta-app-framework/recipes-connectivity/bluez5/bluez5_%.bbappend b/meta-app-framework/recipes-connectivity/bluez5/bluez5_%.bbappend new file mode 100644 index 000000000..20d2a68d7 --- /dev/null +++ b/meta-app-framework/recipes-connectivity/bluez5/bluez5_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'bluez5_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-connectivity/bluez5/bluez5_appfw.inc b/meta-app-framework/recipes-connectivity/bluez5/bluez5_appfw.inc new file mode 100644 index 000000000..21529e96b --- /dev/null +++ b/meta-app-framework/recipes-connectivity/bluez5/bluez5_appfw.inc @@ -0,0 +1,55 @@ +# Recent bluez5 releases started limiting the capabilities of +# bluetoothd. When running on a Smack-enabled system, that change has the +# effect that bluetoothd can no longer create the input device under +# /sys because bluez5 running with label "System" has no write +# access to that. +# +# It works when running as normal root with unrestricted capabilities +# because then CAP_MAC_OVERRIDE (a Smack-specific capability) allows +# the process to ignore Smack rules. +# +# We need to ensure that bluetoothd still has that capability. +# +# To fix the issue, Patick and Casey(the Smack architect) had a talk +# about it in Ostro dev mail list. Casey has some ideas about the issue: +# "Turning off privilege is a great thing to do *so long as you don't +# really need the privilege*. In this case you really need it. +# The application package isn't written to account for Smack's use of +# CAP_MAC_OVERRIDE as the mechanism for controlling this dangerous operation. +# Yes, it would be possible to change /proc to change the Smack label on +# that particular file, but that might open other paths for exploit. +# I say give the program the required capability. The program maintainer +# may well say change the kernel handling of /proc. You're stuck in the +# middle, as both work the way they're intended and hence the system +# doesn't work. :( There isn't a way to make this work without "loosening" +# something." +# Therefore, when we we run the program with CAP_MAC_OVERRIDE, +# the whole reason for having capabilities is so the we can give a +# process the ability to bypass one kind of check without giving it the +# ability to bypass other, unrelated checks. A process with +# CAP_MAC_OVERRIDE is still constrained by the file mode bits. +# We was overly worried about granting that capability. +# When it has no other effect than excluding a process from Smack MAC enforcement, +# then adding to the process seems like the right solution for now. +# +# The conclusion from Patick and Casey is that the Smack architect give the key point +# that this is the solution preferred. +# +# Because the solution is to some extend specific to the environment +# in which connmand runs, this change is not submitted upstream +# and it can be overridden by a distro via FIX_BLUEZ5_CAPABILITIES. +# +# The related patch has been submitted to upstream too. +# upstream link: http://permalink.gmane.org/gmane.linux.bluez.kernel/67993 + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI_append_with-lsm-smack = "\ + file://bluetooth.service.conf \ +" + +FILES_${PN}_append = " ${systemd_unitdir}" + +do_install_append_with-lsm-smack() { + install -Dm0644 ${WORKDIR}/bluetooth.service.conf ${D}${systemd_unitdir}/system/bluetooth.service.d/smack.conf +} diff --git a/meta-app-framework/recipes-connectivity/bluez5/files/bluetooth.service.conf b/meta-app-framework/recipes-connectivity/bluez5/files/bluetooth.service.conf new file mode 100644 index 000000000..b93ab4fee --- /dev/null +++ b/meta-app-framework/recipes-connectivity/bluez5/files/bluetooth.service.conf @@ -0,0 +1,2 @@ +[Service] +CapabilityBoundingSet=CAP_MAC_OVERRIDE diff --git a/meta-app-framework/recipes-connectivity/connman/connman_%.bbappend b/meta-app-framework/recipes-connectivity/connman/connman_%.bbappend new file mode 100644 index 000000000..72aa9f276 --- /dev/null +++ b/meta-app-framework/recipes-connectivity/connman/connman_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'connman_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-connectivity/connman/connman_appfw.inc b/meta-app-framework/recipes-connectivity/connman/connman_appfw.inc new file mode 100644 index 000000000..23af33104 --- /dev/null +++ b/meta-app-framework/recipes-connectivity/connman/connman_appfw.inc @@ -0,0 +1,34 @@ +# Recent ConnMan releases started limiting the capabilities of +# ConnMan. When running on a Smack-enabled system, that change has the +# effect that connmand can no longer change network settings under +# /proc/net because the Smack label of /proc is "_", and connmand +# running with label "System" has no write access to that. +# +# It works when running as normal root with unrestricted capabilities +# because then CAP_MAC_OVERRIDE (a Smack-specific capability) allows +# the process to ignore Smack rules. +# +# We need to ensure that connmand still has that capability. +# +# The alternative would be to set up fine-grained labelling of +# /proc with corresponding rules, which is considerably more work +# and also may depend on kernel changes (like supporting smackfsroot +# for procfs, which seems to be missing at the moment). +# +# Because the solution is to some extend specific to the environment +# in which connmand runs, this change is not submitted upstream +# and it can be overridden by a distro via FIX_CONNMAN_CAPABILITIES. + +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +SRC_URI_append_with-lsm-smack = "\ + file://connman.service.conf \ +" + +RDEPENDS_${PN}_append_with-lsm-smack = " smack" + +FILES_${PN}_append = " ${systemd_unitdir}" + +do_install_append_with-lsm-smack() { + install -Dm0644 ${WORKDIR}/connman.service.conf ${D}${systemd_unitdir}/system/connman.service.d/smack.conf +} diff --git a/meta-app-framework/recipes-connectivity/connman/files/connman.service.conf b/meta-app-framework/recipes-connectivity/connman/files/connman.service.conf new file mode 100644 index 000000000..6ebbf6ad1 --- /dev/null +++ b/meta-app-framework/recipes-connectivity/connman/files/connman.service.conf @@ -0,0 +1,4 @@ +[Service] +CapabilityBoundingSet=CAP_MAC_OVERRIDE +ExecStartPre=+-/bin/mkdir -p /run/connman +ExecStartPre=+-/usr/bin/chsmack -t -a System::Shared /run/connman diff --git a/meta-app-framework/recipes-core/base-files/base-files_%.bbappend b/meta-app-framework/recipes-core/base-files/base-files_%.bbappend index 1dddcd6f2..28b08face 100644 --- a/meta-app-framework/recipes-core/base-files/base-files_%.bbappend +++ b/meta-app-framework/recipes-core/base-files/base-files_%.bbappend @@ -1,32 +1 @@ -RDEPENDS_${PN}_append_with-lsm-smack = " smack" -PACKAGE_WRITE_DEPS_append_with-lsm-smack = " smack-native" - -do_install_append() { - install -m 0700 -d ${D}/${sysconfdir}/skel - chmod -R 0700 ${D}/${sysconfdir}/skel - install -m 0700 -d ${D}/${sysconfdir}/skel/app-data - install -m 0700 -d ${D}/${sysconfdir}/skel/.config - install -m 0755 -d ${D}/var - if [ -d ${D}/usr/local ]; then - mv ${D}/usr/local ${D}/var - else - install -m 0755 -d ${D}/var/local - fi - ln -s ../var/local ${D}/usr/local -} - -do_install_append_with-lsm-smack () { - install -d ${D}/${sysconfdir}/smack/accesses.d - cat > ${D}/${sysconfdir}/smack/accesses.d/default-access-domains-no-user <<EOF -System User::App-Shared rwxat -System User::Home rwxat -EOF - chmod 0644 ${D}/${sysconfdir}/smack/accesses.d/default-access-domains-no-user -} - -pkg_postinst_${PN}_append_with-lsm-smack() { - chsmack -r -a 'User::Home' -t -D $D/${sysconfdir}/skel - chsmack -a 'User::App-Shared' -D $D/${sysconfdir}/skel/app-data - cp -rTf --preserve=all $D/${sysconfdir}/skel $D/${ROOT_HOME} -} - +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'base-files_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/base-files/base-files_appfw.inc b/meta-app-framework/recipes-core/base-files/base-files_appfw.inc new file mode 100644 index 000000000..848a39ff4 --- /dev/null +++ b/meta-app-framework/recipes-core/base-files/base-files_appfw.inc @@ -0,0 +1,113 @@ +RDEPENDS_${PN}_append_with-lsm-smack = " smack" +PACKAGE_WRITE_DEPS_append_with-lsm-smack = " smack-native" + +do_install_append() { + install -m 0700 -d ${D}/${sysconfdir}/skel + chmod -R 0700 ${D}/${sysconfdir}/skel + install -m 0700 -d ${D}/${sysconfdir}/skel/app-data + install -m 0700 -d ${D}/${sysconfdir}/skel/.config + install -m 0755 -d ${D}/var + if [ -d ${D}/usr/local ]; then + mv ${D}/usr/local ${D}/var + else + install -m 0755 -d ${D}/var/local + fi + ln -s ../var/local ${D}/usr/local +} + +do_install_append_with-lsm-smack () { + install -d ${D}/${sysconfdir}/smack/accesses.d + cat > ${D}/${sysconfdir}/smack/accesses.d/default-access-domains-no-user <<EOF +System User::App-Shared rwxat +System User::Home rwxat +EOF + chmod 0644 ${D}/${sysconfdir}/smack/accesses.d/default-access-domains-no-user +} + +pkg_postinst_${PN}_append_with-lsm-smack() { + chsmack -r -a 'User::Home' -t -D $D/${sysconfdir}/skel + chsmack -a 'User::App-Shared' -D $D/${sysconfdir}/skel/app-data + cp -rTf --preserve=all $D/${sysconfdir}/skel $D/${ROOT_HOME} +} + + + +# Install default Smack rules, copied from a running Tizen IVI 3.0. +# Corresponds to manifest file from default-access-domains in Tizen: +# https://review.tizen.org/git?p=platform/core/security/default-ac-domains.git;a=blob;f=packaging/default-ac-domains.manifest +do_install_append_with-lsm-smack () { + install -d ${D}/${sysconfdir}/smack/accesses.d + cat >${D}/${sysconfdir}/smack/accesses.d/default-access-domains <<EOF +System _ -----l +System System::Log rwxa-- +System System::Run rwxat- +System System::Shared rwxat- +System ^ rwxa-- +_ System::Run rwxat- +_ System -wx--- +^ System::Log rwxa-- +^ System::Run rwxat- +^ System rwxa-- +EOF + chmod 0644 ${D}/${sysconfdir}/smack/accesses.d/default-access-domains + + install -d ${D}/${libdir}/tmpfiles.d + cat >${D}/${libdir}/tmpfiles.d/packet-forwarding.conf <<EOF +t /proc/sys/net/ipv4/conf/all/forwarding - - - - security.SMACK64=* +t /proc/sys/net/ipv6/conf/all/forwarding - - - - security.SMACK64=* +t /proc/sys/net/ipv4/conf/default/forwarding - - - - security.SMACK64=* +t /proc/sys/net/ipv6/conf/default/forwarding - - - - security.SMACK64=* +EOF + chmod 0644 ${D}/${libdir}/tmpfiles.d/packet-forwarding.conf + + install -d ${D}/${base_libdir}/udev/rules.d + cat >${D}/${base_libdir}/udev/rules.d/85-netdev-ipconf-smacklabel.rules <<EOF +SUBSYSTEM=="net", ENV{ID_NET_NAME}=="", RUN+="/bin/sh -c '/usr/bin/chsmack -a \* /proc/sys/net/ipv4/conf/%k/*'", RUN+="/bin/sh -c '/usr/bin/chsmack -a \* /proc/sys/net/ipv6/conf/%k/*'" + +SUBSYSTEM=="net", ENV{ID_NET_NAME}!="", RUN+="/bin/sh -c '/usr/bin/chsmack -a \* /proc/sys/net/ipv4/conf/\$env{ID_NET_NAME}/*'", RUN+="/bin/sh -c '/usr/bin/chsmack -a \* /proc/sys/net/ipv6/conf/\$env{ID_NET_NAME}/*'" +EOF + chmod 0644 ${D}/${base_libdir}/udev/rules.d/85-netdev-ipconf-smacklabel.rules +} + +# Do not rely on an rpm with manifest support. Apparently that approach +# will no longer be used in Tizen 3.0. Instead set special Smack attributes +# via postinst. This is much easier to use with bitbake, too: +# - no need to maintain a patched rpm +# - works for directories which are not packaged by default when empty +RDEPENDS_${PN}_append_with-lsm-smack = " smack" +DEPENDS_append_with-lsm-smack = " smack-native" +pkg_postinst_${PN}_with-lsm-smack() { + #!/bin/sh -e + + # https://review.tizen.org/gerrit/gitweb?p=platform/upstream/filesystem.git;a=blob;f=packaging/filesystem.manifest: + # <filesystem path="/etc" label="System::Shared" type="transmutable" /> + install -d $D${sysconfdir} + # This has no effect on files installed into /etc during image construction + # because pseudo does not know the special semantic of SMACK::TRANSMUTE. + # To avoid having different xattrs on files inside /etc when pre-installed + # in an image vs. installed on a device, the xattr-images.bbclass has + # a workaround for this deficiency in pseudo. + chsmack -t $D${sysconfdir} + chsmack -a 'System::Shared' $D${sysconfdir} + + # Same for /media. Any daemon running as "System" will get write access + # to everything. + install -d $D/media + chsmack -t $D/media + chsmack -a 'System::Shared' $D/media + + # Same for /var. Any daemon running as "System" will get write access + # to everything. + install -d $D${localstatedir} + chsmack -t $D${localstatedir} + chsmack -a 'System::Shared' $D${localstatedir} + + # <filesystem path="/tmp" label="*" /> + mkdir -p $D/tmp + chsmack -a '*' $D/tmp + + # <filesystem path="/var/log" label="System::Log" type="transmutable" /> + # <filesystem path="/var/tmp" label="*" /> + # These are in a file system mounted by systemd. We patch the systemd service + # to set these attributes. +} diff --git a/meta-app-framework/recipes-core/coreutils/coreutils_%.bbappend b/meta-app-framework/recipes-core/coreutils/coreutils_%.bbappend new file mode 100644 index 000000000..b7bf9fff4 --- /dev/null +++ b/meta-app-framework/recipes-core/coreutils/coreutils_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'coreutils_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/coreutils/coreutils_appfw.inc b/meta-app-framework/recipes-core/coreutils/coreutils_appfw.inc new file mode 100644 index 000000000..1b9b722ec --- /dev/null +++ b/meta-app-framework/recipes-core/coreutils/coreutils_appfw.inc @@ -0,0 +1,7 @@ +# Smack patches are included in coreutils v8.22, we just need to enable them. +# The default is not deterministic (enabled if libsmack found), so disable +# explicitly otherwise. +EXTRA_OECONF_SMACK_class-target = "--disable-libsmack" +EXTRA_OECONF_SMACK_with-lsm-smack_class-target = "--enable-libsmack" +EXTRA_OECONF_append_class-target = " ${EXTRA_OECONF_SMACK}" +DEPENDS_append_with-lsm-smack_class-target = " smack" diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0001-Integration-of-Cynara-asynchronous-security-checks.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0001-Integration-of-Cynara-asynchronous-security-checks.patch new file mode 100644 index 000000000..55cedb9c7 --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0001-Integration-of-Cynara-asynchronous-security-checks.patch @@ -0,0 +1,2309 @@ +From ea4b650366261e4257e4b0fb95e7f48e30ef36f0 Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Thu, 27 Nov 2014 18:11:05 +0100 +Subject: [PATCH 1/8] Integration of Cynara asynchronous security checks +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This commit introduces basic framework for asynchronous policy +checks and Cynara integration code. Functions for checking security +policy can now return third value - BUS_RESULT_LATER denoting check +result unavailability. Whenever policy checker cannot decide on the +result of the check it is supposed to allocate DeferredMessage structure +that will be passed to the upper layers which can decide what should be +done in such situation. +Proper handling of such case will be implemented in subsequent commits. +Currently such return value results in message denial. + +Cherry picked from 4dcfb02f17247ff9de966b62182cd2e08f301238 +by José Bollo. + +Updated for dbus 1.10.20 by Scott Murray and José Bollo +Updated for dbus 1.12.16 by José Bollo + +Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108 +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +Signed-off-by: Scott Murray <scott.murray@konsulko.com> +--- + bus/Makefile.am | 6 + + bus/activation.c | 5 +- + bus/bus.c | 124 ++++-- + bus/bus.h | 22 +- + bus/check.c | 217 ++++++++++ + bus/check.h | 68 ++++ + bus/config-parser-common.c | 6 + + bus/config-parser-common.h | 1 + + bus/config-parser-trivial.c | 2 + + bus/config-parser.c | 72 +++- + bus/connection.c | 57 ++- + bus/connection.h | 4 + + bus/cynara.c | 374 ++++++++++++++++++ + bus/cynara.h | 37 ++ + bus/dispatch.c | 46 ++- + bus/driver.h | 2 + + bus/policy.c | 195 ++++++--- + bus/policy.h | 29 +- + configure.ac | 12 + + test/Makefile.am | 1 + + .../data/invalid-config-files/badcheck-1.conf | 9 + + .../data/invalid-config-files/badcheck-2.conf | 9 + + test/data/valid-config-files/check-1.conf | 9 + + .../debug-check-some.conf.in | 18 + + 24 files changed, 1181 insertions(+), 144 deletions(-) + create mode 100644 bus/check.c + create mode 100644 bus/check.h + create mode 100644 bus/cynara.c + create mode 100644 bus/cynara.h + create mode 100644 test/data/invalid-config-files/badcheck-1.conf + create mode 100644 test/data/invalid-config-files/badcheck-2.conf + create mode 100644 test/data/valid-config-files/check-1.conf + create mode 100644 test/data/valid-config-files/debug-check-some.conf.in + +diff --git a/bus/Makefile.am b/bus/Makefile.am +index c917063..2a8a72c 100644 +--- a/bus/Makefile.am ++++ b/bus/Makefile.am +@@ -13,6 +13,7 @@ DBUS_BUS_LIBS = \ + $(THREAD_LIBS) \ + $(ADT_LIBS) \ + $(NETWORK_libs) \ ++ $(CYNARA_LIBS) \ + $(NULL) + + DBUS_LAUNCHER_LIBS = \ +@@ -30,6 +31,7 @@ AM_CPPFLAGS = \ + $(APPARMOR_CFLAGS) \ + -DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \ + -DDBUS_COMPILATION \ ++ $(CYNARA_CFLAGS) \ + $(NULL) + + # if assertions are enabled, improve backtraces +@@ -90,6 +92,8 @@ BUS_SOURCES= \ + audit.h \ + bus.c \ + bus.h \ ++ check.c \ ++ check.h \ + config-loader-expat.c \ + config-parser.c \ + config-parser.h \ +@@ -97,6 +101,8 @@ BUS_SOURCES= \ + config-parser-common.h \ + connection.c \ + connection.h \ ++ cynara.c \ ++ cynara.h \ + desktop-file.c \ + desktop-file.h \ + $(DIR_WATCH_SOURCE) \ +diff --git a/bus/activation.c b/bus/activation.c +index 99404b9..f9c6c62 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -1789,14 +1789,15 @@ bus_activation_activate_service (BusActivation *activation, + + if (auto_activation && + entry != NULL && +- !bus_context_check_security_policy (activation->context, ++ BUS_RESULT_TRUE != bus_context_check_security_policy (activation->context, + transaction, + connection, /* sender */ + NULL, /* addressed recipient */ + NULL, /* proposed recipient */ + activation_message, + entry, +- error)) ++ error, ++ NULL)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + _dbus_verbose ("activation not authorized: %s: %s\n", +diff --git a/bus/bus.c b/bus/bus.c +index 2ad8e78..6fc45d0 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -38,6 +38,7 @@ + #include "apparmor.h" + #include "audit.h" + #include "dir-watch.h" ++#include "check.h" + #include <dbus/dbus-auth.h> + #include <dbus/dbus-list.h> + #include <dbus/dbus-hash.h> +@@ -67,6 +68,7 @@ struct BusContext + BusRegistry *registry; + BusPolicy *policy; + BusMatchmaker *matchmaker; ++ BusCheck *check; + BusLimits limits; + DBusRLimit *initial_fd_limit; + unsigned int fork : 1; +@@ -1003,6 +1005,10 @@ bus_context_new (const DBusString *config_file, + parser = NULL; + } + ++ context->check = bus_check_new(context, error); ++ if (context->check == NULL) ++ goto failed; ++ + dbus_server_free_data_slot (&server_data_slot); + + return context; +@@ -1127,6 +1133,12 @@ bus_context_unref (BusContext *context) + + bus_context_shutdown (context); + ++ if (context->check) ++ { ++ bus_check_unref(context->check); ++ context->check = NULL; ++ } ++ + if (context->connections) + { + bus_connections_unref (context->connections); +@@ -1256,6 +1268,12 @@ bus_context_get_loop (BusContext *context) + return context->loop; + } + ++BusCheck* ++bus_context_get_check (BusContext *context) ++{ ++ return context->check; ++} ++ + dbus_bool_t + bus_context_allow_unix_user (BusContext *context, + unsigned long uid) +@@ -1451,6 +1469,7 @@ complain_about_message (BusContext *context, + DBusConnection *proposed_recipient, + dbus_bool_t requested_reply, + dbus_bool_t log, ++ const char *privilege, + DBusError *error) + { + DBusError stack_error = DBUS_ERROR_INIT; +@@ -1480,7 +1499,8 @@ complain_about_message (BusContext *context, + dbus_set_error (&stack_error, error_name, + "%s, %d matched rules; type=\"%s\", sender=\"%s\" (%s) " + "interface=\"%s\" member=\"%s\" error name=\"%s\" " +- "requested_reply=\"%d\" destination=\"%s\" (%s)", ++ "requested_reply=\"%d\" destination=\"%s\" (%s) " ++ "privilege=\"%s\"", + complaint, + matched_rules, + dbus_message_type_to_string (dbus_message_get_type (message)), +@@ -1491,7 +1511,8 @@ complain_about_message (BusContext *context, + nonnull (dbus_message_get_error_name (message), "(unset)"), + requested_reply, + nonnull (dbus_message_get_destination (message), DBUS_SERVICE_DBUS), +- proposed_recipient_loginfo); ++ proposed_recipient_loginfo, ++ nonnull (privilege, "(n/a)")); + + /* If we hit OOM while setting the error, this will syslog "out of memory" + * which is itself an indication that something is seriously wrong */ +@@ -1519,7 +1540,7 @@ complain_about_message (BusContext *context, + * NULL for addressed_recipient may mean the bus driver, or may mean + * no destination was specified in the message (e.g. a signal). + */ +-dbus_bool_t ++BusResult + bus_context_check_security_policy (BusContext *context, + BusTransaction *transaction, + DBusConnection *sender, +@@ -1527,7 +1548,8 @@ bus_context_check_security_policy (BusContext *context, + DBusConnection *proposed_recipient, + DBusMessage *message, + BusActivationEntry *activation_entry, +- DBusError *error) ++ DBusError *error, ++ BusDeferredMessage **deferred_message) + { + const char *src, *dest; + BusClientPolicy *sender_policy; +@@ -1536,6 +1558,7 @@ bus_context_check_security_policy (BusContext *context, + dbus_bool_t log; + int type; + dbus_bool_t requested_reply; ++ const char *privilege; + + type = dbus_message_get_type (message); + src = dbus_message_get_sender (message); +@@ -1565,7 +1588,7 @@ bus_context_check_security_policy (BusContext *context, + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Message bus will not accept messages of unknown type\n"); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + requested_reply = FALSE; +@@ -1595,7 +1618,7 @@ bus_context_check_security_policy (BusContext *context, + if (dbus_error_is_set (&error2)) + { + dbus_move_error (&error2, error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + } + } +@@ -1624,11 +1647,11 @@ bus_context_check_security_policy (BusContext *context, + complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, + "An SELinux policy prevents this sender from sending this " + "message to this recipient", +- 0, message, sender, proposed_recipient, FALSE, FALSE, error); ++ 0, message, sender, proposed_recipient, FALSE, FALSE, NULL, error); + _dbus_verbose ("SELinux security check denying send to service\n"); + } + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + /* next verify AppArmor access controls. If allowed then +@@ -1646,7 +1669,7 @@ bus_context_check_security_policy (BusContext *context, + src ? src : DBUS_SERVICE_DBUS, + activation_entry, + error)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + if (!bus_connection_is_active (sender)) + { +@@ -1660,7 +1683,7 @@ bus_context_check_security_policy (BusContext *context, + { + _dbus_verbose ("security check allowing %s message\n", + "Hello"); +- return TRUE; ++ return BUS_RESULT_TRUE; + } + else + { +@@ -1671,7 +1694,7 @@ bus_context_check_security_policy (BusContext *context, + "Client tried to send a message other than %s without being registered", + "Hello"); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + } + } +@@ -1720,20 +1743,29 @@ bus_context_check_security_policy (BusContext *context, + (proposed_recipient == NULL && recipient_policy == NULL)); + + log = FALSE; +- if (sender_policy && +- !bus_client_policy_check_can_send (sender_policy, +- context->registry, +- requested_reply, +- proposed_recipient, +- message, &toggles, &log)) +- { +- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, +- "Rejected send message", toggles, +- message, sender, proposed_recipient, requested_reply, +- (addressed_recipient == proposed_recipient), error); +- _dbus_verbose ("security policy disallowing message due to sender policy\n"); +- return FALSE; +- } ++ if (sender_policy) ++ { ++ BusResult res = bus_client_policy_check_can_send (sender, ++ sender_policy, ++ context->registry, ++ requested_reply, ++ addressed_recipient, ++ proposed_recipient, ++ message, &toggles, &log, &privilege, ++ deferred_message); ++ if (res == BUS_RESULT_FALSE) ++ { ++ complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, ++ "Rejected send message", toggles, ++ message, sender, proposed_recipient, requested_reply, ++ (addressed_recipient == proposed_recipient), privilege, ++ error); ++ _dbus_verbose ("security policy disallowing message due to sender policy\n"); ++ return BUS_RESULT_FALSE; ++ } ++ else if (res == BUS_RESULT_LATER) ++ return BUS_RESULT_LATER; ++ } + + if (log) + { +@@ -1742,23 +1774,29 @@ bus_context_check_security_policy (BusContext *context, + complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, + "Would reject message", toggles, + message, sender, proposed_recipient, requested_reply, +- TRUE, NULL); ++ TRUE, privilege, NULL); + } + +- if (recipient_policy && +- !bus_client_policy_check_can_receive (recipient_policy, +- context->registry, +- requested_reply, +- sender, +- addressed_recipient, proposed_recipient, +- message, &toggles)) ++ if (recipient_policy) + { +- complain_about_message (context, DBUS_ERROR_ACCESS_DENIED, +- "Rejected receive message", toggles, +- message, sender, proposed_recipient, requested_reply, +- (addressed_recipient == proposed_recipient), error); +- _dbus_verbose ("security policy disallowing message due to recipient policy\n"); +- return FALSE; ++ BusResult res; ++ res = bus_client_policy_check_can_receive (recipient_policy, ++ context->registry, ++ requested_reply, ++ sender, ++ addressed_recipient, proposed_recipient, ++ message, &toggles, &privilege, deferred_message); ++ if (res == BUS_RESULT_FALSE) ++ { ++ complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected receive message", ++ toggles, message, sender, proposed_recipient, requested_reply, ++ (addressed_recipient == proposed_recipient), privilege, error); ++ _dbus_verbose( ++ "security policy disallowing message due to recipient policy\n"); ++ return BUS_RESULT_FALSE; ++ } ++ else if (res == BUS_RESULT_LATER) ++ return BUS_RESULT_LATER; + } + + /* See if limits on size have been exceeded */ +@@ -1768,10 +1806,10 @@ bus_context_check_security_policy (BusContext *context, + { + complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, + "Rejected: destination has a full message queue", +- 0, message, sender, proposed_recipient, requested_reply, TRUE, ++ 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL, + error); + _dbus_verbose ("security policy disallowing message due to full message queue\n"); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + /* Record that we will allow a reply here in the future (don't +@@ -1792,11 +1830,11 @@ bus_context_check_security_policy (BusContext *context, + message, error)) + { + _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n"); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + _dbus_verbose ("security policy allowing message\n"); +- return TRUE; ++ return BUS_RESULT_TRUE; + } + + void +diff --git a/bus/bus.h b/bus/bus.h +index 2e0de82..82c32c8 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -45,6 +45,22 @@ typedef struct BusTransaction BusTransaction; + typedef struct BusMatchmaker BusMatchmaker; + typedef struct BusMatchRule BusMatchRule; + typedef struct BusActivationEntry BusActivationEntry; ++typedef struct BusCheck BusCheck; ++typedef struct BusDeferredMessage BusDeferredMessage; ++typedef struct BusCynara BusCynara; ++ ++/** ++ * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches. ++ * The disadvantage of such solution is that now BusResult variables cannot be used in switch ++ * statement. ++ * Additionally, BUS_RESULT_TRUE is defined as 0 instead of 1 to help detect type mismatches ++ * at runtime. ++ */ ++typedef const struct BusResultStruct { int dummy; } *BusResult; ++ ++static const BusResult BUS_RESULT_TRUE = (BusResult)0x0; ++static const BusResult BUS_RESULT_FALSE = (BusResult)0x1; ++static const BusResult BUS_RESULT_LATER = (BusResult)0x2; + + typedef struct + { +@@ -101,6 +117,7 @@ BusConnections* bus_context_get_connections (BusContext + BusActivation* bus_context_get_activation (BusContext *context); + BusMatchmaker* bus_context_get_matchmaker (BusContext *context); + DBusLoop* bus_context_get_loop (BusContext *context); ++BusCheck * bus_context_get_check (BusContext *context); + dbus_bool_t bus_context_allow_unix_user (BusContext *context, + unsigned long uid); + dbus_bool_t bus_context_allow_windows_user (BusContext *context, +@@ -136,14 +153,15 @@ void bus_context_log_and_set_error (BusContext + const char *name, + const char *msg, + ...) _DBUS_GNUC_PRINTF (5, 6); +-dbus_bool_t bus_context_check_security_policy (BusContext *context, ++BusResult bus_context_check_security_policy (BusContext *context, + BusTransaction *transaction, + DBusConnection *sender, + DBusConnection *addressed_recipient, + DBusConnection *proposed_recipient, + DBusMessage *message, + BusActivationEntry *activation_entry, +- DBusError *error); ++ DBusError *error, ++ BusDeferredMessage **deferred_message); + void bus_context_check_all_watches (BusContext *context); + + #endif /* BUS_BUS_H */ +diff --git a/bus/check.c b/bus/check.c +new file mode 100644 +index 0000000..5b72d31 +--- /dev/null ++++ b/bus/check.c +@@ -0,0 +1,217 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* check.c Bus security policy runtime check ++ * ++ * Copyright (C) 2014 Intel, Inc. ++ * Copyright (c) 2014 Samsung Electronics, Ltd. ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++#include "check.h" ++#include "connection.h" ++#include "dispatch.h" ++#include "cynara.h" ++#include "utils.h" ++#include <dbus/dbus-connection-internal.h> ++#include <dbus/dbus-message-internal.h> ++#include <dbus/dbus-internals.h> ++ ++ ++typedef struct BusCheck ++{ ++ int refcount; ++ ++ BusContext *context; ++ BusCynara *cynara; ++} BusCheck; ++ ++typedef struct BusDeferredMessage ++{ ++ int refcount; ++ ++ DBusMessage *message; ++ DBusConnection *sender; ++ DBusConnection *proposed_recipient; ++ DBusConnection *addressed_recipient; ++ dbus_bool_t full_dispatch; ++ BusDeferredMessageStatus status; ++ BusResult response; ++ BusCheckResponseFunc response_callback; ++} BusDeferredMessage; ++ ++BusCheck * ++bus_check_new (BusContext *context, DBusError *error) ++{ ++ BusCheck *check; ++ ++ check = dbus_new(BusCheck, 1); ++ if (check == NULL) ++ { ++ BUS_SET_OOM(error); ++ return NULL; ++ } ++ ++ check->refcount = 1; ++ check->context = context; ++ check->cynara = bus_cynara_new(check, error); ++ if (dbus_error_is_set(error)) ++ { ++ dbus_free(check); ++ return NULL; ++ } ++ ++ return check; ++} ++ ++BusCheck * ++bus_check_ref (BusCheck *check) ++{ ++ _dbus_assert (check->refcount > 0); ++ check->refcount += 1; ++ ++ return check; ++} ++ ++void ++bus_check_unref (BusCheck *check) ++{ ++ _dbus_assert (check->refcount > 0); ++ ++ check->refcount -= 1; ++ ++ if (check->refcount == 0) ++ { ++ bus_cynara_unref(check->cynara); ++ dbus_free(check); ++ } ++} ++ ++BusContext * ++bus_check_get_context (BusCheck *check) ++{ ++ return check->context; ++} ++ ++BusCynara * ++bus_check_get_cynara (BusCheck *check) ++{ ++ return check->cynara; ++} ++ ++BusResult ++bus_check_privilege (BusCheck *check, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *privilege, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message) ++{ ++ BusResult result = BUS_RESULT_FALSE; ++#ifdef DBUS_ENABLE_CYNARA ++ BusCynara *cynara; ++#endif ++ DBusConnection *connection; ++ ++ connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; ++ ++ if (!dbus_connection_get_is_connected(connection)) ++ { ++ return BUS_RESULT_FALSE; ++ } ++ ++ /* ask policy checkers */ ++#ifdef DBUS_ENABLE_CYNARA ++ cynara = bus_check_get_cynara(check); ++ result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, ++ proposed_recipient, privilege, check_type, deferred_message); ++#endif ++ ++ if (result == BUS_RESULT_LATER && deferred_message != NULL) ++ { ++ (*deferred_message)->status |= check_type; ++ } ++ return result; ++} ++ ++BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ BusResult response) ++{ ++ BusDeferredMessage *deferred_message; ++ ++ deferred_message = dbus_new(BusDeferredMessage, 1); ++ if (deferred_message == NULL) ++ { ++ return NULL; ++ } ++ ++ deferred_message->refcount = 1; ++ deferred_message->sender = sender != NULL ? dbus_connection_ref(sender) : NULL; ++ deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL; ++ deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL; ++ deferred_message->message = dbus_message_ref(message); ++ deferred_message->response = response; ++ deferred_message->status = 0; ++ deferred_message->full_dispatch = FALSE; ++ deferred_message->response_callback = NULL; ++ ++ return deferred_message; ++} ++ ++BusDeferredMessage * ++bus_deferred_message_ref (BusDeferredMessage *deferred_message) ++{ ++ _dbus_assert (deferred_message->refcount > 0); ++ deferred_message->refcount += 1; ++ return deferred_message; ++} ++ ++void ++bus_deferred_message_unref (BusDeferredMessage *deferred_message) ++{ ++ _dbus_assert (deferred_message->refcount > 0); ++ ++ deferred_message->refcount -= 1; ++ ++ if (deferred_message->refcount == 0) ++ { ++ dbus_message_unref(deferred_message->message); ++ if (deferred_message->sender != NULL) ++ dbus_connection_unref(deferred_message->sender); ++ if (deferred_message->addressed_recipient != NULL) ++ dbus_connection_unref(deferred_message->addressed_recipient); ++ if (deferred_message->proposed_recipient != NULL) ++ dbus_connection_unref(deferred_message->proposed_recipient); ++ dbus_free(deferred_message); ++ } ++} ++ ++void ++bus_deferred_message_response_received (BusDeferredMessage *deferred_message, ++ BusResult result) ++{ ++ if (deferred_message->response_callback != NULL) ++ { ++ deferred_message->response_callback(deferred_message, result); ++ } ++} +diff --git a/bus/check.h b/bus/check.h +new file mode 100644 +index 0000000..c3fcaf9 +--- /dev/null ++++ b/bus/check.h +@@ -0,0 +1,68 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* check.h Bus security policy runtime check ++ * ++ * Copyright (C) 2014 Intel, Inc. ++ * Copyright (c) 2014 Samsung Electronics, Ltd. ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#ifndef BUS_CHECK_H ++#define BUS_CHECK_H ++ ++#include "bus.h" ++#include "policy.h" ++ ++ ++typedef void (*BusCheckResponseFunc) (BusDeferredMessage *message, ++ BusResult result); ++ ++typedef enum { ++ BUS_DEFERRED_MESSAGE_CHECK_SEND = 1 << 0, ++ BUS_DEFERRED_MESSAGE_CHECK_RECEIVE = 1 << 1, ++ BUS_DEFERRED_MESSAGE_CHECK_OWN = 1 << 2, ++} BusDeferredMessageStatus; ++ ++ ++BusCheck *bus_check_new (BusContext *context, ++ DBusError *error); ++BusCheck *bus_check_ref (BusCheck *check); ++void bus_check_unref (BusCheck *check); ++ ++BusContext *bus_check_get_context (BusCheck *check); ++BusCynara *bus_check_get_cynara (BusCheck *check); ++BusResult bus_check_privilege (BusCheck *check, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *privilege, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message); ++ ++BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ BusResult response); ++ ++BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message); ++void bus_deferred_message_unref (BusDeferredMessage *deferred_message); ++void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, ++ BusResult result); ++#endif /* BUS_CHECK_H */ +diff --git a/bus/config-parser-common.c b/bus/config-parser-common.c +index c1c4191..e2f253d 100644 +--- a/bus/config-parser-common.c ++++ b/bus/config-parser-common.c +@@ -75,6 +75,10 @@ bus_config_parser_element_name_to_type (const char *name) + { + return ELEMENT_DENY; + } ++ else if (strcmp (name, "check") == 0) ++ { ++ return ELEMENT_CHECK; ++ } + else if (strcmp (name, "servicehelper") == 0) + { + return ELEMENT_SERVICEHELPER; +@@ -159,6 +163,8 @@ bus_config_parser_element_type_to_name (ElementType type) + return "allow"; + case ELEMENT_DENY: + return "deny"; ++ case ELEMENT_CHECK: ++ return "check"; + case ELEMENT_FORK: + return "fork"; + case ELEMENT_PIDFILE: +diff --git a/bus/config-parser-common.h b/bus/config-parser-common.h +index 382a014..9e026d1 100644 +--- a/bus/config-parser-common.h ++++ b/bus/config-parser-common.h +@@ -36,6 +36,7 @@ typedef enum + ELEMENT_LIMIT, + ELEMENT_ALLOW, + ELEMENT_DENY, ++ ELEMENT_CHECK, + ELEMENT_FORK, + ELEMENT_PIDFILE, + ELEMENT_SERVICEDIR, +diff --git a/bus/config-parser-trivial.c b/bus/config-parser-trivial.c +index dd65c6d..23dedb4 100644 +--- a/bus/config-parser-trivial.c ++++ b/bus/config-parser-trivial.c +@@ -194,6 +194,7 @@ bus_config_parser_start_element (BusConfigParser *parser, + case ELEMENT_POLICY: + case ELEMENT_LIMIT: + case ELEMENT_ALLOW: ++ case ELEMENT_CHECK: + case ELEMENT_DENY: + case ELEMENT_FORK: + case ELEMENT_PIDFILE: +@@ -316,6 +317,7 @@ bus_config_parser_content (BusConfigParser *parser, + case ELEMENT_POLICY: + case ELEMENT_LIMIT: + case ELEMENT_ALLOW: ++ case ELEMENT_CHECK: + case ELEMENT_DENY: + case ELEMENT_FORK: + case ELEMENT_PIDFILE: +diff --git a/bus/config-parser.c b/bus/config-parser.c +index be27d38..7f91469 100644 +--- a/bus/config-parser.c ++++ b/bus/config-parser.c +@@ -1318,7 +1318,7 @@ append_rule_from_element (BusConfigParser *parser, + const char *element_name, + const char **attribute_names, + const char **attribute_values, +- dbus_bool_t allow, ++ BusPolicyRuleAccess access, + DBusError *error) + { + const char *log; +@@ -1360,6 +1360,7 @@ append_rule_from_element (BusConfigParser *parser, + const char *own_prefix; + const char *user; + const char *group; ++ const char *privilege; + + BusPolicyRule *rule; + +@@ -1390,6 +1391,7 @@ append_rule_from_element (BusConfigParser *parser, + "user", &user, + "group", &group, + "log", &log, ++ "privilege", &privilege, + NULL)) + return FALSE; + +@@ -1422,6 +1424,7 @@ append_rule_from_element (BusConfigParser *parser, + + if (!(any_send_attribute || + any_receive_attribute || ++ privilege || + own || own_prefix || user || group)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, +@@ -1438,7 +1441,30 @@ append_rule_from_element (BusConfigParser *parser, + element_name); + return FALSE; + } +- ++ ++ if (access == BUS_POLICY_RULE_ACCESS_CHECK) ++ { ++ if (privilege == NULL || !*privilege) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, ++ "On element <%s>, you must specify the privilege to be checked.", ++ element_name); ++ return FALSE; ++ } ++ } ++ else ++ { ++ if (privilege != NULL && *privilege) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, ++ "On element <%s>, privilege %s is used outside of a check rule.", ++ element_name, privilege); ++ return FALSE; ++ } ++ else ++ privilege = NULL; /* replace (potentially) empty string with NULL pointer, it wouldn't be used anyway */ ++ } ++ + /* Allowed combinations of elements are: + * + * base, must be all send or all receive: +@@ -1589,7 +1615,7 @@ append_rule_from_element (BusConfigParser *parser, + error)) + return FALSE; + +- rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_SEND, access); + if (rule == NULL) + goto nomem; + +@@ -1694,7 +1720,7 @@ append_rule_from_element (BusConfigParser *parser, + error)) + return FALSE; + +- rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_RECEIVE, access); + if (rule == NULL) + goto nomem; + +@@ -1726,7 +1752,7 @@ append_rule_from_element (BusConfigParser *parser, + } + else if (own || own_prefix) + { +- rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_OWN, access); + if (rule == NULL) + goto nomem; + +@@ -1752,7 +1778,7 @@ append_rule_from_element (BusConfigParser *parser, + { + if (IS_WILDCARD (user)) + { +- rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access); + if (rule == NULL) + goto nomem; + +@@ -1767,7 +1793,7 @@ append_rule_from_element (BusConfigParser *parser, + + if (_dbus_parse_unix_user_from_config (&username, &uid)) + { +- rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_USER, access); + if (rule == NULL) + goto nomem; + +@@ -1784,7 +1810,7 @@ append_rule_from_element (BusConfigParser *parser, + { + if (IS_WILDCARD (group)) + { +- rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access); + if (rule == NULL) + goto nomem; + +@@ -1799,7 +1825,7 @@ append_rule_from_element (BusConfigParser *parser, + + if (_dbus_parse_unix_group_from_config (&groupname, &gid)) + { +- rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, allow); ++ rule = bus_policy_rule_new (BUS_POLICY_RULE_GROUP, access); + if (rule == NULL) + goto nomem; + +@@ -1823,6 +1849,10 @@ append_rule_from_element (BusConfigParser *parser, + _dbus_assert (pe != NULL); + _dbus_assert (pe->type == ELEMENT_POLICY); + ++ rule->privilege = _dbus_strdup (privilege); ++ if (privilege && !rule->privilege) ++ goto nomem; ++ + switch (pe->d.policy.type) + { + case POLICY_IGNORED: +@@ -1898,7 +1928,7 @@ start_policy_child (BusConfigParser *parser, + { + if (!append_rule_from_element (parser, element_name, + attribute_names, attribute_values, +- TRUE, error)) ++ BUS_POLICY_RULE_ACCESS_ALLOW, error)) + return FALSE; + + if (push_element (parser, ELEMENT_ALLOW) == NULL) +@@ -1913,7 +1943,7 @@ start_policy_child (BusConfigParser *parser, + { + if (!append_rule_from_element (parser, element_name, + attribute_names, attribute_values, +- FALSE, error)) ++ BUS_POLICY_RULE_ACCESS_DENY, error)) + return FALSE; + + if (push_element (parser, ELEMENT_DENY) == NULL) +@@ -1922,6 +1952,21 @@ start_policy_child (BusConfigParser *parser, + return FALSE; + } + ++ return TRUE; ++ } ++ else if (strcmp (element_name, "check") == 0) ++ { ++ if (!append_rule_from_element (parser, element_name, ++ attribute_names, attribute_values, ++ BUS_POLICY_RULE_ACCESS_CHECK, error)) ++ return FALSE; ++ ++ if (push_element (parser, ELEMENT_CHECK) == NULL) ++ { ++ BUS_SET_OOM (error); ++ return FALSE; ++ } ++ + return TRUE; + } + else +@@ -2284,6 +2329,7 @@ bus_config_parser_end_element (BusConfigParser *parser, + case ELEMENT_POLICY: + case ELEMENT_ALLOW: + case ELEMENT_DENY: ++ case ELEMENT_CHECK: + case ELEMENT_FORK: + case ELEMENT_SYSLOG: + case ELEMENT_KEEP_UMASK: +@@ -2600,6 +2646,7 @@ bus_config_parser_content (BusConfigParser *parser, + case ELEMENT_POLICY: + case ELEMENT_ALLOW: + case ELEMENT_DENY: ++ case ELEMENT_CHECK: + case ELEMENT_FORK: + case ELEMENT_SYSLOG: + case ELEMENT_KEEP_UMASK: +@@ -3127,6 +3174,8 @@ do_load (const DBusString *full_path, + dbus_error_init (&error); + + parser = bus_config_load (full_path, TRUE, NULL, &error); ++ if (dbus_error_is_set (&error)) ++ _dbus_verbose ("Failed to load file: %s\n", error.message); + if (parser == NULL) + { + _DBUS_ASSERT_ERROR_IS_SET (&error); +@@ -3359,6 +3408,7 @@ elements_equal (const Element *a, + case ELEMENT_LISTEN: + case ELEMENT_AUTH: + case ELEMENT_ALLOW: ++ case ELEMENT_CHECK: + case ELEMENT_DENY: + case ELEMENT_FORK: + case ELEMENT_PIDFILE: +diff --git a/bus/connection.c b/bus/connection.c +index 53605fa..b348d42 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -36,6 +36,10 @@ + #include <dbus/dbus-timeout.h> + #include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-internals.h> ++#ifdef DBUS_ENABLE_CYNARA ++#include <stdlib.h> ++#include <cynara-session.h> ++#endif + + /* Trim executed commands to this length; we want to keep logs readable */ + #define MAX_LOG_COMMAND_LEN 50 +@@ -116,6 +120,9 @@ typedef struct + + /** non-NULL if and only if this is a monitor */ + DBusList *link_in_monitors; ++#ifdef DBUS_ENABLE_CYNARA ++ char *cynara_session_id; ++#endif + } BusConnectionData; + + static dbus_bool_t bus_pending_reply_expired (BusExpireList *list, +@@ -129,8 +136,8 @@ static dbus_bool_t expire_incomplete_timeout (void *data); + + #define BUS_CONNECTION_DATA(connection) (dbus_connection_get_data ((connection), connection_data_slot)) + +-static DBusLoop* +-connection_get_loop (DBusConnection *connection) ++DBusLoop* ++bus_connection_get_loop (DBusConnection *connection) + { + BusConnectionData *d; + +@@ -354,7 +361,7 @@ add_connection_watch (DBusWatch *watch, + { + DBusConnection *connection = data; + +- return _dbus_loop_add_watch (connection_get_loop (connection), watch); ++ return _dbus_loop_add_watch (bus_connection_get_loop (connection), watch); + } + + static void +@@ -363,7 +370,7 @@ remove_connection_watch (DBusWatch *watch, + { + DBusConnection *connection = data; + +- _dbus_loop_remove_watch (connection_get_loop (connection), watch); ++ _dbus_loop_remove_watch (bus_connection_get_loop (connection), watch); + } + + static void +@@ -372,7 +379,7 @@ toggle_connection_watch (DBusWatch *watch, + { + DBusConnection *connection = data; + +- _dbus_loop_toggle_watch (connection_get_loop (connection), watch); ++ _dbus_loop_toggle_watch (bus_connection_get_loop (connection), watch); + } + + static dbus_bool_t +@@ -381,7 +388,7 @@ add_connection_timeout (DBusTimeout *timeout, + { + DBusConnection *connection = data; + +- return _dbus_loop_add_timeout (connection_get_loop (connection), timeout); ++ return _dbus_loop_add_timeout (bus_connection_get_loop (connection), timeout); + } + + static void +@@ -390,7 +397,7 @@ remove_connection_timeout (DBusTimeout *timeout, + { + DBusConnection *connection = data; + +- _dbus_loop_remove_timeout (connection_get_loop (connection), timeout); ++ _dbus_loop_remove_timeout (bus_connection_get_loop (connection), timeout); + } + + static void +@@ -448,6 +455,10 @@ free_connection_data (void *data) + + dbus_free (d->name); + ++#ifdef DBUS_ENABLE_CYNARA ++ free (d->cynara_session_id); ++#endif ++ + dbus_free (d); + } + +@@ -1078,6 +1089,22 @@ bus_connection_get_policy (DBusConnection *connection) + return d->policy; + } + ++#ifdef DBUS_ENABLE_CYNARA ++const char *bus_connection_get_cynara_session_id (DBusConnection *connection) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA (connection); ++ _dbus_assert (d != NULL); ++ ++ if (d->cynara_session_id == NULL) ++ { ++ unsigned long pid; ++ if (dbus_connection_get_unix_process_id(connection, &pid)) ++ d->cynara_session_id = cynara_session_from_pid(pid); ++ } ++ return d->cynara_session_id; ++} ++#endif ++ + static dbus_bool_t + foreach_active (BusConnections *connections, + BusConnectionForeachFunction function, +@@ -2333,6 +2360,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + DBusMessage *message) + { + DBusError error = DBUS_ERROR_INIT; ++ BusResult res; + + /* We have to set the sender to the driver, and have + * to check security policy since it was not done in +@@ -2370,10 +2398,11 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + * if we're actively capturing messages, it's nice to log that we + * tried to send it and did not allow ourselves to do so. + */ +- if (!bus_context_check_security_policy (bus_transaction_get_context (transaction), +- transaction, +- NULL, connection, connection, +- message, NULL, &error)) ++ res = bus_context_check_security_policy (bus_transaction_get_context (transaction), ++ transaction, ++ NULL, connection, connection, message, NULL, ++ &error, NULL); ++ if (res == BUS_RESULT_FALSE) + { + if (!bus_transaction_capture_error_reply (transaction, connection, + &error, message)) +@@ -2388,6 +2417,12 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + dbus_error_free (&error); + return TRUE; + } ++ else if (res == BUS_RESULT_LATER) ++ { ++ _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); ++ dbus_error_free (&error); ++ return TRUE; ++ } + + return bus_transaction_send (transaction, connection, message); + } +diff --git a/bus/connection.h b/bus/connection.h +index 9e253ae..71078ea 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -31,6 +31,7 @@ + typedef dbus_bool_t (* BusConnectionForeachFunction) (DBusConnection *connection, + void *data); + ++DBusLoop* bus_connection_get_loop (DBusConnection *connection); + + BusConnections* bus_connections_new (BusContext *context); + BusConnections* bus_connections_ref (BusConnections *connections); +@@ -124,6 +125,9 @@ dbus_bool_t bus_connection_be_monitor (DBusConnection *connection, + BusTransaction *transaction, + DBusList **rules, + DBusError *error); ++#ifdef DBUS_ENABLE_CYNARA ++const char *bus_connection_get_cynara_session_id (DBusConnection *connection); ++#endif + + /* transaction API so we can send or not send a block of messages as a whole */ + +diff --git a/bus/cynara.c b/bus/cynara.c +new file mode 100644 +index 0000000..57a4c45 +--- /dev/null ++++ b/bus/cynara.c +@@ -0,0 +1,374 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* cynara.c Cynara runtime privilege checking ++ * ++ * Copyright (c) 2014 Samsung Electronics, Ltd. ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++#include "cynara.h" ++#include "check.h" ++#include "utils.h" ++ ++#include <stdio.h> ++ ++#include <dbus/dbus.h> ++#include <dbus/dbus-watch.h> ++#include <dbus/dbus-connection-internal.h> ++#include <bus/connection.h> ++#ifdef DBUS_ENABLE_CYNARA ++#include <cynara-client-async.h> ++#endif ++ ++ ++#ifdef DBUS_ENABLE_CYNARA ++typedef struct BusCynara ++{ ++ int refcount; ++ ++ BusContext *context; ++ BusCheck *check; ++ cynara_async *cynara; ++ DBusWatch *cynara_watch; ++} BusCynara; ++ ++#define USE_CYNARA_CACHE 1 ++#ifdef USE_CYNARA_CACHE ++#define CYNARA_CACHE_SIZE 1000 ++#endif ++ ++static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch, ++ unsigned int flags, ++ void *data); ++ ++static void status_callback(int old_fd, ++ int new_fd, ++ cynara_async_status status, ++ void *user_status_data); ++static void bus_cynara_check_response_callback (cynara_check_id check_id, ++ cynara_async_call_cause cause, ++ int response, ++ void *user_response_data); ++#endif ++ ++ ++BusCynara * ++bus_cynara_new(BusCheck *check, DBusError *error) ++{ ++#ifdef DBUS_ENABLE_CYNARA ++ BusContext *context; ++ BusCynara *cynara; ++ cynara_async_configuration *conf = NULL; ++ int ret; ++ ++ cynara = dbus_new(BusCynara, 1); ++ if (cynara == NULL) ++ { ++ BUS_SET_OOM(error); ++ return NULL; ++ } ++ ++ context = bus_check_get_context(check); ++ ++ cynara->refcount = 1; ++ cynara->check = check; ++ cynara->context = context; ++ cynara->cynara_watch = NULL; ++ ++ ret = cynara_async_configuration_create(&conf); ++ if (ret != CYNARA_API_SUCCESS) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration"); ++ goto out; ++ } ++ ++#ifdef CYNARA_CACHE_SIZE ++ ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE); ++ if (ret != CYNARA_API_SUCCESS) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size"); ++ goto out; ++ } ++#endif ++ ++ ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara); ++ if (ret != CYNARA_API_SUCCESS) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client"); ++ goto out; ++ } ++ ++out: ++ cynara_async_configuration_destroy(conf); ++ if (ret != CYNARA_API_SUCCESS) ++ { ++ dbus_free(cynara); ++ return NULL; ++ } ++ ++ return cynara; ++#else ++ return NULL; ++#endif ++} ++ ++BusCynara * ++bus_cynara_ref (BusCynara *cynara) ++{ ++#ifdef DBUS_ENABLE_CYNARA ++ _dbus_assert (cynara->refcount > 0); ++ cynara->refcount += 1; ++ ++ return cynara; ++#else ++ return NULL; ++#endif ++} ++ ++void ++bus_cynara_unref (BusCynara *cynara) ++{ ++#ifdef DBUS_ENABLE_CYNARA ++ _dbus_assert (cynara->refcount > 0); ++ ++ cynara->refcount -= 1; ++ ++ if (cynara->refcount == 0) ++ { ++ cynara_async_finish(cynara->cynara); ++ dbus_free(cynara); ++ } ++#endif ++} ++ ++BusResult ++bus_cynara_check_privilege (BusCynara *cynara, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *privilege, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message_param) ++{ ++#ifdef DBUS_ENABLE_CYNARA ++ int result; ++ unsigned long uid; ++ char *label; ++ const char *session_id; ++ char user[32]; ++ cynara_check_id check_id; ++ DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; ++ BusDeferredMessage *deferred_message; ++ BusResult ret; ++ ++ _dbus_assert(connection != NULL); ++ ++ if (dbus_connection_get_unix_user(connection, &uid) == FALSE) ++ return BUS_RESULT_FALSE; ++ ++ if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL) ++ { ++ _dbus_warn("Failed to obtain security label for connection\n"); ++ return BUS_RESULT_FALSE; ++ } ++ ++ session_id = bus_connection_get_cynara_session_id (connection); ++ if (session_id == NULL) ++ { ++ ret = BUS_RESULT_FALSE; ++ goto out; ++ } ++ ++ snprintf(user, sizeof(user), "%lu", uid); ++ ++#if USE_CYNARA_CACHE ++ result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege); ++#else ++ result = CYNARA_API_CACHE_MISS; ++#endif ++ ++ switch (result) ++ { ++ case CYNARA_API_ACCESS_ALLOWED: ++ _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", ++ label, session_id, user, privilege); ++ ret = BUS_RESULT_TRUE; ++ break; ++ ++ case CYNARA_API_ACCESS_DENIED: ++ _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", ++ label, session_id, user, privilege); ++ ret = BUS_RESULT_FALSE; ++ break; ++ ++ case CYNARA_API_CACHE_MISS: ++ deferred_message = bus_deferred_message_new(message, sender, addressed_recipient, ++ proposed_recipient, BUS_RESULT_LATER); ++ if (deferred_message == NULL) ++ { ++ _dbus_verbose("Failed to allocate memory for deferred message\n"); ++ ret = BUS_RESULT_FALSE; ++ goto out; ++ } ++ ++ /* callback is supposed to unref deferred_message*/ ++ result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id, ++ &bus_cynara_check_response_callback, deferred_message); ++ if (result == CYNARA_API_SUCCESS) ++ { ++ _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u " ++ "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message); ++ if (deferred_message_param != NULL) ++ *deferred_message_param = deferred_message; ++ ret = BUS_RESULT_LATER; ++ } ++ else ++ { ++ _dbus_verbose("Error on cynara request create: %i\n", result); ++ bus_deferred_message_unref(deferred_message); ++ ret = BUS_RESULT_FALSE; ++ } ++ break; ++ default: ++ _dbus_verbose("Error when accessing Cynara cache: %i\n", result); ++ ret = BUS_RESULT_FALSE; ++ } ++out: ++ dbus_free(label); ++ return ret; ++ ++#else ++ return BUS_RESULT_FALSE; ++#endif ++} ++ ++ ++ ++#ifdef DBUS_ENABLE_CYNARA ++static void ++status_callback(int old_fd, int new_fd, cynara_async_status status, ++ void *user_status_data) ++{ ++ BusCynara *cynara = (BusCynara *)user_status_data; ++ DBusLoop *loop = bus_context_get_loop(cynara->context); ++ ++ if (cynara->cynara_watch != NULL) ++ { ++ _dbus_loop_remove_watch(loop, cynara->cynara_watch); ++ _dbus_watch_invalidate(cynara->cynara_watch); ++ _dbus_watch_unref(cynara->cynara_watch); ++ cynara->cynara_watch = NULL; ++ } ++ ++ if (new_fd != -1) ++ { ++ unsigned int flags; ++ DBusWatch *watch; ++ ++ switch (status) ++ { ++ case CYNARA_STATUS_FOR_READ: ++ flags = DBUS_WATCH_READABLE; ++ break; ++ case CYNARA_STATUS_FOR_RW: ++ flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; ++ break; ++ default: ++ /* Cynara passed unknown status - warn and add RW watch */ ++ _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status); ++ flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; ++ break; ++ } ++ ++ watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL); ++ if (watch != NULL) ++ { ++ if (_dbus_loop_add_watch(loop, watch) == TRUE) ++ { ++ cynara->cynara_watch = watch; ++ return; ++ } ++ ++ _dbus_watch_invalidate(watch); ++ _dbus_watch_unref(watch); ++ } ++ ++ /* It seems like not much can be done at this point. Cynara events won't be processed ++ * until next Cynara function call triggering status callback */ ++ _dbus_verbose("Failed to add dbus watch\n"); ++ } ++} ++ ++static dbus_bool_t ++bus_cynara_watch_callback(DBusWatch *watch, ++ unsigned int flags, ++ void *data) ++{ ++ BusCynara *cynara = (BusCynara *)data; ++ int result = cynara_async_process(cynara->cynara); ++ if (result != CYNARA_API_SUCCESS) ++ _dbus_verbose("cynara_async_process returned %d\n", result); ++ ++ return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE; ++} ++ ++static inline const char * ++call_cause_to_string(cynara_async_call_cause cause) ++{ ++ switch (cause) ++ { ++ case CYNARA_CALL_CAUSE_ANSWER: ++ return "ANSWER"; ++ case CYNARA_CALL_CAUSE_CANCEL: ++ return "CANCEL"; ++ case CYNARA_CALL_CAUSE_FINISH: ++ return "FINSIH"; ++ case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE: ++ return "SERVICE NOT AVAILABLE"; ++ default: ++ return "INVALID"; ++ } ++} ++ ++static void ++bus_cynara_check_response_callback (cynara_check_id check_id, ++ cynara_async_call_cause cause, ++ int response, ++ void *user_response_data) ++{ ++ BusDeferredMessage *deferred_message = user_response_data; ++ BusResult result; ++ ++ _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n", ++ (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data); ++ ++ if (deferred_message == NULL) ++ return; ++ ++ if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED) ++ result = BUS_RESULT_TRUE; ++ else ++ result = BUS_RESULT_FALSE; ++ ++ bus_deferred_message_response_received(deferred_message, result); ++ bus_deferred_message_unref(deferred_message); ++} ++ ++#endif /* DBUS_ENABLE_CYNARA */ +diff --git a/bus/cynara.h b/bus/cynara.h +new file mode 100644 +index 0000000..c4728bb +--- /dev/null ++++ b/bus/cynara.h +@@ -0,0 +1,37 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* cynara.h Cynara runtime privilege checking ++ * ++ * Copyright (c) 2014 Samsung Electronics, Ltd. ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include "bus.h" ++#include "check.h" ++ ++BusCynara *bus_cynara_new (BusCheck *check, DBusError *error); ++BusCynara *bus_cynara_ref (BusCynara *cynara); ++void bus_cynara_unref (BusCynara *cynara); ++BusResult bus_cynara_check_privilege (BusCynara *cynara, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *privilege, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message); +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 19228be..d3867f7 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -25,6 +25,7 @@ + + #include <config.h> + #include "dispatch.h" ++#include "check.h" + #include "connection.h" + #include "driver.h" + #include "services.h" +@@ -64,14 +65,18 @@ send_one_message (DBusConnection *connection, + DBusError *error) + { + DBusError stack_error = DBUS_ERROR_INIT; ++ BusDeferredMessage *deferred_message; ++ BusResult result; + +- if (!bus_context_check_security_policy (context, transaction, ++ result = bus_context_check_security_policy (context, transaction, + sender, + addressed_recipient, + connection, + message, + NULL, +- &stack_error)) ++ &stack_error, ++ &deferred_message); ++ if (result != BUS_RESULT_TRUE) + { + if (!bus_transaction_capture_error_reply (transaction, sender, + &stack_error, message)) +@@ -130,6 +135,8 @@ bus_dispatch_matches (BusTransaction *transaction, + BusMatchmaker *matchmaker; + DBusList *link; + BusContext *context; ++ BusDeferredMessage *deferred_message; ++ BusResult res; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -145,11 +152,20 @@ bus_dispatch_matches (BusTransaction *transaction, + /* First, send the message to the addressed_recipient, if there is one. */ + if (addressed_recipient != NULL) + { +- if (!bus_context_check_security_policy (context, transaction, +- sender, addressed_recipient, +- addressed_recipient, +- message, NULL, error)) ++ res = bus_context_check_security_policy (context, transaction, ++ sender, addressed_recipient, ++ addressed_recipient, ++ message, NULL, error, ++ &deferred_message); ++ if (res == BUS_RESULT_FALSE) + return FALSE; ++ else if (res == BUS_RESULT_LATER) ++ { ++ dbus_set_error (error, ++ DBUS_ERROR_ACCESS_DENIED, ++ "Rejecting message because time is needed to check security policy"); ++ return FALSE; ++ } + + if (dbus_message_contains_unix_fds (message) && + !dbus_connection_can_send_type (addressed_recipient, +@@ -374,19 +390,31 @@ bus_dispatch (DBusConnection *connection, + if (service_name && + strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ + { ++ BusDeferredMessage *deferred_message; ++ BusResult res; ++ + if (!bus_transaction_capture (transaction, connection, NULL, message)) + { + BUS_SET_OOM (&error); + goto out; + } + +- if (!bus_context_check_security_policy (context, transaction, +- connection, NULL, NULL, message, +- NULL, &error)) ++ res = bus_context_check_security_policy (context, transaction, ++ connection, NULL, NULL, message, NULL, ++ &error, &deferred_message); ++ if (res == BUS_RESULT_FALSE) + { + _dbus_verbose ("Security policy rejected message\n"); + goto out; + } ++ else if (res == BUS_RESULT_LATER) ++ { ++ dbus_set_error (&error, ++ DBUS_ERROR_ACCESS_DENIED, ++ "Rejecting message because time is needed to check security policy"); ++ _dbus_verbose ("Security policy needs time to check policy. Dropping message\n"); ++ goto out; ++ } + + _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); + if (!bus_driver_handle_message (connection, transaction, message, &error)) +diff --git a/bus/driver.h b/bus/driver.h +index ac1289d..a7297ad 100644 +--- a/bus/driver.h ++++ b/bus/driver.h +@@ -66,5 +66,7 @@ dbus_bool_t bus_driver_send_ack_reply (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); ++dbus_bool_t bus_driver_check_message_is_for_us (DBusMessage *message, ++ DBusError *error); + + #endif /* BUS_DRIVER_H */ +diff --git a/bus/policy.c b/bus/policy.c +index a37be80..7de92c6 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -22,6 +22,7 @@ + */ + + #include <config.h> ++#include "check.h" + #include "policy.h" + #include "services.h" + #include "test.h" +@@ -33,7 +34,7 @@ + + BusPolicyRule* + bus_policy_rule_new (BusPolicyRuleType type, +- dbus_bool_t allow) ++ BusPolicyRuleAccess access) + { + BusPolicyRule *rule; + +@@ -43,7 +44,7 @@ bus_policy_rule_new (BusPolicyRuleType type, + + rule->type = type; + rule->refcount = 1; +- rule->allow = allow; ++ rule->access = access; + + switch (rule->type) + { +@@ -55,18 +56,19 @@ bus_policy_rule_new (BusPolicyRuleType type, + break; + case BUS_POLICY_RULE_SEND: + rule->d.send.message_type = DBUS_MESSAGE_TYPE_INVALID; +- + /* allow rules default to TRUE (only requested replies allowed) ++ * check rules default to TRUE (only requested replies are checked) + * deny rules default to FALSE (only unrequested replies denied) + */ +- rule->d.send.requested_reply = rule->allow; ++ rule->d.send.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY; + break; + case BUS_POLICY_RULE_RECEIVE: + rule->d.receive.message_type = DBUS_MESSAGE_TYPE_INVALID; + /* allow rules default to TRUE (only requested replies allowed) ++ * check rules default to TRUE (only requested replies are checked) + * deny rules default to FALSE (only unrequested replies denied) + */ +- rule->d.receive.requested_reply = rule->allow; ++ rule->d.receive.requested_reply = rule->access != BUS_POLICY_RULE_ACCESS_DENY; + break; + case BUS_POLICY_RULE_OWN: + break; +@@ -122,7 +124,8 @@ bus_policy_rule_unref (BusPolicyRule *rule) + default: + _dbus_assert_not_reached ("invalid rule"); + } +- ++ ++ dbus_free (rule->privilege); + dbus_free (rule); + } + } +@@ -435,7 +438,10 @@ list_allows_user (dbus_bool_t def, + else + continue; + +- allowed = rule->allow; ++ /* We don't intend to support <check user="..." /> and <check group="..." /> ++ rules. They are treated like deny. ++ */ ++ allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; + } + + return allowed; +@@ -873,18 +879,23 @@ bus_client_policy_append_rule (BusClientPolicy *policy, + return TRUE; + } + +-dbus_bool_t +-bus_client_policy_check_can_send (BusClientPolicy *policy, +- BusRegistry *registry, +- dbus_bool_t requested_reply, +- DBusConnection *receiver, +- DBusMessage *message, +- dbus_int32_t *toggles, +- dbus_bool_t *log) ++BusResult ++bus_client_policy_check_can_send (DBusConnection *sender, ++ BusClientPolicy *policy, ++ BusRegistry *registry, ++ dbus_bool_t requested_reply, ++ DBusConnection *addressed_recipient, ++ DBusConnection *receiver, ++ DBusMessage *message, ++ dbus_int32_t *toggles, ++ dbus_bool_t *log, ++ const char **privilege_param, ++ BusDeferredMessage **deferred_message) + { + DBusList *link; +- dbus_bool_t allowed; +- ++ BusResult result; ++ const char *privilege; ++ + /* policy->rules is in the order the rules appeared + * in the config file, i.e. last rule that applies wins + */ +@@ -892,7 +903,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, + _dbus_verbose (" (policy) checking send rules\n"); + *toggles = 0; + +- allowed = FALSE; ++ result = BUS_RESULT_FALSE; + link = _dbus_list_get_first_link (&policy->rules); + while (link != NULL) + { +@@ -923,13 +934,14 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, + /* If it's a reply, the requested_reply flag kicks in */ + if (dbus_message_get_reply_serial (message) != 0) + { +- /* for allow, requested_reply=true means the rule applies +- * only when reply was requested. requested_reply=false means +- * always allow. ++ /* for allow or check requested_reply=true means the rule applies ++ * only when reply was requested. requested_reply=false means the ++ * rule always applies + */ +- if (!requested_reply && rule->allow && rule->d.send.requested_reply && !rule->d.send.eavesdrop) ++ if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop) + { +- _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); ++ _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n", ++ rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check"); + continue; + } + +@@ -937,7 +949,7 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, + * when the reply was not requested. requested_reply=true means the + * rule always applies. + */ +- if (requested_reply && !rule->allow && !rule->d.send.requested_reply) ++ if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.send.requested_reply) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); + continue; +@@ -960,13 +972,15 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, + /* The interface is optional in messages. For allow rules, if the message + * has no interface we want to skip the rule (and thus not allow); + * for deny rules, if the message has no interface we want to use the +- * rule (and thus deny). ++ * rule (and thus deny). Check rules are meant to be used like allow ++ * rules (they can grant access, but not remove it), so we treat it like ++ * allow here. + */ + dbus_bool_t no_interface; + + no_interface = dbus_message_get_interface (message) == NULL; + +- if ((no_interface && rule->allow) || ++ if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) || + (!no_interface && + strcmp (dbus_message_get_interface (message), + rule->d.send.interface) != 0)) +@@ -1079,33 +1093,64 @@ bus_client_policy_check_can_send (BusClientPolicy *policy, + } + + /* Use this rule */ +- allowed = rule->allow; ++ switch (rule->access) ++ { ++ case BUS_POLICY_RULE_ACCESS_ALLOW: ++ result = BUS_RESULT_TRUE; ++ break; ++ case BUS_POLICY_RULE_ACCESS_DENY: ++ default: ++ result = BUS_RESULT_FALSE; ++ break; ++ case BUS_POLICY_RULE_ACCESS_CHECK: ++ result = BUS_RESULT_LATER; ++ privilege = rule->privilege; ++ break; ++ } ++ + *log = rule->d.send.log; + (*toggles)++; + +- _dbus_verbose (" (policy) used rule, allow now = %d\n", +- allowed); ++ _dbus_verbose (" (policy) used rule, result now = %d\n", ++ (int)(intptr_t)result); + } + +- return allowed; ++ if (result == BUS_RESULT_LATER) ++ { ++ BusContext *context = bus_connection_get_context(sender); ++ BusCheck *check = bus_context_get_check(context); ++ ++ result = bus_check_privilege(check, message, sender, addressed_recipient, receiver, ++ privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message); ++ } ++ else ++ privilege = NULL; ++ ++ if (privilege_param != NULL) ++ *privilege_param = privilege; ++ ++ return result; + } + + /* See docs on what the args mean on bus_context_check_security_policy() + * comment + */ +-dbus_bool_t +-bus_client_policy_check_can_receive (BusClientPolicy *policy, +- BusRegistry *registry, +- dbus_bool_t requested_reply, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusConnection *proposed_recipient, +- DBusMessage *message, +- dbus_int32_t *toggles) ++BusResult ++bus_client_policy_check_can_receive (BusClientPolicy *policy, ++ BusRegistry *registry, ++ dbus_bool_t requested_reply, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ DBusMessage *message, ++ dbus_int32_t *toggles, ++ const char **privilege_param, ++ BusDeferredMessage **deferred_message) + { + DBusList *link; +- dbus_bool_t allowed; + dbus_bool_t eavesdropping; ++ BusResult result; ++ const char *privilege; + + eavesdropping = + addressed_recipient != proposed_recipient && +@@ -1118,7 +1163,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + _dbus_verbose (" (policy) checking receive rules, eavesdropping = %d\n", eavesdropping); + *toggles = 0; + +- allowed = FALSE; ++ result = BUS_RESULT_FALSE; + link = _dbus_list_get_first_link (&policy->rules); + while (link != NULL) + { +@@ -1141,19 +1186,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + } + } + +- /* for allow, eavesdrop=false means the rule doesn't apply when +- * eavesdropping. eavesdrop=true means always allow. ++ ++ /* for allow or check, eavesdrop=false means the rule doesn't apply when ++ * eavesdropping. eavesdrop=true means the rule always applies + */ +- if (eavesdropping && rule->allow && !rule->d.receive.eavesdrop) ++ if (eavesdropping && rule->access != BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.eavesdrop) + { +- _dbus_verbose (" (policy) skipping allow rule since it doesn't apply to eavesdropping\n"); ++ _dbus_verbose (" (policy) skipping %s rule since it doesn't apply to eavesdropping\n", ++ rule->access == BUS_POLICY_RULE_ACCESS_ALLOW ? "allow" : "check"); + continue; + } + + /* for deny, eavesdrop=true means the rule applies only when + * eavesdropping; eavesdrop=false means always deny. + */ +- if (!eavesdropping && !rule->allow && rule->d.receive.eavesdrop) ++ if (!eavesdropping && rule->access == BUS_POLICY_RULE_ACCESS_DENY && rule->d.receive.eavesdrop) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to eavesdropping\n"); + continue; +@@ -1162,13 +1209,14 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + /* If it's a reply, the requested_reply flag kicks in */ + if (dbus_message_get_reply_serial (message) != 0) + { +- /* for allow, requested_reply=true means the rule applies +- * only when reply was requested. requested_reply=false means +- * always allow. ++ /* for allow or check requested_reply=true means the rule applies ++ * only when reply was requested. requested_reply=false means the ++ * rule always applies + */ +- if (!requested_reply && rule->allow && rule->d.receive.requested_reply && !rule->d.receive.eavesdrop) ++ if (!requested_reply && rule->access != BUS_POLICY_RULE_ACCESS_DENY && rule->d.send.requested_reply && !rule->d.send.eavesdrop) + { +- _dbus_verbose (" (policy) skipping allow rule since it only applies to requested replies and does not allow eavesdropping\n"); ++ _dbus_verbose (" (policy) skipping %s rule since it only applies to requested replies and does not allow eavesdropping\n", ++ rule->access == BUS_POLICY_RULE_ACCESS_DENY ? "allow" : "deny"); + continue; + } + +@@ -1176,7 +1224,7 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + * when the reply was not requested. requested_reply=true means the + * rule always applies. + */ +- if (requested_reply && !rule->allow && !rule->d.receive.requested_reply) ++ if (requested_reply && rule->access == BUS_POLICY_RULE_ACCESS_DENY && !rule->d.receive.requested_reply) + { + _dbus_verbose (" (policy) skipping deny rule since it only applies to unrequested replies\n"); + continue; +@@ -1199,13 +1247,13 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + /* The interface is optional in messages. For allow rules, if the message + * has no interface we want to skip the rule (and thus not allow); + * for deny rules, if the message has no interface we want to use the +- * rule (and thus deny). ++ * rule (and thus deny). Check rules are treated like allow rules. + */ + dbus_bool_t no_interface; + + no_interface = dbus_message_get_interface (message) == NULL; + +- if ((no_interface && rule->allow) || ++ if ((no_interface && rule->access != BUS_POLICY_RULE_ACCESS_DENY) || + (!no_interface && + strcmp (dbus_message_get_interface (message), + rule->d.receive.interface) != 0)) +@@ -1295,14 +1343,43 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + } + + /* Use this rule */ +- allowed = rule->allow; ++ switch (rule->access) ++ { ++ case BUS_POLICY_RULE_ACCESS_ALLOW: ++ result = BUS_RESULT_TRUE; ++ break; ++ case BUS_POLICY_RULE_ACCESS_DENY: ++ default: ++ result = BUS_RESULT_FALSE; ++ break; ++ case BUS_POLICY_RULE_ACCESS_CHECK: ++ result = BUS_RESULT_LATER; ++ privilege = rule->privilege; ++ break; ++ } ++ + (*toggles)++; + +- _dbus_verbose (" (policy) used rule, allow now = %d\n", +- allowed); ++ _dbus_verbose (" (policy) used rule, result now = %d\n", ++ (int)(intptr_t)result); + } + +- return allowed; ++ ++ if (result == BUS_RESULT_LATER) ++ { ++ BusContext *context = bus_connection_get_context(proposed_recipient); ++ BusCheck *check = bus_context_get_check(context); ++ ++ result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient, ++ privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message); ++ } ++ else ++ privilege = NULL; ++ ++ if (privilege_param != NULL) ++ *privilege_param = privilege; ++ ++ return result; + } + + +@@ -1354,7 +1431,7 @@ bus_rules_check_can_own (DBusList *rules, + } + + /* Use this rule */ +- allowed = rule->allow; ++ allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; + } + + return allowed; +diff --git a/bus/policy.h b/bus/policy.h +index ec43ffa..f839d23 100644 +--- a/bus/policy.h ++++ b/bus/policy.h +@@ -46,6 +46,14 @@ typedef enum + BUS_POLICY_TRISTATE_TRUE + } BusPolicyTristate; + ++typedef enum ++{ ++ BUS_POLICY_RULE_ACCESS_DENY, ++ BUS_POLICY_RULE_ACCESS_ALLOW, ++ /** runtime check resulting in allow or deny */ ++ BUS_POLICY_RULE_ACCESS_CHECK ++} BusPolicyRuleAccess; ++ + /** determines whether the rule affects a connection, or some global item */ + #define BUS_POLICY_RULE_IS_PER_CLIENT(rule) (!((rule)->type == BUS_POLICY_RULE_USER || \ + (rule)->type == BUS_POLICY_RULE_GROUP)) +@@ -56,8 +64,9 @@ struct BusPolicyRule + + BusPolicyRuleType type; + +- unsigned int allow : 1; /**< #TRUE if this allows, #FALSE if it denies */ +- ++ unsigned int access : 2; /**< BusPolicyRuleAccess */ ++ char *privilege; /**< for BUS_POLICY_RULE_ACCESS_CHECK */ ++ + union + { + struct +@@ -118,7 +127,7 @@ struct BusPolicyRule + }; + + BusPolicyRule* bus_policy_rule_new (BusPolicyRuleType type, +- dbus_bool_t allow); ++ BusPolicyRuleAccess access); + BusPolicyRule* bus_policy_rule_ref (BusPolicyRule *rule); + void bus_policy_rule_unref (BusPolicyRule *rule); + +@@ -152,21 +161,27 @@ dbus_bool_t bus_policy_merge (BusPolicy *policy, + BusClientPolicy* bus_client_policy_new (void); + BusClientPolicy* bus_client_policy_ref (BusClientPolicy *policy); + void bus_client_policy_unref (BusClientPolicy *policy); +-dbus_bool_t bus_client_policy_check_can_send (BusClientPolicy *policy, ++BusResult bus_client_policy_check_can_send (DBusConnection *sender, ++ BusClientPolicy *policy, + BusRegistry *registry, + dbus_bool_t requested_reply, ++ DBusConnection *addressed_recipient, + DBusConnection *receiver, + DBusMessage *message, + dbus_int32_t *toggles, +- dbus_bool_t *log); +-dbus_bool_t bus_client_policy_check_can_receive (BusClientPolicy *policy, ++ dbus_bool_t *log, ++ const char **privilege_param, ++ BusDeferredMessage **deferred_message); ++BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy, + BusRegistry *registry, + dbus_bool_t requested_reply, + DBusConnection *sender, + DBusConnection *addressed_recipient, + DBusConnection *proposed_recipient, + DBusMessage *message, +- dbus_int32_t *toggles); ++ dbus_int32_t *toggles, ++ const char **privilege_param, ++ BusDeferredMessage **deferred_message); + dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy, + const DBusString *service_name); + dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy, +diff --git a/configure.ac b/configure.ac +index d1e3a29..11b5ffd 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1742,6 +1742,17 @@ AC_ARG_ENABLE([user-session], + AM_CONDITIONAL([DBUS_ENABLE_USER_SESSION], + [test "x$enable_user_session" = xyes]) + ++#enable cynara integration ++AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no]) ++if test "x$enable_cynara" = xyes; then ++ PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0], ++ [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])], ++ [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])]) ++fi ++ ++AC_SUBST([CYNARA_CFLAGS]) ++AC_SUBST([CYNARA_LIBS]) ++ + AC_CONFIG_FILES([ + Doxyfile + dbus/Version +@@ -1824,6 +1835,7 @@ echo " + Building bus stats API: ${enable_stats} + Building SELinux support: ${have_selinux} + Building AppArmor support: ${have_apparmor} ++ Building Cynara support: ${enable_cynara} + Building inotify support: ${have_inotify} + Building kqueue support: ${have_kqueue} + Building systemd support: ${have_systemd} +diff --git a/test/Makefile.am b/test/Makefile.am +index af1e13b..e6f50e1 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -439,6 +439,7 @@ in_data = \ + data/valid-config-files/debug-allow-all.conf.in \ + data/valid-config-files/finite-timeout.conf.in \ + data/valid-config-files/forbidding.conf.in \ ++ data/valid-config-files/debug-check-some.conf.in \ + data/valid-config-files/incoming-limit.conf.in \ + data/valid-config-files/max-completed-connections.conf.in \ + data/valid-config-files/max-connections-per-user.conf.in \ +diff --git a/test/data/invalid-config-files/badcheck-1.conf b/test/data/invalid-config-files/badcheck-1.conf +new file mode 100644 +index 0000000..fad9f50 +--- /dev/null ++++ b/test/data/invalid-config-files/badcheck-1.conf +@@ -0,0 +1,9 @@ ++<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" ++ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> ++<busconfig> ++ <user>mybususer</user> ++ <listen>unix:path=/foo/bar</listen> ++ <policy context="default"> ++ <allow privilege="foo" send_destination="*"/> <!-- extra privilege="foo" --> ++ </policy> ++</busconfig> +diff --git a/test/data/invalid-config-files/badcheck-2.conf b/test/data/invalid-config-files/badcheck-2.conf +new file mode 100644 +index 0000000..63c7ef2 +--- /dev/null ++++ b/test/data/invalid-config-files/badcheck-2.conf +@@ -0,0 +1,9 @@ ++<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" ++ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> ++<busconfig> ++ <user>mybususer</user> ++ <listen>unix:path=/foo/bar</listen> ++ <policy context="default"> ++ <check send_destination="*"/> <!-- missing privilege="foo" --> ++ </policy> ++</busconfig> +diff --git a/test/data/valid-config-files/check-1.conf b/test/data/valid-config-files/check-1.conf +new file mode 100644 +index 0000000..ad71473 +--- /dev/null ++++ b/test/data/valid-config-files/check-1.conf +@@ -0,0 +1,9 @@ ++<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" ++ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> ++<busconfig> ++ <user>mybususer</user> ++ <listen>unix:path=/foo/bar</listen> ++ <policy context="default"> ++ <check privilege="foo" send_destination="*"/> ++ </policy> ++</busconfig> +diff --git a/test/data/valid-config-files/debug-check-some.conf.in b/test/data/valid-config-files/debug-check-some.conf.in +new file mode 100644 +index 0000000..47ee854 +--- /dev/null ++++ b/test/data/valid-config-files/debug-check-some.conf.in +@@ -0,0 +1,18 @@ ++<!-- Bus that listens on a debug pipe and doesn't create any restrictions --> ++ ++<!DOCTYPE busconfig PUBLIC "-//freedesktop//DTD D-BUS Bus Configuration 1.0//EN" ++ "http://www.freedesktop.org/standards/dbus/1.0/busconfig.dtd"> ++<busconfig> ++ <listen>debug-pipe:name=test-server</listen> ++ <listen>@TEST_LISTEN@</listen> ++ <servicedir>@DBUS_TEST_DATA@/valid-service-files</servicedir> ++ <policy context="default"> ++ <allow send_interface="*"/> ++ <allow receive_interface="*"/> ++ <allow own="*"/> ++ <allow user="*"/> ++ ++ <deny send_interface="org.freedesktop.TestSuite" send_member="Echo"/> ++ <check privilege="foo" send_interface="org.freedesktop.TestSuite" send_member="Echo"/> ++ </policy> ++</busconfig> +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0002-Disable-message-dispatching-when-send-rule-result-is.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0002-Disable-message-dispatching-when-send-rule-result-is.patch new file mode 100644 index 000000000..bac8cf97f --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0002-Disable-message-dispatching-when-send-rule-result-is.patch @@ -0,0 +1,967 @@ +From c2f4ba585c777b731df6b6b8a165b6cc4dc5d639 Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Fri, 28 Nov 2014 12:07:39 +0100 +Subject: [PATCH 2/8] Disable message dispatching when send rule result is not + known +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When unicast message is sent to addressed recipient and policy result +is not available message dispatch from the sender is disabled. +This also means that any further messages from the given connection are +put into the incoming queue without being processed. If response is received +message dispatching is resumed. This time answer is attached to the message +which is now processed synchronously. +Receive rule result unavailability is not yet handled - such messages are +rejected. Also, if message is sent to non-addressed recipient and policy result +is unknown, message is silently dropped. + +Cherry-picked from b1b87ad9f20b2052c28431b48e81073078a745ce +by Jose Bollo. + +Updated for dbus 1.10.20 by Scott Murray and José Bollo + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +Signed-off-by: Scott Murray <scott.murray@konsulko.com> +--- + bus/activation.c | 76 +++++++++++-- + bus/check.c | 109 +++++++++++++++++-- + bus/check.h | 10 ++ + bus/cynara.c | 1 - + bus/dispatch.c | 184 ++++++++++++++++++++++++++++---- + bus/dispatch.h | 2 +- + bus/driver.c | 12 ++- + dbus/dbus-connection-internal.h | 15 +++ + dbus/dbus-connection.c | 125 +++++++++++++++++++++- + dbus/dbus-list.c | 29 +++++ + dbus/dbus-list.h | 3 + + dbus/dbus-shared.h | 3 +- + 12 files changed, 528 insertions(+), 41 deletions(-) + +diff --git a/bus/activation.c b/bus/activation.c +index f9c6c62..8301b59 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -32,6 +32,7 @@ + #include "services.h" + #include "test.h" + #include "utils.h" ++#include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-internals.h> + #include <dbus/dbus-hash.h> + #include <dbus/dbus-list.h> +@@ -94,6 +95,8 @@ struct BusPendingActivationEntry + DBusConnection *connection; + + dbus_bool_t auto_activation; ++ ++ dbus_bool_t is_put_back; + }; + + typedef struct +@@ -1241,20 +1244,23 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation + BusPendingActivationEntry *entry = link->data; + DBusList *next = _dbus_list_get_next_link (&pending_activation->entries, link); + +- if (entry->auto_activation && (entry->connection == NULL || dbus_connection_get_is_connected (entry->connection))) ++ if (entry->auto_activation && !entry->is_put_back && ++ (entry->connection == NULL || dbus_connection_get_is_connected (entry->connection))) + { + DBusConnection *addressed_recipient; + DBusError error; ++ BusResult res; + + dbus_error_init (&error); + + addressed_recipient = bus_service_get_primary_owners_connection (service); + + /* Resume dispatching where we left off in bus_dispatch() */ +- if (!bus_dispatch_matches (transaction, +- entry->connection, +- addressed_recipient, +- entry->activation_message, &error)) ++ res = bus_dispatch_matches (transaction, ++ entry->connection, ++ addressed_recipient, ++ entry->activation_message, &error); ++ if (res == BUS_RESULT_FALSE) + { + /* If permission is denied, we just want to return the error + * to the original method invoker; in particular, we don't +@@ -1266,11 +1272,44 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation + bus_connection_send_oom_error (entry->connection, + entry->activation_message); + } +- + dbus_error_free (&error); + link = next; + continue; + } ++ else if (res == BUS_RESULT_LATER) ++ { ++ DBusList *putback_message_link = link; ++ DBusMessage *last_inserted_message = NULL; ++ ++ /* NULL entry->connection implies sending pending ActivationRequest message to systemd */ ++ if (entry->connection == NULL) ++ { ++ _dbus_assert_not_reached ("bus_dispatch_matches returned BUS_RESULT_LATER unexpectedly when sender is NULL"); ++ link = next; ++ continue; ++ } ++ ++ /** ++ * Getting here means that policy check result is not yet available and dispatching ++ * messages from entry->connection has been disabled. ++ * Let's put back all messages for the given connection in the incoming queue and mark ++ * this entry as put back so they are not handled twice. ++ */ ++ while (putback_message_link != NULL) ++ { ++ BusPendingActivationEntry *putback_message = putback_message_link->data; ++ if (putback_message->connection == entry->connection) ++ { ++ if (!_dbus_connection_putback_message (putback_message->connection, last_inserted_message, ++ putback_message->activation_message, &error)) ++ goto error; ++ last_inserted_message = putback_message->activation_message; ++ putback_message->is_put_back = TRUE; ++ } ++ ++ putback_message_link = _dbus_list_get_next_link(&pending_activation->entries, putback_message_link); ++ } ++ } + } + + link = next; +@@ -1287,6 +1326,19 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation + return TRUE; + + error: ++ /* remove all messages that have been put to connections' incoming queues */ ++ link = _dbus_list_get_first_link (&pending_activation->entries); ++ while (link != NULL) ++ { ++ BusPendingActivationEntry *entry = link->data; ++ if (entry->is_put_back) ++ { ++ _dbus_connection_remove_message(entry->connection, entry->activation_message); ++ entry->is_put_back = FALSE; ++ } ++ link = _dbus_list_get_next_link(&pending_activation->entries, link); ++ } ++ + return FALSE; + } + +@@ -2079,6 +2131,7 @@ bus_activation_activate_service (BusActivation *activation, + + if (service != NULL) + { ++ BusResult res; + bus_context_log (activation->context, + DBUS_SYSTEM_LOG_INFO, "Activating via systemd: service name='%s' unit='%s' requested by '%s' (%s)", + service_name, +@@ -2086,8 +2139,17 @@ bus_activation_activate_service (BusActivation *activation, + bus_connection_get_name (connection), + bus_connection_get_loginfo (connection)); + /* Wonderful, systemd is connected, let's just send the msg */ +- retval = bus_dispatch_matches (activation_transaction, NULL, ++ res = bus_dispatch_matches (activation_transaction, NULL, + systemd, message, error); ++ ++ if (res == BUS_RESULT_TRUE) ++ retval = TRUE; ++ else ++ { ++ retval = FALSE; ++ if (res == BUS_RESULT_LATER) ++ _dbus_verbose("Unexpectedly need time to check message from bus driver to systemd - dropping the message.\n"); ++ } + } + else + { +diff --git a/bus/check.c b/bus/check.c +index 5b72d31..4b8a699 100644 +--- a/bus/check.c ++++ b/bus/check.c +@@ -55,6 +55,8 @@ typedef struct BusDeferredMessage + BusCheckResponseFunc response_callback; + } BusDeferredMessage; + ++static dbus_int32_t deferred_message_data_slot = -1; ++ + BusCheck * + bus_check_new (BusContext *context, DBusError *error) + { +@@ -67,11 +69,19 @@ bus_check_new (BusContext *context, DBusError *error) + return NULL; + } + ++ if (!dbus_message_allocate_data_slot(&deferred_message_data_slot)) ++ { ++ dbus_free(check); ++ BUS_SET_OOM(error); ++ return NULL; ++ } ++ + check->refcount = 1; + check->context = context; + check->cynara = bus_cynara_new(check, error); + if (dbus_error_is_set(error)) + { ++ dbus_message_free_data_slot(&deferred_message_data_slot); + dbus_free(check); + return NULL; + } +@@ -98,6 +108,7 @@ bus_check_unref (BusCheck *check) + if (check->refcount == 0) + { + bus_cynara_unref(check->cynara); ++ dbus_message_free_data_slot(&deferred_message_data_slot); + dbus_free(check); + } + } +@@ -114,6 +125,45 @@ bus_check_get_cynara (BusCheck *check) + return check->cynara; + } + ++static void ++bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message, ++ BusResult result) ++{ ++ _dbus_verbose("bus_check_enable_dispatch_callback called deferred_message=%p\n", deferred_message); ++ ++ deferred_message->response = result; ++ _dbus_connection_enable_dispatch(deferred_message->sender); ++} ++ ++static void ++deferred_message_free_function(void *data) ++{ ++ BusDeferredMessage *deferred_message = (BusDeferredMessage *)data; ++ bus_deferred_message_unref(deferred_message); ++} ++ ++void ++bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message) ++{ ++ _dbus_assert(deferred_message != NULL); ++ _dbus_assert(deferred_message->sender != NULL); ++ ++ if (dbus_message_get_data(deferred_message->message, deferred_message_data_slot) == NULL) ++ { ++ if (dbus_message_set_data(deferred_message->message, deferred_message_data_slot, deferred_message, ++ deferred_message_free_function)) ++ bus_deferred_message_ref(deferred_message); ++ } ++ ++ _dbus_connection_disable_dispatch(deferred_message->sender); ++ deferred_message->response_callback = bus_check_enable_dispatch_callback; ++} ++ ++#ifdef DBUS_ENABLE_EMBEDDED_TESTS ++BusResult (*bus_check_test_override) (DBusConnection *connection, ++ const char *privilege); ++#endif ++ + BusResult + bus_check_privilege (BusCheck *check, + DBusMessage *message, +@@ -124,6 +174,7 @@ bus_check_privilege (BusCheck *check, + BusDeferredMessageStatus check_type, + BusDeferredMessage **deferred_message) + { ++ BusDeferredMessage *previous_deferred_message; + BusResult result = BUS_RESULT_FALSE; + #ifdef DBUS_ENABLE_CYNARA + BusCynara *cynara; +@@ -137,16 +188,54 @@ bus_check_privilege (BusCheck *check, + return BUS_RESULT_FALSE; + } + +- /* ask policy checkers */ +-#ifdef DBUS_ENABLE_CYNARA +- cynara = bus_check_get_cynara(check); +- result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, +- proposed_recipient, privilege, check_type, deferred_message); ++#ifdef DBUS_ENABLE_EMBEDDED_TESTS ++ if (bus_check_test_override) ++ return bus_check_test_override (connection, privilege); + #endif + +- if (result == BUS_RESULT_LATER && deferred_message != NULL) ++ previous_deferred_message = dbus_message_get_data(message, deferred_message_data_slot); ++ /* check if message blocked at sender's queue is being processed */ ++ if (previous_deferred_message != NULL) ++ { ++ if ((check_type & BUS_DEFERRED_MESSAGE_CHECK_SEND) && ++ !(previous_deferred_message->status & BUS_DEFERRED_MESSAGE_CHECK_SEND)) ++ { ++ /** ++ * Message has been deferred due to receive or own rule which means that sending this message ++ * is allowed - it must have been checked previously. ++ * This might happen when client calls RequestName method which depending on security ++ * policy might result in both "can_send" and "can_own" Cynara checks. ++ */ ++ result = BUS_RESULT_TRUE; ++ } ++ else ++ { ++ result = previous_deferred_message->response; ++ if (result == BUS_RESULT_LATER) ++ { ++ /* result is still not known - reuse deferred message object */ ++ if (deferred_message != NULL) ++ *deferred_message = previous_deferred_message; ++ } ++ else ++ { ++ /* result is available - we can remove deferred message from the processed message */ ++ dbus_message_set_data(message, deferred_message_data_slot, NULL, NULL); ++ } ++ } ++ } ++ else + { +- (*deferred_message)->status |= check_type; ++ /* ask policy checkers */ ++#ifdef DBUS_ENABLE_CYNARA ++ cynara = bus_check_get_cynara(check); ++ result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, ++ proposed_recipient, privilege, check_type, deferred_message); ++#endif ++ if (result == BUS_RESULT_LATER && deferred_message != NULL) ++ { ++ (*deferred_message)->status |= check_type; ++ } + } + return result; + } +@@ -206,6 +295,12 @@ bus_deferred_message_unref (BusDeferredMessage *deferred_message) + } + } + ++BusDeferredMessageStatus ++bus_deferred_message_get_status (BusDeferredMessage *deferred_message) ++{ ++ return deferred_message->status; ++} ++ + void + bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + BusResult result) +diff --git a/bus/check.h b/bus/check.h +index c3fcaf9..d177549 100644 +--- a/bus/check.h ++++ b/bus/check.h +@@ -55,6 +55,7 @@ BusResult bus_check_privilege (BusCheck *check, + BusDeferredMessageStatus check_type, + BusDeferredMessage **deferred_message); + ++ + BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, + DBusConnection *sender, + DBusConnection *addressed_recipient, +@@ -65,4 +66,13 @@ BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage + void bus_deferred_message_unref (BusDeferredMessage *deferred_message); + void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + BusResult result); ++void bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message); ++ ++BusDeferredMessageStatus bus_deferred_message_get_status (BusDeferredMessage *deferred_message); ++ ++#ifdef DBUS_ENABLE_EMBEDDED_TESTS ++extern BusResult (*bus_check_test_override) (DBusConnection *connection, ++ const char *privilege); ++#endif ++ + #endif /* BUS_CHECK_H */ +diff --git a/bus/cynara.c b/bus/cynara.c +index 57a4c45..77aed62 100644 +--- a/bus/cynara.c ++++ b/bus/cynara.c +@@ -36,7 +36,6 @@ + #include <cynara-client-async.h> + #endif + +- + #ifdef DBUS_ENABLE_CYNARA + typedef struct BusCynara + { +diff --git a/bus/dispatch.c b/bus/dispatch.c +index d3867f7..50a22a3 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -35,6 +35,7 @@ + #include "signals.h" + #include "test.h" + #include <dbus/dbus-internals.h> ++#include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-misc.h> + #include <string.h> + +@@ -122,7 +123,7 @@ send_one_message (DBusConnection *connection, + return TRUE; + } + +-dbus_bool_t ++BusResult + bus_dispatch_matches (BusTransaction *transaction, + DBusConnection *sender, + DBusConnection *addressed_recipient, +@@ -158,13 +159,29 @@ bus_dispatch_matches (BusTransaction *transaction, + message, NULL, error, + &deferred_message); + if (res == BUS_RESULT_FALSE) +- return FALSE; ++ return BUS_RESULT_FALSE; + else if (res == BUS_RESULT_LATER) + { +- dbus_set_error (error, +- DBUS_ERROR_ACCESS_DENIED, +- "Rejecting message because time is needed to check security policy"); +- return FALSE; ++ BusDeferredMessageStatus status; ++ status = bus_deferred_message_get_status(deferred_message); ++ ++ if (status & BUS_DEFERRED_MESSAGE_CHECK_SEND) ++ { ++ /* send rule result not available - disable dispatching messages from the sender */ ++ bus_deferred_message_disable_sender(deferred_message); ++ return BUS_RESULT_LATER; ++ } ++ else if (status & BUS_DEFERRED_MESSAGE_CHECK_RECEIVE) ++ { ++ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, ++ "Rejecting message because time is needed to check security policy"); ++ return BUS_RESULT_FALSE; ++ } ++ else ++ { ++ _dbus_verbose("deferred message has no status field set to send or receive unexpectedly\n"); ++ return BUS_RESULT_FALSE; ++ } + } + + if (dbus_message_contains_unix_fds (message) && +@@ -175,14 +192,14 @@ bus_dispatch_matches (BusTransaction *transaction, + DBUS_ERROR_NOT_SUPPORTED, + "Tried to send message with Unix file descriptors" + "to a client that doesn't support that."); +- return FALSE; +- } ++ return BUS_RESULT_FALSE; ++ } + + /* Dispatch the message */ + if (!bus_transaction_send (transaction, addressed_recipient, message)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + } + +@@ -197,7 +214,7 @@ bus_dispatch_matches (BusTransaction *transaction, + &recipients)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + link = _dbus_list_get_first_link (&recipients); +@@ -219,10 +236,10 @@ bus_dispatch_matches (BusTransaction *transaction, + if (dbus_error_is_set (&tmp_error)) + { + dbus_move_error (&tmp_error, error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + else +- return TRUE; ++ return BUS_RESULT_TRUE; + } + + static DBusHandlerResult +@@ -409,10 +426,12 @@ bus_dispatch (DBusConnection *connection, + } + else if (res == BUS_RESULT_LATER) + { +- dbus_set_error (&error, +- DBUS_ERROR_ACCESS_DENIED, +- "Rejecting message because time is needed to check security policy"); +- _dbus_verbose ("Security policy needs time to check policy. Dropping message\n"); ++ /* Disable dispatching messages from the sender, ++ * roll back and dispatch the message once the policy result is available */ ++ bus_deferred_message_disable_sender(deferred_message); ++ bus_transaction_cancel_and_free (transaction); ++ transaction = NULL; ++ result = DBUS_HANDLER_RESULT_LATER; + goto out; + } + +@@ -514,8 +533,14 @@ bus_dispatch (DBusConnection *connection, + * addressed_recipient == NULL), and match it against other connections' + * match rules. + */ +- if (!bus_dispatch_matches (transaction, connection, addressed_recipient, message, &error)) +- goto out; ++ if (BUS_RESULT_LATER == bus_dispatch_matches (transaction, connection, addressed_recipient, ++ message, &error)) ++ { ++ /* Roll back and dispatch the message once the policy result is available */ ++ bus_transaction_cancel_and_free (transaction); ++ transaction = NULL; ++ result = DBUS_HANDLER_RESULT_LATER; ++ } + + out: + if (dbus_error_is_set (&error)) +@@ -5060,9 +5085,132 @@ bus_dispatch_test_conf_fail (const DBusString *test_data_dir, + } + #endif + ++typedef struct { ++ DBusTimeout *timeout; ++ DBusConnection *connection; ++ dbus_bool_t timedout; ++ int check_counter; ++} BusTestCheckData; ++ ++static BusTestCheckData *cdata; ++ ++static dbus_bool_t ++bus_dispatch_test_check_timeout (void *data) ++{ ++ _dbus_verbose ("timeout triggered - pretend that privilege check result is available\n"); ++ ++ /* should only happen once during the test */ ++ _dbus_assert (!cdata->timedout); ++ cdata->timedout = TRUE; ++ _dbus_connection_enable_dispatch (cdata->connection); ++ ++ /* don't call this again */ ++ _dbus_loop_remove_timeout (bus_connection_get_loop (cdata->connection), ++ cdata->timeout); ++ dbus_connection_unref (cdata->connection); ++ cdata->connection = NULL; ++ return TRUE; ++} ++ ++static BusResult ++bus_dispatch_test_check_override (DBusConnection *connection, ++ const char *privilege) ++{ ++ _dbus_verbose ("overriding privilege check %s #%d\n", privilege, cdata->check_counter); ++ cdata->check_counter++; ++ if (!cdata->timedout) ++ { ++ dbus_bool_t added; ++ ++ /* Should be the first privilege check for the "Echo" method. */ ++ _dbus_assert (cdata->check_counter == 1); ++ cdata->timeout = _dbus_timeout_new (1, bus_dispatch_test_check_timeout, ++ NULL, NULL); ++ _dbus_assert (cdata->timeout); ++ added = _dbus_loop_add_timeout (bus_connection_get_loop (connection), ++ cdata->timeout); ++ _dbus_assert (added); ++ cdata->connection = connection; ++ dbus_connection_ref (connection); ++ _dbus_connection_disable_dispatch (connection); ++ return BUS_RESULT_LATER; ++ } ++ else ++ { ++ /* Should only be checked one more time, and this time succeeds. */ ++ _dbus_assert (cdata->check_counter == 2); ++ return BUS_RESULT_TRUE; ++ } ++} ++ ++static dbus_bool_t ++bus_dispatch_test_check (const DBusString *test_data_dir) ++{ ++ const char *filename = "valid-config-files/debug-check-some.conf"; ++ BusContext *context; ++ DBusConnection *foo; ++ DBusError error; ++ dbus_bool_t result = TRUE; ++ BusTestCheckData data; ++ ++ /* save the config name for the activation helper */ ++ if (!setenv_TEST_LAUNCH_HELPER_CONFIG (test_data_dir, filename)) ++ _dbus_assert_not_reached ("no memory setting TEST_LAUNCH_HELPER_CONFIG"); ++ ++ dbus_error_init (&error); ++ ++ context = bus_context_new_test (test_data_dir, filename); ++ if (context == NULL) ++ return FALSE; ++ ++ foo = dbus_connection_open_private (TEST_DEBUG_PIPE, &error); ++ if (foo == NULL) ++ _dbus_assert_not_reached ("could not alloc connection"); ++ ++ if (!bus_setup_debug_client (foo)) ++ _dbus_assert_not_reached ("could not set up connection"); ++ ++ spin_connection_until_authenticated (context, foo); ++ ++ if (!check_hello_message (context, foo)) ++ _dbus_assert_not_reached ("hello message failed"); ++ ++ if (!check_double_hello_message (context, foo)) ++ _dbus_assert_not_reached ("double hello message failed"); ++ ++ if (!check_add_match (context, foo, "")) ++ _dbus_assert_not_reached ("AddMatch message failed"); ++ ++ /* ++ * Cause bus_check_send_privilege() to return BUS_RESULT_LATER in the ++ * first call, then BUS_RESULT_TRUE. ++ */ ++ cdata = &data; ++ memset (cdata, 0, sizeof(*cdata)); ++ bus_check_test_override = bus_dispatch_test_check_override; ++ ++ result = check_existent_service_auto_start (context, foo); ++ ++ _dbus_assert (cdata->check_counter == 2); ++ _dbus_assert (cdata->timedout); ++ _dbus_assert (cdata->timeout); ++ _dbus_assert (!cdata->connection); ++ _dbus_timeout_unref (cdata->timeout); ++ ++ kill_client_connection_unchecked (foo); ++ ++ bus_context_unref (context); ++ ++ return result; ++} ++ + dbus_bool_t + bus_dispatch_test (const DBusString *test_data_dir) + { ++ _dbus_verbose ("<check> tests\n"); ++ if (!bus_dispatch_test_check (test_data_dir)) ++ return FALSE; ++ + /* run normal activation tests */ + _dbus_verbose ("Normal activation tests\n"); + if (!bus_dispatch_test_conf (test_data_dir, +diff --git a/bus/dispatch.h b/bus/dispatch.h +index fb5ba7a..afba6a2 100644 +--- a/bus/dispatch.h ++++ b/bus/dispatch.h +@@ -29,7 +29,7 @@ + + dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection); + void bus_dispatch_remove_connection (DBusConnection *connection); +-dbus_bool_t bus_dispatch_matches (BusTransaction *transaction, ++BusResult bus_dispatch_matches (BusTransaction *transaction, + DBusConnection *sender, + DBusConnection *recipient, + DBusMessage *message, +diff --git a/bus/driver.c b/bus/driver.c +index cd0a714..f414f64 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -218,6 +218,7 @@ bus_driver_send_service_owner_changed (const char *service_name, + { + DBusMessage *message; + dbus_bool_t retval; ++ BusResult res; + const char *null_service; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -253,7 +254,16 @@ bus_driver_send_service_owner_changed (const char *service_name, + if (!bus_transaction_capture (transaction, NULL, NULL, message)) + goto oom; + +- retval = bus_dispatch_matches (transaction, NULL, NULL, message, error); ++ res = bus_dispatch_matches (transaction, NULL, NULL, message, error); ++ if (res == BUS_RESULT_TRUE) ++ retval = TRUE; ++ else ++ { ++ retval = FALSE; ++ if (res == BUS_RESULT_LATER) ++ /* should never happen */ ++ _dbus_assert_not_reached ("bus_dispatch_matches returned BUS_RESULT_LATER unexpectedly"); ++ } + dbus_message_unref (message); + + return retval; +diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h +index 4835732..94b1c95 100644 +--- a/dbus/dbus-connection-internal.h ++++ b/dbus/dbus-connection-internal.h +@@ -118,6 +118,21 @@ DBUS_PRIVATE_EXPORT + dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection, + char **label_p); + ++DBUS_PRIVATE_EXPORT ++void _dbus_connection_enable_dispatch (DBusConnection *connection); ++DBUS_PRIVATE_EXPORT ++void _dbus_connection_disable_dispatch (DBusConnection *connection); ++ ++DBUS_PRIVATE_EXPORT ++dbus_bool_t _dbus_connection_putback_message (DBusConnection *connection, ++ DBusMessage *after_message, ++ DBusMessage *message, ++ DBusError *error); ++ ++DBUS_PRIVATE_EXPORT ++dbus_bool_t _dbus_connection_remove_message (DBusConnection *connection, ++ DBusMessage *message); ++ + /* if DBUS_ENABLE_STATS */ + DBUS_PRIVATE_EXPORT + void _dbus_connection_get_stats (DBusConnection *connection, +diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c +index c525b6d..958968c 100644 +--- a/dbus/dbus-connection.c ++++ b/dbus/dbus-connection.c +@@ -311,7 +311,8 @@ struct DBusConnection + */ + dbus_bool_t dispatch_acquired; /**< Someone has dispatch path (can drain incoming queue) */ + dbus_bool_t io_path_acquired; /**< Someone has transport io path (can use the transport to read/write messages) */ +- ++ ++ unsigned int dispatch_disabled : 1; /**< if true, then dispatching incoming messages is stopped until enabled again */ + unsigned int shareable : 1; /**< #TRUE if libdbus owns a reference to the connection and can return it from dbus_connection_open() more than once */ + + unsigned int exit_on_disconnect : 1; /**< If #TRUE, exit after handling disconnect signal */ +@@ -439,6 +440,39 @@ _dbus_connection_wakeup_mainloop (DBusConnection *connection) + (*connection->wakeup_main_function) (connection->wakeup_main_data); + } + ++static void ++_dbus_connection_set_dispatch(DBusConnection *connection, ++ dbus_bool_t disabled) ++{ ++ CONNECTION_LOCK (connection); ++ if (connection->dispatch_disabled != disabled) ++ { ++ DBusDispatchStatus status; ++ ++ connection->dispatch_disabled = disabled; ++ status = _dbus_connection_get_dispatch_status_unlocked (connection); ++ _dbus_connection_update_dispatch_status_and_unlock (connection, status); ++ } ++ else ++ { ++ CONNECTION_UNLOCK (connection); ++ } ++} ++ ++ ++void ++_dbus_connection_enable_dispatch (DBusConnection *connection) ++{ ++ _dbus_connection_set_dispatch (connection, FALSE); ++} ++ ++void ++ _dbus_connection_disable_dispatch (DBusConnection *connection) ++{ ++ _dbus_connection_set_dispatch (connection, TRUE); ++} ++ ++ + #ifdef DBUS_ENABLE_EMBEDDED_TESTS + /** + * Gets the locks so we can examine them +@@ -4069,6 +4103,82 @@ _dbus_connection_putback_message_link_unlocked (DBusConnection *connection, + "_dbus_connection_putback_message_link_unlocked"); + } + ++dbus_bool_t ++_dbus_connection_putback_message (DBusConnection *connection, ++ DBusMessage *after_message, ++ DBusMessage *message, ++ DBusError *error) ++{ ++ DBusDispatchStatus status; ++ DBusList *message_link = _dbus_list_alloc_link (message); ++ DBusList *after_link; ++ if (message_link == NULL) ++ { ++ _DBUS_SET_OOM (error); ++ return FALSE; ++ } ++ dbus_message_ref (message); ++ ++ CONNECTION_LOCK (connection); ++ _dbus_connection_acquire_dispatch (connection); ++ HAVE_LOCK_CHECK (connection); ++ ++ after_link = _dbus_list_find_first(&connection->incoming_messages, after_message); ++ _dbus_list_insert_after_link (&connection->incoming_messages, after_link, message_link); ++ connection->n_incoming += 1; ++ ++ _dbus_verbose ("Message %p (%s %s %s '%s') put back into queue %p, %d incoming\n", ++ message_link->data, ++ dbus_message_type_to_string (dbus_message_get_type (message_link->data)), ++ dbus_message_get_interface (message_link->data) ? ++ dbus_message_get_interface (message_link->data) : ++ "no interface", ++ dbus_message_get_member (message_link->data) ? ++ dbus_message_get_member (message_link->data) : ++ "no member", ++ dbus_message_get_signature (message_link->data), ++ connection, connection->n_incoming); ++ ++ _dbus_message_trace_ref (message_link->data, -1, -1, ++ "_dbus_connection_putback_message"); ++ ++ _dbus_connection_release_dispatch (connection); ++ ++ status = _dbus_connection_get_dispatch_status_unlocked (connection); ++ _dbus_connection_update_dispatch_status_and_unlock (connection, status); ++ ++ return TRUE; ++} ++ ++dbus_bool_t ++_dbus_connection_remove_message (DBusConnection *connection, ++ DBusMessage *message) ++{ ++ DBusDispatchStatus status; ++ dbus_bool_t removed; ++ ++ CONNECTION_LOCK (connection); ++ _dbus_connection_acquire_dispatch (connection); ++ HAVE_LOCK_CHECK (connection); ++ ++ removed = _dbus_list_remove(&connection->incoming_messages, message); ++ ++ if (removed) ++ { ++ connection->n_incoming -= 1; ++ dbus_message_unref(message); ++ _dbus_verbose ("Message %p removed from incoming queue\n", message); ++ } ++ else ++ _dbus_verbose ("Message %p not found in the incoming queue\n", message); ++ ++ _dbus_connection_release_dispatch (connection); ++ ++ status = _dbus_connection_get_dispatch_status_unlocked (connection); ++ _dbus_connection_update_dispatch_status_and_unlock (connection, status); ++ return removed; ++} ++ + /** + * Returns the first-received message from the incoming message queue, + * removing it from the queue. The caller owns a reference to the +@@ -4252,8 +4362,9 @@ static DBusDispatchStatus + _dbus_connection_get_dispatch_status_unlocked (DBusConnection *connection) + { + HAVE_LOCK_CHECK (connection); +- +- if (connection->n_incoming > 0) ++ if (connection->dispatch_disabled && _dbus_connection_get_is_connected_unlocked(connection)) ++ return DBUS_DISPATCH_COMPLETE; ++ else if (connection->n_incoming > 0) + return DBUS_DISPATCH_DATA_REMAINS; + else if (!_dbus_transport_queue_messages (connection->transport)) + return DBUS_DISPATCH_NEED_MEMORY; +@@ -4716,6 +4827,8 @@ dbus_connection_dispatch (DBusConnection *connection) + + CONNECTION_LOCK (connection); + ++ if (result == DBUS_HANDLER_RESULT_LATER) ++ goto out; + if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) + { + _dbus_verbose ("No memory\n"); +@@ -4838,9 +4951,11 @@ dbus_connection_dispatch (DBusConnection *connection) + connection); + + out: +- if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) ++ if (result == DBUS_HANDLER_RESULT_LATER || ++ result == DBUS_HANDLER_RESULT_NEED_MEMORY) + { +- _dbus_verbose ("out of memory\n"); ++ if (result == DBUS_HANDLER_RESULT_NEED_MEMORY) ++ _dbus_verbose ("out of memory\n"); + + /* Put message back, and we'll start over. + * Yes this means handlers must be idempotent if they +diff --git a/dbus/dbus-list.c b/dbus/dbus-list.c +index 8e713c0..32ea871 100644 +--- a/dbus/dbus-list.c ++++ b/dbus/dbus-list.c +@@ -458,6 +458,35 @@ _dbus_list_remove_last (DBusList **list, + return FALSE; + } + ++/** ++ * Finds a value in the list. Returns the first link ++ * with value equal to the given data pointer. ++ * This is a linear-time operation. ++ * Returns #NULL if no value found that matches. ++ * ++ * @param list address of the list head. ++ * @param data the value to find. ++ * @returns the link if found ++ */ ++DBusList* ++_dbus_list_find_first (DBusList **list, ++ void *data) ++{ ++ DBusList *link; ++ ++ link = _dbus_list_get_first_link (list); ++ ++ while (link != NULL) ++ { ++ if (link->data == data) ++ return link; ++ ++ link = _dbus_list_get_next_link (list, link); ++ } ++ ++ return NULL; ++} ++ + /** + * Finds a value in the list. Returns the last link + * with value equal to the given data pointer. +diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h +index 9350a0d..fee9f1b 100644 +--- a/dbus/dbus-list.h ++++ b/dbus/dbus-list.h +@@ -68,6 +68,9 @@ DBUS_PRIVATE_EXPORT + void _dbus_list_remove_link (DBusList **list, + DBusList *link); + DBUS_PRIVATE_EXPORT ++DBusList* _dbus_list_find_first (DBusList **list, ++ void *data); ++DBUS_PRIVATE_EXPORT + DBusList* _dbus_list_find_last (DBusList **list, + void *data); + DBUS_PRIVATE_EXPORT +diff --git a/dbus/dbus-shared.h b/dbus/dbus-shared.h +index 7ab9103..e5bfbed 100644 +--- a/dbus/dbus-shared.h ++++ b/dbus/dbus-shared.h +@@ -67,7 +67,8 @@ typedef enum + { + DBUS_HANDLER_RESULT_HANDLED, /**< Message has had its effect - no need to run more handlers. */ + DBUS_HANDLER_RESULT_NOT_YET_HANDLED, /**< Message has not had any effect - see if other handlers want it. */ +- DBUS_HANDLER_RESULT_NEED_MEMORY /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */ ++ DBUS_HANDLER_RESULT_NEED_MEMORY, /**< Need more memory in order to return #DBUS_HANDLER_RESULT_HANDLED or #DBUS_HANDLER_RESULT_NOT_YET_HANDLED. Please try again later with more memory. */ ++ DBUS_HANDLER_RESULT_LATER /**< Message dispatch deferred due to pending policy check */ + } DBusHandlerResult; + + /* Bus names */ +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0003-Handle-unavailability-of-policy-results-for-broadcas.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0003-Handle-unavailability-of-policy-results-for-broadcas.patch new file mode 100644 index 000000000..7d89a7496 --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0003-Handle-unavailability-of-policy-results-for-broadcas.patch @@ -0,0 +1,1095 @@ +From 9d39aa9dd55680529d721a0389ce9ef579bb669a Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Fri, 28 Nov 2014 12:39:33 +0100 +Subject: [PATCH 3/8] Handle unavailability of policy results for broadcasts + and receive rules +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +When message is sent to the addressed recipient and receive rule +result is unavailable we don't want to block the sender +as it most likely will be the privileged service, so instead we queue +it at the recipient. Any further messages sent to it will be queued to +maintain message order. Once the answer from Cynara arrives messages are +dispatched from the recipient queue. In such case full dispatch is +performed - messages are sent to addressed recipient and other +interested connections. +Messages sent to non-addressed recipients (eavesdroppers or broadcast +message recipients) are handled in a similar way. The difference is +that it is not full dispatch meaning message is sent to a single recipient. + +Cherry picked from 1e231194610892dd4360224998d91336097b05a1 by Jose Bollo + +Updated for dbus 1.10.20 by Scott Murray and José Bollo + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +Signed-off-by: Scott Murray <scott.murray@konsulko.com> +--- + bus/activation.c | 4 +- + bus/bus.c | 50 ++++++-- + bus/bus.h | 19 +++ + bus/check.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++ + bus/check.h | 25 ++++ + bus/connection.c | 168 ++++++++++++++++++++++++-- + bus/connection.h | 19 ++- + bus/dispatch.c | 115 +++++++++++++++--- + bus/dispatch.h | 11 +- + bus/driver.c | 2 +- + bus/policy.c | 6 + + 11 files changed, 683 insertions(+), 43 deletions(-) + +diff --git a/bus/activation.c b/bus/activation.c +index 8301b59..d4b597c 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -1259,7 +1259,7 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation + res = bus_dispatch_matches (transaction, + entry->connection, + addressed_recipient, +- entry->activation_message, &error); ++ entry->activation_message, NULL, &error); + if (res == BUS_RESULT_FALSE) + { + /* If permission is denied, we just want to return the error +@@ -2140,7 +2140,7 @@ bus_activation_activate_service (BusActivation *activation, + bus_connection_get_loginfo (connection)); + /* Wonderful, systemd is connected, let's just send the msg */ + res = bus_dispatch_matches (activation_transaction, NULL, +- systemd, message, error); ++ systemd, message, NULL, error); + + if (res == BUS_RESULT_TRUE) + retval = TRUE; +diff --git a/bus/bus.c b/bus/bus.c +index 6fc45d0..0aa700b 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -1800,17 +1800,9 @@ bus_context_check_security_policy (BusContext *context, + } + + /* See if limits on size have been exceeded */ +- if (proposed_recipient && +- ((dbus_connection_get_outgoing_size (proposed_recipient) > context->limits.max_outgoing_bytes) || +- (dbus_connection_get_outgoing_unix_fds (proposed_recipient) > context->limits.max_outgoing_unix_fds))) +- { +- complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, +- "Rejected: destination has a full message queue", +- 0, message, sender, proposed_recipient, requested_reply, TRUE, NULL, +- error); +- _dbus_verbose ("security policy disallowing message due to full message queue\n"); ++ if (!bus_context_check_recipient_message_limits(context, proposed_recipient, sender, message, ++ requested_reply, error)) + return BUS_RESULT_FALSE; +- } + + /* Record that we will allow a reply here in the future (don't + * bother if the recipient is the bus or this is an eavesdropping +@@ -1869,3 +1861,41 @@ bus_context_check_all_watches (BusContext *context) + _dbus_server_toggle_all_watches (server, enabled); + } + } ++ ++void ++bus_context_complain_about_message (BusContext *context, ++ const char *error_name, ++ const char *complaint, ++ int matched_rules, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *proposed_recipient, ++ dbus_bool_t requested_reply, ++ dbus_bool_t log, ++ const char *privilege, ++ DBusError *error) ++{ ++ complain_about_message(context, error_name, complaint, matched_rules, message, sender, ++ proposed_recipient, requested_reply, log, privilege, error); ++} ++ ++dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context, ++ DBusConnection *recipient, ++ DBusConnection *sender, ++ DBusMessage *message, ++ dbus_bool_t requested_reply, ++ DBusError *error) ++{ ++ if (recipient && ++ ((dbus_connection_get_outgoing_size (recipient) > context->limits.max_outgoing_bytes) || ++ (dbus_connection_get_outgoing_unix_fds (recipient) > context->limits.max_outgoing_unix_fds))) ++ { ++ complain_about_message (context, DBUS_ERROR_LIMITS_EXCEEDED, ++ "Rejected: destination has a full message queue", ++ 0, message, sender, recipient, requested_reply, TRUE, NULL, ++ error); ++ _dbus_verbose ("security policy disallowing message due to full message queue\n"); ++ return FALSE; ++ } ++ return TRUE; ++} +diff --git a/bus/bus.h b/bus/bus.h +index 82c32c8..1b08f7c 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -164,4 +164,23 @@ BusResult bus_context_check_security_policy (BusContext + BusDeferredMessage **deferred_message); + void bus_context_check_all_watches (BusContext *context); + ++dbus_bool_t bus_context_check_recipient_message_limits (BusContext *context, ++ DBusConnection *recipient, ++ DBusConnection *sender, ++ DBusMessage *message, ++ dbus_bool_t requested_reply, ++ DBusError *error); ++void bus_context_complain_about_message (BusContext *context, ++ const char *error_name, ++ const char *complaint, ++ int matched_rules, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *proposed_recipient, ++ dbus_bool_t requested_reply, ++ dbus_bool_t log, ++ const char *privilege, ++ DBusError *error); ++ ++ + #endif /* BUS_BUS_H */ +diff --git a/bus/check.c b/bus/check.c +index 4b8a699..f3d283f 100644 +--- a/bus/check.c ++++ b/bus/check.c +@@ -49,6 +49,9 @@ typedef struct BusDeferredMessage + DBusConnection *sender; + DBusConnection *proposed_recipient; + DBusConnection *addressed_recipient; ++ dbus_bool_t requested_reply; ++ int matched_rules; ++ const char *privilege; + dbus_bool_t full_dispatch; + BusDeferredMessageStatus status; + BusResult response; +@@ -135,6 +138,89 @@ bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message, + _dbus_connection_enable_dispatch(deferred_message->sender); + } + ++static void ++bus_check_queued_message_reply_callback (BusDeferredMessage *deferred_message, ++ BusResult result) ++{ ++ int status; ++ ++ _dbus_verbose("bus_check_queued_message_reply_callback called message=%p\n", deferred_message); ++ ++ if (!bus_connection_is_active(deferred_message->proposed_recipient)) ++ return; ++ ++ status = deferred_message->status; ++ ++ deferred_message->status = 0; /* mark message as not waiting for response */ ++ deferred_message->response = result; ++ ++ /* ++ * If send rule allows us to send message we still need to check receive rules. ++ */ ++ if ((status & BUS_DEFERRED_MESSAGE_CHECK_SEND) && (result == BUS_RESULT_TRUE)) ++ { ++ int toggles; ++ BusContext *context; ++ BusRegistry *registry; ++ BusClientPolicy *recipient_policy; ++ BusDeferredMessage *deferred_message_receive; ++ ++ context = bus_connection_get_context(deferred_message->proposed_recipient); ++ registry = bus_context_get_registry(context); ++ recipient_policy = bus_connection_get_policy(deferred_message->proposed_recipient); ++ ++ deferred_message->response = bus_client_policy_check_can_receive(recipient_policy, registry, ++ deferred_message->requested_reply, deferred_message->sender, ++ deferred_message->addressed_recipient, deferred_message->proposed_recipient, deferred_message->message, ++ &toggles, NULL, &deferred_message_receive); ++ if (deferred_message->response == BUS_RESULT_LATER) ++ { ++ /* replace deferred message associated with send check with the one associated with ++ * receive check */ ++ if (!bus_deferred_message_replace(deferred_message, deferred_message_receive)) ++ { ++ /* failed to replace deferred message (due to oom). Set it to rejected */ ++ deferred_message->response = BUS_RESULT_FALSE; ++ } ++ } ++ } ++ ++ bus_connection_dispatch_deferred(deferred_message->proposed_recipient); ++} ++ ++static void ++queue_deferred_message_cancel_transaction_hook (void *data) ++{ ++ BusDeferredMessage *deferred_message = (BusDeferredMessage *)data; ++ bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message); ++} ++ ++ ++dbus_bool_t ++bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message, ++ BusTransaction *transaction, ++ dbus_bool_t full_dispatch, ++ dbus_bool_t prepend) ++{ ++ _dbus_assert(deferred_message != NULL); ++ _dbus_assert(deferred_message->proposed_recipient != NULL); ++ ++ if (!bus_connection_queue_deferred_message(deferred_message->proposed_recipient, ++ deferred_message, prepend)) ++ return FALSE; ++ ++ if (!bus_transaction_add_cancel_hook(transaction, queue_deferred_message_cancel_transaction_hook, ++ deferred_message, NULL)) ++ { ++ bus_connection_remove_deferred_message(deferred_message->proposed_recipient, deferred_message); ++ return FALSE; ++ } ++ deferred_message->response_callback = bus_check_queued_message_reply_callback; ++ deferred_message->full_dispatch = full_dispatch; ++ ++ return TRUE; ++} ++ + static void + deferred_message_free_function(void *data) + { +@@ -159,6 +245,20 @@ bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message) + deferred_message->response_callback = bus_check_enable_dispatch_callback; + } + ++void ++bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message, ++ dbus_bool_t requested_reply, ++ int matched_rules, ++ const char *privilege) ++{ ++ _dbus_assert(deferred_message != NULL); ++ ++ deferred_message->requested_reply = requested_reply; ++ deferred_message->matched_rules = matched_rules; ++ deferred_message->privilege = privilege; ++} ++ ++ + #ifdef DBUS_ENABLE_EMBEDDED_TESTS + BusResult (*bus_check_test_override) (DBusConnection *connection, + const char *privilege); +@@ -259,6 +359,9 @@ BusDeferredMessage *bus_deferred_message_new (DBusMessage *message, + deferred_message->addressed_recipient = addressed_recipient != NULL ? dbus_connection_ref(addressed_recipient) : NULL; + deferred_message->proposed_recipient = proposed_recipient != NULL ? dbus_connection_ref(proposed_recipient) : NULL; + deferred_message->message = dbus_message_ref(message); ++ deferred_message->requested_reply = FALSE; ++ deferred_message->matched_rules = 0; ++ deferred_message->privilege = NULL; + deferred_message->response = response; + deferred_message->status = 0; + deferred_message->full_dispatch = FALSE; +@@ -295,12 +398,215 @@ bus_deferred_message_unref (BusDeferredMessage *deferred_message) + } + } + ++dbus_bool_t ++bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, DBusError *error) ++{ ++ BusContext *context = bus_connection_get_context(deferred_message->proposed_recipient); ++ ++ return bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient, ++ deferred_message->sender, deferred_message->message, deferred_message->requested_reply, ++ error); ++} ++ ++dbus_bool_t ++bus_deferred_message_expect_method_reply(BusDeferredMessage *deferred_message, BusTransaction *transaction, DBusError *error) ++{ ++ int type = dbus_message_get_type(deferred_message->message); ++ if (type == DBUS_MESSAGE_TYPE_METHOD_CALL && ++ deferred_message->sender && ++ deferred_message->addressed_recipient && ++ deferred_message->addressed_recipient == deferred_message->proposed_recipient && /* not eavesdropping */ ++ !bus_connections_expect_reply (bus_connection_get_connections (deferred_message->sender), ++ transaction, ++ deferred_message->sender, deferred_message->addressed_recipient, ++ deferred_message->message, error)) ++ { ++ _dbus_verbose ("Failed to record reply expectation or problem with the message expecting a reply\n"); ++ return FALSE; ++ } ++ return TRUE; ++} ++ ++void ++bus_deferred_message_create_error(BusDeferredMessage *deferred_message, ++ const char *error_message, DBusError *error) ++{ ++ BusContext *context; ++ _dbus_assert (deferred_message->status == 0 && deferred_message->response == BUS_RESULT_FALSE); ++ ++ if (deferred_message->sender == NULL) ++ return; /* error won't be sent to bus driver anyway */ ++ ++ context = bus_connection_get_context(deferred_message->sender); ++ bus_context_complain_about_message(context, DBUS_ERROR_ACCESS_DENIED, "Rejected message", ++ deferred_message->matched_rules, deferred_message->message, deferred_message->sender, ++ deferred_message->proposed_recipient, deferred_message->requested_reply, FALSE, ++ deferred_message->privilege, error); ++} ++ ++BusResult ++bus_deferred_message_dispatch (BusDeferredMessage *deferred_message) ++{ ++ BusContext *context = bus_connection_get_context (deferred_message->proposed_recipient); ++ BusTransaction *transaction = bus_transaction_new (context); ++ BusResult result = BUS_RESULT_TRUE; ++ DBusError error; ++ ++ if (transaction == NULL) ++ { ++ return BUS_RESULT_FALSE; ++ } ++ ++ dbus_error_init(&error); ++ ++ if (!deferred_message->full_dispatch) ++ { ++ result = deferred_message->response; ++ if (result == BUS_RESULT_TRUE) ++ { ++ if (!bus_context_check_recipient_message_limits(context, deferred_message->proposed_recipient, ++ deferred_message->sender, deferred_message->message, deferred_message->requested_reply, &error)) ++ result = BUS_RESULT_FALSE; ++ } ++ else if (result == BUS_RESULT_LATER) ++ { ++ BusDeferredMessage *deferred_message2; ++ result = bus_context_check_security_policy (context, transaction, ++ deferred_message->sender, ++ deferred_message->addressed_recipient, ++ deferred_message->proposed_recipient, ++ deferred_message->message, NULL, NULL, ++ &deferred_message2); ++ ++ if (result == BUS_RESULT_LATER) ++ { ++ /* prepend at recipient */ ++ if (!bus_deferred_message_queue_at_recipient(deferred_message2, transaction, ++ FALSE, TRUE)) ++ result = BUS_RESULT_FALSE; ++ } ++ } ++ ++ /* silently drop messages on access denial */ ++ if (result == BUS_RESULT_TRUE) ++ { ++ if (!bus_transaction_send (transaction, deferred_message->proposed_recipient, deferred_message->message, TRUE)) ++ result = BUS_RESULT_FALSE; ++ } ++ ++ bus_transaction_execute_and_free(transaction); ++ ++ goto out; ++ } ++ ++ /* do not attempt to send message if sender has disconnected */ ++ if (deferred_message->sender != NULL && !bus_connection_is_active(deferred_message->sender)) ++ { ++ bus_transaction_cancel_and_free(transaction); ++ result = BUS_RESULT_FALSE; ++ goto out; ++ } ++ ++ result = bus_dispatch_matches(transaction, deferred_message->sender, ++ deferred_message->addressed_recipient, deferred_message->message, deferred_message, &error); ++ ++ if (result == BUS_RESULT_LATER) ++ { ++ /* Message deferring was already done in bus_dispatch_matches */ ++ bus_transaction_cancel_and_free(transaction); ++ goto out; ++ } ++ ++ /* this part is a copy & paste from bus_dispatch function. Probably can be moved to a function */ ++ if (dbus_error_is_set (&error)) ++ { ++ if (!dbus_connection_get_is_connected (deferred_message->sender)) ++ { ++ /* If we disconnected it, we won't bother to send it any error ++ * messages. ++ */ ++ _dbus_verbose ("Not sending error to connection we disconnected\n"); ++ } ++ else if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) ++ { ++ bus_connection_send_oom_error (deferred_message->sender, deferred_message->message); ++ ++ /* cancel transaction due to OOM */ ++ if (transaction != NULL) ++ { ++ bus_transaction_cancel_and_free (transaction); ++ transaction = NULL; ++ } ++ } ++ else ++ { ++ /* Try to send the real error, if no mem to do that, send ++ * the OOM error ++ */ ++ _dbus_assert (transaction != NULL); ++ if (!bus_transaction_send_error_reply (transaction, deferred_message->sender, ++ &error, deferred_message->message)) ++ { ++ bus_connection_send_oom_error (deferred_message->sender, deferred_message->message); ++ ++ /* cancel transaction due to OOM */ ++ if (transaction != NULL) ++ { ++ bus_transaction_cancel_and_free (transaction); ++ transaction = NULL; ++ } ++ } ++ } ++ } ++ ++ if (transaction != NULL) ++ { ++ bus_transaction_execute_and_free (transaction); ++ } ++ ++out: ++ dbus_error_free(&error); ++ ++ return result; ++} ++ ++dbus_bool_t ++bus_deferred_message_replace (BusDeferredMessage *old_message, BusDeferredMessage *new_message) ++{ ++ if (bus_connection_replace_deferred_message(old_message->proposed_recipient, ++ old_message, new_message)) ++ { ++ new_message->response_callback = old_message->response_callback; ++ new_message->full_dispatch = old_message->full_dispatch; ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++dbus_bool_t ++bus_deferred_message_waits_for_check(BusDeferredMessage *deferred_message) ++{ ++ return deferred_message->status != 0; ++} ++ ++DBusConnection * ++bus_deferred_message_get_recipient(BusDeferredMessage *deferred_message) ++{ ++ return deferred_message->proposed_recipient; ++} ++ + BusDeferredMessageStatus + bus_deferred_message_get_status (BusDeferredMessage *deferred_message) + { + return deferred_message->status; + } + ++BusResult ++bus_deferred_message_get_response (BusDeferredMessage *deferred_message) ++{ ++ return deferred_message->response; ++} ++ + void + bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + BusResult result) +@@ -310,3 +616,4 @@ bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + deferred_message->response_callback(deferred_message, result); + } + } ++ +diff --git a/bus/check.h b/bus/check.h +index d177549..9c13c18 100644 +--- a/bus/check.h ++++ b/bus/check.h +@@ -64,12 +64,37 @@ BusDeferredMessage *bus_deferred_message_new (DBusMessage *messag + + BusDeferredMessage *bus_deferred_message_ref (BusDeferredMessage *deferred_message); + void bus_deferred_message_unref (BusDeferredMessage *deferred_message); ++BusResult bus_deferred_message_dispatch (BusDeferredMessage *deferred_message); ++dbus_bool_t bus_deferred_message_waits_for_check (BusDeferredMessage *deferred_message); ++DBusConnection *bus_deferred_message_get_recipient (BusDeferredMessage *deferred_message); + void bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + BusResult result); ++dbus_bool_t bus_deferred_message_queue_at_recipient (BusDeferredMessage *deferred_message, ++ BusTransaction *transaction, ++ dbus_bool_t full_dispatch, ++ dbus_bool_t prepend); ++dbus_bool_t bus_deferred_message_replace (BusDeferredMessage *old_message, ++ BusDeferredMessage *new_message); + void bus_deferred_message_disable_sender (BusDeferredMessage *deferred_message); ++BusResult bus_deferred_message_get_response (BusDeferredMessage *deferred_message); + + BusDeferredMessageStatus bus_deferred_message_get_status (BusDeferredMessage *deferred_message); + ++ ++dbus_bool_t bus_deferred_message_expect_method_reply (BusDeferredMessage *deferred_message, ++ BusTransaction *transaction, ++ DBusError *error); ++void bus_deferred_message_create_error (BusDeferredMessage *deferred_message, ++ const char *error_message, ++ DBusError *error); ++void bus_deferred_message_set_policy_check_info (BusDeferredMessage *deferred_message, ++ dbus_bool_t requested_reply, ++ int matched_rules, ++ const char *privilege); ++dbus_bool_t bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, ++ DBusError *error); ++ ++ + #ifdef DBUS_ENABLE_EMBEDDED_TESTS + extern BusResult (*bus_check_test_override) (DBusConnection *connection, + const char *privilege); +diff --git a/bus/connection.c b/bus/connection.c +index b348d42..ee93384 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -31,11 +31,13 @@ + #include "expirelist.h" + #include "selinux.h" + #include "apparmor.h" ++#include "check.h" + #include <dbus/dbus-list.h> + #include <dbus/dbus-hash.h> + #include <dbus/dbus-timeout.h> + #include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-internals.h> ++#include <dbus/dbus-message-internal.h> + #ifdef DBUS_ENABLE_CYNARA + #include <stdlib.h> + #include <cynara-session.h> +@@ -102,6 +104,7 @@ typedef struct + DBusMessage *oom_message; + DBusPreallocatedSend *oom_preallocated; + BusClientPolicy *policy; ++ DBusList *deferred_messages; /**< Queue of messages deferred due to pending policy check */ + + char *cached_loginfo_string; + BusSELinuxID *selinux_id; +@@ -268,6 +271,8 @@ bus_connection_disconnected (DBusConnection *connection) + bus_transaction_execute_and_free (transaction); + } + ++ bus_connection_clear_deferred_messages(connection); ++ + bus_dispatch_remove_connection (connection); + + /* no more watching */ +@@ -2307,7 +2312,7 @@ bus_transaction_capture (BusTransaction *transaction, + { + DBusConnection *recipient = link->data; + +- if (!bus_transaction_send (transaction, recipient, message)) ++ if (!bus_transaction_send (transaction, recipient, message, FALSE)) + goto out; + } + +@@ -2361,6 +2366,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + { + DBusError error = DBUS_ERROR_INIT; + BusResult res; ++ BusDeferredMessage *deferred_message; + + /* We have to set the sender to the driver, and have + * to check security policy since it was not done in +@@ -2401,7 +2407,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + res = bus_context_check_security_policy (bus_transaction_get_context (transaction), + transaction, + NULL, connection, connection, message, NULL, +- &error, NULL); ++ &error, &deferred_message); + if (res == BUS_RESULT_FALSE) + { + if (!bus_transaction_capture_error_reply (transaction, connection, +@@ -2419,18 +2425,20 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + } + else if (res == BUS_RESULT_LATER) + { +- _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); + dbus_error_free (&error); +- return TRUE; ++ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE)) ++ return FALSE; ++ return TRUE; /* pretend to have sent it */ + } + +- return bus_transaction_send (transaction, connection, message); ++ return bus_transaction_send (transaction, connection, message, FALSE); + } + + dbus_bool_t + bus_transaction_send (BusTransaction *transaction, + DBusConnection *connection, +- DBusMessage *message) ++ DBusMessage *message, ++ dbus_bool_t deferred_dispatch) + { + MessageToSend *to_send; + BusConnectionData *d; +@@ -2456,7 +2464,28 @@ bus_transaction_send (BusTransaction *transaction, + + d = BUS_CONNECTION_DATA (connection); + _dbus_assert (d != NULL); +- ++ ++ if (!deferred_dispatch && d->deferred_messages != NULL) ++ { ++ BusDeferredMessage *deferred_message; ++ dbus_bool_t success; ++ /* sender and addressed recipient are not required at this point as we only need to send message ++ * to a single recipient without performing policy check. */ ++ deferred_message = bus_deferred_message_new (message, ++ NULL, ++ NULL, ++ connection, ++ BUS_RESULT_TRUE); ++ if (deferred_message == NULL) ++ return FALSE; ++ ++ success = bus_deferred_message_queue_at_recipient(deferred_message, transaction, ++ FALSE, FALSE); ++ bus_deferred_message_unref(deferred_message); ++ ++ return success; ++ } ++ + to_send = dbus_new (MessageToSend, 1); + if (to_send == NULL) + { +@@ -2708,6 +2737,131 @@ bus_transaction_add_cancel_hook (BusTransaction *transaction, + return TRUE; + } + ++void ++bus_connection_dispatch_deferred (DBusConnection *connection) ++{ ++ BusDeferredMessage *message; ++ ++ _dbus_return_if_fail (connection != NULL); ++ ++ while ((message = bus_connection_pop_deferred_message(connection)) != NULL) ++ { ++ bus_deferred_message_dispatch(message); ++ bus_deferred_message_unref(message); ++ } ++} ++ ++dbus_bool_t ++bus_connection_has_deferred_messages (DBusConnection *connection) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ return d->deferred_messages != NULL ? TRUE : FALSE; ++} ++ ++dbus_bool_t ++bus_connection_queue_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *message, ++ dbus_bool_t prepend) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ dbus_bool_t success; ++ if (prepend) ++ success = _dbus_list_prepend(&d->deferred_messages, message); ++ else ++ success = _dbus_list_append(&d->deferred_messages, message); ++ ++ if (success) ++ { ++ bus_deferred_message_ref(message); ++ return TRUE; ++ } ++ ++ return FALSE; ++} ++ ++dbus_bool_t ++bus_connection_replace_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *oldMessage, ++ BusDeferredMessage *newMessage) ++{ ++ DBusList *link; ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ ++ link = _dbus_list_find_first(&d->deferred_messages, oldMessage); ++ if (link == NULL) ++ return FALSE; ++ ++ if (!_dbus_list_insert_after(&d->deferred_messages, link, newMessage)) ++ return FALSE; ++ ++ bus_deferred_message_ref(newMessage); ++ _dbus_list_remove_link(&d->deferred_messages, link); ++ bus_deferred_message_unref(oldMessage); ++ return TRUE; ++} ++ ++BusDeferredMessage * ++bus_connection_pop_deferred_message (DBusConnection *connection) ++{ ++ DBusList *link; ++ BusDeferredMessage *message; ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ ++ link =_dbus_list_get_first_link(&d->deferred_messages); ++ if (link != NULL) ++ { ++ message = link->data; ++ if (!bus_deferred_message_waits_for_check(message)) ++ { ++ _dbus_list_remove_link(&d->deferred_messages, link); ++ return message; ++ } ++ } ++ ++ return NULL; ++} ++ ++dbus_bool_t ++bus_connection_putback_deferred_message (DBusConnection *connection, BusDeferredMessage *message) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ if (_dbus_list_prepend(&d->deferred_messages, message)) ++ { ++ return TRUE; ++ } ++ return FALSE; ++} ++ ++void ++bus_connection_clear_deferred_messages (DBusConnection *connection) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ DBusList *link; ++ DBusList *next; ++ BusDeferredMessage *message; ++ ++ link =_dbus_list_get_first_link(&d->deferred_messages); ++ while (link != NULL) ++ { ++ next = _dbus_list_get_next_link (&d->deferred_messages, link); ++ message = link->data; ++ ++ bus_deferred_message_unref(message); ++ _dbus_list_remove_link(&d->deferred_messages, link); ++ ++ link = next; ++ } ++} ++ ++void ++bus_connection_remove_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *message) ++{ ++ BusConnectionData *d = BUS_CONNECTION_DATA(connection); ++ if (_dbus_list_remove(&d->deferred_messages, message)) ++ bus_deferred_message_unref(message); ++} ++ + int + bus_connections_get_n_active (BusConnections *connections) + { +diff --git a/bus/connection.h b/bus/connection.h +index 71078ea..97dae96 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -85,6 +85,22 @@ dbus_bool_t bus_connection_preallocate_oom_error (DBusConnection *connection); + void bus_connection_send_oom_error (DBusConnection *connection, + DBusMessage *in_reply_to); + ++dbus_bool_t bus_connection_has_deferred_messages (DBusConnection *connection); ++dbus_bool_t bus_connection_queue_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *message, ++ dbus_bool_t prepend); ++BusDeferredMessage *bus_connection_pop_deferred_message (DBusConnection *connection); ++dbus_bool_t bus_connection_putback_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *message); ++void bus_connection_remove_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *message); ++dbus_bool_t bus_connection_replace_deferred_message (DBusConnection *connection, ++ BusDeferredMessage *oldMessage, ++ BusDeferredMessage *newMessage); ++void bus_connection_dispatch_deferred (DBusConnection *connection); ++void bus_connection_clear_deferred_messages (DBusConnection *connection); ++ ++ + /* called by signals.c */ + dbus_bool_t bus_connection_add_match_rule (DBusConnection *connection, + BusMatchRule *rule); +@@ -137,7 +153,8 @@ BusTransaction* bus_transaction_new (BusContext * + BusContext* bus_transaction_get_context (BusTransaction *transaction); + dbus_bool_t bus_transaction_send (BusTransaction *transaction, + DBusConnection *connection, +- DBusMessage *message); ++ DBusMessage *message, ++ dbus_bool_t deferred_dispatch); + dbus_bool_t bus_transaction_capture (BusTransaction *transaction, + DBusConnection *connection, + DBusConnection *addressed_recipient, +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 50a22a3..7d30ce4 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -33,6 +33,7 @@ + #include "utils.h" + #include "bus.h" + #include "signals.h" ++#include "dispatch.h" + #include "test.h" + #include <dbus/dbus-internals.h> + #include <dbus/dbus-connection-internal.h> +@@ -77,7 +78,7 @@ send_one_message (DBusConnection *connection, + NULL, + &stack_error, + &deferred_message); +- if (result != BUS_RESULT_TRUE) ++ if (result == BUS_RESULT_FALSE) + { + if (!bus_transaction_capture_error_reply (transaction, sender, + &stack_error, message)) +@@ -112,9 +113,19 @@ send_one_message (DBusConnection *connection, + return TRUE; /* don't send it but don't return an error either */ + } + ++ if (result == BUS_RESULT_LATER) ++ { ++ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, FALSE, FALSE)) ++ { ++ BUS_SET_OOM (error); ++ return FALSE; ++ } ++ return TRUE; /* pretend to have sent it */ ++ } ++ + if (!bus_transaction_send (transaction, + connection, +- message)) ++ message, FALSE)) + { + BUS_SET_OOM (error); + return FALSE; +@@ -124,11 +135,12 @@ send_one_message (DBusConnection *connection, + } + + BusResult +-bus_dispatch_matches (BusTransaction *transaction, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusMessage *message, +- DBusError *error) ++bus_dispatch_matches (BusTransaction *transaction, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusMessage *message, ++ BusDeferredMessage *dispatched_deferred_message, ++ DBusError *error) + { + DBusError tmp_error; + BusConnections *connections; +@@ -137,7 +149,6 @@ bus_dispatch_matches (BusTransaction *transaction, + DBusList *link; + BusContext *context; + BusDeferredMessage *deferred_message; +- BusResult res; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -153,16 +164,80 @@ bus_dispatch_matches (BusTransaction *transaction, + /* First, send the message to the addressed_recipient, if there is one. */ + if (addressed_recipient != NULL) + { +- res = bus_context_check_security_policy (context, transaction, ++ BusResult result; ++ /* To maintain message order message needs to be appended at the recipient if there are already ++ * deferred messages and we are not doing deferred dispatch ++ */ ++ if (dispatched_deferred_message == NULL && bus_connection_has_deferred_messages(addressed_recipient)) ++ { ++ deferred_message = bus_deferred_message_new(message, sender, ++ addressed_recipient, addressed_recipient, BUS_RESULT_LATER); ++ ++ if (deferred_message == NULL) ++ { ++ BUS_SET_OOM(error); ++ return BUS_RESULT_FALSE; ++ } ++ ++ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE)) ++ { ++ bus_deferred_message_unref(deferred_message); ++ BUS_SET_OOM(error); ++ return BUS_RESULT_FALSE; ++ } ++ ++ bus_deferred_message_unref(deferred_message); ++ return BUS_RESULT_TRUE; /* pretend to have sent it */ ++ } ++ ++ if (dispatched_deferred_message != NULL) ++ { ++ result = bus_deferred_message_get_response(dispatched_deferred_message); ++ if (result == BUS_RESULT_TRUE) ++ { ++ /* if we know the result of policy check we still need to check if message limits ++ * are not exceeded. It is also required to add entry in expected replies list if ++ * this is a method call ++ */ ++ if (!bus_deferred_message_check_message_limits(dispatched_deferred_message, error)) ++ return BUS_RESULT_FALSE; ++ ++ if (!bus_deferred_message_expect_method_reply(dispatched_deferred_message, transaction, error)) ++ return BUS_RESULT_FALSE; ++ } ++ else if (result == BUS_RESULT_FALSE) ++ { ++ bus_deferred_message_create_error(dispatched_deferred_message, "Rejected message", error); ++ return BUS_RESULT_FALSE; ++ } ++ } ++ else ++ result = BUS_RESULT_LATER; ++ ++ if (result == BUS_RESULT_LATER) ++ result = bus_context_check_security_policy (context, transaction, + sender, addressed_recipient, + addressed_recipient, + message, NULL, error, + &deferred_message); +- if (res == BUS_RESULT_FALSE) ++ ++ if (result == BUS_RESULT_FALSE) + return BUS_RESULT_FALSE; +- else if (res == BUS_RESULT_LATER) ++ else if (result == BUS_RESULT_LATER) + { + BusDeferredMessageStatus status; ++ ++ if (dispatched_deferred_message != NULL) ++ { ++ /* for deferred dispatch prepend message at the recipient */ ++ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, TRUE)) ++ { ++ BUS_SET_OOM(error); ++ return BUS_RESULT_FALSE; ++ } ++ return BUS_RESULT_TRUE; /* pretend to have sent it */ ++ } ++ + status = bus_deferred_message_get_status(deferred_message); + + if (status & BUS_DEFERRED_MESSAGE_CHECK_SEND) +@@ -173,13 +248,18 @@ bus_dispatch_matches (BusTransaction *transaction, + } + else if (status & BUS_DEFERRED_MESSAGE_CHECK_RECEIVE) + { +- dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, +- "Rejecting message because time is needed to check security policy"); +- return BUS_RESULT_FALSE; ++ /* receive rule result not available - queue message at the recipient */ ++ if (!bus_deferred_message_queue_at_recipient(deferred_message, transaction, TRUE, FALSE)) ++ { ++ BUS_SET_OOM(error); ++ return BUS_RESULT_FALSE; ++ } ++ ++ return BUS_RESULT_TRUE; /* pretend to have sent it */ + } + else + { +- _dbus_verbose("deferred message has no status field set to send or receive unexpectedly\n"); ++ _dbus_verbose("deferred message has no status field set unexpectedly\n"); + return BUS_RESULT_FALSE; + } + } +@@ -196,7 +276,8 @@ bus_dispatch_matches (BusTransaction *transaction, + } + + /* Dispatch the message */ +- if (!bus_transaction_send (transaction, addressed_recipient, message)) ++ if (!bus_transaction_send(transaction, addressed_recipient, message, ++ dispatched_deferred_message != NULL ? TRUE : FALSE)) + { + BUS_SET_OOM (error); + return BUS_RESULT_FALSE; +@@ -534,7 +615,7 @@ bus_dispatch (DBusConnection *connection, + * match rules. + */ + if (BUS_RESULT_LATER == bus_dispatch_matches (transaction, connection, addressed_recipient, +- message, &error)) ++ message, NULL, &error)) + { + /* Roll back and dispatch the message once the policy result is available */ + bus_transaction_cancel_and_free (transaction); +diff --git a/bus/dispatch.h b/bus/dispatch.h +index afba6a2..f6102e8 100644 +--- a/bus/dispatch.h ++++ b/bus/dispatch.h +@@ -29,10 +29,11 @@ + + dbus_bool_t bus_dispatch_add_connection (DBusConnection *connection); + void bus_dispatch_remove_connection (DBusConnection *connection); +-BusResult bus_dispatch_matches (BusTransaction *transaction, +- DBusConnection *sender, +- DBusConnection *recipient, +- DBusMessage *message, +- DBusError *error); ++BusResult bus_dispatch_matches (BusTransaction *transaction, ++ DBusConnection *sender, ++ DBusConnection *recipient, ++ DBusMessage *message, ++ BusDeferredMessage *dispatched_deferred_message, ++ DBusError *error); + + #endif /* BUS_DISPATCH_H */ +diff --git a/bus/driver.c b/bus/driver.c +index f414f64..d89a658 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -254,7 +254,7 @@ bus_driver_send_service_owner_changed (const char *service_name, + if (!bus_transaction_capture (transaction, NULL, NULL, message)) + goto oom; + +- res = bus_dispatch_matches (transaction, NULL, NULL, message, error); ++ res = bus_dispatch_matches (transaction, NULL, NULL, message, NULL, error); + if (res == BUS_RESULT_TRUE) + retval = TRUE; + else +diff --git a/bus/policy.c b/bus/policy.c +index 7de92c6..483cc97 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -1122,6 +1122,9 @@ bus_client_policy_check_can_send (DBusConnection *sender, + + result = bus_check_privilege(check, message, sender, addressed_recipient, receiver, + privilege, BUS_DEFERRED_MESSAGE_CHECK_SEND, deferred_message); ++ if (result == BUS_RESULT_LATER && deferred_message != NULL) ++ bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply, ++ *toggles, privilege); + } + else + privilege = NULL; +@@ -1372,6 +1375,9 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + + result = bus_check_privilege(check, message, sender, addressed_recipient, proposed_recipient, + privilege, BUS_DEFERRED_MESSAGE_CHECK_RECEIVE, deferred_message); ++ if (result == BUS_RESULT_LATER && deferred_message != NULL) ++ bus_deferred_message_set_policy_check_info(*deferred_message, requested_reply, ++ *toggles, privilege); + } + else + privilege = NULL; +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0004-Add-own-rule-result-unavailability-handling.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0004-Add-own-rule-result-unavailability-handling.patch new file mode 100644 index 000000000..9953dcaac --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0004-Add-own-rule-result-unavailability-handling.patch @@ -0,0 +1,1505 @@ +From 28ada62c98d74285dc22b66650b09b6c8f2c28c4 Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Thu, 27 Nov 2014 11:26:21 +0100 +Subject: [PATCH 4/8] Add own rule result unavailability handling +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Own rule result unavailability is handled like send rules - dispatching +messages from the sender is blocked and resumed when result becomes +available. + +Handler of "RequestName" method needs to return BUS_RESULT_LATER when +policy result is not known therefore its return type is modified. +Since bus message handlers are put into function pointer array other +message handler function singatures are also affected. + +Cherry-picked from 35ef89cd6777ea2430077fc621d21bd01df92349 by Jose.bollo + +Updated for dbus 1.10.20 by Scott Murray and José Bollo + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +Signed-off-by: Scott Murray <scott.murray@konsulko.com> +--- + bus/dispatch.c | 11 +- + bus/driver.c | 334 ++++++++++++++++++++++++++++--------------------- + bus/driver.h | 2 +- + bus/policy.c | 52 ++++++-- + bus/policy.h | 6 +- + bus/services.c | 26 ++-- + bus/services.h | 3 +- + bus/stats.c | 23 ++-- + bus/stats.h | 6 +- + 9 files changed, 283 insertions(+), 180 deletions(-) + +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 7d30ce4..4b84c21 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -517,8 +517,17 @@ bus_dispatch (DBusConnection *connection, + } + + _dbus_verbose ("Giving message to %s\n", DBUS_SERVICE_DBUS); +- if (!bus_driver_handle_message (connection, transaction, message, &error)) ++ res = bus_driver_handle_message (connection, transaction, message, &error); ++ if (res == BUS_RESULT_FALSE) + goto out; ++ else if (res == BUS_RESULT_LATER) ++ { ++ /* connection has been disabled in message handler */ ++ bus_transaction_cancel_and_free (transaction); ++ transaction = NULL; ++ result = DBUS_HANDLER_RESULT_LATER; ++ goto out; ++ } + } + else if (!bus_connection_is_active (connection)) /* clients must talk to bus driver first */ + { +diff --git a/bus/driver.c b/bus/driver.c +index d89a658..aaeb3b2 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -420,7 +420,7 @@ create_unique_client_name (BusRegistry *registry, + return TRUE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_hello (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -428,7 +428,7 @@ bus_driver_handle_hello (DBusConnection *connection, + { + DBusString unique_name; + BusService *service; +- dbus_bool_t retval; ++ BusResult retval; + BusRegistry *registry; + BusConnections *connections; + DBusError tmp_error; +@@ -442,7 +442,7 @@ bus_driver_handle_hello (DBusConnection *connection, + /* We already handled an Hello message for this connection. */ + dbus_set_error (error, DBUS_ERROR_FAILED, + "Already handled an Hello message"); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + /* Note that when these limits are exceeded we don't disconnect the +@@ -464,16 +464,16 @@ bus_driver_handle_hello (DBusConnection *connection, + bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, "%s (%s=%d)", + tmp_error.message, limit_name, limit); + dbus_move_error (&tmp_error, error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!_dbus_string_init (&unique_name)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + registry = bus_connection_get_registry (connection); + +@@ -506,7 +506,7 @@ bus_driver_handle_hello (DBusConnection *connection, + goto out_0; + + _dbus_assert (bus_connection_is_active (connection)); +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out_0: + _dbus_string_free (&unique_name); +@@ -558,7 +558,7 @@ bus_driver_send_welcome_message (DBusConnection *connection, + } + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_list_services (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -580,14 +580,14 @@ bus_driver_handle_list_services (DBusConnection *connection, + if (reply == NULL) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!bus_registry_list_services (registry, &services, &len)) + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + dbus_message_iter_init_append (reply, &iter); +@@ -599,7 +599,7 @@ bus_driver_handle_list_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + { +@@ -611,7 +611,7 @@ bus_driver_handle_list_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + } + +@@ -624,7 +624,7 @@ bus_driver_handle_list_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + ++i; + } +@@ -635,23 +635,23 @@ bus_driver_handle_list_services (DBusConnection *connection, + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!bus_transaction_send_from_driver (transaction, connection, reply)) + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + else + { + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + } + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_list_activatable_services (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -673,14 +673,14 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, + if (reply == NULL) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!bus_activation_list_services (activation, &services, &len)) + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + dbus_message_iter_init_append (reply, &iter); +@@ -692,7 +692,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + { +@@ -704,7 +704,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + } + +@@ -717,7 +717,7 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, + dbus_free_string_array (services); + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + ++i; + } +@@ -728,23 +728,23 @@ bus_driver_handle_list_activatable_services (DBusConnection *connection, + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!bus_transaction_send_from_driver (transaction, connection, reply)) + { + dbus_message_unref (reply); + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + else + { + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + } + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_acquire_service (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -755,7 +755,8 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + const char *name; + dbus_uint32_t service_reply; + dbus_uint32_t flags; +- dbus_bool_t retval; ++ BusResult retval; ++ BusResult res; + BusRegistry *registry; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -766,20 +767,24 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_UINT32, &flags, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + _dbus_verbose ("Trying to own name %s with flags 0x%x\n", name, flags); + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + reply = NULL; + + _dbus_string_init_const (&service_name, name); + +- if (!bus_registry_acquire_service (registry, connection, +- &service_name, flags, +- &service_reply, transaction, +- error)) +- goto out; ++ res = bus_registry_acquire_service (registry, connection, message, ++ &service_name, flags, ++ &service_reply, transaction, ++ error); ++ if (res != BUS_RESULT_TRUE) ++ { ++ retval = res; ++ goto out; ++ } + + reply = dbus_message_new_method_return (message); + if (reply == NULL) +@@ -800,7 +805,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -808,7 +813,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + return retval; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_release_service (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -818,7 +823,7 @@ bus_driver_handle_release_service (DBusConnection *connection, + DBusString service_name; + const char *name; + dbus_uint32_t service_reply; +- dbus_bool_t retval; ++ BusResult retval; + BusRegistry *registry; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -828,11 +833,11 @@ bus_driver_handle_release_service (DBusConnection *connection, + if (!dbus_message_get_args (message, error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + _dbus_verbose ("Trying to release name %s\n", name); + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + reply = NULL; + + _dbus_string_init_const (&service_name, name); +@@ -861,7 +866,7 @@ bus_driver_handle_release_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -869,7 +874,7 @@ bus_driver_handle_release_service (DBusConnection *connection, + return retval; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_service_exists (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -880,7 +885,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, + BusService *service; + dbus_bool_t service_exists; + const char *name; +- dbus_bool_t retval; ++ BusResult retval; + BusRegistry *registry; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -890,9 +895,9 @@ bus_driver_handle_service_exists (DBusConnection *connection, + if (!dbus_message_get_args (message, error, + DBUS_TYPE_STRING, &name, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + if (strcmp (name, DBUS_SERVICE_DBUS) == 0) + { +@@ -926,7 +931,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -935,7 +940,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, + return retval; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_activate_service (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -943,7 +948,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, + { + dbus_uint32_t flags; + const char *name; +- dbus_bool_t retval; ++ BusResult retval; + BusActivation *activation; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -957,10 +962,10 @@ bus_driver_handle_activate_service (DBusConnection *connection, + { + _DBUS_ASSERT_ERROR_IS_SET (error); + _dbus_verbose ("No memory to get arguments to StartServiceByName\n"); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + if (!bus_activation_activate_service (activation, connection, transaction, FALSE, + message, name, error)) +@@ -970,7 +975,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + return retval; +@@ -1072,13 +1077,13 @@ bus_driver_send_or_activate (BusTransaction *transaction, + return TRUE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_update_activation_environment (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) + { +- dbus_bool_t retval; ++ BusResult retval; + BusActivation *activation; + BusContext *context; + DBusMessageIter iter; +@@ -1100,7 +1105,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Cannot change activation environment " + "on a system bus."); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + activation = bus_connection_get_activation (connection); +@@ -1114,7 +1119,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + + dbus_message_iter_recurse (&iter, &dict_iter); + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + systemd_message = NULL; + + /* Then loop through the sent dictionary, add the location of +@@ -1279,7 +1284,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + if (!bus_driver_send_ack_reply (connection, transaction, message, error)) + goto out; + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (systemd_message != NULL) +@@ -1289,7 +1294,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + return retval; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_add_match (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1371,16 +1376,16 @@ bus_driver_handle_add_match (DBusConnection *connection, + + bus_match_rule_unref (rule); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + failed: + _DBUS_ASSERT_ERROR_IS_SET (error); + if (rule) + bus_match_rule_unref (rule); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_remove_match (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1423,16 +1428,16 @@ bus_driver_handle_remove_match (DBusConnection *connection, + + bus_match_rule_unref (rule); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + failed: + _DBUS_ASSERT_ERROR_IS_SET (error); + if (rule) + bus_match_rule_unref (rule); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_service_owner (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1502,7 +1507,7 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1511,10 +1516,10 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_list_queued_owners (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1606,7 +1611,7 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1619,10 +1624,10 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection, + if (base_names) + _dbus_list_clear (&base_names); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_connection_unix_user (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1679,7 +1684,7 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1688,10 +1693,10 @@ bus_driver_handle_get_connection_unix_user (DBusConnection *connection, + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1748,7 +1753,7 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1757,10 +1762,10 @@ bus_driver_handle_get_connection_unix_process_id (DBusConnection *connection, + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1811,7 +1816,7 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1820,10 +1825,10 @@ bus_driver_handle_get_adt_audit_session_data (DBusConnection *connection, + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_connection_selinux_security_context (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1872,7 +1877,7 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1881,10 +1886,10 @@ bus_driver_handle_get_connection_selinux_security_context (DBusConnection *conne + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_connection_credentials (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1998,7 +2003,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -2012,10 +2017,10 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + dbus_message_unref (reply); + } + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_reload_config (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2040,7 +2045,7 @@ bus_driver_handle_reload_config (DBusConnection *connection, + goto oom; + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -2049,11 +2054,11 @@ bus_driver_handle_reload_config (DBusConnection *connection, + _DBUS_ASSERT_ERROR_IS_SET (error); + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + #ifdef DBUS_ENABLE_VERBOSE_MODE +-static dbus_bool_t ++static BusResult + bus_driver_handle_enable_verbose (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2073,7 +2078,7 @@ bus_driver_handle_enable_verbose (DBusConnection *connection, + _dbus_set_verbose(TRUE); + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -2082,10 +2087,10 @@ bus_driver_handle_enable_verbose (DBusConnection *connection, + + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_disable_verbose (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2105,7 +2110,7 @@ bus_driver_handle_disable_verbose (DBusConnection *connection, + _dbus_set_verbose(FALSE); + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -2114,11 +2119,11 @@ bus_driver_handle_disable_verbose (DBusConnection *connection, + + if (reply) + dbus_message_unref (reply); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + #endif + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_id (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2134,7 +2139,7 @@ bus_driver_handle_get_id (DBusConnection *connection, + if (!_dbus_string_init (&uuid)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + reply = NULL; +@@ -2160,7 +2165,7 @@ bus_driver_handle_get_id (DBusConnection *connection, + + _dbus_string_free (&uuid); + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -2170,10 +2175,10 @@ bus_driver_handle_get_id (DBusConnection *connection, + if (reply) + dbus_message_unref (reply); + _dbus_string_free (&uuid); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_become_monitor (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2189,7 +2194,7 @@ bus_driver_handle_become_monitor (DBusConnection *connection, + int i; + int n_match_rules; + dbus_uint32_t flags; +- dbus_bool_t ret = FALSE; ++ BusResult ret = BUS_RESULT_FALSE; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -2262,10 +2267,10 @@ bus_driver_handle_become_monitor (DBusConnection *connection, + if (!bus_connection_be_monitor (connection, transaction, &rules, error)) + goto out; + +- ret = TRUE; ++ ret = BUS_RESULT_TRUE; + + out: +- if (ret) ++ if (ret == BUS_RESULT_TRUE) + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + else + _DBUS_ASSERT_ERROR_IS_SET (error); +@@ -2281,7 +2286,7 @@ out: + return ret; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_machine_id (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2296,7 +2301,7 @@ bus_driver_handle_get_machine_id (DBusConnection *connection, + if (!_dbus_string_init (&uuid)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!_dbus_get_local_machine_uuid_encoded (&uuid, error)) +@@ -2321,7 +2326,7 @@ bus_driver_handle_get_machine_id (DBusConnection *connection, + + _dbus_string_free (&uuid); + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -2335,29 +2340,30 @@ fail: + dbus_message_unref (reply); + + _dbus_string_free (&uuid); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_ping (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error) + { +- return bus_driver_send_ack_reply (connection, transaction, message, error); ++ return bus_driver_send_ack_reply (connection, transaction, message, error) == TRUE ++ ? BUS_RESULT_TRUE : BUS_RESULT_FALSE; + } + +-static dbus_bool_t bus_driver_handle_get (DBusConnection *connection, ++static BusResult bus_driver_handle_get (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); + +-static dbus_bool_t bus_driver_handle_get_all (DBusConnection *connection, ++static BusResult bus_driver_handle_get_all (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); + +-static dbus_bool_t bus_driver_handle_set (DBusConnection *connection, ++static BusResult bus_driver_handle_set (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); +@@ -2389,10 +2395,10 @@ typedef struct + const char *name; + const char *in_args; + const char *out_args; +- dbus_bool_t (* handler) (DBusConnection *connection, +- BusTransaction *transaction, +- DBusMessage *message, +- DBusError *error); ++ BusResult (* handler) (DBusConnection *connection, ++ BusTransaction *transaction, ++ DBusMessage *message, ++ DBusError *error); + MethodFlags flags; + } MessageHandler; + +@@ -2511,7 +2517,7 @@ static const PropertyHandler dbus_property_handlers[] = { + { NULL, NULL, NULL } + }; + +-static dbus_bool_t bus_driver_handle_introspect (DBusConnection *, ++static BusResult bus_driver_handle_introspect (DBusConnection *, + BusTransaction *, DBusMessage *, DBusError *); + + static const MessageHandler properties_message_handlers[] = { +@@ -2763,7 +2769,7 @@ bus_driver_generate_introspect_string (DBusString *xml, + return TRUE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_introspect (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2784,13 +2790,13 @@ bus_driver_handle_introspect (DBusConnection *connection, + DBUS_TYPE_INVALID)) + { + _DBUS_ASSERT_ERROR_IS_SET (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + if (!_dbus_string_init (&xml)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + is_canonical_path = dbus_message_has_path (message, DBUS_PATH_DBUS); +@@ -2815,7 +2821,7 @@ bus_driver_handle_introspect (DBusConnection *connection, + dbus_message_unref (reply); + _dbus_string_free (&xml); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -2825,10 +2831,42 @@ bus_driver_handle_introspect (DBusConnection *connection, + + _dbus_string_free (&xml); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + ++/* ++ * Set @error and return FALSE if the message is not directed to the ++ * dbus-daemon by its canonical object path. This is hardening against ++ * system services with poorly-written security policy files, which ++ * might allow sending dangerously broad equivalence classes of messages ++ * such as "anything with this assumed-to-be-safe object path". ++ * ++ * dbus-daemon is unusual in that it normally ignores the object path ++ * of incoming messages; we need to keep that behaviour for the "read" ++ * read-only method calls like GetConnectionUnixUser for backwards ++ * compatibility, but it seems safer to be more restrictive for things ++ * intended to be root-only or privileged-developers-only. ++ * ++ * It is possible that there are other system services with the same ++ * quirk as dbus-daemon. ++ */ + dbus_bool_t ++bus_driver_check_message_is_for_us (DBusMessage *message, ++ DBusError *error) ++{ ++ if (!dbus_message_has_path (message, DBUS_PATH_DBUS)) ++ { ++ dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, ++ "Method '%s' is only available at the canonical object path '%s'", ++ dbus_message_get_member (message), DBUS_PATH_DBUS); ++ ++ return FALSE; ++ } ++ ++ return TRUE; ++} ++ ++BusResult + bus_driver_handle_message (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2839,6 +2877,7 @@ bus_driver_handle_message (DBusConnection *connection, + const MessageHandler *mh; + dbus_bool_t found_interface = FALSE; + dbus_bool_t is_canonical_path; ++ BusResult res; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -2854,7 +2893,7 @@ bus_driver_handle_message (DBusConnection *connection, + transaction, + message, + error)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + context = bus_connection_get_context (connection); + systemd = bus_driver_get_owner_of_name (connection, +@@ -2871,7 +2910,7 @@ bus_driver_handle_message (DBusConnection *connection, + attacker ? attacker : "(unauthenticated)", + bus_connection_get_loginfo (connection)); + /* ignore it */ +- return TRUE; ++ return BUS_RESULT_TRUE; + } + + if (!bus_context_get_systemd_activation (context)) +@@ -2879,16 +2918,16 @@ bus_driver_handle_message (DBusConnection *connection, + bus_context_log (context, DBUS_SYSTEM_LOG_WARNING, + "Ignoring unexpected ActivationFailure message " + "while not using systemd activation"); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +- return dbus_activation_systemd_failure(bus_context_get_activation(context), message); ++ return dbus_activation_systemd_failure(bus_context_get_activation(context), message) == TRUE ? BUS_RESULT_TRUE : BUS_RESULT_FALSE; + } + + if (dbus_message_get_type (message) != DBUS_MESSAGE_TYPE_METHOD_CALL) + { + _dbus_verbose ("Driver got a non-method-call message, ignoring\n"); +- return TRUE; /* we just ignore this */ ++ return BUS_RESULT_TRUE; /* we just ignore this */ + } + + /* may be NULL, which means "any interface will do" */ +@@ -2953,20 +2992,27 @@ bus_driver_handle_message (DBusConnection *connection, + name, dbus_message_get_signature (message), + mh->in_args); + _DBUS_ASSERT_ERROR_IS_SET (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +- if ((* mh->handler) (connection, transaction, message, error)) ++ res = (* mh->handler) (connection, transaction, message, error); ++ if (res == BUS_RESULT_TRUE) + { + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + _dbus_verbose ("Driver handler succeeded\n"); +- return TRUE; ++ return BUS_RESULT_TRUE; + } +- else ++ else if (res == BUS_RESULT_FALSE) + { + _DBUS_ASSERT_ERROR_IS_SET (error); + _dbus_verbose ("Driver handler returned failure\n"); +- return FALSE; ++ return BUS_RESULT_FALSE; ++ } ++ else if (res == BUS_RESULT_LATER) ++ { ++ _DBUS_ASSERT_ERROR_IS_CLEAR (error); ++ _dbus_verbose ("Driver handler delayed message processing due to policy check\n"); ++ return BUS_RESULT_LATER; + } + } + } +@@ -2978,7 +3024,7 @@ bus_driver_handle_message (DBusConnection *connection, + "%s does not understand message %s", + DBUS_SERVICE_DBUS, name); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + void +@@ -3099,7 +3145,7 @@ interface_handler_find_property (const InterfaceHandler *ih, + return NULL; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -3120,18 +3166,18 @@ bus_driver_handle_get (DBusConnection *connection, + DBUS_TYPE_STRING, &iface, + DBUS_TYPE_STRING, &prop, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + /* We only implement Properties on /org/freedesktop/DBus so far. */ + ih = bus_driver_find_interface (iface, TRUE, error); + + if (ih == NULL) +- return FALSE; ++ return BUS_RESULT_FALSE; + + handler = interface_handler_find_property (ih, prop, error); + + if (handler == NULL) +- return FALSE; ++ return BUS_RESULT_FALSE; + + context = bus_transaction_get_context (transaction); + +@@ -3159,17 +3205,17 @@ bus_driver_handle_get (DBusConnection *connection, + goto oom; + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + if (reply != NULL) + dbus_message_unref (reply); + + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_all (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -3188,13 +3234,13 @@ bus_driver_handle_get_all (DBusConnection *connection, + if (!dbus_message_get_args (message, error, + DBUS_TYPE_STRING, &iface, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + /* We only implement Properties on /org/freedesktop/DBus so far. */ + ih = bus_driver_find_interface (iface, TRUE, error); + + if (ih == NULL) +- return FALSE; ++ return BUS_RESULT_FALSE; + + context = bus_transaction_get_context (transaction); + +@@ -3229,7 +3275,7 @@ bus_driver_handle_get_all (DBusConnection *connection, + goto oom; + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom_abandon_message: + _dbus_asv_abandon (&reply_iter, &array_iter); +@@ -3239,10 +3285,10 @@ oom: + dbus_message_unref (reply); + + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_set (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -3271,15 +3317,15 @@ bus_driver_handle_set (DBusConnection *connection, + ih = bus_driver_find_interface (iface, TRUE, error); + + if (ih == NULL) +- return FALSE; ++ return BUS_RESULT_FALSE; + + handler = interface_handler_find_property (ih, prop, error); + + if (handler == NULL) +- return FALSE; ++ return BUS_RESULT_FALSE; + + /* We don't implement any properties that can be set yet. */ + dbus_set_error (error, DBUS_ERROR_PROPERTY_READ_ONLY, + "Property '%s.%s' cannot be set", iface, prop); +- return FALSE; ++ return BUS_RESULT_FALSE; + } +diff --git a/bus/driver.h b/bus/driver.h +index a7297ad..05e9886 100644 +--- a/bus/driver.h ++++ b/bus/driver.h +@@ -35,7 +35,7 @@ typedef enum + } BusDriverFound; + + void bus_driver_remove_connection (DBusConnection *connection); +-dbus_bool_t bus_driver_handle_message (DBusConnection *connection, ++BusResult bus_driver_handle_message (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); +diff --git a/bus/policy.c b/bus/policy.c +index 483cc97..f6f4d85 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -1390,18 +1390,21 @@ bus_client_policy_check_can_receive (BusClientPolicy *policy, + + + +-static dbus_bool_t ++static BusResult + bus_rules_check_can_own (DBusList *rules, +- const DBusString *service_name) ++ const DBusString *service_name, ++ DBusConnection *connection, ++ DBusMessage *message) + { + DBusList *link; +- dbus_bool_t allowed; ++ BusResult result; ++ const char *privilege; + + /* rules is in the order the rules appeared + * in the config file, i.e. last rule that applies wins + */ + +- allowed = FALSE; ++ result = BUS_RESULT_FALSE; + link = _dbus_list_get_first_link (&rules); + while (link != NULL) + { +@@ -1437,17 +1440,46 @@ bus_rules_check_can_own (DBusList *rules, + } + + /* Use this rule */ +- allowed = rule->access == BUS_POLICY_RULE_ACCESS_ALLOW; ++ switch (rule->access) ++ { ++ case BUS_POLICY_RULE_ACCESS_ALLOW: ++ result = BUS_RESULT_TRUE; ++ break; ++ default: ++ case BUS_POLICY_RULE_ACCESS_DENY: ++ result = BUS_RESULT_FALSE; ++ break; ++ case BUS_POLICY_RULE_ACCESS_CHECK: ++ result = BUS_RESULT_LATER; ++ privilege = rule->privilege; ++ break; ++ } + } + +- return allowed; ++ if (result == BUS_RESULT_LATER) ++ { ++ BusContext *context = bus_connection_get_context(connection); ++ BusCheck *check = bus_context_get_check(context); ++ BusDeferredMessage *deferred_message; ++ ++ result = bus_check_privilege(check, message, connection, NULL, NULL, ++ privilege, BUS_DEFERRED_MESSAGE_CHECK_OWN, &deferred_message); ++ if (result == BUS_RESULT_LATER) ++ { ++ bus_deferred_message_disable_sender(deferred_message); ++ } ++ } ++ ++ return result; + } + +-dbus_bool_t ++BusResult + bus_client_policy_check_can_own (BusClientPolicy *policy, +- const DBusString *service_name) ++ const DBusString *service_name, ++ DBusConnection *connection, ++ DBusMessage *message) + { +- return bus_rules_check_can_own (policy->rules, service_name); ++ return bus_rules_check_can_own (policy->rules, service_name, connection, message); + } + + #ifdef DBUS_ENABLE_EMBEDDED_TESTS +@@ -1455,7 +1487,7 @@ dbus_bool_t + bus_policy_check_can_own (BusPolicy *policy, + const DBusString *service_name) + { +- return bus_rules_check_can_own (policy->default_rules, service_name); ++ return bus_rules_check_can_own (policy->default_rules, service_name, NULL, NULL) == BUS_RESULT_TRUE; + } + #endif /* DBUS_ENABLE_EMBEDDED_TESTS */ + +diff --git a/bus/policy.h b/bus/policy.h +index f839d23..28ce8f2 100644 +--- a/bus/policy.h ++++ b/bus/policy.h +@@ -182,8 +182,10 @@ BusResult bus_client_policy_check_can_receive (BusClientPolicy *policy, + dbus_int32_t *toggles, + const char **privilege_param, + BusDeferredMessage **deferred_message); +-dbus_bool_t bus_client_policy_check_can_own (BusClientPolicy *policy, +- const DBusString *service_name); ++BusResult bus_client_policy_check_can_own (BusClientPolicy *policy, ++ const DBusString *service_name, ++ DBusConnection *connection, ++ DBusMessage *message); + dbus_bool_t bus_client_policy_append_rule (BusClientPolicy *policy, + BusPolicyRule *rule); + void bus_client_policy_optimize (BusClientPolicy *policy); +diff --git a/bus/services.c b/bus/services.c +index 127edda..586af18 100644 +--- a/bus/services.c ++++ b/bus/services.c +@@ -376,16 +376,17 @@ bus_registry_list_services (BusRegistry *registry, + return FALSE; + } + +-dbus_bool_t ++BusResult + bus_registry_acquire_service (BusRegistry *registry, + DBusConnection *connection, ++ DBusMessage *message, + const DBusString *service_name, + dbus_uint32_t flags, + dbus_uint32_t *result, + BusTransaction *transaction, + DBusError *error) + { +- dbus_bool_t retval; ++ BusResult retval; + DBusConnection *old_owner_conn; + BusClientPolicy *policy; + BusService *service; +@@ -393,8 +394,9 @@ bus_registry_acquire_service (BusRegistry *registry, + BusSELinuxID *sid; + BusOwner *primary_owner; + int limit; ++ BusResult res; + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + if (!_dbus_validate_bus_name (service_name, 0, + _dbus_string_get_length (service_name))) +@@ -467,7 +469,8 @@ bus_registry_acquire_service (BusRegistry *registry, + _dbus_string_get_const_data (service_name), error)) + goto out; + +- if (!bus_client_policy_check_can_own (policy, service_name)) ++ res = bus_client_policy_check_can_own (policy, service_name, connection, message); ++ if (res == BUS_RESULT_FALSE) + { + dbus_set_error (error, DBUS_ERROR_ACCESS_DENIED, + "Connection \"%s\" is not allowed to own the service \"%s\" due " +@@ -478,6 +481,11 @@ bus_registry_acquire_service (BusRegistry *registry, + _dbus_string_get_const_data (service_name)); + goto out; + } ++ else if (res == BUS_RESULT_LATER) ++ { ++ retval = BUS_RESULT_LATER; ++ goto out; ++ } + + limit = bus_context_get_max_services_per_connection (registry->context); + +@@ -603,11 +611,13 @@ bus_registry_acquire_service (BusRegistry *registry, + } + + activation = bus_context_get_activation (registry->context); +- retval = bus_activation_send_pending_auto_activation_messages (activation, ++ ++ if (bus_activation_send_pending_auto_activation_messages (activation, + service, +- transaction); +- if (!retval) +- BUS_SET_OOM (error); ++ transaction)) ++ retval = BUS_RESULT_TRUE; ++ else ++ BUS_SET_OOM (error); + + out: + return retval; +diff --git a/bus/services.h b/bus/services.h +index 056dd9f..3df3dd7 100644 +--- a/bus/services.h ++++ b/bus/services.h +@@ -50,8 +50,9 @@ void bus_registry_foreach (BusRegistry *registry + dbus_bool_t bus_registry_list_services (BusRegistry *registry, + char ***listp, + int *array_len); +-dbus_bool_t bus_registry_acquire_service (BusRegistry *registry, ++BusResult bus_registry_acquire_service (BusRegistry *registry, + DBusConnection *connection, ++ DBusMessage *message, + const DBusString *service_name, + dbus_uint32_t flags, + dbus_uint32_t *result, +diff --git a/bus/stats.c b/bus/stats.c +index 1582255..c25be98 100644 +--- a/bus/stats.c ++++ b/bus/stats.c +@@ -36,7 +36,7 @@ + + #ifdef DBUS_ENABLE_STATS + +-dbus_bool_t ++BusResult + bus_stats_handle_get_stats (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -51,6 +51,9 @@ bus_stats_handle_get_stats (DBusConnection *connection, + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + ++ if (!bus_driver_check_message_is_for_us (message, error)) ++ return BUS_RESULT_FALSE; ++ + context = bus_transaction_get_context (transaction); + connections = bus_context_get_connections (context); + +@@ -104,17 +107,17 @@ bus_stats_handle_get_stats (DBusConnection *connection, + goto oom; + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + if (reply != NULL) + dbus_message_unref (reply); + + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + +-dbus_bool_t ++BusResult + bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -209,7 +212,7 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, + goto oom; + + dbus_message_unref (reply); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -218,11 +221,11 @@ failed: + if (reply != NULL) + dbus_message_unref (reply); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + +-dbus_bool_t ++BusResult + bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -246,7 +249,7 @@ bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection, + matchmaker = bus_context_get_matchmaker (context); + + if (!bus_registry_list_services (registry, &services, &services_len)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + reply = dbus_message_new_method_return (message); + if (reply == NULL) +@@ -325,7 +328,7 @@ bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection, + + dbus_message_unref (reply); + dbus_free_string_array (services); +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + if (reply != NULL) +@@ -334,7 +337,7 @@ oom: + dbus_free_string_array (services); + + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + #endif +diff --git a/bus/stats.h b/bus/stats.h +index dcb022c..683fa17 100644 +--- a/bus/stats.h ++++ b/bus/stats.h +@@ -25,17 +25,17 @@ + + #define BUS_INTERFACE_STATS "org.freedesktop.DBus.Debug.Stats" + +-dbus_bool_t bus_stats_handle_get_stats (DBusConnection *connection, ++BusResult bus_stats_handle_get_stats (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); + +-dbus_bool_t bus_stats_handle_get_connection_stats (DBusConnection *connection, ++BusResult bus_stats_handle_get_connection_stats (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); + +-dbus_bool_t bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection, ++BusResult bus_stats_handle_get_all_match_rules (DBusConnection *caller_connection, + BusTransaction *transaction, + DBusMessage *message, + DBusError *error); +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0005-Perform-Cynara-runtime-policy-checks-by-default.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0005-Perform-Cynara-runtime-policy-checks-by-default.patch new file mode 100644 index 000000000..5f7e96a3b --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0005-Perform-Cynara-runtime-policy-checks-by-default.patch @@ -0,0 +1,180 @@ +From 1f7ba56c9ced669951061d13b06e31d96a170e37 Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Tue, 23 Jun 2015 11:08:48 +0200 +Subject: [PATCH 5/8] Perform Cynara runtime policy checks by default +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +This change introduces http://tizen.org/privilege/internal/dbus privilege +which is supposed to be available only to trusted system resources. +Checks for this privilege are used in place of certain allow rules to +make security policy more strict. + +For system bus sending and receiving signals now requires +http://tizen.org/privilege/internal/dbus privilege. Requesting name +ownership and sending methods is still denied by default. + +For session bus http://tizen.org/privilege/internal/dbus privilege +is now required for requesting name, calling methods, sending and receiving +signals. + +Services are supposed to override these default settings to implement their +own security policy. + +Cherry picked from e8610297cf7031e94eb314a2e8c11246f4405403 by Jose Bollo + +Updated for dbus 1.10.20 by Scott Murray and José Bollo + +Signed-off-by: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +Signed-off-by: Scott Murray <scott.murray@konsulko.com> +--- + bus/activation.c | 42 ++++++++++++++++++++++++++---------------- + bus/session.conf.in | 32 ++++++++++++++++++++++++++------ + bus/system.conf.in | 19 +++++++++++++++---- + 3 files changed, 67 insertions(+), 26 deletions(-) + +diff --git a/bus/activation.c b/bus/activation.c +index d4b597c..8aabeaa 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -1840,22 +1840,32 @@ bus_activation_activate_service (BusActivation *activation, + } + + if (auto_activation && +- entry != NULL && +- BUS_RESULT_TRUE != bus_context_check_security_policy (activation->context, +- transaction, +- connection, /* sender */ +- NULL, /* addressed recipient */ +- NULL, /* proposed recipient */ +- activation_message, +- entry, +- error, +- NULL)) +- { +- _DBUS_ASSERT_ERROR_IS_SET (error); +- _dbus_verbose ("activation not authorized: %s: %s\n", +- error != NULL ? error->name : "(error ignored)", +- error != NULL ? error->message : "(error ignored)"); +- return FALSE; ++ entry != NULL) ++ { ++ BusResult result; ++ ++ result = bus_context_check_security_policy (activation->context, ++ transaction, ++ connection, /* sender */ ++ NULL, /* addressed recipient */ ++ NULL, /* proposed recipient */ ++ activation_message, ++ entry, ++ error, ++ NULL); ++ if (result == BUS_RESULT_FALSE) ++ { ++ _DBUS_ASSERT_ERROR_IS_SET (error); ++ _dbus_verbose ("activation not authorized: %s: %s\n", ++ error != NULL ? error->name : "(error ignored)", ++ error != NULL ? error->message : "(error ignored)"); ++ return FALSE; ++ } ++ if (result == BUS_RESULT_LATER) ++ { ++ /* TODO */ ++ _dbus_verbose ("ALERT FIX ME!!!!!!!!!!!!!!!"); ++ } + } + + /* Bypass the registry lookup if we're auto-activating, bus_dispatch would not +diff --git a/bus/session.conf.in b/bus/session.conf.in +index affa7f1..157dfb4 100644 +--- a/bus/session.conf.in ++++ b/bus/session.conf.in +@@ -27,12 +27,32 @@ + <standard_session_servicedirs /> + + <policy context="default"> +- <!-- Allow everything to be sent --> +- <allow send_destination="*" eavesdrop="true"/> +- <!-- Allow everything to be received --> +- <allow eavesdrop="true"/> +- <!-- Allow anyone to own anything --> +- <allow own="*"/> ++ <!-- By default clients require internal/dbus privilege to communicate ++ with D-Bus services and to claim name ownership. This is internal privilege that ++ is only accessible to trusted system services --> ++ <check own="*" privilege="http://tizen.org/privilege/internal/dbus" /> ++ <check send_type="method_call" privilege="http://tizen.org/privilege/internal/dbus" /> ++ <check send_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> ++ <check receive_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> ++ ++ <!-- Reply messages (method returns, errors) are allowed ++ by default --> ++ <allow send_requested_reply="true" send_type="method_return"/> ++ <allow send_requested_reply="true" send_type="error"/> ++ ++ <!-- All messages but signals may be received by default --> ++ <allow receive_type="method_call"/> ++ <allow receive_type="method_return"/> ++ <allow receive_type="error"/> ++ ++ <!-- Allow anyone to talk to the message bus --> ++ <allow send_destination="org.freedesktop.DBus"/> ++ <allow receive_sender="org.freedesktop.DBus"/> ++ ++ <!-- But disallow some specific bus services --> ++ <deny send_destination="org.freedesktop.DBus" ++ send_interface="org.freedesktop.DBus" ++ send_member="UpdateActivationEnvironment"/> + </policy> + + <!-- Include legacy configuration location --> +diff --git a/bus/system.conf.in b/bus/system.conf.in +index f139b55..19d0c04 100644 +--- a/bus/system.conf.in ++++ b/bus/system.conf.in +@@ -50,17 +50,20 @@ + <deny own="*"/> + <deny send_type="method_call"/> + +- <!-- Signals and reply messages (method returns, errors) are allowed ++ <!-- By default clients require internal/dbus privilege to send and receive signaks. ++ This is internal privilege that is only accessible to trusted system services --> ++ <check send_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> ++ <check receive_type="signal" privilege="http://tizen.org/privilege/internal/dbus" /> ++ ++ <!-- Reply messages (method returns, errors) are allowed + by default --> +- <allow send_type="signal"/> + <allow send_requested_reply="true" send_type="method_return"/> + <allow send_requested_reply="true" send_type="error"/> + +- <!-- All messages may be received by default --> ++ <!-- All messages but signals may be received by default --> + <allow receive_type="method_call"/> + <allow receive_type="method_return"/> + <allow receive_type="error"/> +- <allow receive_type="signal"/> + + <!-- Allow anyone to talk to the message bus --> + <allow send_destination="org.freedesktop.DBus" +@@ -69,6 +72,14 @@ + send_interface="org.freedesktop.DBus.Introspectable"/> + <allow send_destination="org.freedesktop.DBus" + send_interface="org.freedesktop.DBus.Properties"/> ++ <!-- If there is a need specific bus services could be protected by Cynara as well. ++ However, this can lead to deadlock during the boot process when such check is made and ++ Cynara is not yet activated (systemd calls protected method synchronously, ++ dbus daemon tries to consult Cynara, Cynara waits for systemd activation). ++ Therefore it is advised to allow root processes to use bus services. ++ Currently anyone is allowed to talk to the message bus --> ++ <allow receive_sender="org.freedesktop.DBus"/> ++ + <!-- But disallow some specific bus services --> + <deny send_destination="org.freedesktop.DBus" + send_interface="org.freedesktop.DBus" +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0006-Fix-SIGSEGV-on-disconnections.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0006-Fix-SIGSEGV-on-disconnections.patch new file mode 100644 index 000000000..e51ad7ce4 --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0006-Fix-SIGSEGV-on-disconnections.patch @@ -0,0 +1,109 @@ +From 28077faa11827e1ca7a7245ffd62ee78091b6bd2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Fri, 16 Aug 2019 13:29:23 +0200 +Subject: [PATCH 6/8] Fix SIGSEGV on disconnections +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Sometime, at start of the system, dbus-daemon was crashing +because a pending authorisation were reactivating a closed +connection. + +Also, clean unused function. + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + bus/check.c | 5 +++++ + bus/check.h | 1 + + bus/connection.c | 14 +++----------- + bus/connection.h | 3 --- + 4 files changed, 9 insertions(+), 14 deletions(-) + +diff --git a/bus/check.c b/bus/check.c +index f3d283f..b73d08b 100644 +--- a/bus/check.c ++++ b/bus/check.c +@@ -617,3 +617,8 @@ bus_deferred_message_response_received (BusDeferredMessage *deferred_message, + } + } + ++void ++bus_deferred_message_abort (BusDeferredMessage *deferred_message) ++{ ++ deferred_message->response_callback = NULL; ++} +diff --git a/bus/check.h b/bus/check.h +index 9c13c18..d718a69 100644 +--- a/bus/check.h ++++ b/bus/check.h +@@ -93,6 +93,7 @@ void bus_deferred_message_set_policy_check_info (BusDeferredMessa + const char *privilege); + dbus_bool_t bus_deferred_message_check_message_limits (BusDeferredMessage *deferred_message, + DBusError *error); ++void bus_deferred_message_abort (BusDeferredMessage *deferred_message); + + + #ifdef DBUS_ENABLE_EMBEDDED_TESTS +diff --git a/bus/connection.c b/bus/connection.c +index ee93384..b520d57 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -47,6 +47,7 @@ + #define MAX_LOG_COMMAND_LEN 50 + + static void bus_connection_remove_transactions (DBusConnection *connection); ++static void bus_connection_clear_deferred_messages (DBusConnection *connection); + + typedef struct + { +@@ -2821,17 +2822,7 @@ bus_connection_pop_deferred_message (DBusConnection *connection) + return NULL; + } + +-dbus_bool_t +-bus_connection_putback_deferred_message (DBusConnection *connection, BusDeferredMessage *message) +-{ +- BusConnectionData *d = BUS_CONNECTION_DATA(connection); +- if (_dbus_list_prepend(&d->deferred_messages, message)) +- { +- return TRUE; +- } +- return FALSE; +-} +- ++static + void + bus_connection_clear_deferred_messages (DBusConnection *connection) + { +@@ -2846,6 +2837,7 @@ bus_connection_clear_deferred_messages (DBusConnection *connection) + next = _dbus_list_get_next_link (&d->deferred_messages, link); + message = link->data; + ++ bus_deferred_message_abort(message); + bus_deferred_message_unref(message); + _dbus_list_remove_link(&d->deferred_messages, link); + +diff --git a/bus/connection.h b/bus/connection.h +index 97dae96..6af7bf1 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -90,15 +90,12 @@ dbus_bool_t bus_connection_queue_deferred_message (DBusConnection *con + BusDeferredMessage *message, + dbus_bool_t prepend); + BusDeferredMessage *bus_connection_pop_deferred_message (DBusConnection *connection); +-dbus_bool_t bus_connection_putback_deferred_message (DBusConnection *connection, +- BusDeferredMessage *message); + void bus_connection_remove_deferred_message (DBusConnection *connection, + BusDeferredMessage *message); + dbus_bool_t bus_connection_replace_deferred_message (DBusConnection *connection, + BusDeferredMessage *oldMessage, + BusDeferredMessage *newMessage); + void bus_connection_dispatch_deferred (DBusConnection *connection); +-void bus_connection_clear_deferred_messages (DBusConnection *connection); + + + /* called by signals.c */ +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0007-Switch-from-cynara-to-cynagora.patch b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0007-Switch-from-cynara-to-cynagora.patch new file mode 100644 index 000000000..7a69efcd2 --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus-cynagora/0007-Switch-from-cynara-to-cynagora.patch @@ -0,0 +1,1048 @@ +From 43cc361a5c32c81c0f93451bdb0ef781cd19a1cb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Tue, 4 Feb 2020 12:23:36 +0100 +Subject: [PATCH 7/8] Switch from cynara to cynagora +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + bus/Makefile.am | 8 +- + bus/bus.h | 2 +- + bus/check.c | 26 +- + bus/check.h | 2 +- + bus/connection.c | 27 --- + bus/connection.h | 3 - + bus/cynagora-check.c | 330 +++++++++++++++++++++++++ + bus/{cynara.h => cynagora-check.h} | 10 +- + bus/cynara.c | 373 ----------------------------- + bus/system.conf.in | 6 +- + configure.ac | 18 +- + 11 files changed, 366 insertions(+), 439 deletions(-) + create mode 100644 bus/cynagora-check.c + rename bus/{cynara.h => cynagora-check.h} (81%) + delete mode 100644 bus/cynara.c + +diff --git a/bus/Makefile.am b/bus/Makefile.am +index 2a8a72c..1720048 100644 +--- a/bus/Makefile.am ++++ b/bus/Makefile.am +@@ -13,7 +13,7 @@ DBUS_BUS_LIBS = \ + $(THREAD_LIBS) \ + $(ADT_LIBS) \ + $(NETWORK_libs) \ +- $(CYNARA_LIBS) \ ++ $(CYNAGORA_LIBS) \ + $(NULL) + + DBUS_LAUNCHER_LIBS = \ +@@ -31,7 +31,7 @@ AM_CPPFLAGS = \ + $(APPARMOR_CFLAGS) \ + -DDBUS_SYSTEM_CONFIG_FILE=\""$(dbusdatadir)/system.conf"\" \ + -DDBUS_COMPILATION \ +- $(CYNARA_CFLAGS) \ ++ $(CYNAGORA_CFLAGS) \ + $(NULL) + + # if assertions are enabled, improve backtraces +@@ -101,8 +101,8 @@ BUS_SOURCES= \ + config-parser-common.h \ + connection.c \ + connection.h \ +- cynara.c \ +- cynara.h \ ++ cynagora-check.c \ ++ cynagora-check.h \ + desktop-file.c \ + desktop-file.h \ + $(DIR_WATCH_SOURCE) \ +diff --git a/bus/bus.h b/bus/bus.h +index 1b08f7c..e167d9e 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -47,7 +47,7 @@ typedef struct BusMatchRule BusMatchRule; + typedef struct BusActivationEntry BusActivationEntry; + typedef struct BusCheck BusCheck; + typedef struct BusDeferredMessage BusDeferredMessage; +-typedef struct BusCynara BusCynara; ++typedef struct BusCynagora BusCynagora; + + /** + * BusResult is defined as a pointer to a dummy structure to allow detection of type mismatches. +diff --git a/bus/check.c b/bus/check.c +index b73d08b..ec30770 100644 +--- a/bus/check.c ++++ b/bus/check.c +@@ -26,7 +26,7 @@ + #include "check.h" + #include "connection.h" + #include "dispatch.h" +-#include "cynara.h" ++#include "cynagora-check.h" + #include "utils.h" + #include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-message-internal.h> +@@ -38,7 +38,7 @@ typedef struct BusCheck + int refcount; + + BusContext *context; +- BusCynara *cynara; ++ BusCynagora *cynagora; + } BusCheck; + + typedef struct BusDeferredMessage +@@ -81,7 +81,7 @@ bus_check_new (BusContext *context, DBusError *error) + + check->refcount = 1; + check->context = context; +- check->cynara = bus_cynara_new(check, error); ++ check->cynagora = bus_cynagora_new(check, error); + if (dbus_error_is_set(error)) + { + dbus_message_free_data_slot(&deferred_message_data_slot); +@@ -110,7 +110,7 @@ bus_check_unref (BusCheck *check) + + if (check->refcount == 0) + { +- bus_cynara_unref(check->cynara); ++ bus_cynagora_unref(check->cynagora); + dbus_message_free_data_slot(&deferred_message_data_slot); + dbus_free(check); + } +@@ -122,10 +122,10 @@ bus_check_get_context (BusCheck *check) + return check->context; + } + +-BusCynara * +-bus_check_get_cynara (BusCheck *check) ++BusCynagora * ++bus_check_get_cynagora (BusCheck *check) + { +- return check->cynara; ++ return check->cynagora; + } + + static void +@@ -276,8 +276,8 @@ bus_check_privilege (BusCheck *check, + { + BusDeferredMessage *previous_deferred_message; + BusResult result = BUS_RESULT_FALSE; +-#ifdef DBUS_ENABLE_CYNARA +- BusCynara *cynara; ++#ifdef DBUS_ENABLE_CYNAGORA ++ BusCynagora *cynagora; + #endif + DBusConnection *connection; + +@@ -304,7 +304,7 @@ bus_check_privilege (BusCheck *check, + * Message has been deferred due to receive or own rule which means that sending this message + * is allowed - it must have been checked previously. + * This might happen when client calls RequestName method which depending on security +- * policy might result in both "can_send" and "can_own" Cynara checks. ++ * policy might result in both "can_send" and "can_own" Cynagora checks. + */ + result = BUS_RESULT_TRUE; + } +@@ -327,9 +327,9 @@ bus_check_privilege (BusCheck *check, + else + { + /* ask policy checkers */ +-#ifdef DBUS_ENABLE_CYNARA +- cynara = bus_check_get_cynara(check); +- result = bus_cynara_check_privilege(cynara, message, sender, addressed_recipient, ++#ifdef DBUS_ENABLE_CYNAGORA ++ cynagora = bus_check_get_cynagora(check); ++ result = bus_cynagora_check_privilege(cynagora, message, sender, addressed_recipient, + proposed_recipient, privilege, check_type, deferred_message); + #endif + if (result == BUS_RESULT_LATER && deferred_message != NULL) +diff --git a/bus/check.h b/bus/check.h +index d718a69..ab63c18 100644 +--- a/bus/check.h ++++ b/bus/check.h +@@ -45,7 +45,7 @@ BusCheck *bus_check_ref (BusCheck *check); + void bus_check_unref (BusCheck *check); + + BusContext *bus_check_get_context (BusCheck *check); +-BusCynara *bus_check_get_cynara (BusCheck *check); ++BusCynagora *bus_check_get_cynagora (BusCheck *check); + BusResult bus_check_privilege (BusCheck *check, + DBusMessage *message, + DBusConnection *sender, +diff --git a/bus/connection.c b/bus/connection.c +index b520d57..48910e0 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -38,10 +38,6 @@ + #include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-internals.h> + #include <dbus/dbus-message-internal.h> +-#ifdef DBUS_ENABLE_CYNARA +-#include <stdlib.h> +-#include <cynara-session.h> +-#endif + + /* Trim executed commands to this length; we want to keep logs readable */ + #define MAX_LOG_COMMAND_LEN 50 +@@ -124,9 +120,6 @@ typedef struct + + /** non-NULL if and only if this is a monitor */ + DBusList *link_in_monitors; +-#ifdef DBUS_ENABLE_CYNARA +- char *cynara_session_id; +-#endif + } BusConnectionData; + + static dbus_bool_t bus_pending_reply_expired (BusExpireList *list, +@@ -461,10 +454,6 @@ free_connection_data (void *data) + + dbus_free (d->name); + +-#ifdef DBUS_ENABLE_CYNARA +- free (d->cynara_session_id); +-#endif +- + dbus_free (d); + } + +@@ -1095,22 +1084,6 @@ bus_connection_get_policy (DBusConnection *connection) + return d->policy; + } + +-#ifdef DBUS_ENABLE_CYNARA +-const char *bus_connection_get_cynara_session_id (DBusConnection *connection) +-{ +- BusConnectionData *d = BUS_CONNECTION_DATA (connection); +- _dbus_assert (d != NULL); +- +- if (d->cynara_session_id == NULL) +- { +- unsigned long pid; +- if (dbus_connection_get_unix_process_id(connection, &pid)) +- d->cynara_session_id = cynara_session_from_pid(pid); +- } +- return d->cynara_session_id; +-} +-#endif +- + static dbus_bool_t + foreach_active (BusConnections *connections, + BusConnectionForeachFunction function, +diff --git a/bus/connection.h b/bus/connection.h +index 6af7bf1..3116bcf 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -138,9 +138,6 @@ dbus_bool_t bus_connection_be_monitor (DBusConnection *connection, + BusTransaction *transaction, + DBusList **rules, + DBusError *error); +-#ifdef DBUS_ENABLE_CYNARA +-const char *bus_connection_get_cynara_session_id (DBusConnection *connection); +-#endif + + /* transaction API so we can send or not send a block of messages as a whole */ + +diff --git a/bus/cynagora-check.c b/bus/cynagora-check.c +new file mode 100644 +index 0000000..6c0c635 +--- /dev/null ++++ b/bus/cynagora-check.c +@@ -0,0 +1,330 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++/* cynagora.c Cynagora runtime privilege checking ++ * ++ * Copyright (c) 2014 Samsung Electronics, Ltd. ++ * ++ * Licensed under the Academic Free License version 2.1 ++ * ++ * This program is free software; you can redistribute it and/or modify ++ * it under the terms of the GNU General Public License as published by ++ * the Free Software Foundation; either version 2 of the License, or ++ * (at your option) any later version. ++ * ++ * This program 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 General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ++ * ++ */ ++ ++#include <config.h> ++#include "cynagora-check.h" ++#include "check.h" ++#include "utils.h" ++ ++#include <stdlib.h> ++#include <stdio.h> ++#include <errno.h> ++ ++#include <dbus/dbus.h> ++#include <dbus/dbus-watch.h> ++#include <dbus/dbus-connection-internal.h> ++#include <bus/connection.h> ++ ++#ifndef DBUS_ENABLE_CYNAGORA ++ ++BusCynagora * ++bus_cynagora_new(BusCheck *check, DBusError *error) ++{ ++ return NULL; ++} ++ ++BusCynagora * ++bus_cynagora_ref (BusCynagora *cynagora) ++{ ++ return NULL; ++} ++ ++void ++bus_cynagora_unref (BusCynagora *cynagora) ++{ ++} ++ ++BusResult ++bus_cynagora_check_privilege (BusCynagora *cynagora, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *privilege, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message_param) ++{ ++ return BUS_RESULT_FALSE; ++} ++ ++#endif ++ ++#ifdef DBUS_ENABLE_CYNAGORA ++ ++#include <time.h> ++#include <sys/epoll.h> ++ ++#include <cynagora.h> ++ ++#ifndef CYNAGORA_CACHE_SIZE ++#define CYNAGORA_CACHE_SIZE 8000 ++#endif ++ ++typedef struct BusCynagora ++{ ++ int refcount; ++ ++ BusContext *context; ++ BusCheck *check; ++ cynagora_t *cynagora; ++ DBusWatch *cynagora_watch; ++} BusCynagora; ++ ++static int async_callback(void *closure, ++ int op, ++ int fd, ++ uint32_t events); ++ ++BusCynagora * ++bus_cynagora_new(BusCheck *check, DBusError *error) ++{ ++ BusContext *context; ++ BusCynagora *cynagora; ++ int ret; ++ ++ cynagora = dbus_new(BusCynagora, 1); ++ if (cynagora == NULL) ++ { ++ BUS_SET_OOM(error); ++ return NULL; ++ } ++ ++ context = bus_check_get_context(check); ++ ++ cynagora->refcount = 1; ++ cynagora->check = check; ++ cynagora->context = context; ++ cynagora->cynagora_watch = NULL; ++ ++ ret = cynagora_create(&cynagora->cynagora, cynagora_Check, CYNAGORA_CACHE_SIZE, NULL); ++ if (ret < 0) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynagora configuration"); ++ } ++ else ++ { ++ ret = cynagora_async_setup(cynagora->cynagora, async_callback, cynagora); ++ if (ret < 0) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynagora client"); ++ } ++ else ++ { ++ return cynagora; ++ } ++ cynagora_destroy(cynagora->cynagora); ++ } ++ ++ dbus_free(cynagora); ++ return NULL; ++} ++ ++BusCynagora * ++bus_cynagora_ref (BusCynagora *cynagora) ++{ ++ _dbus_assert (cynagora->refcount > 0); ++ cynagora->refcount += 1; ++ ++ return cynagora; ++} ++ ++void ++bus_cynagora_unref (BusCynagora *cynagora) ++{ ++ _dbus_assert (cynagora->refcount > 0); ++ ++ cynagora->refcount -= 1; ++ ++ if (cynagora->refcount == 0) ++ { ++ cynagora_destroy(cynagora->cynagora); ++ dbus_free(cynagora); ++ } ++} ++ ++static void ++async_check_callback (void *closure, int status) ++{ ++ BusDeferredMessage *deferred_message = closure; ++ BusResult result; ++ ++ if (deferred_message == NULL) ++ return; ++ ++ if (status == 1) ++ result = BUS_RESULT_TRUE; ++ else ++ result = BUS_RESULT_FALSE; ++ ++ bus_deferred_message_response_received(deferred_message, result); ++ bus_deferred_message_unref(deferred_message); ++} ++ ++BusResult ++bus_cynagora_check_privilege (BusCynagora *cynagora, ++ DBusMessage *message, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ const char *permission, ++ BusDeferredMessageStatus check_type, ++ BusDeferredMessage **deferred_message_param) ++{ ++ int result; ++ unsigned long uid; ++ unsigned long pid; ++ char *label; ++ char user[32]; ++ char session[32]; ++ DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; ++ BusDeferredMessage *deferred_message; ++ BusResult ret; ++ cynagora_key_t key; ++ ++ _dbus_assert(connection != NULL); ++ ++ if (dbus_connection_get_unix_user(connection, &uid) == FALSE) ++ return BUS_RESULT_FALSE; ++ ++ if (dbus_connection_get_unix_process_id(connection, &pid) == FALSE) ++ return BUS_RESULT_FALSE; ++ ++ if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL) ++ { ++ _dbus_warn("Failed to obtain security label for connection\n"); ++ return BUS_RESULT_FALSE; ++ } ++ ++ snprintf(user, sizeof(user), "%lu", uid); ++ snprintf(session, sizeof(session), "%lu", pid); ++ ++ key.client = label; ++ key.session = session; ++ key.user = user; ++ key.permission = permission; ++ ++ result = cynagora_cache_check(cynagora->cynagora, &key); ++ switch (result) ++ { ++ case 1: ++ _dbus_verbose("Cynagora: got ALLOWED answer from cache (client=%s session_id=%s user=%s permission=%s)\n", ++ label, session_id, user, permission); ++ ret = BUS_RESULT_TRUE; ++ break; ++ ++ case 0: ++ _dbus_verbose("Cynagora: got DENIED answer from cache (client=%s session_id=%s user=%s permission=%s)\n", ++ label, session_id, user, permission); ++ ret = BUS_RESULT_FALSE; ++ break; ++ ++ default: ++ deferred_message = bus_deferred_message_new(message, sender, addressed_recipient, ++ proposed_recipient, BUS_RESULT_LATER); ++ if (deferred_message == NULL) ++ { ++ _dbus_verbose("Failed to allocate memory for deferred message\n"); ++ ret = BUS_RESULT_FALSE; ++ goto out; ++ } ++ ++ /* callback is supposed to unref deferred_message*/ ++ result = cynagora_async_check(cynagora->cynagora, &key, 1, 0, async_check_callback, deferred_message); ++ if (result == 0) ++ { ++ _dbus_verbose("Created Cynagora request: client=%s session_id=%s user=%s permission=%s " ++ "deferred_message=%p\n", label, session_id, user, permission, deferred_message); ++ if (deferred_message_param != NULL) ++ *deferred_message_param = deferred_message; ++ ret = BUS_RESULT_LATER; ++ } ++ else ++ { ++ _dbus_verbose("Error on cynagora request create: %i\n", result); ++ bus_deferred_message_unref(deferred_message); ++ ret = BUS_RESULT_FALSE; ++ } ++ break; ++ } ++out: ++ dbus_free(label); ++ return ret; ++} ++ ++static dbus_bool_t ++watch_handler_callback(DBusWatch *watch, ++ unsigned int flags, ++ void *data) ++{ ++ BusCynagora *cynagora = (BusCynagora *)data; ++ int result = cynagora_async_process(cynagora->cynagora); ++ if (result < 0) ++ _dbus_verbose("cynagora_async_process returned %d\n", result); ++ ++ return result != -ENOMEM ? TRUE : FALSE; ++} ++ ++static int ++async_callback(void *closure, int op, int fd, uint32_t events) ++{ ++ BusCynagora *cynagora = (BusCynagora *)closure; ++ DBusLoop *loop = bus_context_get_loop(cynagora->context); ++ unsigned int flags; ++ DBusWatch *watch; ++ ++ /* compute flags */ ++ flags = 0; ++ if (events & EPOLLIN) ++ flags |= DBUS_WATCH_READABLE; ++ if (events & EPOLLOUT) ++ flags |= DBUS_WATCH_WRITABLE; ++ ++ /* remove the watch if needed */ ++ watch = cynagora->cynagora_watch; ++ if (watch != NULL) ++ { ++ cynagora->cynagora_watch = NULL; ++ _dbus_loop_remove_watch(loop, watch); ++ _dbus_watch_invalidate(watch); ++ _dbus_watch_unref(watch); ++ } ++ ++ /* create the watch if needed */ ++ watch = cynagora->cynagora_watch; ++ if (op != EPOLL_CTL_DEL) ++ { ++ watch = _dbus_watch_new(fd, flags, TRUE, watch_handler_callback, cynagora, NULL); ++ if (watch == NULL) ++ return -ENOMEM; ++ if (_dbus_loop_add_watch(loop, watch) != TRUE) ++ { ++ _dbus_watch_invalidate(watch); ++ _dbus_watch_unref(watch); ++ return -ENOMEM; ++ } ++ cynagora->cynagora_watch = watch; ++ } ++ return 0; ++} ++ ++#endif /* DBUS_ENABLE_CYNAGORA */ +diff --git a/bus/cynara.h b/bus/cynagora-check.h +similarity index 81% +rename from bus/cynara.h +rename to bus/cynagora-check.h +index c4728bb..c0892c3 100644 +--- a/bus/cynara.h ++++ b/bus/cynagora-check.h +@@ -1,5 +1,5 @@ + /* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +-/* cynara.h Cynara runtime privilege checking ++/* cynagora.h Cynagora runtime privilege checking + * + * Copyright (c) 2014 Samsung Electronics, Ltd. + * +@@ -24,10 +24,10 @@ + #include "bus.h" + #include "check.h" + +-BusCynara *bus_cynara_new (BusCheck *check, DBusError *error); +-BusCynara *bus_cynara_ref (BusCynara *cynara); +-void bus_cynara_unref (BusCynara *cynara); +-BusResult bus_cynara_check_privilege (BusCynara *cynara, ++BusCynagora *bus_cynagora_new (BusCheck *check, DBusError *error); ++BusCynagora *bus_cynagora_ref (BusCynagora *cynagora); ++void bus_cynagora_unref (BusCynagora *cynagora); ++BusResult bus_cynagora_check_privilege (BusCynagora *cynagora, + DBusMessage *message, + DBusConnection *sender, + DBusConnection *addressed_recipient, +diff --git a/bus/cynara.c b/bus/cynara.c +deleted file mode 100644 +index 77aed62..0000000 +--- a/bus/cynara.c ++++ /dev/null +@@ -1,373 +0,0 @@ +-/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +-/* cynara.c Cynara runtime privilege checking +- * +- * Copyright (c) 2014 Samsung Electronics, Ltd. +- * +- * Licensed under the Academic Free License version 2.1 +- * +- * This program is free software; you can redistribute it and/or modify +- * it under the terms of the GNU General Public License as published by +- * the Free Software Foundation; either version 2 of the License, or +- * (at your option) any later version. +- * +- * This program 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 General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA +- * +- */ +- +-#include <config.h> +-#include "cynara.h" +-#include "check.h" +-#include "utils.h" +- +-#include <stdio.h> +- +-#include <dbus/dbus.h> +-#include <dbus/dbus-watch.h> +-#include <dbus/dbus-connection-internal.h> +-#include <bus/connection.h> +-#ifdef DBUS_ENABLE_CYNARA +-#include <cynara-client-async.h> +-#endif +- +-#ifdef DBUS_ENABLE_CYNARA +-typedef struct BusCynara +-{ +- int refcount; +- +- BusContext *context; +- BusCheck *check; +- cynara_async *cynara; +- DBusWatch *cynara_watch; +-} BusCynara; +- +-#define USE_CYNARA_CACHE 1 +-#ifdef USE_CYNARA_CACHE +-#define CYNARA_CACHE_SIZE 1000 +-#endif +- +-static dbus_bool_t bus_cynara_watch_callback(DBusWatch *watch, +- unsigned int flags, +- void *data); +- +-static void status_callback(int old_fd, +- int new_fd, +- cynara_async_status status, +- void *user_status_data); +-static void bus_cynara_check_response_callback (cynara_check_id check_id, +- cynara_async_call_cause cause, +- int response, +- void *user_response_data); +-#endif +- +- +-BusCynara * +-bus_cynara_new(BusCheck *check, DBusError *error) +-{ +-#ifdef DBUS_ENABLE_CYNARA +- BusContext *context; +- BusCynara *cynara; +- cynara_async_configuration *conf = NULL; +- int ret; +- +- cynara = dbus_new(BusCynara, 1); +- if (cynara == NULL) +- { +- BUS_SET_OOM(error); +- return NULL; +- } +- +- context = bus_check_get_context(check); +- +- cynara->refcount = 1; +- cynara->check = check; +- cynara->context = context; +- cynara->cynara_watch = NULL; +- +- ret = cynara_async_configuration_create(&conf); +- if (ret != CYNARA_API_SUCCESS) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to create Cynara configuration"); +- goto out; +- } +- +-#ifdef CYNARA_CACHE_SIZE +- ret = cynara_async_configuration_set_cache_size(conf, CYNARA_CACHE_SIZE); +- if (ret != CYNARA_API_SUCCESS) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to Cynara cache size"); +- goto out; +- } +-#endif +- +- ret = cynara_async_initialize(&cynara->cynara, conf, &status_callback, cynara); +- if (ret != CYNARA_API_SUCCESS) +- { +- dbus_set_error (error, DBUS_ERROR_FAILED, "Failed to initialize Cynara client"); +- goto out; +- } +- +-out: +- cynara_async_configuration_destroy(conf); +- if (ret != CYNARA_API_SUCCESS) +- { +- dbus_free(cynara); +- return NULL; +- } +- +- return cynara; +-#else +- return NULL; +-#endif +-} +- +-BusCynara * +-bus_cynara_ref (BusCynara *cynara) +-{ +-#ifdef DBUS_ENABLE_CYNARA +- _dbus_assert (cynara->refcount > 0); +- cynara->refcount += 1; +- +- return cynara; +-#else +- return NULL; +-#endif +-} +- +-void +-bus_cynara_unref (BusCynara *cynara) +-{ +-#ifdef DBUS_ENABLE_CYNARA +- _dbus_assert (cynara->refcount > 0); +- +- cynara->refcount -= 1; +- +- if (cynara->refcount == 0) +- { +- cynara_async_finish(cynara->cynara); +- dbus_free(cynara); +- } +-#endif +-} +- +-BusResult +-bus_cynara_check_privilege (BusCynara *cynara, +- DBusMessage *message, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusConnection *proposed_recipient, +- const char *privilege, +- BusDeferredMessageStatus check_type, +- BusDeferredMessage **deferred_message_param) +-{ +-#ifdef DBUS_ENABLE_CYNARA +- int result; +- unsigned long uid; +- char *label; +- const char *session_id; +- char user[32]; +- cynara_check_id check_id; +- DBusConnection *connection = check_type == BUS_DEFERRED_MESSAGE_CHECK_RECEIVE ? proposed_recipient : sender; +- BusDeferredMessage *deferred_message; +- BusResult ret; +- +- _dbus_assert(connection != NULL); +- +- if (dbus_connection_get_unix_user(connection, &uid) == FALSE) +- return BUS_RESULT_FALSE; +- +- if (_dbus_connection_get_linux_security_label(connection, &label) == FALSE || label == NULL) +- { +- _dbus_warn("Failed to obtain security label for connection\n"); +- return BUS_RESULT_FALSE; +- } +- +- session_id = bus_connection_get_cynara_session_id (connection); +- if (session_id == NULL) +- { +- ret = BUS_RESULT_FALSE; +- goto out; +- } +- +- snprintf(user, sizeof(user), "%lu", uid); +- +-#if USE_CYNARA_CACHE +- result = cynara_async_check_cache(cynara->cynara, label, session_id, user, privilege); +-#else +- result = CYNARA_API_CACHE_MISS; +-#endif +- +- switch (result) +- { +- case CYNARA_API_ACCESS_ALLOWED: +- _dbus_verbose("Cynara: got ALLOWED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", +- label, session_id, user, privilege); +- ret = BUS_RESULT_TRUE; +- break; +- +- case CYNARA_API_ACCESS_DENIED: +- _dbus_verbose("Cynara: got DENIED answer from cache (client=%s session_id=%s user=%s privilege=%s)\n", +- label, session_id, user, privilege); +- ret = BUS_RESULT_FALSE; +- break; +- +- case CYNARA_API_CACHE_MISS: +- deferred_message = bus_deferred_message_new(message, sender, addressed_recipient, +- proposed_recipient, BUS_RESULT_LATER); +- if (deferred_message == NULL) +- { +- _dbus_verbose("Failed to allocate memory for deferred message\n"); +- ret = BUS_RESULT_FALSE; +- goto out; +- } +- +- /* callback is supposed to unref deferred_message*/ +- result = cynara_async_create_request(cynara->cynara, label, session_id, user, privilege, &check_id, +- &bus_cynara_check_response_callback, deferred_message); +- if (result == CYNARA_API_SUCCESS) +- { +- _dbus_verbose("Created Cynara request: client=%s session_id=%s user=%s privilege=%s check_id=%u " +- "deferred_message=%p\n", label, session_id, user, privilege, (unsigned int)check_id, deferred_message); +- if (deferred_message_param != NULL) +- *deferred_message_param = deferred_message; +- ret = BUS_RESULT_LATER; +- } +- else +- { +- _dbus_verbose("Error on cynara request create: %i\n", result); +- bus_deferred_message_unref(deferred_message); +- ret = BUS_RESULT_FALSE; +- } +- break; +- default: +- _dbus_verbose("Error when accessing Cynara cache: %i\n", result); +- ret = BUS_RESULT_FALSE; +- } +-out: +- dbus_free(label); +- return ret; +- +-#else +- return BUS_RESULT_FALSE; +-#endif +-} +- +- +- +-#ifdef DBUS_ENABLE_CYNARA +-static void +-status_callback(int old_fd, int new_fd, cynara_async_status status, +- void *user_status_data) +-{ +- BusCynara *cynara = (BusCynara *)user_status_data; +- DBusLoop *loop = bus_context_get_loop(cynara->context); +- +- if (cynara->cynara_watch != NULL) +- { +- _dbus_loop_remove_watch(loop, cynara->cynara_watch); +- _dbus_watch_invalidate(cynara->cynara_watch); +- _dbus_watch_unref(cynara->cynara_watch); +- cynara->cynara_watch = NULL; +- } +- +- if (new_fd != -1) +- { +- unsigned int flags; +- DBusWatch *watch; +- +- switch (status) +- { +- case CYNARA_STATUS_FOR_READ: +- flags = DBUS_WATCH_READABLE; +- break; +- case CYNARA_STATUS_FOR_RW: +- flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; +- break; +- default: +- /* Cynara passed unknown status - warn and add RW watch */ +- _dbus_verbose("Cynara passed unknown status value: 0x%08X\n", (unsigned int)status); +- flags = DBUS_WATCH_READABLE | DBUS_WATCH_WRITABLE; +- break; +- } +- +- watch = _dbus_watch_new(new_fd, flags, TRUE, &bus_cynara_watch_callback, cynara, NULL); +- if (watch != NULL) +- { +- if (_dbus_loop_add_watch(loop, watch) == TRUE) +- { +- cynara->cynara_watch = watch; +- return; +- } +- +- _dbus_watch_invalidate(watch); +- _dbus_watch_unref(watch); +- } +- +- /* It seems like not much can be done at this point. Cynara events won't be processed +- * until next Cynara function call triggering status callback */ +- _dbus_verbose("Failed to add dbus watch\n"); +- } +-} +- +-static dbus_bool_t +-bus_cynara_watch_callback(DBusWatch *watch, +- unsigned int flags, +- void *data) +-{ +- BusCynara *cynara = (BusCynara *)data; +- int result = cynara_async_process(cynara->cynara); +- if (result != CYNARA_API_SUCCESS) +- _dbus_verbose("cynara_async_process returned %d\n", result); +- +- return result != CYNARA_API_OUT_OF_MEMORY ? TRUE : FALSE; +-} +- +-static inline const char * +-call_cause_to_string(cynara_async_call_cause cause) +-{ +- switch (cause) +- { +- case CYNARA_CALL_CAUSE_ANSWER: +- return "ANSWER"; +- case CYNARA_CALL_CAUSE_CANCEL: +- return "CANCEL"; +- case CYNARA_CALL_CAUSE_FINISH: +- return "FINSIH"; +- case CYNARA_CALL_CAUSE_SERVICE_NOT_AVAILABLE: +- return "SERVICE NOT AVAILABLE"; +- default: +- return "INVALID"; +- } +-} +- +-static void +-bus_cynara_check_response_callback (cynara_check_id check_id, +- cynara_async_call_cause cause, +- int response, +- void *user_response_data) +-{ +- BusDeferredMessage *deferred_message = user_response_data; +- BusResult result; +- +- _dbus_verbose("Cynara callback: check_id=%u, cause=%s response=%i response_data=%p\n", +- (unsigned int)check_id, call_cause_to_string(cause), response, user_response_data); +- +- if (deferred_message == NULL) +- return; +- +- if (cause == CYNARA_CALL_CAUSE_ANSWER && response == CYNARA_API_ACCESS_ALLOWED) +- result = BUS_RESULT_TRUE; +- else +- result = BUS_RESULT_FALSE; +- +- bus_deferred_message_response_received(deferred_message, result); +- bus_deferred_message_unref(deferred_message); +-} +- +-#endif /* DBUS_ENABLE_CYNARA */ +diff --git a/bus/system.conf.in b/bus/system.conf.in +index 19d0c04..81c39c8 100644 +--- a/bus/system.conf.in ++++ b/bus/system.conf.in +@@ -72,10 +72,10 @@ + send_interface="org.freedesktop.DBus.Introspectable"/> + <allow send_destination="org.freedesktop.DBus" + send_interface="org.freedesktop.DBus.Properties"/> +- <!-- If there is a need specific bus services could be protected by Cynara as well. ++ <!-- If there is a need specific bus services could be protected by Cynagora as well. + However, this can lead to deadlock during the boot process when such check is made and +- Cynara is not yet activated (systemd calls protected method synchronously, +- dbus daemon tries to consult Cynara, Cynara waits for systemd activation). ++ Cynagora is not yet activated (systemd calls protected method synchronously, ++ dbus daemon tries to consult Cynagora, Cynagora waits for systemd activation). + Therefore it is advised to allow root processes to use bus services. + Currently anyone is allowed to talk to the message bus --> + <allow receive_sender="org.freedesktop.DBus"/> +diff --git a/configure.ac b/configure.ac +index 11b5ffd..df9341c 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1742,16 +1742,16 @@ AC_ARG_ENABLE([user-session], + AM_CONDITIONAL([DBUS_ENABLE_USER_SESSION], + [test "x$enable_user_session" = xyes]) + +-#enable cynara integration +-AC_ARG_ENABLE([cynara], [AS_HELP_STRING([--enable-cynara], [enable Cynara integration])], [], [enable_cynara=no]) +-if test "x$enable_cynara" = xyes; then +- PKG_CHECK_MODULES([CYNARA], [cynara-client-async >= 0.6.0 cynara-session >= 0.6.0], +- [AC_DEFINE([DBUS_ENABLE_CYNARA], [1], [Define to enable Cynara privilege checks in dbus-daemon])], +- [AC_MSG_ERROR([libcynara-client-async and cynara-session are required to enable Cynara integration])]) ++#enable cynagora integration ++AC_ARG_ENABLE([cynagora], [AS_HELP_STRING([--enable-cynagora], [enable Cynagora integration])], [], [enable_cynagora=no]) ++if test "x$enable_cynagora" = xyes; then ++ PKG_CHECK_MODULES([CYNAGORA], [cynagora], ++ [AC_DEFINE([DBUS_ENABLE_CYNAGORA], [1], [Define to enable Cynagora privilege checks in dbus-daemon])], ++ [AC_MSG_ERROR([libcynagora is required to enable Cynagora integration])]) + fi + +-AC_SUBST([CYNARA_CFLAGS]) +-AC_SUBST([CYNARA_LIBS]) ++AC_SUBST([CYNAGORA_CFLAGS]) ++AC_SUBST([CYNAGORA_LIBS]) + + AC_CONFIG_FILES([ + Doxyfile +@@ -1835,7 +1835,7 @@ echo " + Building bus stats API: ${enable_stats} + Building SELinux support: ${have_selinux} + Building AppArmor support: ${have_apparmor} +- Building Cynara support: ${enable_cynara} ++ Building Cynagora support: ${enable_cynagora} + Building inotify support: ${have_inotify} + Building kqueue support: ${have_kqueue} + Building systemd support: ${have_systemd} +-- +2.21.1 + diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus_1.12.16.bbappend b/meta-app-framework/recipes-core/dbus-cynagora/dbus_1.12.16.bbappend new file mode 100644 index 000000000..028c734aa --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus_1.12.16.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'dbus_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/dbus-cynagora/dbus_appfw.inc b/meta-app-framework/recipes-core/dbus-cynagora/dbus_appfw.inc new file mode 100644 index 000000000..177a117b8 --- /dev/null +++ b/meta-app-framework/recipes-core/dbus-cynagora/dbus_appfw.inc @@ -0,0 +1,15 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/dbus-cynagora:" + +SRC_URI_append_class-target = "\ + file://0001-Integration-of-Cynara-asynchronous-security-checks.patch \ + file://0002-Disable-message-dispatching-when-send-rule-result-is.patch \ + file://0003-Handle-unavailability-of-policy-results-for-broadcas.patch \ + file://0004-Add-own-rule-result-unavailability-handling.patch \ + file://0005-Perform-Cynara-runtime-policy-checks-by-default.patch \ + file://0006-Fix-SIGSEGV-on-disconnections.patch \ + file://0007-Switch-from-cynara-to-cynagora.patch \ +" + +DEPENDS_append_class-target = " cynagora smack" +EXTRA_OECONF_append_class-target = " ${@bb.utils.contains('DISTRO_FEATURES','smack','--enable-cynagora --disable-selinux','',d)}" + diff --git a/meta-app-framework/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend b/meta-app-framework/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend deleted file mode 100644 index fc73e8f3d..000000000 --- a/meta-app-framework/recipes-core/packagegroups/nativesdk-packagegroup-sdk-host.bbappend +++ /dev/null @@ -1,2 +0,0 @@ -RDEPENDS_${PN} =+ "nativesdk-af-main-tools nativesdk-af-binder-devtools" - diff --git a/meta-app-framework/recipes-core/security-manager/security-manager_%.bbappend b/meta-app-framework/recipes-core/security-manager/security-manager_%.bbappend deleted file mode 100644 index 3306d4c72..000000000 --- a/meta-app-framework/recipes-core/security-manager/security-manager_%.bbappend +++ /dev/null @@ -1,7 +0,0 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/security-manager:" - -EXTRA_OECMAKE =+ " -DGLOBALUSER=afm" -SRC_URI += " \ - file://0001-Adapt-rules-to-AGL.patch \ -" - diff --git a/meta-app-framework/recipes-core/shadow/shadow_%.bbappend b/meta-app-framework/recipes-core/shadow/shadow_%.bbappend index 4f594d47c..70a0c3c82 100644 --- a/meta-app-framework/recipes-core/shadow/shadow_%.bbappend +++ b/meta-app-framework/recipes-core/shadow/shadow_%.bbappend @@ -1,6 +1,3 @@ - -do_install_append() { - sed -i '/^UMASK/s:^.*$:UMASK 077:' ${D}${sysconfdir}/login.defs -} +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'shadow_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/shadow/shadow_appfw.inc b/meta-app-framework/recipes-core/shadow/shadow_appfw.inc new file mode 100644 index 000000000..472ffef2c --- /dev/null +++ b/meta-app-framework/recipes-core/shadow/shadow_appfw.inc @@ -0,0 +1,3 @@ +do_install_append() { + sed -i '/^UMASK/s:^.*$:UMASK 077:' ${D}${sysconfdir}/login.defs +} diff --git a/meta-app-framework/recipes-core/smack-system-setup/files/55-udev-smack-default.rules b/meta-app-framework/recipes-core/smack-system-setup/files/55-udev-smack-default.rules new file mode 100644 index 000000000..eca65292f --- /dev/null +++ b/meta-app-framework/recipes-core/smack-system-setup/files/55-udev-smack-default.rules @@ -0,0 +1,27 @@ +# do not edit this file, it will be overwritten on update + +KERNEL=="null", SECLABEL{smack}="*" +KERNEL=="zero", SECLABEL{smack}="*" +KERNEL=="console", SECLABEL{smack}="*" +KERNEL=="kmsg", SECLABEL{smack}="*" +KERNEL=="video*", SECLABEL{smack}="*" +KERNEL=="card*", SECLABEL{smack}="*" +KERNEL=="ptmx", SECLABEL{smack}="*" +KERNEL=="tty", SECLABEL{smack}="*" +KERNEL=="rfkill", SECLABEL{smack}="*" + +SUBSYSTEM=="most_cdev_aim", SECLABEL{smack}="*" + +SUBSYSTEM=="graphics", GROUP="video", SECLABEL{smack}="*" +SUBSYSTEM=="drm", GROUP="video", SECLABEL{smack}="*" +SUBSYSTEM=="dvb", GROUP="video", SECLABEL{smack}="*" +SUBSYSTEM=="sound", GROUP="audio", SECLABEL{smack}="*" + +SUBSYSTEM=="tty", KERNEL=="ptmx", GROUP="tty", MODE="0666", SECLABEL{smack}="*" +SUBSYSTEM=="tty", KERNEL=="tty", GROUP="tty", MODE="0666", SECLABEL{smack}="*" +SUBSYSTEM=="tty", KERNEL=="tty[0-9]*", GROUP="tty", MODE="0620", SECLABEL{smack}="*" +SUBSYSTEM=="vc", KERNEL=="vcs*|vcsa*", GROUP="tty", SECLABEL{smack}="*" +KERNEL=="tty[A-Z]*[0-9]|pppox[0-9]*|ircomm[0-9]*|noz[0-9]*|rfcomm[0-9]*", GROUP="dialout", SECLABEL{smack}="*" + +SUBSYSTEM=="input", KERNEL=="mouse*|mice|event*", MODE="0640", SECLABEL{smack}="*" +SUBSYSTEM=="input", KERNEL=="ts[0-9]*|uinput", MODE="0640", SECLABEL{smack}="*" diff --git a/meta-app-framework/recipes-core/smack-system-setup/files/systemd-journald.service.conf b/meta-app-framework/recipes-core/smack-system-setup/files/systemd-journald.service.conf new file mode 100644 index 000000000..7035a1410 --- /dev/null +++ b/meta-app-framework/recipes-core/smack-system-setup/files/systemd-journald.service.conf @@ -0,0 +1,16 @@ +# Run systemd-journald with the hat ("^") Smack label. +# +# The journal daemon needs global read access to gather information +# about the services spawned by systemd. The hat label is intended +# for this purpose. The journal daemon is the only part of the +# System domain that needs read access to the User domain. Giving +# the journal daemon the hat label means that we can remove the +# System domain's read access to the User domain and we can avoid +# hard-coding a specific label name for that domain. +# +# Original author: Casey Schaufler <casey@schaufler-ca.com> +# +# This is considered a configuration change and thus distro specific. +[Service] +SmackProcessLabel=^ + diff --git a/meta-app-framework/recipes-core/smack-system-setup/files/systemd-tmpfiles-setup.service.conf b/meta-app-framework/recipes-core/smack-system-setup/files/systemd-tmpfiles-setup.service.conf new file mode 100644 index 000000000..db43c8c51 --- /dev/null +++ b/meta-app-framework/recipes-core/smack-system-setup/files/systemd-tmpfiles-setup.service.conf @@ -0,0 +1,2 @@ +[Service] +ExecStartPost=/bin/sh -c '([ ! -d /var/tmp ] || chsmack -L -a \"*\" /var/tmp) && ([ ! -d /var/log ] || chsmack -L -a System::Log /var/log && chsmack -L -t /var/log)' diff --git a/meta-app-framework/recipes-core/smack-system-setup/files/tmp.mount.conf b/meta-app-framework/recipes-core/smack-system-setup/files/tmp.mount.conf new file mode 100644 index 000000000..388986e82 --- /dev/null +++ b/meta-app-framework/recipes-core/smack-system-setup/files/tmp.mount.conf @@ -0,0 +1,12 @@ +# Mount /tmp publicly accessable. Based on patch by Michael Demeter <michael.demeter@intel.com>. +# Upstream systemd temporarily had SmackFileSystemRoot for this (https://github.com/systemd/systemd/pull/1664), +# but it was removed again (https://github.com/systemd/systemd/issues/1696) because +# util-linux mount will ignore smackfsroot when Smack is not active. However, +# busybox is not that intelligent. +# +# When using busybox mount, adding smackfsroot=* and booting without +# Smack (i.e. security=none), tmp.mount will fail with an error about +# "Bad mount option smackfsroot". +[Mount] +Options=smackfsroot=* + diff --git a/meta-app-framework/recipes-core/smack-system-setup/smack-system-setup_1.bb b/meta-app-framework/recipes-core/smack-system-setup/smack-system-setup_1.bb new file mode 100644 index 000000000..49b12ad3f --- /dev/null +++ b/meta-app-framework/recipes-core/smack-system-setup/smack-system-setup_1.bb @@ -0,0 +1,28 @@ +DESCRIPTION = "setup of a system using smack" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" + +SRC_URI = "\ + file://55-udev-smack-default.rules \ + file://systemd-journald.service.conf \ + file://systemd-tmpfiles-setup.service.conf \ + file://tmp.mount.conf \ +" + +RDEPENDS_${PN}_append_with-lsm-smack = " smack" + +do_install_append_with-lsm-smack() { + # tuning systemd units + install -Dm0644 ${WORKDIR}/systemd-tmpfiles-setup.service.conf \ + ${D}${systemd_unitdir}/system/systemd-tmpfiles-setup.service.d/smack.conf + install -Dm0644 ${WORKDIR}/systemd-journald.service.conf \ + ${D}${systemd_unitdir}/system/systemd-journald.service.d/smack.conf + install -Dm0644 ${WORKDIR}/tmp.mount.conf \ + ${D}${systemd_unitdir}/system/tmp.mount.d/smack.conf + + # add udev rules + install -Dm0644 ${WORKDIR}/55-udev-smack-default.rules \ + ${D}${sysconfdir}/udev/rules.d/55-udev-smack-default.rules +} + +FILES_${PN} += "${systemd_unitdir}" diff --git a/meta-app-framework/recipes-core/systemd-sync/systemd-agl-sync_1.0.bb b/meta-app-framework/recipes-core/systemd-sync/systemd-agl-sync_1.0.bb deleted file mode 100644 index 389ab2424..000000000 --- a/meta-app-framework/recipes-core/systemd-sync/systemd-agl-sync_1.0.bb +++ /dev/null @@ -1,39 +0,0 @@ -SUMMARY = "Systemd synchronization script" -DESCRIPTION = "\ -Systemd synchronization script \ -reload daemon at the first boot. \ -" -LICENSE = "Apache-2.0" -LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" - -#This script should be the last to be execute at the first boot -POST_INSTALL_LEVEL = "X0" -POST_INSTALL_SCRIPT ?= "${POST_INSTALL_LEVEL}-${PN}.sh" - -do_install() { - install -d ${D}/${sysconfdir}/agl-postinsts - cat > ${D}/${sysconfdir}/agl-postinsts/${POST_INSTALL_SCRIPT} <<EOF -#!/bin/sh -e -echo "restart daemon ..." -result=0 -systemctl daemon-reload -if [ \$? -ne 0 ]; then - result=1 -fi -systemctl restart sockets.target -if [ \$? -ne 0 ]; then - result=1 -fi - -if [ \$result -eq 0 ]; then - echo "restart daemon OK" - exit \$result -else - echo "restart daemon failed" - exit \$result -fi -EOF - chmod a+x ${D}/${sysconfdir}/agl-postinsts/${POST_INSTALL_SCRIPT} -} - -FILES_${PN} = "${sysconfdir}/agl-postinsts/${POST_INSTALL_SCRIPT}" diff --git a/meta-app-framework/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch b/meta-app-framework/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch new file mode 100644 index 000000000..46445be73 --- /dev/null +++ b/meta-app-framework/recipes-core/systemd/systemd/0001-Switch-Smack-label-earlier.patch @@ -0,0 +1,52 @@ +From 6cc74075797edb6f698cb7f312bb1c3d8cc6cb28 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Thu, 12 Oct 2017 17:17:56 +0200 +Subject: [PATCH] Switch Smack label earlier +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Switching label after removing capability isn't +possible. + +Change-Id: Ib7dac8f071f36119520ed3205d743c1e3df3cd5e +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + src/core/execute.c | 14 +++++++------- + 1 file changed, 7 insertions(+), 7 deletions(-) + +diff --git a/src/core/execute.c b/src/core/execute.c +index d72e5bf08..0abffd569 100644 +--- a/src/core/execute.c ++++ b/src/core/execute.c +@@ -2707,6 +2707,13 @@ static int exec_child( + } + } + ++ r = setup_smack(context, command); ++ if (r < 0) { ++ *exit_status = EXIT_SMACK_PROCESS_LABEL; ++ *error_message = strdup("Failed to set SMACK process label"); ++ return r; ++ } ++ + if (!cap_test_all(context->capability_bounding_set)) { + r = capability_bounding_set_drop(context->capability_bounding_set, false); + if (r < 0) { +@@ -2775,13 +2782,6 @@ static int exec_child( + } + #endif + +- r = setup_smack(context, command); +- if (r < 0) { +- *exit_status = EXIT_SMACK_PROCESS_LABEL; +- *error_message = strdup("Failed to set SMACK process label"); +- return r; +- } +- + #ifdef HAVE_APPARMOR + if (context->apparmor_profile && mac_apparmor_use()) { + r = aa_change_onexec(context->apparmor_profile); +-- +2.14.3 + diff --git a/meta-app-framework/recipes-core/systemd/systemd_2%.bbappend b/meta-app-framework/recipes-core/systemd/systemd_2%.bbappend new file mode 100644 index 000000000..11b1df9bb --- /dev/null +++ b/meta-app-framework/recipes-core/systemd/systemd_2%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'systemd_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/systemd/systemd_appfw.inc b/meta-app-framework/recipes-core/systemd/systemd_appfw.inc new file mode 100644 index 000000000..a5e1ae840 --- /dev/null +++ b/meta-app-framework/recipes-core/systemd/systemd_appfw.inc @@ -0,0 +1,40 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/systemd:" + +# Ensures systemd runs with label "System" +EXTRA_OEMESON_append_with-lsm-smack = " -Dsmack-run-label=System" + +################################################################################## +# Maintaining trivial, non-upstreamable configuration changes as patches +# is tedious. But in same cases (like early mounting of special directories) +# the configuration has to be in code. We make these changes here directly. +################################################################################## +do_patch[prefuncs] += "patch_systemd" +do_patch[vardeps] += "patch_systemd" +patch_systemd() { + # Handling of /run and /sys/fs/cgroup. Make /run a transmuting directory to + # enable systemd communications with services in the User domain. + # Original patch by Michael Demeter <michael.demeter@intel.com>. + # + # We simplify the patching by touching only lines which check the result of + # mac_smack_use(). Those are the ones which are used when Smack is active. + # + # smackfsroot=* on /sys/fs/cgroup may be upstreamable, but smackfstransmute=System::Run + # is too distro specific (depends on Smack rules) and thus has to remain here. + sed -i -e 's;\("/sys/fs/cgroup", *"[^"]*", *"[^"]*\)\(.*mac_smack_use.*\);\1,smackfsroot=*\2;' \ + -e 's;\("/run", *"[^"]*", *"[^"]*\)\(.*mac_smack_use.*\);\1,smackfstransmute=System::Run\2;' \ + ${S}/src/core/mount-setup.c +} + +################################################################################## +# What follows is temporary. +# This is a solution to the Bug-AGL SPEC-539 +# (see https://jira.automotivelinux.org/browse/SPEC-539). +# +# It renames the file "touchscreen.rules" to "55-touchscreen.rules" +# This comes with the recipe systemd_230/234 of poky (meta/recipes-core/systemd) +# It should be removed when poky changes. +################################################################################## +do_install_prepend() { + mv ${WORKDIR}/touchscreen.rules ${WORKDIR}/55-touchscreen.rules || true +} + diff --git a/meta-app-framework/recipes-core/util-linux/util-linux_%.bbappend b/meta-app-framework/recipes-core/util-linux/util-linux_%.bbappend new file mode 100644 index 000000000..3894f57cc --- /dev/null +++ b/meta-app-framework/recipes-core/util-linux/util-linux_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'util-linux_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-core/util-linux/util-linux_appfw.inc b/meta-app-framework/recipes-core/util-linux/util-linux_appfw.inc new file mode 100644 index 000000000..05286f80d --- /dev/null +++ b/meta-app-framework/recipes-core/util-linux/util-linux_appfw.inc @@ -0,0 +1,8 @@ +# Enabling Smack support in util-linux enables special support +# in [lib]mount for Smack mount options: they get removed if +# Smack is not active in the current kernel. Important for +# booting with "security=none" when userspace otherwise is +# compiled to use Smack. + +PACKAGECONFIG_append_with-lsm-smack_class-target = " smack" +PACKAGECONFIG[smack] = "--with-smack, --without-smack" diff --git a/meta-app-framework/recipes-devtools/cmake-apps-module/cmake-apps-module_git.bb b/meta-app-framework/recipes-devtools/cmake-apps-module/cmake-apps-module_git.bb new file mode 100644 index 000000000..3fea2ed91 --- /dev/null +++ b/meta-app-framework/recipes-devtools/cmake-apps-module/cmake-apps-module_git.bb @@ -0,0 +1,20 @@ +SUMMARY = "CMake module to ease development of apps" +DESCRIPTION = "This is a migration of former app-templates git submodule which let you \ +ease the development of apps and widget building." +HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/#/admin/projects/src/cmake-apps-module" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" +SECTION = "apps" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/cmake-apps-module;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "7c03348d9c2de43684fa69c3c9e227b25daceaaa" + +PV = "${AGLVERSION}" +S = "${WORKDIR}/git" + +inherit cmake + +FILES_${PN} += " ${datadir}/*/Modules/CMakeAfbTemplates*" + +BBCLASSEXTEND = "native nativesdk" + diff --git a/meta-app-framework/recipes-devtools/json-c/json-c_%.bbappend b/meta-app-framework/recipes-devtools/json-c/json-c_%.bbappend new file mode 100644 index 000000000..051f66aaf --- /dev/null +++ b/meta-app-framework/recipes-devtools/json-c/json-c_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'json-c_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-devtools/json-c/json-c_appfw.inc b/meta-app-framework/recipes-devtools/json-c/json-c_appfw.inc new file mode 100644 index 000000000..f1547e14b --- /dev/null +++ b/meta-app-framework/recipes-devtools/json-c/json-c_appfw.inc @@ -0,0 +1 @@ +EXTRA_OECONF_append = " --enable-threading" diff --git a/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.bb b/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.bb new file mode 100644 index 000000000..1174ac4d7 --- /dev/null +++ b/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.bb @@ -0,0 +1,8 @@ +require libafb-helpers_git.inc + +inherit cmake + +RDEPENDS_${PN}_append = " af-binder" + +ALLOW_EMPTY_${PN} = "1" + diff --git a/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.inc b/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.inc new file mode 100644 index 000000000..6753225b4 --- /dev/null +++ b/meta-app-framework/recipes-devtools/libafb-helpers/libafb-helpers_git.inc @@ -0,0 +1,14 @@ +SUMMARY = "AFB helpers library" +DESCRIPTION = "AFB helpers library to ease JSON object manipulation and binding interaction" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/libafb-helpers;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "1d1c6cef6039effd4c045a76d30414b589336d0e" + +PV = "${AGLVERSION}" +S = "${WORKDIR}/git" + +DEPENDS_append = " af-binder jq" + diff --git a/meta-app-framework/recipes-devtools/libappcontroller/libappcontroller_git.bb b/meta-app-framework/recipes-devtools/libappcontroller/libappcontroller_git.bb new file mode 100644 index 000000000..0ee9c5e84 --- /dev/null +++ b/meta-app-framework/recipes-devtools/libappcontroller/libappcontroller_git.bb @@ -0,0 +1,19 @@ +SUMMARY = "Controller library for an Application Framework" +DESCRIPTION = "Controller library to be used to easily create a binding for AGL App Framework" + +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/Apache-2.0;md5=89aea4e17d99a7cacdbeed46a0096b10" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/libappcontroller;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "1bef31c8bbad27f4914484c5007b2e199fb073d4" + +PV = "${AGLVERSION}" +S = "${WORKDIR}/git" + +DEPENDS_append = " af-binder libafb-helpers lua" +RDEPENDS_${PN}_append = " af-binder lua" + +inherit cmake + +ALLOW_EMPTY_${PN} = "1" + diff --git a/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend b/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend new file mode 100644 index 000000000..837b85392 --- /dev/null +++ b/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'nativesdk-packagegroup-sdk-host_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host_appfw.inc b/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host_appfw.inc new file mode 100644 index 000000000..8d6ffb5b3 --- /dev/null +++ b/meta-app-framework/recipes-devtools/packagegroups/nativesdk-packagegroup-sdk-host_appfw.inc @@ -0,0 +1,5 @@ +RDEPENDS_${PN}_append = " \ + nativesdk-af-main-tools \ + nativesdk-af-binder-devtools \ + nativesdk-cmake-apps-module \ +" diff --git a/meta-app-framework/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bbappend b/meta-app-framework/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bbappend deleted file mode 100644 index 590ab708a..000000000 --- a/meta-app-framework/recipes-devtools/run-agl-postinsts/run-agl-postinsts_1.0.bbappend +++ /dev/null @@ -1 +0,0 @@ -SYSTEMD_SERVICE_AFTER_append = " afm-system-daemon.service" diff --git a/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts/ldconfig-wait.conf b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts/ldconfig-wait.conf new file mode 100644 index 000000000..d706cc5f7 --- /dev/null +++ b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts/ldconfig-wait.conf @@ -0,0 +1,2 @@ +[Unit] +After=ldconfig.service diff --git a/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_%.bbappend b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_%.bbappend new file mode 100644 index 000000000..6b9025dc5 --- /dev/null +++ b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'run-postinsts_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_appfw.inc b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_appfw.inc new file mode 100644 index 000000000..2f3effce6 --- /dev/null +++ b/meta-app-framework/recipes-devtools/run-postinsts/run-postinsts_appfw.inc @@ -0,0 +1,14 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/run-postinsts:" + +SRC_URI_append = " file://ldconfig-wait.conf" + +do_configure_append() { + if ! grep -q StandardOutput= ${WORKDIR}/run-postinsts.service; then + sed -i '/ExecStart=/iStandardOutput=journal+console' ${WORKDIR}/run-postinsts.service + fi +} + +do_install_append() { + install -d ${D}${sysconfdir}/systemd/system/run-postinsts.service.d + install -m 0644 ${WORKDIR}/ldconfig-wait.conf ${D}${sysconfdir}/systemd/system/run-postinsts.service.d +} diff --git a/meta-app-framework/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch b/meta-app-framework/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch new file mode 100644 index 000000000..d0dcb45af --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/wayland/0001-Change-socket-mode-add-rw-for-group.patch @@ -0,0 +1,29 @@ +From 9162f7d4cfeec7103474e8703218b3679ca9ed10 Mon Sep 17 00:00:00 2001 +From: Ronan Le Martret <ronan.lemartret@iot.bzh> +Date: Tue, 18 Apr 2017 13:53:26 +0200 +Subject: [PATCH] Change socket mode:add rw for group + +Signed-off-by: Ronan Le Martret <ronan.lemartret@iot.bzh> +[Updated for 1.18.0 to remove fuzz] +Signed-off-by: Scott Murray <scott.murray@konsulko.com> + +--- + src/wayland-server.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/wayland-server.c b/src/wayland-server.c +index 3f48dfe..fbccb45 100644 +--- a/src/wayland-server.c ++++ b/src/wayland-server.c +@@ -1528,7 +1528,10 @@ _wl_display_add_socket(struct wl_display *display, struct wl_socket *s) + wl_log("bind() failed with error: %s\n", strerror(errno)); + return -1; + } +- ++ if (chmod(s->addr.sun_path, 0660) < 0) { ++ wl_log("chmod() failed with error: %m\n"); ++ return -1; ++ } + if (listen(s->fd, 128) < 0) { + wl_log("listen() failed with error: %s\n", strerror(errno)); + return -1; diff --git a/meta-app-framework/recipes-graphics/wayland/wayland_%.bbappend b/meta-app-framework/recipes-graphics/wayland/wayland_%.bbappend new file mode 100644 index 000000000..50cad0354 --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/wayland_%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'wayland_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-graphics/wayland/wayland_appfw.inc b/meta-app-framework/recipes-graphics/wayland/wayland_appfw.inc new file mode 100644 index 000000000..f39122de2 --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/wayland_appfw.inc @@ -0,0 +1,5 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/wayland:" + +SRC_URI_append = "\ + file://0001-Change-socket-mode-add-rw-for-group.patch \ + " diff --git a/meta-app-framework/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_7.0.0.patch b/meta-app-framework/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_7.0.0.patch new file mode 100644 index 000000000..362f6b064 --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/weston/0001-Allow-regular-users-to-launch-Weston_7.0.0.patch @@ -0,0 +1,51 @@ +Allow regular users to launch Weston + +Signed-off-by: Ronan Le Martret <ronan.lemartret@iot.bzh> +[Reworked for Weston 7.0.0 switch to meson] +Signed-off-by: Scott Murray <scott.murray@konsulko.com> + +diff --git a/libweston/launcher-direct.c b/libweston/launcher-direct.c +index 9fa329b6..8e218804 100644 +--- a/libweston/launcher-direct.c ++++ b/libweston/launcher-direct.c +@@ -291,8 +291,10 @@ launcher_direct_connect(struct weston_launcher **out, struct weston_compositor * + { + struct launcher_direct *launcher; + ++#ifndef ENABLE_USER_START + if (geteuid() != 0) + return -EINVAL; ++#endif + + launcher = zalloc(sizeof(*launcher)); + if (launcher == NULL) +diff --git a/libweston/meson.build b/libweston/meson.build +index d8d3fc07..0d39ebf1 100644 +--- a/libweston/meson.build ++++ b/libweston/meson.build +@@ -216,6 +216,10 @@ if get_option('weston-launch') + meson.add_install_script('echo', 'REMINDER: You are installing weston-launch, please make it setuid-root.') + endif + ++if get_option('enable-user-start') ++ config_h.set('ENABLE_USER_START', '1') ++endif ++ + subdir('renderer-gl') + subdir('backend-drm') + subdir('backend-fbdev') +diff --git a/meson_options.txt b/meson_options.txt +index d5bf1d54..c93f31d1 100644 +--- a/meson_options.txt ++++ b/meson_options.txt +@@ -217,3 +217,10 @@ option( + value: false, + description: 'Generate documentation' + ) ++ ++option( ++ 'enable-user-start', ++ type: 'boolean', ++ value: true, ++ description: 'Tests: enable start as non-root user' ++) diff --git a/meta-app-framework/recipes-graphics/wayland/weston/smack-weston b/meta-app-framework/recipes-graphics/wayland/weston/smack-weston new file mode 100644 index 000000000..63a32405a --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/weston/smack-weston @@ -0,0 +1,8 @@ +System System::Weston rwxa-- +System::Weston System rwx--- +System::Weston System::Shared rwx--- +System::Weston System::Run rwxat- +System::Weston System::Log rwxa-- +System::Weston _ r-x--l +System::Weston User::Home r-x--l +System::Weston User::App-Shared rwxat- diff --git a/meta-app-framework/recipes-graphics/wayland/weston_8.0.%.bbappend b/meta-app-framework/recipes-graphics/wayland/weston_8.0.%.bbappend new file mode 100644 index 000000000..00bb510bf --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/weston_8.0.%.bbappend @@ -0,0 +1 @@ +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'weston_8.0_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-graphics/wayland/weston_8.0_appfw.inc b/meta-app-framework/recipes-graphics/wayland/weston_8.0_appfw.inc new file mode 100644 index 000000000..219ed1aef --- /dev/null +++ b/meta-app-framework/recipes-graphics/wayland/weston_8.0_appfw.inc @@ -0,0 +1,19 @@ +FILESEXTRAPATHS_append := ":${THISDIR}/weston" + +SRC_URI_append = "\ + file://0001-Allow-regular-users-to-launch-Weston_7.0.0.patch \ + file://smack-weston \ + " + +EXTRA_OEMESON_append = " -Denable-user-start=true" + +do_install_append() { + if ${@bb.utils.contains('DISTRO_FEATURES', 'smack', 'true', 'false', d)}; then + # Install SMACK rules + install -D -m 0644 ${WORKDIR}/smack-weston ${D}${sysconfdir}/smack/accesses.d/weston + fi +} + +FILES_${PN}_append = "\ + ${sysconfdir}/smack/accesses.d/* \ +" diff --git a/meta-app-framework/recipes-kernel/linux/linux-%.bbappend b/meta-app-framework/recipes-kernel/linux/linux-%.bbappend index fba5bf13d..acce6cc1b 100644 --- a/meta-app-framework/recipes-kernel/linux/linux-%.bbappend +++ b/meta-app-framework/recipes-kernel/linux/linux-%.bbappend @@ -1,3 +1,2 @@ -FILESEXTRAPATHS_prepend := "${THISDIR}/linux:" -SRC_URI_append_with-lsm-smack = " file://audit.cfg" +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'linux-appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-kernel/linux/linux-appfw.inc b/meta-app-framework/recipes-kernel/linux/linux-appfw.inc new file mode 100644 index 000000000..cbf6567e0 --- /dev/null +++ b/meta-app-framework/recipes-kernel/linux/linux-appfw.inc @@ -0,0 +1,21 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/linux:" + +IS_KERNEL_RECIPE := "${@bb.data.inherits_class('kernel', d) and 'yes' or 'no'}" +SMACK_KERNEL_SRC_URI_no = "" +SMACK_KERNEL_SRC_URI_yes = "" + +# Kernel config fragment enabling Smack, without making it the default explicitly. +SMACK_KERNEL_SRC_URI_yes += "file://smack.cfg" + +# When added, set Smack as the default LSM. +SMACK_DEFAULT_SECURITY_CFG = "file://smack-default-lsm.cfg" +# Add it by default, can be overridden by changing this variable here. +SMACK_DEFAULT_SECURITY ??= "${SMACK_DEFAULT_SECURITY_CFG}" +SMACK_KERNEL_SRC_URI_yes += " ${SMACK_DEFAULT_SECURITY}" + +# add audit.cfg +SMACK_KERNEL_SRC_URI_yes += " file://audit.cfg" + + +SRC_URI_append_with-lsm-smack = "${SMACK_KERNEL_SRC_URI_${IS_KERNEL_RECIPE}}" + diff --git a/meta-app-framework/recipes-kernel/linux/linux/smack-default-lsm.cfg b/meta-app-framework/recipes-kernel/linux/linux/smack-default-lsm.cfg new file mode 100644 index 000000000..b5c48454e --- /dev/null +++ b/meta-app-framework/recipes-kernel/linux/linux/smack-default-lsm.cfg @@ -0,0 +1,2 @@ +CONFIG_DEFAULT_SECURITY="smack" +CONFIG_DEFAULT_SECURITY_SMACK=y diff --git a/meta-app-framework/recipes-kernel/linux/linux/smack.cfg b/meta-app-framework/recipes-kernel/linux/linux/smack.cfg new file mode 100644 index 000000000..45a92f148 --- /dev/null +++ b/meta-app-framework/recipes-kernel/linux/linux/smack.cfg @@ -0,0 +1,9 @@ +CONFIG_IP_NF_SECURITY=m +CONFIG_IP6_NF_SECURITY=m +CONFIG_EXT2_FS_SECURITY=y +CONFIG_EXT3_FS_SECURITY=y +CONFIG_EXT4_FS_SECURITY=y +CONFIG_SECURITY=y +CONFIG_SECURITY_SMACK=y +CONFIG_SECURITY_SMACK_APPEND_SIGNALS=y +CONFIG_TMPFS_XATTR=y diff --git a/meta-app-framework/recipes-core/packagegroups/packagegroup-agl-app-framework-examples.bb b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-app-framework-examples.bb index 7ba909162..7ba909162 100644 --- a/meta-app-framework/recipes-core/packagegroups/packagegroup-agl-app-framework-examples.bb +++ b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-app-framework-examples.bb diff --git a/meta-app-framework/recipes-core/packagegroups/packagegroup-agl-app-framework.bb b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-app-framework.bb index 854835d4c..d15607a40 100644 --- a/meta-app-framework/recipes-core/packagegroups/packagegroup-agl-app-framework.bb +++ b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-app-framework.bb @@ -4,17 +4,16 @@ LICENSE = "MIT" inherit packagegroup -PACKAGES = "\ +PACKAGES_${PN} = "\ packagegroup-agl-app-framework \ " ALLOW_EMPTY_${PN} = "1" -RDEPENDS_${PN} += "\ +RDEPENDS_${PN} = "\ af-binder \ libafbwsc \ af-main \ nss-localuser \ - systemd-agl-sync \ af-platform-setup \ " diff --git a/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-appfw-native.bb b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-appfw-native.bb new file mode 100644 index 000000000..750fe678d --- /dev/null +++ b/meta-app-framework/recipes-platform/packagegroups/packagegroup-agl-appfw-native.bb @@ -0,0 +1,16 @@ +SUMMARY = "The software for application framework of AGL IVI profile" +DESCRIPTION = "A set of packages belong to AGL application framework which required by \ +Native App Fw Subsystem" + +LICENSE = "MIT" + +inherit packagegroup + +PACKAGES = "\ + packagegroup-agl-appfw-native \ + " + +ALLOW_EMPTY_${PN} = "1" + +RDEPENDS_${PN} += "\ + " diff --git a/meta-app-framework/recipes-platform/packagegroups/packagegroup-security-framework.bb b/meta-app-framework/recipes-platform/packagegroups/packagegroup-security-framework.bb new file mode 100644 index 000000000..bc708600f --- /dev/null +++ b/meta-app-framework/recipes-platform/packagegroups/packagegroup-security-framework.bb @@ -0,0 +1,23 @@ +SUMMARY = "Security middleware components" +LICENSE = "MIT" + +inherit packagegroup + +# Install Cynara and security-manager by default if (and only if) +# Smack is enabled. +# +# Cynara does not have a hard dependency on Smack security, +# but is meant to be used with it. security-manager however +# links against smack and expects Smack to be active, +# so we do not have any choice. +# +# Without configuration, security-manager is not usable. We use +# the policy packaged from the upstream source code here. Adapting +# it for the distro can be done by patching that source. +RDEPENDS_${PN}_append_with-lsm-smack = " \ + cynagora \ + security-manager \ + security-manager-policy \ + smacknet \ + smack-system-setup \ +" diff --git a/meta-app-framework/recipes-security/audit/audit/0001-lib-i386_table.h-add-new-syscall.patch b/meta-app-framework/recipes-security/audit/audit/0001-lib-i386_table.h-add-new-syscall.patch new file mode 100644 index 000000000..6e1827c08 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/0001-lib-i386_table.h-add-new-syscall.patch @@ -0,0 +1,42 @@ +From df878b92e01f4d1c3de7f7d8229cea6a431509eb Mon Sep 17 00:00:00 2001 +From: Mingli Yu <mingli.yu@windriver.com> +Date: Wed, 19 Feb 2020 15:23:40 +0800 +Subject: [PATCH] lib/i386_table.h: add new syscall + +On 32bit system, +After upgrade glibc to 2.31 + # strace -o /tmp/test.log date -s 09:16:45 + # tail -f /tmp/test.log + close(3) = 0 + stat64("/etc/localtime", {st_mode=S_IFREG|0644, st_size=114, ...}) = 0 + clock_settime64(CLOCK_REALTIME, {tv_sec=1582103805, tv_nsec=0}) = 0 + fstat64(1, {st_mode=S_IFCHR|0600, st_rdev=makedev(0x4, 0x40), ...}) = 0 + ioctl(1, TCGETS, {B115200 opost isig icanon echo ...}) = 0 + write(1, "Wed Feb 19 09:16:45 UTC 2020\n", 29) = 29 + close(1) = 0 + close(2) = 0 + exit_group(0) = ? + +++ exited with 0 +++ + +It means the clock_settime64 syscall is used, so +add the syscall. + +Upstream-Status: Submitted [https://github.com/linux-audit/audit-userspace/pull/116] + +Signed-off-by: Mingli Yu <mingli.yu@windriver.com> +--- + lib/i386_table.h | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/lib/i386_table.h b/lib/i386_table.h +index 1a64c88..65fd4d9 100644 +--- a/lib/i386_table.h ++++ b/lib/i386_table.h +@@ -405,3 +405,4 @@ _S(383, "statx") + _S(384, "arch_prctl") + _S(385, "io_pgetevents") + _S(386, "rseq") ++_S(404, "clock_settime64") +-- +2.7.4 + diff --git a/meta-app-framework/recipes-security/audit/audit/Add-substitue-functions-for-strndupa-rawmemchr.patch b/meta-app-framework/recipes-security/audit/audit/Add-substitue-functions-for-strndupa-rawmemchr.patch new file mode 100644 index 000000000..bb6c61e80 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/Add-substitue-functions-for-strndupa-rawmemchr.patch @@ -0,0 +1,133 @@ +From bdcdc3dff4469aac88e718bd15958d5ed4b9392a Mon Sep 17 00:00:00 2001 +From: Steve Grubb <sgrubb@redhat.com> +Date: Tue, 26 Feb 2019 18:33:33 -0500 +Subject: [PATCH] Add substitue functions for strndupa & rawmemchr + +Upstream-Status: Backport +[https://github.com/linux-audit/audit-userspace/commit/d579a08bb1cde71f939c13ac6b2261052ae9f77e] +--- + auparse/auparse.c | 12 +++++++++++- + auparse/interpret.c | 9 ++++++++- + configure.ac | 14 +++++++++++++- + src/ausearch-lol.c | 12 +++++++++++- + 4 files changed, 43 insertions(+), 4 deletions(-) + +diff --git a/auparse/auparse.c b/auparse/auparse.c +index 650db02..2e1c737 100644 +--- a/auparse/auparse.c ++++ b/auparse/auparse.c +@@ -1,5 +1,5 @@ + /* auparse.c -- +- * Copyright 2006-08,2012-17 Red Hat Inc., Durham, North Carolina. ++ * Copyright 2006-08,2012-19 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This library is free software; you can redistribute it and/or +@@ -1118,6 +1118,16 @@ static int str2event(char *s, au_event_t *e) + return 0; + } + ++#ifndef HAVE_STRNDUPA ++static inline char *strndupa(const char *old, size_t n) ++{ ++ size_t len = strnlen(old, n); ++ char *tmp = alloca(len + 1); ++ tmp[len] = 0; ++ return memcpy(tmp, old, len); ++} ++#endif ++ + /* Returns 0 on success and 1 on error */ + static int extract_timestamp(const char *b, au_event_t *e) + { +diff --git a/auparse/interpret.c b/auparse/interpret.c +index 51c4a5e..67b7b77 100644 +--- a/auparse/interpret.c ++++ b/auparse/interpret.c +@@ -853,6 +853,13 @@ err_out: + return print_escaped(id->val); + } + ++// rawmemchr is faster. Let's use it if we have it. ++#ifdef HAVE_RAWMEMCHR ++#define STRCHR rawmemchr ++#else ++#define STRCHR strchr ++#endif ++ + static const char *print_proctitle(const char *val) + { + char *out = (char *)print_escaped(val); +@@ -863,7 +870,7 @@ static const char *print_proctitle(const char *val) + // Proctitle has arguments separated by NUL bytes + // We need to write over the NUL bytes with a space + // so that we can see the arguments +- while ((ptr = rawmemchr(ptr, '\0'))) { ++ while ((ptr = STRCHR(ptr, '\0'))) { + if (ptr >= end) + break; + *ptr = ' '; +diff --git a/configure.ac b/configure.ac +index 54bdbf1..aef07fb 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1,7 +1,7 @@ + dnl + define([AC_INIT_NOTICE], + [### Generated automatically using autoconf version] AC_ACVERSION [ +-### Copyright 2005-18 Steve Grubb <sgrubb@redhat.com> ++### Copyright 2005-19 Steve Grubb <sgrubb@redhat.com> + ### + ### Permission is hereby granted, free of charge, to any person obtaining a + ### copy of this software and associated documentation files (the "Software"), +@@ -72,6 +72,18 @@ dnl; posix_fallocate is used in audisp-remote + AC_CHECK_FUNCS([posix_fallocate]) + dnl; signalfd is needed for libev + AC_CHECK_FUNC([signalfd], [], [ AC_MSG_ERROR([The signalfd system call is necessary for auditd]) ]) ++dnl; check if rawmemchr is available ++AC_CHECK_FUNCS([rawmemchr]) ++dnl; check if strndupa is available ++AC_LINK_IFELSE( ++ [AC_LANG_SOURCE( ++ [[ ++ #define _GNU_SOURCE ++ #include <string.h> ++ int main() { (void) strndupa("test", 10); return 0; }]])], ++ [AC_DEFINE(HAVE_STRNDUPA, 1, [Let us know if we have it or not])], ++ [] ++) + + ALLWARNS="" + ALLDEBUG="-g" +diff --git a/src/ausearch-lol.c b/src/ausearch-lol.c +index 5d17a72..758c33e 100644 +--- a/src/ausearch-lol.c ++++ b/src/ausearch-lol.c +@@ -1,6 +1,6 @@ + /* + * ausearch-lol.c - linked list of linked lists library +-* Copyright (c) 2008,2010,2014,2016 Red Hat Inc., Durham, North Carolina. ++* Copyright (c) 2008,2010,2014,2016,2019 Red Hat Inc., Durham, North Carolina. + * All Rights Reserved. + * + * This software may be freely redistributed and/or modified under the +@@ -152,6 +152,16 @@ static int compare_event_time(event *e1, event *e2) + return 0; + } + ++#ifndef HAVE_STRNDUPA ++static inline char *strndupa(const char *old, size_t n) ++{ ++ size_t len = strnlen(old, n); ++ char *tmp = alloca(len + 1); ++ tmp[len] = 0; ++ return memcpy(tmp, old, len); ++} ++#endif ++ + /* + * This function will look at the line and pick out pieces of it. + */ +-- +2.7.4 + diff --git a/meta-app-framework/recipes-security/audit/audit/Fixed-swig-host-contamination-issue.patch b/meta-app-framework/recipes-security/audit/audit/Fixed-swig-host-contamination-issue.patch new file mode 100644 index 000000000..7c2699540 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/Fixed-swig-host-contamination-issue.patch @@ -0,0 +1,57 @@ +From a07271f1cce82122610b622bcea4a8a37528f321 Mon Sep 17 00:00:00 2001 +From: Li xin <lixin.fnst@cn.fujitsu.com> +Date: Sun, 19 Jul 2015 02:42:58 +0900 +Subject: [PATCH] audit: Fixed swig host contamination issue + +The audit build uses swig to generate a python wrapper. +Unfortunately, the swig info file references host include +directories. Some of these were previously noticed and +eliminated, but the one fixed here was not. + +Upstream-Status: Inappropriate [embedded specific] + +Signed-off-by: Anders Hedlund <anders.hedlund@windriver.com> +Signed-off-by: Joe Slater <jslater@windriver.com> +Signed-off-by: Yi Zhao <yi.zhao@windriver.com> +--- + bindings/swig/python3/Makefile.am | 3 ++- + bindings/swig/src/auditswig.i | 2 +- + 2 files changed, 3 insertions(+), 2 deletions(-) + +diff --git a/bindings/swig/python3/Makefile.am b/bindings/swig/python3/Makefile.am +index 9938418..fa46aac 100644 +--- a/bindings/swig/python3/Makefile.am ++++ b/bindings/swig/python3/Makefile.am +@@ -22,6 +22,7 @@ + CONFIG_CLEAN_FILES = *.loT *.rej *.orig + AM_CFLAGS = -fPIC -DPIC -fno-strict-aliasing $(PYTHON3_CFLAGS) + AM_CPPFLAGS = -I. -I$(top_builddir) -I${top_srcdir}/lib $(PYTHON3_INCLUDES) ++STDINC ?= /usr/include + LIBS = $(top_builddir)/lib/libaudit.la + SWIG_FLAGS = -python -py3 -modern + SWIG_INCLUDES = -I. -I$(top_builddir) -I${top_srcdir}/lib $(PYTHON3_INCLUDES) +@@ -37,7 +38,7 @@ _audit_la_DEPENDENCIES =${top_srcdir}/lib/libaudit.h ${top_builddir}/lib/libaudi + _audit_la_LIBADD = ${top_builddir}/lib/libaudit.la + nodist__audit_la_SOURCES = audit_wrap.c + audit.py audit_wrap.c: ${srcdir}/../src/auditswig.i +- swig -o audit_wrap.c ${SWIG_FLAGS} ${SWIG_INCLUDES} ${srcdir}/../src/auditswig.i ++ swig -o audit_wrap.c ${SWIG_FLAGS} ${SWIG_INCLUDES} -I$(STDINC) ${srcdir}/../src/auditswig.i + + CLEANFILES = audit.py* audit_wrap.c *~ + +diff --git a/bindings/swig/src/auditswig.i b/bindings/swig/src/auditswig.i +index 7ebb373..424fb68 100644 +--- a/bindings/swig/src/auditswig.i ++++ b/bindings/swig/src/auditswig.i +@@ -39,7 +39,7 @@ signed + #define __attribute(X) /*nothing*/ + typedef unsigned __u32; + typedef unsigned uid_t; +-%include "/usr/include/linux/audit.h" ++%include "linux/audit.h" + #define __extension__ /*nothing*/ + #include <stdint.h> + %include "../lib/libaudit.h" +-- +2.7.4 + diff --git a/meta-app-framework/recipes-security/audit/audit/audit-volatile.conf b/meta-app-framework/recipes-security/audit/audit/audit-volatile.conf new file mode 100644 index 000000000..9cbe1547a --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/audit-volatile.conf @@ -0,0 +1 @@ +d /var/log/audit 0750 root root - diff --git a/meta-app-framework/recipes-security/audit/audit/auditd b/meta-app-framework/recipes-security/audit/audit/auditd new file mode 100755 index 000000000..cda2e43d4 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/auditd @@ -0,0 +1,153 @@ +#! /bin/sh +### BEGIN INIT INFO +# Provides: auditd +# Required-Start: $local_fs +# Required-Stop: $local_fs +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: Audit Daemon +# Description: Collects audit information from Linux 2.6 Kernels. +### END INIT INFO + +# Author: Philipp Matthias Hahn <pmhahn@debian.org> +# Based on Debians /etc/init.d/skeleton and Auditds init.d/auditd.init + +# June, 2012: Adopted for yocto <amy.fong@windriver.com> + +# PATH should only include /usr/* if it runs after the mountnfs.sh script +PATH=/sbin:/bin:/usr/sbin:/usr/bin +DESC="audit daemon" +NAME=auditd +DAEMON=/sbin/auditd +PIDFILE=/var/run/"$NAME".pid +SCRIPTNAME=/etc/init.d/"$NAME" + +# Exit if the package is not installed +[ -x "$DAEMON" ] || exit 0 + +# Read configuration variable file if it is present +[ -r /etc/default/"$NAME" ] && . /etc/default/"$NAME" + +. /etc/default/rcS + +. /etc/init.d/functions + +# +# Function that starts the daemon/service +# +do_start() +{ + # Return + # 0 if daemon has been started + # 1 if daemon was already running + # 2 if daemon could not be started + start-stop-daemon -S --quiet --pidfile "$PIDFILE" --exec "$DAEMON" --test > /dev/null \ + || return 1 + start-stop-daemon -S --quiet --pidfile "$PIDFILE" --exec "$DAEMON" -- \ + $EXTRAOPTIONS \ + || return 2 + if [ -f /etc/audit/audit.rules ] + then + /sbin/auditctl -R /etc/audit/audit.rules >/dev/null + fi +} + +# +# Function that stops the daemon/service +# +do_stop() +{ + # Return + # 0 if daemon has been stopped + # 1 if daemon was already stopped + # 2 if daemon could not be stopped + # other if a failure occurred + start-stop-daemon -K --quiet --pidfile "$PIDFILE" --name "$NAME" + RETVAL="$?" + [ "$RETVAL" = 2 ] && return 2 + # Many daemons don't delete their pidfiles when they exit. + rm -f "$PIDFILE" + rm -f /var/run/audit_events + # Remove watches so shutdown works cleanly + case "$AUDITD_CLEAN_STOP" in + no|NO) ;; + *) /sbin/auditctl -D >/dev/null ;; + esac + return "$RETVAL" +} + +# +# Function that sends a SIGHUP to the daemon/service +# +do_reload() { + start-stop-daemon -K --signal HUP --quiet --pidfile $PIDFILE --name $NAME + return 0 +} + +if [ ! -e /var/log/audit ]; then + mkdir -p /var/log/audit + [ -x /sbin/restorecon ] && /sbin/restorecon -F /var/log/audit +fi + +case "$1" in + start) + [ "$VERBOSE" != no ] && echo "Starting $DESC" "$NAME" + do_start + case "$?" in + 0|1) [ "$VERBOSE" != no ] && echo 0 ;; + 2) [ "$VERBOSE" != no ] && echo 1 ;; + esac + ;; + stop) + [ "$VERBOSE" != no ] && echo "Stopping $DESC" "$NAME" + do_stop + case "$?" in + 0|1) [ "$VERBOSE" != no ] && echo 0 ;; + 2) [ "$VERBOSE" != no ] && echo 1 ;; + esac + ;; + reload|force-reload) + echo "Reloading $DESC" "$NAME" + do_reload + echo $? + ;; + restart) + echo "Restarting $DESC" "$NAME" + do_stop + case "$?" in + 0|1) + do_start + case "$?" in + 0) echo 0 ;; + 1) echo 1 ;; # Old process is still running + *) echo 1 ;; # Failed to start + esac + ;; + *) + # Failed to stop + echo 1 + ;; + esac + ;; + rotate) + echo "Rotating $DESC logs" "$NAME" + start-stop-daemon -K --signal USR1 --quiet --pidfile "$PIDFILE" --name "$NAME" + echo $? + ;; + status) + pidofproc "$DAEMON" >/dev/null + status=$? + if [ $status -eq 0 ]; then + echo "$NAME is running." + else + echo "$NAME is not running." + fi + exit $status + ;; + *) + echo "Usage: $SCRIPTNAME {start|stop|restart|reload|force-reload|rotate|status}" >&2 + exit 3 + ;; +esac + +: diff --git a/meta-app-framework/recipes-security/audit/audit/auditd.service b/meta-app-framework/recipes-security/audit/audit/auditd.service new file mode 100644 index 000000000..ebc079897 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit/auditd.service @@ -0,0 +1,20 @@ +[Unit] +Description=Security Auditing Service +DefaultDependencies=no +After=local-fs.target +Conflicts=shutdown.target +Before=sysinit.target shutdown.target +After=systemd-tmpfiles-setup.service + +[Service] +ExecStart=/sbin/auditd -n +## To use augenrules, copy this file to /etc/systemd/system/auditd.service +## and uncomment the next line and delete/comment out the auditctl line. +## Then copy existing rules to /etc/audit/rules.d/ +## Not doing this last step can cause loss of existing rules +#ExecStartPost=-/sbin/augenrules --load +ExecStartPost=-/sbin/auditctl -R /etc/audit/audit.rules +ExecReload=/bin/kill -HUP $MAINPID + +[Install] +WantedBy=multi-user.target diff --git a/meta-app-framework/recipes-security/audit/audit_2.8.5.bb b/meta-app-framework/recipes-security/audit/audit_2.8.5.bb new file mode 100644 index 000000000..af36ed5e2 --- /dev/null +++ b/meta-app-framework/recipes-security/audit/audit_2.8.5.bb @@ -0,0 +1,106 @@ +SUMMARY = "User space tools for kernel auditing" +DESCRIPTION = "The audit package contains the user space utilities for \ +storing and searching the audit records generated by the audit subsystem \ +in the Linux kernel." +HOMEPAGE = "http://people.redhat.com/sgrubb/audit/" +SECTION = "base" +LICENSE = "GPLv2+ & LGPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" + +SRC_URI = "git://github.com/linux-audit/${BPN}-userspace.git;branch=2.8_maintenance \ + file://Add-substitue-functions-for-strndupa-rawmemchr.patch \ + file://Fixed-swig-host-contamination-issue.patch \ + file://0001-lib-i386_table.h-add-new-syscall.patch \ + file://auditd \ + file://auditd.service \ + file://audit-volatile.conf \ +" + +S = "${WORKDIR}/git" +SRCREV = "5fae55c1ad15b3cefe6890eba7311af163e9133c" + +inherit autotools python3native update-rc.d systemd + +UPDATERCPN = "auditd" +INITSCRIPT_NAME = "auditd" +INITSCRIPT_PARAMS = "defaults" + +SYSTEMD_PACKAGES = "auditd" +SYSTEMD_SERVICE_auditd = "auditd.service" + +DEPENDS += "python3 tcp-wrappers libcap-ng linux-libc-headers swig-native" + +EXTRA_OECONF += "--without-prelude \ + --with-libwrap \ + --enable-gssapi-krb5=no \ + --with-libcap-ng=yes \ + --with-python3=yes \ + --libdir=${base_libdir} \ + --sbindir=${base_sbindir} \ + --without-python \ + --without-golang \ + --disable-zos-remote \ + " +EXTRA_OECONF_append_arm = " --with-arm=yes" +EXTRA_OECONF_append_aarch64 = " --with-aarch64=yes" + +EXTRA_OEMAKE += "PYLIBVER='python${PYTHON_BASEVERSION}' \ + PYINC='${STAGING_INCDIR}/$(PYLIBVER)' \ + pyexecdir=${libdir}/python${PYTHON_BASEVERSION}/site-packages \ + STDINC='${STAGING_INCDIR}' \ + pkgconfigdir=${libdir}/pkgconfig \ + " + +SUMMARY_audispd-plugins = "Plugins for the audit event dispatcher" +DESCRIPTION_audispd-plugins = "The audispd-plugins package provides plugins for the real-time \ +interface to the audit system, audispd. These plugins can do things \ +like relay events to remote machines or analyze events for suspicious \ +behavior." + +PACKAGES =+ "audispd-plugins" +PACKAGES += "auditd ${PN}-python" + +FILES_${PN} = "${sysconfdir}/libaudit.conf ${base_libdir}/libaudit.so.1* ${base_libdir}/libauparse.so.*" +FILES_auditd += "${bindir}/* ${base_sbindir}/* ${sysconfdir}/*" +FILES_audispd-plugins += "${sysconfdir}/audisp/audisp-remote.conf \ + ${sysconfdir}/audisp/plugins.d/au-remote.conf \ + ${sbindir}/audisp-remote ${localstatedir}/spool/audit \ + " +FILES_${PN}-dbg += "${libdir}/python${PYTHON_BASEVERSION}/*/.debug" +FILES_${PN}-python = "${libdir}/python${PYTHON_BASEVERSION}" + +CONFFILES_auditd += "${sysconfdir}/audit/audit.rules" +RDEPENDS_auditd += "bash" + +do_install_append() { + rm -f ${D}/${libdir}/python${PYTHON_BASEVERSION}/site-packages/*.a + rm -f ${D}/${libdir}/python${PYTHON_BASEVERSION}/site-packages/*.la + + # reuse auditd config + [ ! -e ${D}/etc/default ] && mkdir ${D}/etc/default + mv ${D}/etc/sysconfig/auditd ${D}/etc/default + rmdir ${D}/etc/sysconfig/ + + # replace init.d + install -D -m 0755 ${WORKDIR}/auditd ${D}/etc/init.d/auditd + rm -rf ${D}/etc/rc.d + + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + install -d ${D}${sysconfdir}/tmpfiles.d/ + install -m 0644 ${WORKDIR}/audit-volatile.conf ${D}${sysconfdir}/tmpfiles.d/ + fi + + # install systemd unit files + install -d ${D}${systemd_unitdir}/system + install -m 0644 ${WORKDIR}/auditd.service ${D}${systemd_unitdir}/system + + # audit-2.5 doesn't install any rules by default, so we do that here + mkdir -p ${D}/etc/audit ${D}/etc/audit/rules.d + cp ${S}/rules/10-base-config.rules ${D}/etc/audit/rules.d/audit.rules + + chmod 750 ${D}/etc/audit ${D}/etc/audit/rules.d + chmod 640 ${D}/etc/audit/auditd.conf ${D}/etc/audit/rules.d/audit.rules + + # Based on the audit.spec "Copy default rules into place on new installation" + cp ${D}/etc/audit/rules.d/audit.rules ${D}/etc/audit/audit.rules +} diff --git a/meta-app-framework/recipes-security/cynagoauth/cynagoauth_0.1.bb b/meta-app-framework/recipes-security/cynagoauth/cynagoauth_0.1.bb new file mode 100644 index 000000000..c77c99189 --- /dev/null +++ b/meta-app-framework/recipes-security/cynagoauth/cynagoauth_0.1.bb @@ -0,0 +1,23 @@ +DESCRIPTION = "OAuth server using cynagora backend" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE.txt;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/cynagoauth.git;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "26a5dbddf3a9bfde481a6fcd2aae16c7ecba665f" +PV = "0.1+git${SRCPV}" + +S = "${WORKDIR}/git" + +DEPENDS = "json-c libmicrohttpd openssl cynagora" + +inherit cmake + +EXTRA_OECMAKE += " \ + -DDEFAULTHOSTS=:7777 \ + -DDEFAULTURL=http://localhost:7777/tok \ + -DUNITDIR_SYSTEM=${systemd_system_unitdir} \ +" + +FILES_${PN} += "${systemd_system_unitdir}" + + diff --git a/meta-app-framework/recipes-security/cynagora/cynagora-cynara-compat_2.1.bb b/meta-app-framework/recipes-security/cynagora/cynagora-cynara-compat_2.1.bb new file mode 100644 index 000000000..f146051cd --- /dev/null +++ b/meta-app-framework/recipes-security/cynagora/cynagora-cynara-compat_2.1.bb @@ -0,0 +1,30 @@ +DESCRIPTION = "Cynara service with client libraries" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://Apache-2.0;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/cynagora;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "7d7907651c42c5c32deabc17b639e0e1765eae60" +PV = "2.1+git${SRCPV}" + +S = "${WORKDIR}/git" + +inherit cmake + +PROVIDES = "cynara" +RPROVIDES_${PN} = "cynara" +DEPENDS = "libcap" +RDEPENDS_${PN} = "cynagora" + +EXTRA_OECMAKE += " \ + -DWITH_SYSTEMD=OFF \ + -DWITH_CYNARA_COMPAT=ON \ + -DDIRECT_CYNARA_COMPAT=ON \ +" + +do_install_append() { + # remove cynagora stuff + rm $(find ${D} -name '*cynagora*') + # remove stupid test + rm -r ${D}${bindir} +} + diff --git a/meta-app-framework/recipes-security/cynagora/cynagora/run-ptest b/meta-app-framework/recipes-security/cynagora/cynagora/run-ptest new file mode 100755 index 000000000..f95f0725b --- /dev/null +++ b/meta-app-framework/recipes-security/cynagora/cynagora/run-ptest @@ -0,0 +1,4 @@ +#!/bin/sh + +# test access to cynagora server +cynagora-admin list > /dev/null diff --git a/meta-app-framework/recipes-security/cynagora/cynagora_2.1.bb b/meta-app-framework/recipes-security/cynagora/cynagora_2.1.bb new file mode 100644 index 000000000..73f2f0949 --- /dev/null +++ b/meta-app-framework/recipes-security/cynagora/cynagora_2.1.bb @@ -0,0 +1,38 @@ +DESCRIPTION = "Cynagora service and client libraries" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://Apache-2.0;md5=3b83ef96387f14655fc854ddc3c6bd57" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/src/cynagora;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "7d7907651c42c5c32deabc17b639e0e1765eae60" +PV = "2.1+git${SRCPV}" + +S = "${WORKDIR}/git" + +DEPENDS = "systemd libcap" + +inherit cmake + +EXTRA_OECMAKE += " \ + -DSYSTEMD_UNIT_DIR=${systemd_system_unitdir} \ + -DWITH_SYSTEMD=ON \ + -DWITH_CYNARA_COMPAT=OFF \ +" + +inherit useradd +USERADD_PACKAGES = "${PN}" +GROUPADD_PARAM_${PN} = "-r cynagora" +USERADD_PARAM_${PN} = "\ +--system --home ${localstatedir}/lib/empty \ +--no-create-home --shell /bin/false \ +--gid cynagora cynagora \ +" + +FILES_${PN} += "${systemd_system_unitdir}" + +PACKAGES =+ "${PN}-tools" +FILES_${PN}-tools += "${bindir}/cynagora-admin ${bindir}/cynagora-agent" +RDEPENDS_${PN}_append_agl-devel = " ${PN}-tools" + +inherit ptest +SRC_URI_append = " file://run-ptest" +RDEPENDS_${PN}-ptest_append = " ${PN}-tools" diff --git a/meta-app-framework/recipes-security/security-manager/security-manager.inc b/meta-app-framework/recipes-security/security-manager/security-manager.inc new file mode 100644 index 000000000..e1d1f4011 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager.inc @@ -0,0 +1,83 @@ +DESCRIPTION = "Security manager and utilities" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327;beginline=3" + +inherit cmake + +B = "${S}" + +DEPENDS = " \ + attr \ + boost \ + cynara \ + icu \ + libcap \ + smack \ + sqlite3 \ + systemd \ +" + +PACKAGECONFIG ??= "" +PACKAGECONFIG[debug] = "-DCMAKE_BUILD_TYPE=DEBUG,-DCMAKE_BUILD_TYPE=RELEASE" + +TZ_SYS_DB ?= "/var/db/security-manager" + +EXTRA_OECMAKE = " \ + -DCMAKE_VERBOSE_MAKEFILE=ON \ + -DVERSION=${PV} \ + -DSYSTEMD_INSTALL_DIR=${systemd_unitdir}/system \ + -DBIN_INSTALL_DIR=${bindir} \ + -DDB_INSTALL_DIR=${TZ_SYS_DB} \ + -DLIB_INSTALL_DIR=${libdir} \ + -DSHARE_INSTALL_PREFIX=${datadir} \ + -DINCLUDE_INSTALL_DIR=${includedir} \ +" + +inherit systemd +SYSTEMD_SERVICE_${PN} = "security-manager.service" + +inherit features_check +REQUIRED_DISTRO_FEATURES += "smack" + +# The upstream source code contains the Tizen-specific policy configuration files. +# To replace them, create a security-manager.bbappend and set the following variable to a +# space-separated list of policy file names (not URIs!), for example: +# SECURITY_MANAGER_POLICY = "privilege-group.list usertype-system.profile" +# +# Leave it empty to use the upstream Tizen policy. +SECURITY_MANAGER_POLICY ?= "" +SRC_URI_append = " ${@' '.join(['file://' + x for x in d.getVar('SECURITY_MANAGER_POLICY', True).split()])}" +python do_patch_append () { + import os + import shutil + import glob + files = d.getVar('SECURITY_MANAGER_POLICY', True).split() + if files: + s = d.getVar('S', True) + workdir = d.getVar('WORKDIR', True) + for pattern in ['*.profile', '*.list']: + for old_file in glob.glob(s + '/policy/' + pattern): + os.unlink(old_file) + for file in files: + shutil.copy(file, s + '/policy') +} + +do_install_append () { + install -d ${D}/${systemd_unitdir}/system/multi-user.target.wants + ln -s ../security-manager.service ${D}/${systemd_unitdir}/system/multi-user.target.wants/security-manager.service + install -d ${D}/${systemd_unitdir}/system/sockets.target.wants + ln -s ../security-manager.socket ${D}/${systemd_unitdir}/system/sockets.target.wants/security-manager.socket +} + +RDEPENDS_${PN} += "sqlite3 cynara" +FILES_${PN} += " \ + ${systemd_unitdir} \ + ${TZ_SYS_DB} \ + ${bindir}/.security-manager-setup \ +" + +PACKAGES =+ "${PN}-policy" +FILES_${PN}-policy = " \ + ${datadir}/${PN} \ + ${bindir}/security-manager-policy-reload \ +" diff --git a/meta-app-framework/recipes-core/security-manager/security-manager/0001-Adapt-rules-to-AGL.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0001-Adapt-rules-to-AGL.patch index 4c91f7fa3..4c91f7fa3 100644 --- a/meta-app-framework/recipes-core/security-manager/security-manager/0001-Adapt-rules-to-AGL.patch +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0001-Adapt-rules-to-AGL.patch diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0001-systemd-stop-using-compat-libs.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0001-systemd-stop-using-compat-libs.patch new file mode 100644 index 000000000..91ce81963 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0001-systemd-stop-using-compat-libs.patch @@ -0,0 +1,47 @@ +From 3d9d1d83fe298a364f51ad752c17aad461beded3 Mon Sep 17 00:00:00 2001 +From: Patrick Ohly <patrick.ohly@intel.com> +Date: Tue, 24 Mar 2015 04:54:03 -0700 +Subject: [PATCH 01/14] systemd: stop using compat libs + +libsystemd-journal and libsystemd-daemon are considered obsolete +in systemd since 2.09 and may not be available (not compiled +by default). + +The code works fine with the current libsystemd, so just +use that. + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +Upstream-Status: Submitted (https://github.com/Samsung/security-manager/pull/1 +--- + src/common/CMakeLists.txt | 2 +- + src/server/CMakeLists.txt | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt +index 2da9c3e..968c7c1 100644 +--- a/src/common/CMakeLists.txt ++++ b/src/common/CMakeLists.txt +@@ -3,7 +3,7 @@ SET(COMMON_VERSION ${COMMON_VERSION_MAJOR}.0.2) + + PKG_CHECK_MODULES(COMMON_DEP + REQUIRED +- libsystemd-journal ++ libsystemd + libsmack + db-util + cynara-admin +diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt +index 753eb96..6849d76 100644 +--- a/src/server/CMakeLists.txt ++++ b/src/server/CMakeLists.txt +@@ -1,6 +1,6 @@ + PKG_CHECK_MODULES(SERVER_DEP + REQUIRED +- libsystemd-daemon ++ libsystemd + ) + + FIND_PACKAGE(Boost REQUIRED) +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0002-security-manager-policy-reload-do-not-depend-on-GNU-.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0002-security-manager-policy-reload-do-not-depend-on-GNU-.patch new file mode 100644 index 000000000..b6346480b --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0002-security-manager-policy-reload-do-not-depend-on-GNU-.patch @@ -0,0 +1,36 @@ +From a90515613f09140049b2bdf471fa83d5dd7bad1c Mon Sep 17 00:00:00 2001 +From: Patrick Ohly <patrick.ohly@intel.com> +Date: Wed, 19 Aug 2015 15:02:32 +0200 +Subject: [PATCH 02/14] security-manager-policy-reload: do not depend on GNU + sed + +\U (= make replacement uppercase) is a GNU sed extension which is not +supported by other sed implementation's (like the one from +busybox). When using busybox, the bucket for user profiles became +USER_TYPE_Uadmin instead USER_TYPE_ADMIN. + +To make SecurityManager more portable, better use tr to turn the +bucket name into uppercase. + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +Upstream-Status: Submitted (https://github.com/Samsung/security-manager/pull/1 +--- + policy/security-manager-policy-reload | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/policy/security-manager-policy-reload b/policy/security-manager-policy-reload +index 274c49c..6f211c6 100755 +--- a/policy/security-manager-policy-reload ++++ b/policy/security-manager-policy-reload +@@ -33,7 +33,7 @@ END + find "$POLICY_PATH" -name "usertype-*.profile" | + while read file + do +- bucket="`echo $file | sed -r 's|.*/usertype-(.*).profile$|USER_TYPE_\U\1|'`" ++ bucket="`echo $file | sed -r 's|.*/usertype-(.*).profile$|USER_TYPE_\1|' | tr '[:lower:]' '[:upper:]'`" + + # Re-create the bucket with empty contents + cyad --delete-bucket=$bucket || true +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0003-Smack-rules-create-two-new-functions.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0003-Smack-rules-create-two-new-functions.patch new file mode 100644 index 000000000..d79345e01 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0003-Smack-rules-create-two-new-functions.patch @@ -0,0 +1,117 @@ +From a80e33bc0a10fa4bed5d0b7bf29f45dd2565d309 Mon Sep 17 00:00:00 2001 +From: Alejandro Joya <alejandro.joya.cruz@intel.com> +Date: Wed, 4 Nov 2015 19:01:35 -0600 +Subject: [PATCH 03/14] Smack-rules: create two new functions + +It let to smack-rules to create multiple set of rules +related with the privileges. + +It runs from the same bases than for a static set of rules on the +template, but let you add 1 or many templates for different cases. + +Change-Id: I14f8d4e914ad5a7ba34c96f3cb5589f0b15292de +Signed-off-by: Alejandro Joya <alejandro.joya.cruz@intel.com> +--- + src/common/include/smack-rules.h | 15 +++++++++++ + src/common/smack-rules.cpp | 44 ++++++++++++++++++++++++++++++++ + 2 files changed, 59 insertions(+) + +diff --git a/src/common/include/smack-rules.h b/src/common/include/smack-rules.h +index 91446a7..3ad9dd4 100644 +--- a/src/common/include/smack-rules.h ++++ b/src/common/include/smack-rules.h +@@ -47,6 +47,8 @@ public: + void addFromTemplate(const std::vector<std::string> &templateRules, + const std::string &appId, const std::string &pkgId); + void addFromTemplateFile(const std::string &appId, const std::string &pkgId); ++ void addFromTemplateFile(const std::string &appId, const std::string &pkgId, ++ const std::string &path); + + void apply() const; + void clear() const; +@@ -74,6 +76,19 @@ public: + */ + static void installApplicationRules(const std::string &appId, const std::string &pkgId, + const std::vector<std::string> &pkgContents); ++ /** ++ * Install privileges-specific smack rules. ++ * ++ * Function creates smack rules using predefined template. Rules are applied ++ * to the kernel and saved on persistent storage so they are loaded on system boot. ++ * ++ * @param[in] appId - application id that is beeing installed ++ * @param[in] pkgId - package id that the application is in ++ * @param[in] pkgContents - a list of all applications in the package ++ * @param[in] privileges - a list of all prvileges ++ */ ++ static void installApplicationPrivilegesRules(const std::string &appId, const std::string &pkgId, ++ const std::vector<std::string> &pkgContents, const std::vector<std::string> &privileges); + /** + * Uninstall package-specific smack rules. + * +diff --git a/src/common/smack-rules.cpp b/src/common/smack-rules.cpp +index 3629e0f..922a56f 100644 +--- a/src/common/smack-rules.cpp ++++ b/src/common/smack-rules.cpp +@@ -135,6 +135,29 @@ void SmackRules::saveToFile(const std::string &path) const + } + } + ++void SmackRules::addFromTemplateFile(const std::string &appId, ++ const std::string &pkgId, const std::string &path) ++{ ++ std::vector<std::string> templateRules; ++ std::string line; ++ std::ifstream templateRulesFile(path); ++ ++ if (!templateRulesFile.is_open()) { ++ LogError("Cannot open rules template file: " << path); ++ ThrowMsg(SmackException::FileError, "Cannot open rules template file: " << path); ++ } ++ ++ while (std::getline(templateRulesFile, line)) { ++ templateRules.push_back(line); ++ } ++ ++ if (templateRulesFile.bad()) { ++ LogError("Error reading template file: " << APP_RULES_TEMPLATE_FILE_PATH); ++ ThrowMsg(SmackException::FileError, "Error reading template file: " << APP_RULES_TEMPLATE_FILE_PATH); ++ } ++ ++ addFromTemplate(templateRules, appId, pkgId); ++} + + void SmackRules::addFromTemplateFile(const std::string &appId, + const std::string &pkgId) +@@ -223,7 +246,28 @@ std::string SmackRules::getApplicationRulesFilePath(const std::string &appId) + std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("app_" + appId).c_str())); + return path; + } ++void SmackRules::installApplicationPrivilegesRules(const std::string &appId, const std::string &pkgId, ++ const std::vector<std::string> &pkgContents, const std::vector<std::string> &privileges) ++{ ++ SmackRules smackRules; ++ std::string appPath = getApplicationRulesFilePath(appId); ++ smackRules.loadFromFile(appPath); ++ struct stat buffer; ++ for (auto privilege : privileges) { ++ if (privilege.empty()) ++ continue; ++ std::string fprivilege ( privilege + "-template.smack"); ++ std::string path(tzplatform_mkpath4(TZ_SYS_SHARE, "security-manager", "policy", fprivilege.c_str())); ++ if( stat(path.c_str(), &buffer) == 0) ++ smackRules.addFromTemplateFile(appId, pkgId, path); ++ } ++ ++ if (smack_smackfs_path() != NULL) ++ smackRules.apply(); + ++ smackRules.saveToFile(appPath); ++ updatePackageRules(pkgId, pkgContents); ++} + void SmackRules::installApplicationRules(const std::string &appId, const std::string &pkgId, + const std::vector<std::string> &pkgContents) + { +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0004-app-install-implement-multiple-set-of-smack-rules.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0004-app-install-implement-multiple-set-of-smack-rules.patch new file mode 100644 index 000000000..59d4971ff --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0004-app-install-implement-multiple-set-of-smack-rules.patch @@ -0,0 +1,34 @@ +From a5979d9d674e400ecd7fcdf5d7589cfa0cfeb492 Mon Sep 17 00:00:00 2001 +From: Alejandro Joya <alejandro.joya.cruz@intel.com> +Date: Wed, 4 Nov 2015 19:06:23 -0600 +Subject: [PATCH 04/14] app-install: implement multiple set of smack-rules + +If it's need it could create load multiple set of smack rules +related with the privileges. +It wouldn't affect the case that only the default set of rules is need it. + +Signed-off-by: Alejandro Joya <alejandro.joya.cruz@intel.com> +--- + src/common/service_impl.cpp | 6 ++++++ + 1 file changed, 6 insertions(+) + +diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp +index 7fd621c..ae305d3 100644 +--- a/src/common/service_impl.cpp ++++ b/src/common/service_impl.cpp +@@ -338,6 +338,12 @@ int appInstall(const app_inst_req &req, uid_t uid) + LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: " + << req.pkgId << ". Applications in package: " << pkgContents.size()); + SmackRules::installApplicationRules(req.appId, req.pkgId, pkgContents); ++ /*Setup for privileges custom rules*/ ++ LogDebug("Adding Smack rules for new appId: " << req.appId << " with pkgId: " ++ << req.pkgId << ". Applications in package: " << pkgContents.size() ++ << " and Privileges"); ++ SmackRules::installApplicationPrivilegesRules(req.appId, req.pkgId, ++ pkgContents,req.privileges); + } catch (const SmackException::Base &e) { + LogError("Error while applying Smack policy for application: " << e.DumpToString()); + return SECURITY_MANAGER_API_ERROR_SETTING_FILE_LABEL_FAILED; +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0005-c-11-replace-deprecated-auto_ptr.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0005-c-11-replace-deprecated-auto_ptr.patch new file mode 100644 index 000000000..0739f28c7 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0005-c-11-replace-deprecated-auto_ptr.patch @@ -0,0 +1,32 @@ +From 198ba9b9782fda19803e94d2afeff91189ac27af Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jobol@nonadev.net> +Date: Wed, 13 Jan 2016 17:30:06 +0100 +Subject: [PATCH 05/14] c++11: replace deprecated auto_ptr +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Upstream-Status: Submitted [https://review.tizen.org/gerrit/#/c/56940/] + +Change-Id: Id793c784c9674eef48f346226c094bdd9f7bbda8 +Signed-off-by: José Bollo <jobol@nonadev.net> +--- + src/dpl/core/include/dpl/binary_queue.h | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dpl/core/include/dpl/binary_queue.h b/src/dpl/core/include/dpl/binary_queue.h +index dd03f5e..185b6c7 100644 +--- a/src/dpl/core/include/dpl/binary_queue.h ++++ b/src/dpl/core/include/dpl/binary_queue.h +@@ -33,7 +33,7 @@ namespace SecurityManager { + * Binary queue auto pointer + */ + class BinaryQueue; +-typedef std::auto_ptr<BinaryQueue> BinaryQueueAutoPtr; ++typedef std::unique_ptr<BinaryQueue> BinaryQueueAutoPtr; + + /** + * Binary stream implemented as constant size bucket list +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0006-socket-manager-removes-tizen-specific-call.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0006-socket-manager-removes-tizen-specific-call.patch new file mode 100644 index 000000000..3b8aad98c --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0006-socket-manager-removes-tizen-specific-call.patch @@ -0,0 +1,47 @@ +From ec098bf03cea23350ca7d1ea2ad88b9c88228943 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Fri, 8 Jan 2016 16:53:46 +0100 +Subject: [PATCH 06/14] socket-manager: removes tizen specific call +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The function 'smack_fgetlabel' is specific to Tizen +and is no more maintained upstream. + +Upstream-Status: Accepted [https://review.tizen.org/gerrit/#/c/56507/] + +Change-Id: I3802742b1758efe37b33e6d968ff727d68f2fd1f +Signed-off-by: José Bollo <jobol@nonadev.net> +--- + src/server/main/socket-manager.cpp | 7 ++++--- + 1 file changed, 4 insertions(+), 3 deletions(-) + +diff --git a/src/server/main/socket-manager.cpp b/src/server/main/socket-manager.cpp +index 94c54c6..5e1a79b 100644 +--- a/src/server/main/socket-manager.cpp ++++ b/src/server/main/socket-manager.cpp +@@ -30,6 +30,7 @@ + #include <sys/types.h> + #include <sys/socket.h> + #include <sys/smack.h> ++#include <linux/xattr.h> + #include <sys/un.h> + #include <sys/stat.h> + #include <unistd.h> +@@ -493,9 +494,9 @@ int SocketManager::CreateDomainSocketHelp( + if (smack_check()) { + LogInfo("Set up smack label: " << desc.smackLabel); + +- if (0 != smack_fsetlabel(sockfd, desc.smackLabel.c_str(), SMACK_LABEL_IPIN)) { +- LogError("Error in smack_fsetlabel"); +- ThrowMsg(Exception::InitFailed, "Error in smack_fsetlabel"); ++ if (0 != smack_set_label_for_file(sockfd, XATTR_NAME_SMACKIPIN, desc.smackLabel.c_str())) { ++ LogError("Error in smack_set_label_for_file"); ++ ThrowMsg(Exception::InitFailed, "Error in smack_set_label_for_file"); + } + } else { + LogInfo("No smack on platform. Socket won't be securied with smack label!"); +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0007-removes-dependency-to-libslp-db-utils.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0007-removes-dependency-to-libslp-db-utils.patch new file mode 100644 index 000000000..bad99d25a --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0007-removes-dependency-to-libslp-db-utils.patch @@ -0,0 +1,78 @@ +From 9d0791dab4b4df086374c5c0ba2a6558e10e81c1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Mon, 16 Nov 2015 15:56:27 +0100 +Subject: [PATCH 07/14] removes dependency to libslp-db-utils + +Change-Id: I90471e77d20e04bae58cc42eb2639e4aef97fdec +--- + src/common/CMakeLists.txt | 3 ++- + src/dpl/db/src/sql_connection.cpp | 17 +---------------- + 2 files changed, 3 insertions(+), 17 deletions(-) + +diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt +index 968c7c1..9ae376f 100644 +--- a/src/common/CMakeLists.txt ++++ b/src/common/CMakeLists.txt +@@ -5,7 +5,8 @@ PKG_CHECK_MODULES(COMMON_DEP + REQUIRED + libsystemd + libsmack +- db-util ++ sqlite3 ++ icu-i18n + cynara-admin + cynara-client + ) +diff --git a/src/dpl/db/src/sql_connection.cpp b/src/dpl/db/src/sql_connection.cpp +index fdb4fe4..f49a6dc 100644 +--- a/src/dpl/db/src/sql_connection.cpp ++++ b/src/dpl/db/src/sql_connection.cpp +@@ -26,7 +26,6 @@ + #include <memory> + #include <dpl/noncopyable.h> + #include <dpl/assert.h> +-#include <db-util.h> + #include <unistd.h> + #include <cstdio> + #include <cstdarg> +@@ -606,16 +605,7 @@ void SqlConnection::Connect(const std::string &address, + + // Connect to database + int result; +- if (type & Flag::UseLucene) { +- result = db_util_open_with_options( +- address.c_str(), +- &m_connection, +- flag, +- NULL); +- +- m_usingLucene = true; +- LogPedantic("Lucene index enabled"); +- } else { ++ (void)type; + result = sqlite3_open_v2( + address.c_str(), + &m_connection, +@@ -624,7 +614,6 @@ void SqlConnection::Connect(const std::string &address, + + m_usingLucene = false; + LogPedantic("Lucene index disabled"); +- } + + if (result == SQLITE_OK) { + LogPedantic("Connected to DB"); +@@ -653,11 +642,7 @@ void SqlConnection::Disconnect() + + int result; + +- if (m_usingLucene) { +- result = db_util_close(m_connection); +- } else { + result = sqlite3_close(m_connection); +- } + + if (result != SQLITE_OK) { + const char *error = sqlite3_errmsg(m_connection); +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0008-Fix-gcc6-build.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0008-Fix-gcc6-build.patch new file mode 100644 index 000000000..5ece7ef4f --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0008-Fix-gcc6-build.patch @@ -0,0 +1,38 @@ +From a1d9b40b4fa2e73d31a53e398c286bffeaae1732 Mon Sep 17 00:00:00 2001 +From: Ronan <ronan.lemartret@iot.bzh> +Date: Wed, 12 Oct 2016 17:48:55 +0200 +Subject: [PATCH 08/14] Fix gcc6 build + +Signed-off-by: ronan <ronan@ot.bzh> +--- + src/client/client-security-manager.cpp | 1 + + src/common/include/privilege_db.h | 1 + + 2 files changed, 2 insertions(+) + +diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp +index 74a6b30..347cddd 100644 +--- a/src/client/client-security-manager.cpp ++++ b/src/client/client-security-manager.cpp +@@ -46,6 +46,7 @@ + #include <service_impl.h> + #include <security-manager.h> + #include <client-offline.h> ++#include <linux/xattr.h> + + static const char *EMPTY = ""; + +diff --git a/src/common/include/privilege_db.h b/src/common/include/privilege_db.h +index 4d73d90..08fb9d6 100644 +--- a/src/common/include/privilege_db.h ++++ b/src/common/include/privilege_db.h +@@ -32,6 +32,7 @@ + #include <map> + #include <stdbool.h> + #include <string> ++#include <vector> + + #include <dpl/db/sql_connection.h> + #include <tzplatform_config.h> +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0009-Fix-Cmake-conf-for-gcc6-build.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0009-Fix-Cmake-conf-for-gcc6-build.patch new file mode 100644 index 000000000..706eb1a93 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0009-Fix-Cmake-conf-for-gcc6-build.patch @@ -0,0 +1,40 @@ +From 382379d74221bcc60a0ab70d63430a1c0587b2ec Mon Sep 17 00:00:00 2001 +From: Ronan <ronan.lemartret@iot.bzh> +Date: Thu, 13 Oct 2016 11:37:47 +0200 +Subject: [PATCH 09/14] Fix Cmake conf for gcc6 build + +Signed-off-by: Ronan <ronan.lemartret@iot.bzh> +--- + src/cmd/CMakeLists.txt | 4 +--- + src/server/CMakeLists.txt | 1 - + 2 files changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/cmd/CMakeLists.txt b/src/cmd/CMakeLists.txt +index ee9a160..aa7a12c 100644 +--- a/src/cmd/CMakeLists.txt ++++ b/src/cmd/CMakeLists.txt +@@ -1,8 +1,6 @@ + FIND_PACKAGE(Boost REQUIRED COMPONENTS program_options) + +-INCLUDE_DIRECTORIES(SYSTEM +- ${Boost_INCLUDE_DIRS} +- ) ++ + + INCLUDE_DIRECTORIES( + ${INCLUDE_PATH} +diff --git a/src/server/CMakeLists.txt b/src/server/CMakeLists.txt +index 6849d76..9598037 100644 +--- a/src/server/CMakeLists.txt ++++ b/src/server/CMakeLists.txt +@@ -8,7 +8,6 @@ FIND_PACKAGE(Threads REQUIRED) + + INCLUDE_DIRECTORIES(SYSTEM + ${SERVER_DEP_INCLUDE_DIRS} +- ${Boost_INCLUDE_DIRS} + ${Threads_INCLUDE_DIRS} + ) + +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0010-gcc-7-requires-include-functional-for-std-function.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0010-gcc-7-requires-include-functional-for-std-function.patch new file mode 100644 index 000000000..0f48c5f68 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0010-gcc-7-requires-include-functional-for-std-function.patch @@ -0,0 +1,51 @@ +From 8e93699c0f225716f3cd5eff790270ae9e3880f9 Mon Sep 17 00:00:00 2001 +From: Changhyeok Bae <changhyeok.bae@gmail.com> +Date: Sun, 17 Dec 2017 15:40:58 +0000 +Subject: [PATCH 10/14] gcc-7 requires include <functional> for std::function + +Signed-off-by: Changhyeok Bae <changhyeok.bae@gmail.com> +--- + src/client/client-common.cpp | 1 + + src/common/smack-labels.cpp | 1 + + src/dpl/core/src/binary_queue.cpp | 1 + + 3 files changed, 3 insertions(+) + +diff --git a/src/client/client-common.cpp b/src/client/client-common.cpp +index 883ab8d..1babdf7 100644 +--- a/src/client/client-common.cpp ++++ b/src/client/client-common.cpp +@@ -31,6 +31,7 @@ + #include <sys/xattr.h> + #include <linux/xattr.h> + #include <unistd.h> ++#include <functional> + + #include <dpl/log/log.h> + #include <dpl/serialization.h> +diff --git a/src/common/smack-labels.cpp b/src/common/smack-labels.cpp +index 0294a42..1598099 100644 +--- a/src/common/smack-labels.cpp ++++ b/src/common/smack-labels.cpp +@@ -29,6 +29,7 @@ + #include <sys/xattr.h> + #include <linux/xattr.h> + #include <memory> ++#include <functional> + #include <fts.h> + #include <cstring> + #include <string> +diff --git a/src/dpl/core/src/binary_queue.cpp b/src/dpl/core/src/binary_queue.cpp +index 72817a6..838409f 100644 +--- a/src/dpl/core/src/binary_queue.cpp ++++ b/src/dpl/core/src/binary_queue.cpp +@@ -26,6 +26,7 @@ + #include <malloc.h> + #include <cstring> + #include <new> ++#include <functional> + + namespace SecurityManager { + BinaryQueue::BinaryQueue() : +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0011-Fix-gcc8-warning-error-Werror-catch-value.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0011-Fix-gcc8-warning-error-Werror-catch-value.patch new file mode 100644 index 000000000..5c679fc26 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0011-Fix-gcc8-warning-error-Werror-catch-value.patch @@ -0,0 +1,32 @@ +From 243b7ffee16558d7cb9b411f49380138efeffca9 Mon Sep 17 00:00:00 2001 +From: Stephane Desneux <stephane.desneux@iot.bzh> +Date: Fri, 1 Feb 2019 12:26:17 +0000 +Subject: [PATCH 11/14] Fix gcc8 warning/error [-Werror=catch-value=] + +Fixes the following warning/error during compile: + +src/dpl/core/src/assert.cpp:61:14: error: catching polymorphic type 'class SecurityManager::Exception' by value [-Werror=catch-value=] +| } catch (Exception) { +| ^~~~~~~~~ + +Signed-off-by: Stephane Desneux <stephane.desneux@iot.bzh> +--- + src/dpl/core/src/assert.cpp | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/dpl/core/src/assert.cpp b/src/dpl/core/src/assert.cpp +index 63538a2..fc60ce9 100644 +--- a/src/dpl/core/src/assert.cpp ++++ b/src/dpl/core/src/assert.cpp +@@ -58,7 +58,7 @@ void AssertProc(const char *condition, + INTERNAL_LOG("### Function: " << function); + INTERNAL_LOG( + "################################################################################"); +- } catch (Exception) { ++ } catch (Exception const&) { + // Just ignore possible double errors + } + +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0012-Avoid-casting-from-const-T-to-void.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0012-Avoid-casting-from-const-T-to-void.patch new file mode 100644 index 000000000..91ccf9ee2 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0012-Avoid-casting-from-const-T-to-void.patch @@ -0,0 +1,122 @@ +From 5ee51d38575f289c2bf37ed817ef680ed47bb320 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Fri, 1 Feb 2019 15:37:44 +0100 +Subject: [PATCH 12/14] Avoid casting from "const T&" to "void*" +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Latest version of g++ refuse the cast + + reinterpret_cast<void (Service::*)(void*)>(serviceFunction) + +I made no investigation to know if the problem +is coming from the const or not. + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + src/server/main/include/service-thread.h | 42 ++++++++++-------------- + 1 file changed, 18 insertions(+), 24 deletions(-) + +diff --git a/src/server/main/include/service-thread.h b/src/server/main/include/service-thread.h +index 964d168..61fdda8 100644 +--- a/src/server/main/include/service-thread.h ++++ b/src/server/main/include/service-thread.h +@@ -94,7 +94,7 @@ public: + Join(); + while (!m_eventQueue.empty()){ + auto front = m_eventQueue.front(); +- delete front.eventPtr; ++ delete front; + m_eventQueue.pop(); + } + } +@@ -104,34 +104,28 @@ public: + Service *servicePtr, + void (Service::*serviceFunction)(const T &)) + { +- EventDescription description; +- description.serviceFunctionPtr = +- reinterpret_cast<void (Service::*)(void*)>(serviceFunction); +- description.servicePtr = servicePtr; +- description.eventFunctionPtr = &ServiceThread::EventCall<T>; +- description.eventPtr = new T(event); ++ EventCallerBase *ec = new EventCaller<T>(event, servicePtr, serviceFunction); + { + std::lock_guard<std::mutex> lock(m_eventQueueMutex); +- m_eventQueue.push(description); ++ m_eventQueue.push(ec); + } + m_waitCondition.notify_one(); + } + + protected: + +- struct EventDescription { +- void (Service::*serviceFunctionPtr)(void *); +- Service *servicePtr; +- void (ServiceThread::*eventFunctionPtr)(const EventDescription &event); +- GenericEvent* eventPtr; ++ struct EventCallerBase { ++ virtual void fire() = 0; ++ virtual ~EventCallerBase() {} + }; + + template <class T> +- void EventCall(const EventDescription &desc) { +- auto fun = reinterpret_cast<void (Service::*)(const T&)>(desc.serviceFunctionPtr); +- const T& eventLocale = *(static_cast<T*>(desc.eventPtr)); +- (desc.servicePtr->*fun)(eventLocale); +- } ++ struct EventCaller : public EventCallerBase { ++ T *event; Service *target; void (Service::*function)(const T&); ++ EventCaller(const T &e, Service *c, void (Service::*f)(const T&)) : event(new T(e)), target(c), function(f) {} ++ ~EventCaller() { delete event; } ++ void fire() { (target->*function)(*event); } ++ }; + + static void ThreadLoopStatic(ServiceThread *ptr) { + ptr->ThreadLoop(); +@@ -139,33 +133,33 @@ protected: + + void ThreadLoop(){ + for (;;) { +- EventDescription description = {NULL, NULL, NULL, NULL}; ++ EventCallerBase *ec = NULL; + { + std::unique_lock<std::mutex> ulock(m_eventQueueMutex); + if (m_quit) + return; + if (!m_eventQueue.empty()) { +- description = m_eventQueue.front(); ++ ec = m_eventQueue.front(); + m_eventQueue.pop(); + } else { + m_waitCondition.wait(ulock); + } + } + +- if (description.eventPtr != NULL) { ++ if (ec != NULL) { + UNHANDLED_EXCEPTION_HANDLER_BEGIN + { +- (this->*description.eventFunctionPtr)(description); +- delete description.eventPtr; ++ ec->fire(); + } + UNHANDLED_EXCEPTION_HANDLER_END ++ delete ec; + } + } + } + + std::thread m_thread; + std::mutex m_eventQueueMutex; +- std::queue<EventDescription> m_eventQueue; ++ std::queue<EventCallerBase*> m_eventQueue; + std::condition_variable m_waitCondition; + + State m_state; +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0013-Removing-tizen-platform-config.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0013-Removing-tizen-platform-config.patch new file mode 100644 index 000000000..fb6215923 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0013-Removing-tizen-platform-config.patch @@ -0,0 +1,259 @@ +From 6c96a39ba7a7763ccd47e379dbfd8d376164985f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Mon, 16 Nov 2015 14:26:25 +0100 +Subject: [PATCH 13/14] Removing tizen-platform-config + +Change-Id: Ic832a2b75229517b09faba969c27fb1a4b490121 +--- + CMakeLists.txt | 16 +++++++- + db/CMakeLists.txt | 2 +- + policy/CMakeLists.txt | 1 + + ...load => security-manager-policy-reload.in} | 4 +- + src/common/file-lock.cpp | 4 +- + src/common/include/file-lock.h | 1 - + src/common/include/privilege_db.h | 3 +- + src/common/service_impl.cpp | 39 ++++++------------- + src/common/smack-rules.cpp | 12 ++---- + 9 files changed, 37 insertions(+), 45 deletions(-) + rename policy/{security-manager-policy-reload => security-manager-policy-reload.in} (94%) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index 28790d8..37a43cc 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -49,7 +49,7 @@ ADD_DEFINITIONS("-Wall") # Generate all warnings + ADD_DEFINITIONS("-Wextra") # Generate even more extra warnings + + STRING(REGEX MATCH "([^.]*)" API_VERSION "${VERSION}") +-ADD_DEFINITIONS("-DAPI_VERSION=\"$(API_VERSION)\"") ++ADD_DEFINITIONS("-DAPI_VERSION=\"${API_VERSION}\"") + + ADD_DEFINITIONS("-DSMACK_ENABLED") + +@@ -58,6 +58,20 @@ IF (CMAKE_BUILD_TYPE MATCHES "DEBUG") + ADD_DEFINITIONS("-DBUILD_TYPE_DEBUG") + ENDIF (CMAKE_BUILD_TYPE MATCHES "DEBUG") + ++SET(DATADIR "/usr/share/security-manager" CACHE STRING "path to data directory") ++SET(SMACKRULESDIR "/etc/smack/accesses.d" CACHE STRING "path to Smack rules directory") ++SET(LOCKDIR "/var/run/lock" CACHE STRING "path to lock directory") ++SET(DB_INSTALL_DIR "/var/db/security-manager" CACHE STRING "path to database directory") ++SET(DB_FILENAME ".security-manager.db" CACHE STRING "basename of database") ++SET(GLOBALUSER "userapp" CACHE STRING "name of the global user") ++ ++ADD_DEFINITIONS("-DDATADIR=\"${DATADIR}\"") ++ADD_DEFINITIONS("-DSMACKRULESDIR=\"${SMACKRULESDIR}\"") ++ADD_DEFINITIONS("-DLOCKDIR=\"${LOCKDIR}\"") ++ADD_DEFINITIONS("-DDB_INSTALL_DIR=\"${DB_INSTALL_DIR}\"") ++ADD_DEFINITIONS("-DDB_FILENAME=\"${DB_FILENAME}\"") ++ADD_DEFINITIONS("-DGLOBALUSER=\"${GLOBALUSER}\"") ++ + ADD_SUBDIRECTORY(src) + ADD_SUBDIRECTORY(pc) + ADD_SUBDIRECTORY(systemd) +diff --git a/db/CMakeLists.txt b/db/CMakeLists.txt +index 9e8ffcc..d7af1a0 100644 +--- a/db/CMakeLists.txt ++++ b/db/CMakeLists.txt +@@ -1,4 +1,4 @@ +-SET(TARGET_DB ".security-manager.db") ++SET(TARGET_DB "$(DB_FILENAME)") + + ADD_CUSTOM_COMMAND( + OUTPUT ${TARGET_DB} ${TARGET_DB}-journal +diff --git a/policy/CMakeLists.txt b/policy/CMakeLists.txt +index bd08edc..626a2bd 100644 +--- a/policy/CMakeLists.txt ++++ b/policy/CMakeLists.txt +@@ -1,4 +1,5 @@ + FILE(GLOB USERTYPE_POLICY_FILES usertype-*.profile) ++CONFIGURE_FILE(security-manager-policy-reload.in security-manager-policy-reload @ONLY) + INSTALL(FILES ${USERTYPE_POLICY_FILES} DESTINATION ${SHARE_INSTALL_PREFIX}/security-manager/policy) + INSTALL(FILES "app-rules-template.smack" DESTINATION ${SHARE_INSTALL_PREFIX}/security-manager/policy) + INSTALL(FILES "privilege-group.list" DESTINATION ${SHARE_INSTALL_PREFIX}/security-manager/policy) +diff --git a/policy/security-manager-policy-reload b/policy/security-manager-policy-reload.in +similarity index 94% +rename from policy/security-manager-policy-reload +rename to policy/security-manager-policy-reload.in +index 6f211c6..c1bc4e2 100755 +--- a/policy/security-manager-policy-reload ++++ b/policy/security-manager-policy-reload.in +@@ -1,8 +1,8 @@ + #!/bin/sh -e + +-POLICY_PATH=/usr/share/security-manager/policy ++POLICY_PATH=@DATADIR@/policy + PRIVILEGE_GROUP_MAPPING=$POLICY_PATH/privilege-group.list +-DB_FILE=`tzplatform-get TZ_SYS_DB | cut -d= -f2`/.security-manager.db ++DB_FILE=@DB_INSTALL_DIR@/@DB_FILENAME@ + + # Create default buckets + while read bucket default_policy +diff --git a/src/common/file-lock.cpp b/src/common/file-lock.cpp +index 6f3996c..88d2092 100644 +--- a/src/common/file-lock.cpp ++++ b/src/common/file-lock.cpp +@@ -30,9 +30,7 @@ + + namespace SecurityManager { + +-char const * const SERVICE_LOCK_FILE = tzplatform_mkpath3(TZ_SYS_RUN, +- "lock", +- "security-manager.lock"); ++char const * const SERVICE_LOCK_FILE = LOCKDIR "/security-manager.lock"; + + FileLocker::FileLocker(const std::string &lockFile, bool blocking) + { +diff --git a/src/common/include/file-lock.h b/src/common/include/file-lock.h +index 604b019..21a86a0 100644 +--- a/src/common/include/file-lock.h ++++ b/src/common/include/file-lock.h +@@ -29,7 +29,6 @@ + + #include <dpl/exception.h> + #include <dpl/noncopyable.h> +-#include <tzplatform_config.h> + + namespace SecurityManager { + +diff --git a/src/common/include/privilege_db.h b/src/common/include/privilege_db.h +index 08fb9d6..3344987 100644 +--- a/src/common/include/privilege_db.h ++++ b/src/common/include/privilege_db.h +@@ -35,14 +35,13 @@ + #include <vector> + + #include <dpl/db/sql_connection.h> +-#include <tzplatform_config.h> + + #ifndef PRIVILEGE_DB_H_ + #define PRIVILEGE_DB_H_ + + namespace SecurityManager { + +-const char *const PRIVILEGE_DB_PATH = tzplatform_mkpath(TZ_SYS_DB, ".security-manager.db"); ++const char *const PRIVILEGE_DB_PATH = DB_INSTALL_DIR "/" DB_FILENAME; + + enum class QueryType { + EGetPkgPrivileges, +diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp +index ae305d3..42150fe 100644 +--- a/src/common/service_impl.cpp ++++ b/src/common/service_impl.cpp +@@ -32,7 +32,6 @@ + #include <algorithm> + + #include <dpl/log/log.h> +-#include <tzplatform_config.h> + + #include "protocols.h" + #include "privilege_db.h" +@@ -131,7 +130,13 @@ static inline int validatePolicy(policy_entry &policyEntry, std::string uidStr, + + static uid_t getGlobalUserId(void) + { +- static uid_t globaluid = tzplatform_getuid(TZ_SYS_GLOBALAPP_USER); ++ static uid_t globaluid = 0; ++ if (!globaluid) { ++ struct passwd pw, *p; ++ char buf[4096]; ++ int rc = getpwnam_r(GLOBALUSER, &pw, buf, sizeof buf, &p); ++ globaluid = (rc || p == NULL) ? 555 : p->pw_uid; ++ } + return globaluid; + } + +@@ -161,37 +166,17 @@ static inline bool isSubDir(const char *parent, const char *subdir) + + static bool getUserAppDir(const uid_t &uid, std::string &userAppDir) + { +- struct tzplatform_context *tz_ctx = nullptr; +- +- if (tzplatform_context_create(&tz_ctx)) +- return false; +- +- if (tzplatform_context_set_user(tz_ctx, uid)) { +- tzplatform_context_destroy(tz_ctx); +- tz_ctx = nullptr; ++ struct passwd pw, *p; ++ char buf[4096]; ++ int rc = getpwuid_r(uid, &pw, buf, sizeof buf, &p); ++ if (rc || p == NULL) + return false; +- } +- +- enum tzplatform_variable id = +- (uid == getGlobalUserId()) ? TZ_SYS_RW_APP : TZ_USER_APP; +- const char *appDir = tzplatform_context_getenv(tz_ctx, id); +- if (!appDir) { +- tzplatform_context_destroy(tz_ctx); +- tz_ctx = nullptr; +- return false; +- } +- +- userAppDir = appDir; +- +- tzplatform_context_destroy(tz_ctx); +- tz_ctx = nullptr; +- ++ userAppDir = p->pw_dir; + return true; + } + + static inline bool installRequestAuthCheck(const app_inst_req &req, uid_t uid, bool &isCorrectPath, std::string &appPath) + { +- std::string userHome; + std::string userAppDir; + std::stringstream correctPath; + +diff --git a/src/common/smack-rules.cpp b/src/common/smack-rules.cpp +index 922a56f..c2e0041 100644 +--- a/src/common/smack-rules.cpp ++++ b/src/common/smack-rules.cpp +@@ -34,7 +34,6 @@ + #include <memory> + + #include <dpl/log/log.h> +-#include <tzplatform_config.h> + + #include "smack-labels.h" + #include "smack-rules.h" +@@ -43,7 +42,7 @@ namespace SecurityManager { + + const char *const SMACK_APP_LABEL_TEMPLATE = "~APP~"; + const char *const SMACK_PKG_LABEL_TEMPLATE = "~PKG~"; +-const char *const APP_RULES_TEMPLATE_FILE_PATH = tzplatform_mkpath4(TZ_SYS_SHARE, "security-manager", "policy", "app-rules-template.smack"); ++const char *const APP_RULES_TEMPLATE_FILE_PATH = DATADIR "/policy/app-rules-template.smack"; + const char *const SMACK_APP_IN_PACKAGE_PERMS = "rwxat"; + + SmackRules::SmackRules() +@@ -237,14 +236,12 @@ void SmackRules::generatePackageCrossDeps(const std::vector<std::string> &pkgCon + + std::string SmackRules::getPackageRulesFilePath(const std::string &pkgId) + { +- std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("pkg_" + pkgId).c_str())); +- return path; ++ return SMACKRULESDIR "/pkg_" + pkgId; + } + + std::string SmackRules::getApplicationRulesFilePath(const std::string &appId) + { +- std::string path(tzplatform_mkpath3(TZ_SYS_SMACK, "accesses.d", ("app_" + appId).c_str())); +- return path; ++ return SMACKRULESDIR "/app_" + appId; + } + void SmackRules::installApplicationPrivilegesRules(const std::string &appId, const std::string &pkgId, + const std::vector<std::string> &pkgContents, const std::vector<std::string> &privileges) +@@ -256,8 +253,7 @@ void SmackRules::installApplicationPrivilegesRules(const std::string &appId, con + for (auto privilege : privileges) { + if (privilege.empty()) + continue; +- std::string fprivilege ( privilege + "-template.smack"); +- std::string path(tzplatform_mkpath4(TZ_SYS_SHARE, "security-manager", "policy", fprivilege.c_str())); ++ std::string path = DATADIR "/policy/" + privilege + "-template.smack"; + if( stat(path.c_str(), &buffer) == 0) + smackRules.addFromTemplateFile(appId, pkgId, path); + } +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0014-Ensure-post-install-initialization-of-database.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0014-Ensure-post-install-initialization-of-database.patch new file mode 100644 index 000000000..542a387d2 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0014-Ensure-post-install-initialization-of-database.patch @@ -0,0 +1,78 @@ +From c7f9d14e38a1b6d40b2fffa01433a3025eff9abd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Tue, 26 Nov 2019 12:34:39 +0100 +Subject: [PATCH 14/14] Ensure post install initialization of database +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Creation of the database was made during image creation, +leading to issue with SOTA. This adds the creation on +need before launching the service. + +Change-Id: Idfd0676bd87d39f7c10eaafd63f3a318f675c972 +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + db/CMakeLists.txt | 14 ++++++-------- + db/security-manager-setup | 14 ++++++++++++++ + systemd/security-manager.service.in | 1 + + 3 files changed, 21 insertions(+), 8 deletions(-) + create mode 100644 db/security-manager-setup + +diff --git a/db/CMakeLists.txt b/db/CMakeLists.txt +index d7af1a0..dcf5bc8 100644 +--- a/db/CMakeLists.txt ++++ b/db/CMakeLists.txt +@@ -1,12 +1,10 @@ +-SET(TARGET_DB "$(DB_FILENAME)") +- + ADD_CUSTOM_COMMAND( +- OUTPUT ${TARGET_DB} ${TARGET_DB}-journal +- COMMAND sqlite3 ${TARGET_DB} <db.sql +- ) ++ OUTPUT .security-manager-setup ++ COMMAND sed '/--DB\.SQL--/r db.sql' security-manager-setup > .security-manager-setup ++ DEPENDS security-manager-setup db.sql ++) + + # Add a dummy build target to trigger building of ${TARGET_DB} +-ADD_CUSTOM_TARGET(DB ALL DEPENDS ${TARGET_DB}) ++ADD_CUSTOM_TARGET(DB ALL DEPENDS .security-manager-setup) + +-INSTALL(FILES ${TARGET_DB} DESTINATION ${DB_INSTALL_DIR}) +-INSTALL(FILES ${TARGET_DB}-journal DESTINATION ${DB_INSTALL_DIR}) ++INSTALL(PROGRAMS .security-manager-setup DESTINATION ${BIN_INSTALL_DIR}) +diff --git a/db/security-manager-setup b/db/security-manager-setup +new file mode 100644 +index 0000000..5675baf +--- /dev/null ++++ b/db/security-manager-setup +@@ -0,0 +1,14 @@ ++#!/bin/sh ++ ++if test -f "$1"; then exit; fi ++set -e ++dbdir="$(dirname "$1")" ++dbfile="$(basename "$1")" ++test -n "$dbfile" ++test -n "$dbdir" ++mkdir -p "$dbdir" ++cd "$dbdir" ++sqlite3 "$dbfile" << END-OF-CAT ++--DB.SQL-- ++END-OF-CAT ++ +diff --git a/systemd/security-manager.service.in b/systemd/security-manager.service.in +index 23fd1b2..2bf97d7 100644 +--- a/systemd/security-manager.service.in ++++ b/systemd/security-manager.service.in +@@ -3,5 +3,6 @@ Description=Start the security manager + + [Service] + Type=notify ++ExecStartPre=@BIN_INSTALL_DIR@/.security-manager-setup @DB_INSTALL_DIR@/@DB_FILENAME@ + ExecStart=@BIN_INSTALL_DIR@/security-manager + Sockets=security-manager.socket +-- +2.21.0 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager/0015-Restrict-socket-accesses.patch b/meta-app-framework/recipes-security/security-manager/security-manager/0015-Restrict-socket-accesses.patch new file mode 100644 index 000000000..d9949193b --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager/0015-Restrict-socket-accesses.patch @@ -0,0 +1,34 @@ +From 7cffcd61378a9d7c0e7db5691b2da3a37448c969 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Thu, 30 Jan 2020 09:19:25 +0100 +Subject: [PATCH 15/15] Restrict socket accesses +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Ensure that only members of the group and the owner can access +the security manager. + +Bug-AGL: SPEC-3146 + +Change-Id: I68ce6523db4bfd4707c3680555c3cb0cf8858ef2 +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + systemd/security-manager.socket | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/systemd/security-manager.socket b/systemd/security-manager.socket +index af1c1da..b401f77 100644 +--- a/systemd/security-manager.socket ++++ b/systemd/security-manager.socket +@@ -1,6 +1,6 @@ + [Socket] + ListenStream=/run/security-manager.socket +-SocketMode=0777 ++SocketMode=0660 + SmackLabelIPIn=* + SmackLabelIPOut=@ + +-- +2.21.1 + diff --git a/meta-app-framework/recipes-security/security-manager/security-manager_%.bbappend b/meta-app-framework/recipes-security/security-manager/security-manager_%.bbappend new file mode 100644 index 000000000..ec8435369 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager_%.bbappend @@ -0,0 +1,13 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/security-manager:" + +EXTRA_OECMAKE =+ " -DGLOBALUSER=afm" + +SRC_URI += " \ + file://0001-Adapt-rules-to-AGL.patch \ +" + +do_install_append() { + # Needed for wayland-0 socket access and memfd usage + echo "~APP~ System::Weston rw" >> ${D}${datadir}/security-manager/policy/app-rules-template.smack + echo "System::Weston ~APP~ rw" >> ${D}${datadir}/security-manager/policy/app-rules-template.smack +} diff --git a/meta-app-framework/recipes-security/security-manager/security-manager_git.bb b/meta-app-framework/recipes-security/security-manager/security-manager_git.bb new file mode 100644 index 000000000..b34973519 --- /dev/null +++ b/meta-app-framework/recipes-security/security-manager/security-manager_git.bb @@ -0,0 +1,27 @@ +require security-manager.inc + +PV = "1.0.2+git${SRCPV}" +SRCREV = "860305a595d681d650024ad07b3b0977e1fcb0a6" +SRC_URI += "git://github.com/Samsung/security-manager.git" +S = "${WORKDIR}/git" + +SRC_URI += " \ + file://0001-systemd-stop-using-compat-libs.patch \ + file://0002-security-manager-policy-reload-do-not-depend-on-GNU-.patch \ + file://0003-Smack-rules-create-two-new-functions.patch \ + file://0004-app-install-implement-multiple-set-of-smack-rules.patch \ + file://0005-c-11-replace-deprecated-auto_ptr.patch \ + file://0006-socket-manager-removes-tizen-specific-call.patch \ + file://0007-removes-dependency-to-libslp-db-utils.patch \ + file://0008-Fix-gcc6-build.patch \ + file://0009-Fix-Cmake-conf-for-gcc6-build.patch \ + file://0010-gcc-7-requires-include-functional-for-std-function.patch \ + file://0011-Fix-gcc8-warning-error-Werror-catch-value.patch \ + file://0012-Avoid-casting-from-const-T-to-void.patch \ + file://0013-Removing-tizen-platform-config.patch \ + file://0014-Ensure-post-install-initialization-of-database.patch \ + file://0015-Restrict-socket-accesses.patch \ +" + +# Use make with cmake and not ninja +OECMAKE_GENERATOR = "Unix Makefiles" diff --git a/meta-app-framework/recipes-security/xmlsec1/xmlsec1_1.%.bbappend b/meta-app-framework/recipes-security/xmlsec1/xmlsec1_1.%.bbappend index 09820be2f..afbc16c30 100644 --- a/meta-app-framework/recipes-security/xmlsec1/xmlsec1_1.%.bbappend +++ b/meta-app-framework/recipes-security/xmlsec1/xmlsec1_1.%.bbappend @@ -1,4 +1 @@ -# Disable nss to avoid build issues on native -PACKAGECONFIG = "gnutls libgcrypt openssl des" - -BBCLASSEXTEND = "native nativesdk" +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'xmlsec1_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-security/xmlsec1/xmlsec1_appfw.inc b/meta-app-framework/recipes-security/xmlsec1/xmlsec1_appfw.inc new file mode 100644 index 000000000..09820be2f --- /dev/null +++ b/meta-app-framework/recipes-security/xmlsec1/xmlsec1_appfw.inc @@ -0,0 +1,4 @@ +# Disable nss to avoid build issues on native +PACKAGECONFIG = "gnutls libgcrypt openssl des" + +BBCLASSEXTEND = "native nativesdk" diff --git a/meta-app-framework/recipes-support/libcap/libcap_%.bbappend b/meta-app-framework/recipes-support/libcap/libcap_%.bbappend index ac909a64c..6107ee7f6 100644 --- a/meta-app-framework/recipes-support/libcap/libcap_%.bbappend +++ b/meta-app-framework/recipes-support/libcap/libcap_%.bbappend @@ -1,3 +1 @@ -FILESEXTRAPATHS_append_class-native := ":${THISDIR}/${PN}" -# FIXME: It needs to be determined if this is still required -#SRC_URI_append_class-native = " file://removing-capability-enforcement.patch" +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'libcap_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-support/libcap/libcap_appfw.inc b/meta-app-framework/recipes-support/libcap/libcap_appfw.inc new file mode 100644 index 000000000..9ece5ce27 --- /dev/null +++ b/meta-app-framework/recipes-support/libcap/libcap_appfw.inc @@ -0,0 +1,3 @@ +FILESEXTRAPATHS_append_class-native := ":${THISDIR}/libcap" +# FIXME: It needs to be determined if this is still required +#SRC_URI_append_class-native = " file://removing-capability-enforcement.patch" diff --git a/meta-app-framework/recipes-support/libzip/libzip_%.bbappend b/meta-app-framework/recipes-support/libzip/libzip_%.bbappend index 5174650b1..d559c2fbe 100644 --- a/meta-app-framework/recipes-support/libzip/libzip_%.bbappend +++ b/meta-app-framework/recipes-support/libzip/libzip_%.bbappend @@ -1 +1 @@ -BBCLASSEXTEND += "native nativesdk" +require ${@bb.utils.contains('APPFW_ENABLED', '1', 'libzip_appfw.inc', '', d)} diff --git a/meta-app-framework/recipes-support/libzip/libzip_appfw.inc b/meta-app-framework/recipes-support/libzip/libzip_appfw.inc new file mode 100644 index 000000000..5174650b1 --- /dev/null +++ b/meta-app-framework/recipes-support/libzip/libzip_appfw.inc @@ -0,0 +1 @@ +BBCLASSEXTEND += "native nativesdk" diff --git a/meta-app-framework/recipes-test/afb-test/afb-test_git.bb b/meta-app-framework/recipes-test/afb-test/afb-test_git.bb new file mode 100644 index 000000000..5246abb00 --- /dev/null +++ b/meta-app-framework/recipes-test/afb-test/afb-test_git.bb @@ -0,0 +1,25 @@ +SUMMARY = "Binding embedding test framework to test others binding" +DESCRIPTION = "This make testing binding running with Application Framework binder \ +easier by simply test verb return as well as event reception." +HOMEPAGE = "https://gerrit.automotivelinux.org/gerrit/#/admin/projects/apps/app-afb-test" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=3b83ef96387f14655fc854ddc3c6bd57" +SECTION = "apps" + +SRC_URI = "git://gerrit.automotivelinux.org/gerrit/apps/app-afb-test;protocol=https;branch=${AGL_BRANCH}" +SRCREV = "${AGL_APP_REVISION}" + +DEPENDS += "lua libafb-helpers libappcontroller" +RDEPENDS_${PN} += "lua bash jq" +RDEPENDS_${PN}-ptest += "af-binder" + +PV = "${AGLVERSION}" +S = "${WORKDIR}/git" + +inherit cmake aglwgt pkgconfig ptest + +do_install_append() { + install -d ${D}${bindir} + install -m 775 ${S}/afm-test.target.sh ${D}${bindir}/afm-test +} + diff --git a/meta-app-framework/recipes-test/afb-test/files/run-ptest b/meta-app-framework/recipes-test/afb-test/files/run-ptest new file mode 100644 index 000000000..883939a83 --- /dev/null +++ b/meta-app-framework/recipes-test/afb-test/files/run-ptest @@ -0,0 +1,3 @@ +#!/bin/sh + +afm-test /usr/AGL/apps/testwgt/aftest-test.wgt diff --git a/meta-app-framework/scripts/run-yocto-check-layer-enabled-flags.sh b/meta-app-framework/scripts/run-yocto-check-layer-enabled-flags.sh new file mode 100755 index 000000000..37d2f5615 --- /dev/null +++ b/meta-app-framework/scripts/run-yocto-check-layer-enabled-flags.sh @@ -0,0 +1,51 @@ +#!/bin/bash +set -x +SCRIPTPATH="$( cd $(dirname $0) >/dev/null 2>&1 ; pwd -P )" +echo $SCRIPTPATH +AGLROOT="$SCRIPTPATH/../../.." +POKYDIR="$AGLROOT/external/poky" +TMPROOT="/tmp" + +rm -rf ${TMPROOT}/testbuild-ycl || true +mkdir -p ${TMPROOT}/testbuild-ycl +cd ${TMPROOT}/testbuild-ycl + +source $POKYDIR/oe-init-build-env . + +cat << EOF >> conf/local.conf +# just define defaults +AGL_FEATURES ?= "" +AGL_EXTRA_IMAGE_FSTYPES ?= "" + +# important settings imported from poky-agl.conf +# we do not import +DISTRO_FEATURES_append = " systemd smack" +DISTRO_FEATURES_BACKFILL_CONSIDERED_append = " sysvinit" +VIRTUAL-RUNTIME_init_manager = "systemd" + +# skip unnecessary in yocto-check-layer - aka FIXME upstream +BBMASK += "meta-security/recipes-mac/smack/smack-test_1.0.bb" +BBMASK += "packagegroup-core-security-ptest.bb" + +# missing in upstream recipes ... aka FIXME upstream +BBCLASSEXTEND_pn-libzip = "native nativesdk" +BBCLASSEXTEND_pn-xmlsec1 = "native nativesdk" + +DISTRO_FEATURES_append = " appfw smack " + +EOF + + +yocto-check-layer \ + --dependency $AGLROOT/external/meta-openembedded/meta-oe \ + $AGLROOT/external/meta-security \ + $AGLROOT/external/meta-openembedded/meta-python \ + $AGLROOT/external/meta-openembedded/meta-networking \ + $AGLROOT/external/meta-openembedded/meta-perl \ + $AGLROOT/external/meta-qt5/ \ + -- \ + $AGLROOT/meta-agl/meta-app-framework/ + +[ $? = 0 ] && rm -rf ${TMPROOT}/testbuild-ycl + + diff --git a/meta-app-framework/scripts/run-yocto-check-layer.sh b/meta-app-framework/scripts/run-yocto-check-layer.sh new file mode 100755 index 000000000..3b19cd012 --- /dev/null +++ b/meta-app-framework/scripts/run-yocto-check-layer.sh @@ -0,0 +1,49 @@ +#!/bin/bash +set -x +SCRIPTPATH="$( cd $(dirname $0) >/dev/null 2>&1 ; pwd -P )" +echo $SCRIPTPATH +AGLROOT="$SCRIPTPATH/../../.." +POKYDIR="$AGLROOT/external/poky" +TMPROOT="/tmp" + +rm -rf ${TMPROOT}/testbuild-ycl || true +mkdir -p ${TMPROOT}/testbuild-ycl +cd ${TMPROOT}/testbuild-ycl + +source $POKYDIR/oe-init-build-env . + +cat << EOF >> conf/local.conf +# just define defaults +AGL_FEATURES ?= "" +AGL_EXTRA_IMAGE_FSTYPES ?= "" + +# important settings imported from poky-agl.conf +# we do not import +DISTRO_FEATURES_append = " systemd smack" +DISTRO_FEATURES_BACKFILL_CONSIDERED_append = " sysvinit" +VIRTUAL-RUNTIME_init_manager = "systemd" + +# skip unnecessary in yocto-check-layer - aka FIXME upstream +BBMASK += "meta-security/recipes-mac/smack/smack-test_1.0.bb" +BBMASK += "packagegroup-core-security-ptest.bb" + +# missing in upstream recipes ... aka FIXME upstream +BBCLASSEXTEND_pn-libzip = "native nativesdk" +BBCLASSEXTEND_pn-xmlsec1 = "native nativesdk" + +EOF + + +yocto-check-layer \ + --dependency $AGLROOT/external/meta-openembedded/meta-oe \ + $AGLROOT/external/meta-security \ + $AGLROOT/external/meta-openembedded/meta-python \ + $AGLROOT/external/meta-openembedded/meta-networking \ + $AGLROOT/external/meta-openembedded/meta-perl \ + $AGLROOT/external/meta-qt5/ \ + -- \ + $AGLROOT/meta-agl/meta-app-framework/ + +[ $? = 0 ] && rm -rf ${TMPROOT}/testbuild-ycl + + |