diff options
author | José Bollo <jose.bollo@iot.bzh> | 2018-01-24 11:38:43 +0100 |
---|---|---|
committer | José Bollo <jose.bollo@iot.bzh> | 2018-02-13 11:02:00 +0100 |
commit | f70d712e4f505f5c5b50ae17f4f023d20a667568 (patch) | |
tree | 57b0aaa702651012e1adfc07f9b6b6c580506f66 /meta-security | |
parent | 3f962c7d202055777dd0238f12dbcf70f09ac07d (diff) |
Integrate parts of meta-intel-iot-security
Adds the recipes of the sub layers
- meta-security-framework
- meta-security-smack
Change-Id: I618608008a3b3d1d34adb6e38048110f13ac0643
Signed-off-by: José Bollo <jose.bollo@iot.bzh>
Diffstat (limited to 'meta-security')
112 files changed, 15442 insertions, 0 deletions
diff --git a/meta-security/COPYING.MIT b/meta-security/COPYING.MIT new file mode 100644 index 000000000..89de35479 --- /dev/null +++ b/meta-security/COPYING.MIT @@ -0,0 +1,17 @@ +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/meta-security/README.md b/meta-security/README.md new file mode 100644 index 000000000..0bae9f3fb --- /dev/null +++ b/meta-security/README.md @@ -0,0 +1,31 @@ +This README file contains information on the contents of the +meta-security layer. + +Please see the corresponding sections below for details. + + +Dependencies +============ + +This layer depends on: + + URI: git://git.openembedded.org/bitbake + branch: master + + URI: git://git.openembedded.org/openembedded-core + layers: meta + branch: master + + URI: git://git.yoctoproject.org/meta-security + branch: master + + +Patches +======= + +Please submit any patches against the meta-security layer via gerrit +reviews. + +For discussion use the discussion mailing list +mailto:automotive-discussions@lists.linuxfoundation.org + diff --git a/meta-security/classes/deploy-files.bbclass b/meta-security/classes/deploy-files.bbclass new file mode 100644 index 000000000..ec19323a3 --- /dev/null +++ b/meta-security/classes/deploy-files.bbclass @@ -0,0 +1,68 @@ +DEPLOY_FILES_DIR = "${WORKDIR}/deploy-files-${PN}" +SSTATETASKS += "do_deploy_files" +do_deploy_files[sstate-inputdirs] = "${DEPLOY_FILES_DIR}" +do_deploy_files[sstate-outputdirs] = "${DEPLOY_DIR}/files/" + +python do_deploy_files_setscene () { + sstate_setscene(d) +} +addtask do_deploy_files_setscene +do_deploy_files[dirs] = "${DEPLOY_FILES_DIR} ${B}" + +# Use like this: +# DEPLOY_FILES = "abc xyz" +# DEPLOY_FILES_FROM[abc] = "file-ab dir-c" +# DEPLOY_FILES_TO[abc] = "directory-for-abc" +# DEPLOY_FILES_FROM[xyz] = "file-xyz" +# DEPLOY_FILES_TO[xyz] = "directory-for-xyz" +# +# The destination directory will be created inside +# ${DEPLOYDIR}. The source files and directories +# will be copied such that their name and (for +# directories) the directory tree below it will +# be preserved. Shell wildcards are supported. +# +# The default DEPLOY_FILES copies files for the native host +# and the target into two different directories. Use that as follows: +# DEPLOY_FILES_FROM_native = "native-file" +# DEPLOY_FILES_FROM_target = "target-file" + +DEPLOY_FILES ?= "native target" +DEPLOY_FILES_FROM[native] ?= "" +DEPLOY_FILES_TO[native] = "native/${BUILD_ARCH}" +DEPLOY_FILES_FROM[target] ?= "" +DEPLOY_FILES_TO[target] = "target/${MACHINE}" + +# We have to use a Python function to access variable flags. Because +# bitbake then does not know about the dependency on these variables, +# we need to explicitly declare that. DEPLOYDIR may change without +# invalidating the sstate, therefore it is not listed. +do_deploy_files[vardeps] = "DEPLOY_FILES DEPLOY_FILES_FROM DEPLOY_FILES_TO" +python do_deploy_files () { + import glob + import os + import shutil + + for file in (d.getVar('DEPLOY_FILES', True) or '').split(): + bb.note('file: %s' % file) + from_pattern = d.getVarFlag('DEPLOY_FILES_FROM', file, True) + bb.note('from: %s' % from_pattern) + if from_pattern: + to = os.path.join(d.getVar('DEPLOY_FILES_DIR', True), d.getVarFlag('DEPLOY_FILES_TO', file, True)) + bb.note('to: %s' % to) + if not os.path.isdir(to): + os.makedirs(to) + for from_path in from_pattern.split(): + for src in (glob.glob(from_path) or [from_path]): + bb.note('Deploying %s to %s' % (src, to)) + if os.path.isdir(src): + src_dirname = shutil._basename(src) + to = os.path.join(to, src_dirname) + if os.path.exists(to): + bb.utils.remove(to, True) + shutil.copytree(src, to) + else: + shutil.copy(src, to) +} + +addtask deploy_files before do_build after do_compile diff --git a/meta-security/classes/xattr-images.bbclass b/meta-security/classes/xattr-images.bbclass new file mode 100644 index 000000000..565a3fb6e --- /dev/null +++ b/meta-security/classes/xattr-images.bbclass @@ -0,0 +1,137 @@ +# Both Smack and IMA/EVM rely on xattrs. Inheriting this class ensures +# that these xattrs get preserved in tar and jffs2 images. +# +# It also fixes the rootfs so that the content of directories with +# SMACK::TRANSMUTE is correctly labelled. This is because pseudo does +# not know the special semantic of SMACK::TRANSMUTE and omits the +# updating of the Smack label when creating entries inside such a directory, +# for example /etc (see base-files_%.bbappend). Without the fixup, +# files already installed during the image creation would have different (and +# wrong) Smack labels. + +# xattr support is expected to be compiled into mtd-utils. We just need to +# use it. +EXTRA_IMAGECMD_jffs2_append = " --with-xattr" + +# By default, OE-core uses tar from the host, which may or may not have the +# --xattrs parameter which was introduced in 1.27. For image building we +# use a recent enough tar instead. +# +# The GNU documentation does not specify whether --xattrs-include is necessary. +# In practice, it turned out to be not needed when creating archives and +# required when extracting, but it seems prudent to use it in both cases. +IMAGE_DEPENDS_tar_append = " tar-replacement-native" +EXTRANATIVEPATH += "tar-native" +IMAGE_CMD_TAR = "tar --xattrs --xattrs-include=*" + +xattr_images_fix_transmute[dirs] = "${IMAGE_ROOTFS}" +python xattr_images_fix_transmute () { + # The recursive updating of the Smack label ensures that each entry + # has the label set for its parent directories if one of those was + # marked as transmuting. + # + # In addition, "_" is set explicitly on everything that would not + # have a label otherwise. This is a workaround for tools like swupd + # which transfers files from a rootfs onto a target device where Smack + # is active: on the target, each file gets assigned a label, typically + # the one from the process which creates it. swupd (or rather, the tools + # it is currently built on) knows how to set security.SMACK64="_" when + # it is set on the original files, but it does not know that it needs + # to remove that xattr when not set. + import os + import errno + + if getattr(os, 'getxattr', None): + # Python 3: os has xattr support. + def lgetxattr(f, attr): + try: + value = os.getxattr(f, attr, follow_symlinks=False) + return value.decode('utf8') + except OSError as ex: + if ex.errno == errno.ENODATA: + return None + + def lsetxattr(f, attr, value): + os.setxattr(f, attr.encode('utf8'), value.encode('utf8'), follow_symlinks=False) + else: + # Python 2: xattr support only in xattr module. + # + # Cannot use the 'xattr' module, it is not part of a standard Python + # installation. Instead re-implement using ctypes. Only has to be good + # enough for xattrs that are strings. Always operates on the symlinks themselves, + # not what they point to. + import ctypes + + # We cannot look up the xattr functions inside libc. That bypasses + # pseudo, which overrides these functions via LD_PRELOAD. Instead we have to + # find the function address and then create a ctypes function from it. + libdl = ctypes.CDLL("libdl.so.2") + _dlsym = libdl.dlsym + _dlsym.restype = ctypes.c_void_p + RTLD_DEFAULT = ctypes.c_void_p(0) + _lgetxattr = ctypes.CFUNCTYPE(ctypes.c_ssize_t, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_size_t, + use_errno=True)(_dlsym(RTLD_DEFAULT, 'lgetxattr')) + _lsetxattr = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_char_p, ctypes.c_char_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.c_int, + use_errno=True)(_dlsym(RTLD_DEFAULT, 'lsetxattr')) + + def lgetxattr(f, attr): + len = 32 + while True: + buffer = ctypes.create_string_buffer('\000' * len) + res = _lgetxattr(f, attr, buffer, ctypes.c_size_t(len)) + if res >= 0: + return buffer.value + else: + error = ctypes.get_errno() + if ctypes.get_errno() == errno.ERANGE: + len *= 2 + elif error == errno.ENODATA: + return None + else: + raise IOError(error, 'lgetxattr(%s, %s): %d = %s = %s' % + (f, attr, error, errno.errorcode[error], os.strerror(error))) + + def lsetxattr(f, attr, value): + res = _lsetxattr(f, attr, value, ctypes.c_size_t(len(value)), ctypes.c_int(0)) + if res != 0: + error = ctypes.get_errno() + raise IOError(error, 'lsetxattr(%s, %s, %s): %d = %s = %s' % + (f, attr, value, error, errno.errorcode[error], os.strerror(error))) + + def visit(path, deflabel, deftransmute): + isrealdir = os.path.isdir(path) and not os.path.islink(path) + curlabel = lgetxattr(path, 'security.SMACK64') + transmute = lgetxattr(path, 'security.SMACK64TRANSMUTE') == 'TRUE' + + if not curlabel: + # Since swupd doesn't remove the label from an updated file assigned by + # the target device's kernel upon unpacking the file from an update, + # we have to set the floor label explicitly even though it is the default label + # and thus adding it would create additional overhead. Otherwise this + # would result in hash mismatches reported by `swupd verify`. + lsetxattr(path, 'security.SMACK64', deflabel) + if not transmute and deftransmute and isrealdir: + lsetxattr(path, 'security.SMACK64TRANSMUTE', 'TRUE') + + # Identify transmuting directories and change the default Smack + # label inside them. In addition, directories themselves must become + # transmuting. + if isrealdir: + if transmute: + deflabel = lgetxattr(path, 'security.SMACK64') + deftransmute = True + if deflabel is None: + raise RuntimeError('%s: transmuting directory without Smack label' % path) + elif curlabel: + # Directory with explicit label set and not transmuting => do not + # change the content unless we run into another transmuting directory. + deflabel = '_' + deftransmute = False + + for entry in os.listdir(path): + visit(os.path.join(path, entry), deflabel, deftransmute) + + visit('.', '_', False) +} +# Same logic as in ima-evm-rootfs.bbclass: try to run as late as possible. +IMAGE_PREPROCESS_COMMAND_append_with-lsm-smack = " xattr_images_fix_transmute ; " diff --git a/meta-security/conf/layer.conf b/meta-security/conf/layer.conf new file mode 100644 index 000000000..c051e5885 --- /dev/null +++ b/meta-security/conf/layer.conf @@ -0,0 +1,12 @@ +# We have a conf and classes directory, add to BBPATH +BBPATH =. "${LAYERDIR}:" + +# We have a packages directory, add to BBFILES +BBFILES := "${BBFILES} \ + ${LAYERDIR}/recipes-*/*/*.bb \ + ${LAYERDIR}/recipes-*/*/*.bbappend" + +# Must prioritize our rpm recipe over the default ones. +BBFILE_COLLECTIONS += "security-smack" +BBFILE_PATTERN_security-smack := "^${LAYERDIR}/" +BBFILE_PRIORITY_security-smack = "8" diff --git a/meta-security/lib/oeqa/runtime/__init__.py b/meta-security/lib/oeqa/runtime/__init__.py new file mode 100644 index 000000000..e69de29bb --- /dev/null +++ b/meta-security/lib/oeqa/runtime/__init__.py diff --git a/meta-security/lib/oeqa/runtime/files/notroot.py b/meta-security/lib/oeqa/runtime/files/notroot.py new file mode 100644 index 000000000..f0eb0b5b9 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/notroot.py @@ -0,0 +1,33 @@ +#!/usr/bin/env python +# +# Script used for running executables with custom labels, as well as custom uid/gid +# Process label is changed by writing to /proc/self/attr/curent +# +# Script expects user id and group id to exist, and be the same. +# +# From adduser manual: +# """By default, each user in Debian GNU/Linux is given a corresponding group +# with the same name. """ +# +# Usage: root@desk:~# python notroot.py <uid> <label> <full_path_to_executable> [arguments ..] +# eg: python notroot.py 1000 User::Label /bin/ping -c 3 192.168.1.1 +# +# Author: Alexandru Cornea <alexandru.cornea@intel.com> +import os +import sys + +try: + uid = int(sys.argv[1]) + sys.argv.pop(1) + label = sys.argv[1] + sys.argv.pop(1) + open("/proc/self/attr/current", "w").write(label) + path=sys.argv[1] + sys.argv.pop(0) + os.setgid(uid) + os.setuid(uid) + os.execv(path,sys.argv) + +except Exception,e: + print e.message + sys.exit(1) diff --git a/meta-security/lib/oeqa/runtime/files/smack_test_file_access.sh b/meta-security/lib/oeqa/runtime/files/smack_test_file_access.sh new file mode 100644 index 000000000..5a0ce84f2 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/smack_test_file_access.sh @@ -0,0 +1,54 @@ +#!/bin/sh + +SMACK_PATH=`grep smack /proc/mounts | awk '{print $2}' ` +RC=0 +TMP="/tmp" +test_file=$TMP/smack_test_access_file +CAT=`which cat` +ECHO=`which echo` +uid=1000 +initial_label=`cat /proc/self/attr/current` +python $TMP/notroot.py $uid "TheOther" $ECHO 'TEST' > $test_file +chsmack -a "TheOther" $test_file + +# 12345678901234567890123456789012345678901234567890123456 +delrule="TheOne TheOther -----" +rule_ro="TheOne TheOther r----" + +# Remove pre-existent rules for "TheOne TheOther <access>" +echo -n "$delrule" > $SMACK_PATH/load +python $TMP/notroot.py $uid "TheOne" $CAT $test_file 2>&1 1>/dev/null | grep -q "Permission denied" || RC=$? +if [ $RC -ne 0 ]; then + echo "Process with different label than the test file and no read access on it can read it" + exit $RC +fi + +# adding read access +echo -n "$rule_ro" > $SMACK_PATH/load +python $TMP/notroot.py $uid "TheOne" $CAT $test_file | grep -q "TEST" || RC=$? +if [ $RC -ne 0 ]; then + echo "Process with different label than the test file but with read access on it cannot read it" + exit $RC +fi + +# Remove pre-existent rules for "TheOne TheOther <access>" +echo -n "$delrule" > $SMACK_PATH/load +# changing label of test file to * +# according to SMACK documentation, read access on a * object is always permitted +chsmack -a '*' $test_file +python $TMP/notroot.py $uid "TheOne" $CAT $test_file | grep -q "TEST" || RC=$? +if [ $RC -ne 0 ]; then + echo "Process cannot read file with * label" + exit $RC +fi + +# changing subject label to * +# according to SMACK documentation, every access requested by a star labeled subject is rejected +TOUCH=`which touch` +python $TMP/notroot.py $uid '*' $TOUCH $TMP/test_file_2 +ls -la $TMP/test_file_2 2>&1 | grep -q 'No such file or directory' || RC=$? +if [ $RC -ne 0 ];then + echo "Process with label '*' should not have any access" + exit $RC +fi +exit 0 diff --git a/meta-security/lib/oeqa/runtime/files/test_privileged_change_self_label.sh b/meta-security/lib/oeqa/runtime/files/test_privileged_change_self_label.sh new file mode 100644 index 000000000..26d9e9d22 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/test_privileged_change_self_label.sh @@ -0,0 +1,18 @@ +#!/bin/sh + +initial_label=`cat /proc/self/attr/current 2>/dev/null` +modified_label="test_label" + +echo "$modified_label" >/proc/self/attr/current 2>/dev/null + +new_label=`cat /proc/self/attr/current 2>/dev/null` + +if [ "$new_label" != "$modified_label" ]; then + # restore proper label + echo $initial_label >/proc/self/attr/current + echo "Privileged process could not change its label" + exit 1 +fi + +echo "$initial_label" >/proc/self/attr/current 2>/dev/null +exit 0
\ No newline at end of file diff --git a/meta-security/lib/oeqa/runtime/files/test_smack_onlycap.sh b/meta-security/lib/oeqa/runtime/files/test_smack_onlycap.sh new file mode 100644 index 000000000..1c4a93ab6 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/test_smack_onlycap.sh @@ -0,0 +1,27 @@ +#!/bin/sh +RC=0 +SMACK_PATH=`grep smack /proc/mounts | awk '{print $2}'` +test_label="test_label" +onlycap_initial=`cat $SMACK_PATH/onlycap` +smack_initial=`cat /proc/self/attr/current` + +# need to set out label to be the same as onlycap, otherwise we lose our smack privileges +# even if we are root +echo "$test_label" > /proc/self/attr/current + +echo "$test_label" > $SMACK_PATH/onlycap || RC=$? +if [ $RC -ne 0 ]; then + echo "Onlycap label could not be set" + return $RC +fi + +if [ `cat $SMACK_PATH/onlycap` != "$test_label" ]; then + echo "Onlycap label was not set correctly." + return 1 +fi + +# resetting original onlycap label +echo "$onlycap_initial" > $SMACK_PATH/onlycap 2>/dev/null + +# resetting our initial's process label +echo "$smack_initial" > /proc/self/attr/current diff --git a/meta-security/lib/oeqa/runtime/files/test_smack_tcp_sockets.sh b/meta-security/lib/oeqa/runtime/files/test_smack_tcp_sockets.sh new file mode 100644 index 000000000..ed18f2371 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/test_smack_tcp_sockets.sh @@ -0,0 +1,108 @@ +#!/bin/sh +RC=0 +test_file=/tmp/smack_socket_tcp +SMACK_PATH=`grep smack /proc/mounts | awk '{print $2}' ` +# make sure no access is granted +# 12345678901234567890123456789012345678901234567890123456 +echo -n "label1 label2 -----" > $SMACK_PATH/load + +tcp_server=`which tcp_server` +if [ -z $tcp_server ]; then + if [ -f "/tmp/tcp_server" ]; then + tcp_server="/tmp/tcp_server" + else + echo "tcp_server binary not found" + exit 1 + fi +fi +tcp_client=`which tcp_client` +if [ -z $tcp_client ]; then + if [ -f "/tmp/tcp_client" ]; then + tcp_client="/tmp/tcp_client" + else + echo "tcp_client binary not found" + exit 1 + fi +fi + +# checking access for sockets with different labels +$tcp_server 50016 label1 &>/dev/null & +server_pid=$! +sleep 2 +$tcp_client 50016 label2 label1 &>/dev/null & +client_pid=$! + +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? + +if [ $server_rv -eq 0 -o $client_rv -eq 0 ]; then + echo "Sockets with different labels should not communicate on tcp" + exit 1 +fi + +# granting access between different labels +# 12345678901234567890123456789012345678901234567890123456 +echo -n "label1 label2 rw---" > $SMACK_PATH/load +# checking access for sockets with different labels, but having a rule granting rw +$tcp_server 50017 label1 2>$test_file & +server_pid=$! +sleep 1 +$tcp_client 50017 label2 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Sockets with different labels, but having rw access, should communicate on tcp" + exit 1 +fi + +# checking access for sockets with the same label +$tcp_server 50018 label1 2>$test_file & +server_pid=$! +sleep 1 +$tcp_client 50018 label1 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Sockets with same labels should communicate on tcp" + exit 1 +fi + +# checking access on socket labeled star (*) +# should always be permitted +$tcp_server 50019 \* 2>$test_file & +server_pid=$! +sleep 1 +$tcp_client 50019 label1 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Should have access on tcp socket labeled star (*)" + exit 1 +fi + +# checking access from socket labeled star (*) +# all access from subject star should be denied +$tcp_server 50020 label1 2>$test_file & +server_pid=$! +sleep 1 +$tcp_client 50020 label1 \* 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -eq 0 -o $client_rv -eq 0 ]; then + echo "Socket labeled star should not have access to any tcp socket" + exit 1 +fi diff --git a/meta-security/lib/oeqa/runtime/files/test_smack_udp_sockets.sh b/meta-security/lib/oeqa/runtime/files/test_smack_udp_sockets.sh new file mode 100644 index 000000000..419ab9f91 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/files/test_smack_udp_sockets.sh @@ -0,0 +1,107 @@ +#!/bin/sh +RC=0 +test_file="/tmp/smack_socket_udp" +SMACK_PATH=`grep smack /proc/mounts | awk '{print $2}' ` + +udp_server=`which udp_server` +if [ -z $udp_server ]; then + if [ -f "/tmp/udp_server" ]; then + udp_server="/tmp/udp_server" + else + echo "udp_server binary not found" + exit 1 + fi +fi +udp_client=`which udp_client` +if [ -z $udp_client ]; then + if [ -f "/tmp/udp_client" ]; then + udp_client="/tmp/udp_client" + else + echo "udp_client binary not found" + exit 1 + fi +fi + +# make sure no access is granted +# 12345678901234567890123456789012345678901234567890123456 +echo -n "label1 label2 -----" > $SMACK_PATH/load + +# checking access for sockets with different labels +$udp_server 50021 label2 2>$test_file & +server_pid=$! +sleep 1 +$udp_client 50021 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -eq 0 ]; then + echo "Sockets with different labels should not communicate on udp" + exit 1 +fi + +# granting access between different labels +# 12345678901234567890123456789012345678901234567890123456 +echo -n "label1 label2 rw---" > $SMACK_PATH/load +# checking access for sockets with different labels, but having a rule granting rw +$udp_server 50022 label2 2>$test_file & +server_pid=$! +sleep 1 +$udp_client 50022 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Sockets with different labels, but having rw access, should communicate on udp" + exit 1 +fi + +# checking access for sockets with the same label +$udp_server 50023 label1 & +server_pid=$! +sleep 1 +$udp_client 50023 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Sockets with same labels should communicate on udp" + exit 1 +fi + +# checking access on socket labeled star (*) +# should always be permitted +$udp_server 50024 \* 2>$test_file & +server_pid=$! +sleep 1 +$udp_client 50024 label1 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -ne 0 -o $client_rv -ne 0 ]; then + echo "Should have access on udp socket labeled star (*)" + exit 1 +fi + +# checking access from socket labeled star (*) +# all access from subject star should be denied +$udp_server 50025 label1 2>$test_file & +server_pid=$! +sleep 1 +$udp_client 50025 \* 2>$test_file & +client_pid=$! +wait $server_pid +server_rv=$? +wait $client_pid +client_rv=$? +if [ $server_rv -eq 0 ]; then + echo "Socket labeled star should not have access to any udp socket" + exit 1 +fi diff --git a/meta-security/lib/oeqa/runtime/securitymanager.py b/meta-security/lib/oeqa/runtime/securitymanager.py new file mode 100644 index 000000000..ab0df5a42 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/securitymanager.py @@ -0,0 +1,108 @@ +import unittest +import re +import os +import string +from oeqa.oetest import oeRuntimeTest, skipModule +from oeqa.utils.decorators import * + +def get_files_dir(): + """Get directory of supporting files""" + pkgarch = oeRuntimeTest.tc.d.getVar('MACHINE', True) + deploydir = oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True) + return os.path.join(deploydir, "files", "target", pkgarch) + +MAX_LABEL_LEN = 255 +LABEL = "a" * MAX_LABEL_LEN + +def setUpModule(): + if not oeRuntimeTest.hasPackage('security-manager'): + skipModule( + "security-manager module skipped: " + "target doesn't have security-manager installed") + +class SecurityManagerBasicTest(oeRuntimeTest): + ''' base smack test ''' + def setUp(self): + # TODO: avoid hardcoding path (also in SecurityManager itself) + self.security_manager_db = '/usr/dbspace/.security-manager.db' + cmd = "sqlite3 %s 'SELECT name from privilege ORDER BY privilege_id'" % self.security_manager_db + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + self.privileges = output.split() + if not self.privileges: + # Only privileges that map to a Unix group need to be known to + # SecurityManager. Therefore it is possible that the query above + # returns nothing. In that case, make up something for the tests. + self.privileges.append('FoobarPrivilege') + self.appid = 'test-app-id' + self.pkgid = 'test-pkg-id' + self.user = 'security-manager-user' + idcmd = 'id -u %s' % self.user + status, output = self.target.run(idcmd) + if status: + # -D is from busybox. It disables setting a password. + createcmd = 'adduser -D %s' % self.user + status, output = self.target.run(createcmd) + self.assertFalse(status, msg="%s failed: %s" % (createcmd, output)) + status, output = self.target.run(idcmd) + self.assertTrue(output.isdigit(), msg="Unexpected output from %s: %s" % (idcmd, output)) + self.uid = output + +class SecurityManagerApp(SecurityManagerBasicTest): + '''Tests covering app installation. Ordering is important, therefore tests are numbered.''' + + @skipUnlessPassed('test_ssh') + def test_security_manager_01_setup(self): + '''Check that basic SecurityManager setup is in place.''' + # If we get this far, then at least the sqlite db must have been in place. + # This does not mean much, but we need to start somewhere. + pass + + @skipUnlessPassed('test_security_manager_01_setup') + def test_security_manager_02_install(self): + '''Test if installing an app sets up privilege rules for it, also in Cynara.''' + self.target.copy_to(os.path.join(get_files_dir(), "app-runas"), "/tmp/") + cmd = '/tmp/app-runas -a %s -p %s -u %s -r %s -i' % \ + (self.appid, self.pkgid, self.uid, self.privileges[0]) + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + cmd = '''sqlite3 %s 'SELECT uid,app_name,pkg_name from app_pkg_view WHERE app_name = "%s"' ''' % \ + (self.security_manager_db, self.appid) + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + self.assertEqual(output, '|'.join((self.uid, self.appid, self.pkgid))) + cmd = 'grep -r %s /var/cynara/db/' % self.appid + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + # User::App:: prefix still hard-coded here because it is not customizable at the moment. + self.assertEqual(output, '/var/cynara/db/_MANIFESTS:User::App::%s;%s;%s;0xFFFF;' % \ + (self.appid, self.uid, self.privileges[0])) + + @skipUnlessPassed('test_security_manager_02_install') + def test_security_manager_03_run(self): + '''Test running as app. Depends on preparations in test_security_manager_install().''' + cmd = '''/tmp/app-runas -a %s -u %s -e -- sh -c 'id -u && cat /proc/self/attr/current' ''' % \ + (self.appid, self.uid) + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + self.assertEqual(output, '%s\nUser::App::%s' % (self.uid, self.appid)) + + @skipUnlessPassed('test_security_manager_02_install') + def test_security_manager_03_uninstall(self): + '''Test removal of an app.''' + cmd = '/tmp/app-runas -a %s -p %s -u %s -d' % \ + (self.appid, self.pkgid, self.uid) + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + cmd = '''sqlite3 %s 'SELECT uid,app_name,pkg_name from app_pkg_view WHERE app_name = "%s"' ''' % \ + (self.security_manager_db, self.appid) + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + # Entry does not really get removed. Bug filed here: + # https://github.com/Samsung/security-manager/issues/2 + # self.assertEqual(output, '') + cmd = 'grep -r %s /var/cynara/db/' % self.appid + status, output = self.target.run(cmd) + self.assertFalse(status, msg="%s failed: %s" % (cmd, output)) + # This also does not get removed. Perhaps same root cause. + # self.assertEqual(output, '') diff --git a/meta-security/lib/oeqa/runtime/smack.py b/meta-security/lib/oeqa/runtime/smack.py new file mode 100644 index 000000000..96af443b8 --- /dev/null +++ b/meta-security/lib/oeqa/runtime/smack.py @@ -0,0 +1,589 @@ +import unittest +import re +import os +import string +from oeqa.oetest import oeRuntimeTest, skipModule +from oeqa.utils.decorators import * + +def get_files_dir(): + """Get directory of supporting files""" + pkgarch = oeRuntimeTest.tc.d.getVar('MACHINE', True) + deploydir = oeRuntimeTest.tc.d.getVar('DEPLOY_DIR', True) + return os.path.join(deploydir, "files", "target", pkgarch) + +MAX_LABEL_LEN = 255 +LABEL = "a" * MAX_LABEL_LEN + +def setUpModule(): + if not oeRuntimeTest.hasFeature('smack'): + skipModule( + "smack module skipped: " + "target doesn't have smack in DISTRO_FEATURES") + +class SmackBasicTest(oeRuntimeTest): + ''' base smack test ''' + def setUp(self): + status, output = self.target.run( + "grep smack /proc/mounts | awk '{print $2}'") + self.smack_path = output + self.files_dir = os.path.join( + os.path.abspath(os.path.dirname(__file__)), 'files') + self.uid = 1000 + status,output = self.target.run("cat /proc/self/attr/current") + self.current_label = output.strip() + +class SmackAccessLabel(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_add_access_label(self): + ''' Test if chsmack can correctly set a SMACK label ''' + filename = "/tmp/test_access_label" + self.target.run("touch %s" %filename) + status, output = self.target.run("chsmack -a %s %s" %(LABEL, filename)) + self.assertEqual( + status, 0, + "Cannot set smack access label. " + "Status and output: %d %s" %(status, output)) + status, output = self.target.run("chsmack %s" %filename) + self.target.run("rm %s" %filename) + m = re.search('(?<=access=")\S+(?=")', output) + if m is None: + self.fail("Did not find access attribute") + else: + label_retrieved = m .group(0) + self.assertEqual( + LABEL, label_retrieved, + "label not set correctly. expected and gotten: " + "%s %s" %(LABEL,label_retrieved)) + +class SmackExecLabel(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_add_exec_label(self): + '''Test if chsmack can correctly set a SMACK Exec label''' + filename = "/tmp/test_exec_label" + self.target.run("touch %s" %filename) + status, output = self.target.run("chsmack -e %s %s" %(LABEL, filename)) + self.assertEqual( + status, 0, + "Cannot set smack exec label. " + "Status and output: %d %s" %(status, output)) + status, output = self.target.run("chsmack %s" %filename) + self.target.run("rm %s" %filename) + m= re.search('(?<=execute=")\S+(?=")', output) + if m is None: + self.fail("Did not find execute attribute") + else: + label_retrieved = m.group(0) + self.assertEqual( + LABEL, label_retrieved, + "label not set correctly. expected and gotten: " + + "%s %s" %(LABEL,label_retrieved)) + +class SmackMmapLabel(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_add_mmap_label(self): + '''Test if chsmack can correctly set a SMACK mmap label''' + filename = "/tmp/test_exec_label" + self.target.run("touch %s" %filename) + status, output = self.target.run("chsmack -m %s %s" %(LABEL, filename)) + self.assertEqual( + status, 0, + "Cannot set smack mmap label. " + "Status and output: %d %s" %(status, output)) + status, output = self.target.run("chsmack %s" %filename) + self.target.run("rm %s" %filename) + m = re.search('(?<=mmap=")\S+(?=")', output) + if m is None: + self.fail("Did not find mmap attribute") + else: + label_retrieved = m.group(0) + self.assertEqual( + LABEL, label_retrieved, + "label not set correctly. expected and gotten: " + + "%s %s" %(LABEL,label_retrieved)) + +class SmackTransmutable(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_add_transmutable(self): + '''Test if chsmack can correctly set a SMACK transmutable mode''' + + directory = "~/test_transmutable" + self.target.run("mkdir -p %s" %directory) + status, output = self.target.run("chsmack -t %s" %directory) + self.assertEqual(status, 0, "Cannot set smack transmutable. " + "Status and output: %d %s" %(status, output)) + status, output = self.target.run("chsmack %s" %directory) + self.target.run("rmdir %s" %directory) + m = re.search('(?<=transmute=")\S+(?=")', output) + if m is None: + self.fail("Did not find transmute attribute") + else: + label_retrieved = m.group(0) + self.assertEqual( + "TRUE", label_retrieved, + "label not set correctly. expected and gotten: " + + "%s %s" %(LABEL,label_retrieved)) + +class SmackChangeSelfLabelPrivilege(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_privileged_change_self_label(self): + '''Test if privileged process (with CAP_MAC_ADMIN privilege) + can change its label. + ''' + + status, output = self.target.run("ls /tmp/notroot.py") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'notroot.py'), + "/tmp/notroot.py") + + labelf = "/proc/self/attr/current" + command = "/bin/sh -c 'echo PRIVILEGED >%s; cat %s'" %(labelf, labelf) + + status, output = self.target.run( + "python /tmp/notroot.py 0 %s %s" %(self.current_label, command)) + + self.assertIn("PRIVILEGED", output, + "Privilege process did not change label.Output: %s" %output) + +class SmackChangeSelfLabelUnprivilege(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_unprivileged_change_self_label(self): + '''Test if unprivileged process (without CAP_MAC_ADMIN privilege) + cannot change its label''' + + status, output = self.target.run("ls /tmp/notroot.py") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'notroot.py'), + "/tmp/notroot.py") + + command = "/bin/sh -c 'echo %s >/proc/self/attr/current'" %LABEL + status, output = self.target.run( + "python /tmp/notroot.py %d %s %s" + %(self.uid, self.current_label, command) + + " 2>&1 | grep 'Operation not permitted'" ) + + self.assertEqual( + status, 0, + "Unprivileged process should not be able to change its label") + + +class SmackChangeFileLabelPrivilege(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_unprivileged_change_file_label(self): + '''Test if unprivileged process cannot change file labels''' + + status, chsmack = self.target.run("which chsmack") + status, touch = self.target.run("which touch") + filename = "/tmp/test_unprivileged_change_file_label" + + status, output = self.target.run("ls /tmp/notroot.py") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'notroot.py'), + "/tmp/notroot.py") + + self.target.run("python /tmp/notroot.py %d %s %s %s" %(self.uid, self.current_label, touch, filename)) + status, output = self.target.run( + "python /tmp/notroot.py " + + "%d unprivileged %s -a %s %s 2>&1 " %(self.uid, chsmack, LABEL, filename) + + "| grep 'Operation not permitted'" ) + + self.target.run("rm %s" %filename) + self.assertEqual( + status, 0, + "Unprivileged process changed label for %s" %filename) + +class SmackLoadRule(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_load_smack_rule(self): + '''Test if new smack access rules can be loaded''' + + # old 23 character format requires special spaces formatting + # 12345678901234567890123456789012345678901234567890123 + ruleA="TheOne TheOther rwxat" + ruleB="TheOne TheOther r----" + clean="TheOne TheOther -----" + modeA = "rwxat" + modeB = "r" + + status, output = self.target.run( + 'echo -n "%s" > %s/load' %(ruleA, self.smack_path)) + status, output = self.target.run( + 'cat %s/load | grep "^TheOne" | grep " TheOther "' %self.smack_path) + self.assertEqual(status, 0, "Rule A was not added") + mode = list(filter(bool, output.split(" ")))[2].strip() + self.assertEqual( + mode, modeA, + "Mode A was not set correctly; mode: %s" %mode) + + status, output = self.target.run( + 'echo -n "%s" > %s/load' %(ruleB, self.smack_path)) + status, output = self.target.run( + 'cat %s/load | grep "^TheOne" | grep " TheOther "' %self.smack_path) + mode = list(filter(bool, output.split(" ")))[2].strip() + self.assertEqual( + mode, modeB, + "Mode B was not set correctly; mode: %s" %mode) + + self.target.run('echo -n "%s" > %s/load' %(clean, self.smack_path)) + + +class SmackOnlycap(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_smack_onlycap(self): + '''Test if smack onlycap label can be set + + test needs to change the running label of the current process, + so whole test takes places on image + ''' + status, output = self.target.run("ls /tmp/test_smack_onlycap.sh") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'test_smack_onlycap.sh'), + "/tmp/test_smack_onlycap.sh") + + status, output = self.target.run("sh /tmp/test_smack_onlycap.sh") + self.assertEqual(status, 0, output) + +class SmackNetlabel(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smack_netlabel(self): + + test_label="191.191.191.191 TheOne" + expected_label="191.191.191.191/32 TheOne" + + status, output = self.target.run( + "echo -n '%s' > %s/netlabel" %(test_label, self.smack_path)) + self.assertEqual( + status, 0, + "Netlabel /32 could not be set. Output: %s" %output) + + status, output = self.target.run("cat %s/netlabel" %self.smack_path) + self.assertIn( + expected_label, output, + "Did not find expected label in output: %s" %output) + + test_label="253.253.253.0/24 TheOther" + status, output = self.target.run( + "echo -n '%s' > %s/netlabel" %(test_label, self.smack_path)) + self.assertEqual( + status, 0, + "Netlabel /24 could not be set. Output: %s" %output) + + status, output = self.target.run("cat %s/netlabel" %self.smack_path) + self.assertIn( + test_label, output, + "Did not find expected label in output: %s" %output) + +class SmackCipso(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smack_cipso(self): + '''Test if smack cipso rules can be set''' + # 12345678901234567890123456789012345678901234567890123456 + ruleA="TheOneA 2 0 " + ruleB="TheOneB 3 1 55 " + ruleC="TheOneC 4 2 17 33 " + + status, output = self.target.run( + "echo -n '%s' > %s/cipso" %(ruleA, self.smack_path)) + self.assertEqual(status, 0, + "Could not set cipso label A. Ouput: %s" %output) + + status, output = self.target.run( + "cat %s/cipso | grep '^TheOneA'" %self.smack_path) + self.assertEqual(status, 0, "Cipso rule A was not set") + self.assertIn(" 2", output, "Rule A was not set correctly") + + status, output = self.target.run( + "echo -n '%s' > %s/cipso" %(ruleB, self.smack_path)) + self.assertEqual(status, 0, + "Could not set cipso label B. Ouput: %s" %output) + + status, output = self.target.run( + "cat %s/cipso | grep '^TheOneB'" %self.smack_path) + self.assertEqual(status, 0, "Cipso rule B was not set") + self.assertIn("/55", output, "Rule B was not set correctly") + + status, output = self.target.run( + "echo -n '%s' > %s/cipso" %(ruleC, self.smack_path)) + self.assertEqual( + status, 0, + "Could not set cipso label C. Ouput: %s" %output) + + status, output = self.target.run( + "cat %s/cipso | grep '^TheOneC'" %self.smack_path) + self.assertEqual(status, 0, "Cipso rule C was not set") + self.assertIn("/17,33", output, "Rule C was not set correctly") + +class SmackDirect(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smack_direct(self): + status, initial_direct = self.target.run( + "cat %s/direct" %self.smack_path) + + test_direct="17" + status, output = self.target.run( + "echo '%s' > %s/direct" %(test_direct, self.smack_path)) + self.assertEqual(status, 0 , + "Could not set smack direct. Output: %s" %output) + status, new_direct = self.target.run("cat %s/direct" %self.smack_path) + # initial label before checking + status, output = self.target.run( + "echo '%s' > %s/direct" %(initial_direct, self.smack_path)) + self.assertEqual( + test_direct, new_direct.strip(), + "Smack direct label does not match.") + + +class SmackAmbient(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smack_ambient(self): + test_ambient = "test_ambient" + status, initial_ambient = self.target.run("cat %s/ambient" %self.smack_path) + status, output = self.target.run( + "echo '%s' > %s/ambient" %(test_ambient, self.smack_path)) + self.assertEqual(status, 0, + "Could not set smack ambient. Output: %s" %output) + + status, output = self.target.run("cat %s/ambient" %self.smack_path) + # Filter '\x00', which is sometimes added to the ambient label + new_ambient = ''.join(filter(lambda x: x in string.printable, output)) + initial_ambient = ''.join(filter(lambda x: x in string.printable, initial_ambient)) + status, output = self.target.run( + "echo '%s' > %s/ambient" %(initial_ambient, self.smack_path)) + self.assertEqual( + test_ambient, new_ambient.strip(), + "Ambient label does not match") + + +class SmackloadBinary(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smackload(self): + '''Test if smackload command works''' + rule="testobject testsubject rwx" + + status, output = self.target.run("echo -n '%s' > /tmp/rules" %rule) + status, output = self.target.run("smackload /tmp/rules") + self.assertEqual( + status, 0, + "Smackload failed to load rule. Output: %s" %output) + + status, output = self.target.run( + "cat %s/load | grep '%s'" %(self.smack_path, rule)) + self.assertEqual(status, 0, "Smackload rule was loaded correctly") + +class SmackcipsoBinary(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_smackcipso(self): + '''Test if smackcipso command works''' + # 12345678901234567890123456789012345678901234567890123456 + rule="cipsolabel 2 2 " + + status, output = self.target.run("echo '%s' | smackcipso" %rule) + self.assertEqual( + status, 0, + "Smackcipso failed to load rule. Output: %s" %output) + + status, output = self.target.run( + "cat %s/cipso | grep 'cipsolabel'" %self.smack_path) + self.assertEqual(status, 0, "Smackload rule was loaded correctly") + self.assertIn( + "2/2", output, + "Rule was not set correctly. Got: %s" %output) + +class SmackEnforceFileAccess(SmackBasicTest): + @skipUnlessPassed('test_ssh') + def test_smack_enforce_file_access(self): + '''Test if smack file access is enforced (rwx) + + test needs to change the running label of the current process, + so whole test takes places on image + ''' + status, output = self.target.run("ls /tmp/smack_test_file_access.sh") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'smack_test_file_access.sh'), + "/tmp/smack_test_file_access.sh") + + status, output = self.target.run("sh /tmp/smack_test_file_access.sh") + self.assertEqual(status, 0, output) + +class SmackEnforceMmap(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_smack_mmap_enforced(self): + '''Test if smack mmap access is enforced''' + raise unittest.SkipTest("Depends on mmap_test, which was removed from the layer while investigating its license.") + + # 12345678901234567890123456789012345678901234567890123456 + delr1="mmap_label mmap_test_label1 -----" + delr2="mmap_label mmap_test_label2 -----" + delr3="mmap_file_label mmap_test_label1 -----" + delr4="mmap_file_label mmap_test_label2 -----" + + RuleA="mmap_label mmap_test_label1 rw---" + RuleB="mmap_label mmap_test_label2 r--at" + RuleC="mmap_file_label mmap_test_label1 rw---" + RuleD="mmap_file_label mmap_test_label2 rwxat" + + mmap_label="mmap_label" + file_label="mmap_file_label" + test_file = "/tmp/smack_test_mmap" + self.target.copy_to(os.path.join(get_files_dir(), "mmap_test"), "/tmp/") + mmap_exe = "/tmp/mmap_test" + status, echo = self.target.run("which echo") + status, output = self.target.run("ls /tmp/notroot.py") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'notroot.py'), + "/tmp/notroot.py") + status, output = self.target.run( + "python /tmp/notroot.py %d %s %s 'test' > %s" \ + %(self.uid, self.current_label, echo, test_file)) + status, output = self.target.run("ls %s" %test_file) + self.assertEqual(status, 0, "Could not create mmap test file") + self.target.run("chsmack -m %s %s" %(file_label, test_file)) + self.target.run("chsmack -e %s %s" %(mmap_label, mmap_exe)) + + # test with no rules with mmap label or exec label as subject + # access should be granted + self.target.run('echo -n "%s" > %s/load' %(delr1, self.smack_path)) + self.target.run('echo -n "%s" > %s/load' %(delr2, self.smack_path)) + self.target.run('echo -n "%s" > %s/load' %(delr3, self.smack_path)) + self.target.run('echo -n "%s" > %s/load' %(delr4, self.smack_path)) + status, output = self.target.run("%s %s 0 2" % (mmap_exe, test_file)) + self.assertEqual( + status, 0, + "Should have mmap access without rules. Output: %s" %output) + + # add rules that do not match access required + self.target.run('echo -n "%s" > %s/load' %(RuleA, self.smack_path)) + self.target.run('echo -n "%s" > %s/load' %(RuleB, self.smack_path)) + status, output = self.target.run("%s %s 0 2" % (mmap_exe, test_file)) + self.assertNotEqual( + status, 0, + "Should not have mmap access with unmatching rules. " + + "Output: %s" %output) + self.assertIn( + "Permission denied", output, + "Mmap access should be denied with unmatching rules") + + # add rule to match only partially (one way) + self.target.run('echo -n "%s" > %s/load' %(RuleC, self.smack_path)) + status, output = self.target.run("%s %s 0 2" %(mmap_exe, test_file)) + self.assertNotEqual( + status, 0, + "Should not have mmap access with partial matching rules. " + + "Output: %s" %output) + self.assertIn( + "Permission denied", output, + "Mmap access should be denied with partial matching rules") + + # add rule to match fully + self.target.run('echo -n "%s" > %s/load' %(RuleD, self.smack_path)) + status, output = self.target.run("%s %s 0 2" %(mmap_exe, test_file)) + self.assertEqual( + status, 0, + "Should have mmap access with full matching rules." + + "Output: %s" %output) + +class SmackEnforceTransmutable(SmackBasicTest): + + def test_smack_transmute_dir(self): + '''Test if smack transmute attribute works + + test needs to change the running label of the current process, + so whole test takes places on image + ''' + test_dir = "/tmp/smack_transmute_dir" + label="transmute_label" + status, initial_label = self.target.run("cat /proc/self/attr/current") + + self.target.run("mkdir -p %s" %test_dir) + self.target.run("chsmack -a %s %s" %(label, test_dir)) + self.target.run("chsmack -t %s" %test_dir) + self.target.run( + "echo -n '%s %s rwxat' | smackload" %(initial_label, label) ) + + self.target.run("touch %s/test" %test_dir) + status, output = self.target.run("chsmack %s/test" %test_dir) + self.assertIn( + 'access="%s"' %label, output, + "Did not get expected label. Output: %s" %output) + + +class SmackTcpSockets(SmackBasicTest): + def test_smack_tcp_sockets(self): + '''Test if smack is enforced on tcp sockets + + whole test takes places on image, depends on tcp_server/tcp_client''' + + self.target.copy_to(os.path.join(get_files_dir(), "tcp_client"), "/tmp/") + self.target.copy_to(os.path.join(get_files_dir(), "tcp_server"), "/tmp/") + status, output = self.target.run("ls /tmp/test_smack_tcp_sockets.sh") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'test_smack_tcp_sockets.sh'), + "/tmp/test_smack_tcp_sockets.sh") + + status, output = self.target.run("sh /tmp/test_smack_tcp_sockets.sh") + self.assertEqual(status, 0, output) + +class SmackUdpSockets(SmackBasicTest): + def test_smack_udp_sockets(self): + '''Test if smack is enforced on udp sockets + + whole test takes places on image, depends on udp_server/udp_client''' + + self.target.copy_to(os.path.join(get_files_dir(), "udp_client"), "/tmp/") + self.target.copy_to(os.path.join(get_files_dir(), "udp_server"), "/tmp/") + status, output = self.target.run("ls /tmp/test_smack_udp_sockets.sh") + if status != 0: + self.target.copy_to( + os.path.join(self.files_dir, 'test_smack_udp_sockets.sh'), + "/tmp/test_smack_udp_sockets.sh") + + status, output = self.target.run("sh /tmp/test_smack_udp_sockets.sh") + self.assertEqual(status, 0, output) + +class SmackFileLabels(SmackBasicTest): + + @skipUnlessPassed('test_ssh') + def test_smack_labels(self): + '''Check for correct Smack labels.''' + expected = ''' +/tmp/ access="*" +/etc/ access="System::Shared" transmute="TRUE" +/etc/passwd access="System::Shared" +/etc/terminfo access="System::Shared" transmute="TRUE" +/etc/skel/ access="System::Shared" transmute="TRUE" +/etc/skel/.profile access="System::Shared" +/var/log/ access="System::Log" transmute="TRUE" +/var/tmp/ access="*" +''' + files = ' '.join([x.split()[0] for x in expected.split('\n') if x]) + files_wildcard = ' '.join([x + '/*' for x in files.split()]) + # Auxiliary information. + status, output = self.target.run( + 'set -x; mount; ls -l -d %s; find %s | xargs ls -d -l; find %s | xargs chsmack' % ( + ' '.join([x.rstrip('/') for x in files.split()]), files, files + ) + ) + msg = "File status:\n" + output + status, output = self.target.run('chsmack %s' % files) + self.assertEqual( + status, 0, msg="status and output: %s and %s\n%s" % (status,output, msg)) + self.longMessage = True + self.maxDiff = None + self.assertEqual(output.strip().split('\n'), expected.strip().split('\n'), msg=msg) diff --git a/meta-security/recipes-connectivity/bluez5/bluez5_%.bbappend b/meta-security/recipes-connectivity/bluez5/bluez5_%.bbappend new file mode 100644 index 000000000..c62842d5b --- /dev/null +++ b/meta-security/recipes-connectivity/bluez5/bluez5_%.bbappend @@ -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 + +FIX_BLUEZ5_CAPABILITIES ??= "" +FIX_BLUEZ5_CAPABILITIES_with-lsm-smack ??= "fix_bluez5_capabilities" +do_install[postfuncs] += "${FIX_BLUEZ5_CAPABILITIES}" + +fix_bluez5_capabilities () { + service="${D}/${systemd_unitdir}/system/bluetooth.service" + if [ -f "$service" ] && + grep -q '^CapabilityBoundingSet=' "$service"; then + sed -i -e 's/^CapabilityBoundingSet=/CapabilityBoundingSet=CAP_MAC_OVERRIDE /' "$service" + fi +} diff --git a/meta-security/recipes-connectivity/connman/connman_%.bbappend b/meta-security/recipes-connectivity/connman/connman_%.bbappend new file mode 100644 index 000000000..f66c1e79b --- /dev/null +++ b/meta-security/recipes-connectivity/connman/connman_%.bbappend @@ -0,0 +1,32 @@ +# 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. + +FIX_CONNMAN_CAPABILITIES ??= "" +FIX_CONNMAN_CAPABILITIES_with-lsm-smack ??= "fix_connman_capabilities" +do_install[postfuncs] += "${FIX_CONNMAN_CAPABILITIES}" + +fix_connman_capabilities () { + service="${D}/${systemd_unitdir}/system/connman.service" + if [ -f "$service" ] && + grep -q '^CapabilityBoundingSet=' "$service"; then + sed -i -e 's/^CapabilityBoundingSet=/CapabilityBoundingSet=CAP_MAC_OVERRIDE /' "$service" + fi +} diff --git a/meta-security/recipes-core/base-files/base-files_%.bbappend b/meta-security/recipes-core/base-files/base-files_%.bbappend new file mode 100644 index 000000000..7a37eb9dc --- /dev/null +++ b/meta-security/recipes-core/base-files/base-files_%.bbappend @@ -0,0 +1,73 @@ +# 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-userspace" +DEPENDS_append_with-lsm-smack = " smack-userspace-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 /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-security/recipes-core/coreutils/coreutils_%.bbappend b/meta-security/recipes-core/coreutils/coreutils_%.bbappend new file mode 100644 index 000000000..ceaf6a29c --- /dev/null +++ b/meta-security/recipes-core/coreutils/coreutils_%.bbappend @@ -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 = "--disable-libsmack" +EXTRA_OECONF_SMACK_with-lsm-smack = "--enable-libsmack" +EXTRA_OECONF_append = " ${EXTRA_OECONF_SMACK}" +DEPENDS_append_with-lsm-smack = " smack" diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch b/meta-security/recipes-core/dbus/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch new file mode 100644 index 000000000..271ac48a1 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0001-Fix-memleak-in-GetConnectionCredentials-handler.patch @@ -0,0 +1,32 @@ +From eacdc525a1f7bfc534e248a5a946c08b6f4aab35 Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Wed, 17 Jun 2015 18:53:41 +0100 +Subject: [PATCH 1/8] Fix memleak in GetConnectionCredentials handler + +Reply message was not unreferenced when GetConnectionCredentials +handler was successful. + +Signed-off-by: Jacek Bukarewicz <j.bukarewicz@samsung.com> +[smcv: changed bus_message_unref() to dbus_message_unref()] +Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> +Bug: https://bugs.freedesktop.org/show_bug.cgi?id=91008 +--- + bus/driver.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/bus/driver.c b/bus/driver.c +index f5d3ebe..888c7ca 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -1613,6 +1613,8 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + goto oom; + } + ++ dbus_message_unref (reply); ++ + return TRUE; + + oom: +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch b/meta-security/recipes-core/dbus/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch new file mode 100644 index 000000000..64c8b9b50 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch @@ -0,0 +1,97 @@ +From 25cb15916402c55112cae2be0954d24afe74e2f2 Mon Sep 17 00:00:00 2001 +From: Tyler Hicks <tyhicks@canonical.com> +Date: Thu, 13 Mar 2014 17:37:38 -0500 +Subject: [PATCH 2/8] New a{sv} helper for using byte arrays as the variant + +Create a new helper for using a byte array as the value in the mapping +from string to variant. + +Bug: https://bugs.freedesktop.org/show_bug.cgi?id=75113 +Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89041 +Signed-off-by: Tyler Hicks <tyhicks@canonical.com> +Reviewed-by: Simon McVittie <simon.mcvittie@collabora.co.uk> +Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk> +--- + dbus/dbus-asv-util.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ + dbus/dbus-asv-util.h | 4 ++++ + 2 files changed, 58 insertions(+) + +diff --git a/dbus/dbus-asv-util.c b/dbus/dbus-asv-util.c +index 583e41f..d3ac5e9 100644 +--- a/dbus/dbus-asv-util.c ++++ b/dbus/dbus-asv-util.c +@@ -258,3 +258,57 @@ _dbus_asv_add_string (DBusMessageIter *arr_iter, + + return TRUE; + } ++ ++/** ++ * Create a new entry in an a{sv} (map from string to variant) ++ * with a byte array value. ++ * ++ * If this function fails, the a{sv} must be abandoned, for instance ++ * with _dbus_asv_abandon(). ++ * ++ * @param arr_iter the iterator which is appending to the array ++ * @param key a UTF-8 key for the map ++ * @param value the value ++ * @param n_elements the number of elements to append ++ * @returns #TRUE on success, or #FALSE if not enough memory ++ */ ++dbus_bool_t ++_dbus_asv_add_byte_array (DBusMessageIter *arr_iter, ++ const char *key, ++ const void *value, ++ int n_elements) ++{ ++ DBusMessageIter entry_iter; ++ DBusMessageIter var_iter; ++ DBusMessageIter byte_array_iter; ++ ++ if (!_dbus_asv_open_entry (arr_iter, &entry_iter, key, "ay", &var_iter)) ++ return FALSE; ++ ++ if (!dbus_message_iter_open_container (&var_iter, DBUS_TYPE_ARRAY, ++ DBUS_TYPE_BYTE_AS_STRING, ++ &byte_array_iter)) ++ { ++ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); ++ return FALSE; ++ } ++ ++ if (!dbus_message_iter_append_fixed_array (&byte_array_iter, DBUS_TYPE_BYTE, ++ &value, n_elements)) ++ { ++ dbus_message_iter_abandon_container (&var_iter, &byte_array_iter); ++ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); ++ return FALSE; ++ } ++ ++ if (!dbus_message_iter_close_container (&var_iter, &byte_array_iter)) ++ { ++ _dbus_asv_abandon_entry (arr_iter, &entry_iter, &var_iter); ++ return FALSE; ++ } ++ ++ if (!_dbus_asv_close_entry (arr_iter, &entry_iter, &var_iter)) ++ return FALSE; ++ ++ return TRUE; ++} +diff --git a/dbus/dbus-asv-util.h b/dbus/dbus-asv-util.h +index 0337260..277ab80 100644 +--- a/dbus/dbus-asv-util.h ++++ b/dbus/dbus-asv-util.h +@@ -42,5 +42,9 @@ dbus_bool_t _dbus_asv_add_uint32 (DBusMessageIter *arr_iter, + dbus_bool_t _dbus_asv_add_string (DBusMessageIter *arr_iter, + const char *key, + const char *value); ++dbus_bool_t _dbus_asv_add_byte_array (DBusMessageIter *arr_iter, ++ const char *key, ++ const void *value, ++ int n_elements); + + #endif +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch b/meta-security/recipes-core/dbus/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch new file mode 100644 index 000000000..fcb85504d --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch @@ -0,0 +1,515 @@ +From 9da49d4eb6982c659fec988231baef8cd1b05be2 Mon Sep 17 00:00:00 2001 +From: Simon McVittie <simon.mcvittie@collabora.co.uk> +Date: Wed, 11 Feb 2015 13:19:15 +0000 +Subject: [PATCH 3/8] Add LSM-agnostic support for LinuxSecurityLabel + credential + +Bug: https://bugs.freedesktop.org/show_bug.cgi?id=89041 +Change-Id: I70512843d1a7661c87461b1b6d86fbfbda934ad5 +Reviewed-by: Philip Withnall <philip.withnall@collabora.co.uk> +Acked-by: Stephen Smalley <sds@tycho.nsa.gov> (for SELinux) +Acked-by: John Johansen <john.johansen@canonical.com> (for AppArmor) +Acked-by: Casey Schaufler <casey@schaufler-ca.com> (for Smack) +Tested-by: Tyler Hicks <tyhicks@canonical.com> +--- + bus/driver.c | 19 ++++++++ + dbus/dbus-auth.c | 11 +++-- + dbus/dbus-connection-internal.h | 3 ++ + dbus/dbus-connection.c | 26 ++++++++++ + dbus/dbus-credentials.c | 68 ++++++++++++++++++++++++++ + dbus/dbus-credentials.h | 4 ++ + dbus/dbus-sysdeps-unix.c | 105 ++++++++++++++++++++++++++++++++++++++++ + dbus/dbus-transport.c | 27 +++++++++++ + dbus/dbus-transport.h | 3 ++ + 9 files changed, 262 insertions(+), 4 deletions(-) + +diff --git a/bus/driver.c b/bus/driver.c +index 888c7ca..11706f8 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -34,6 +34,7 @@ + #include "utils.h" + + #include <dbus/dbus-asv-util.h> ++#include <dbus/dbus-connection-internal.h> + #include <dbus/dbus-string.h> + #include <dbus/dbus-internals.h> + #include <dbus/dbus-message.h> +@@ -1567,6 +1568,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + DBusMessageIter reply_iter; + DBusMessageIter array_iter; + unsigned long ulong_val; ++ char *s; + const char *service; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); +@@ -1601,6 +1603,23 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + goto oom; + } + ++ if (_dbus_connection_get_linux_security_label (conn, &s)) ++ { ++ if (s == NULL) ++ goto oom; ++ ++ /* use the GVariant bytestring convention for strings of unknown ++ * encoding: include the \0 in the payload, for zero-copy reading */ ++ if (!_dbus_asv_add_byte_array (&array_iter, "LinuxSecurityLabel", ++ s, strlen (s) + 1)) ++ { ++ dbus_free (s); ++ goto oom; ++ } ++ ++ dbus_free (s); ++ } ++ + if (!_dbus_asv_close (&reply_iter, &array_iter)) + goto oom; + +diff --git a/dbus/dbus-auth.c b/dbus/dbus-auth.c +index 6a07665..aee877d 100644 +--- a/dbus/dbus-auth.c ++++ b/dbus/dbus-auth.c +@@ -1102,20 +1102,23 @@ handle_server_data_external_mech (DBusAuth *auth, + auth->desired_identity)) + return FALSE; + +- /* also copy process ID from the socket credentials ++ /* also copy misc process info from the socket credentials + */ + if (!_dbus_credentials_add_credential (auth->authorized_identity, + DBUS_CREDENTIAL_UNIX_PROCESS_ID, + auth->credentials)) + return FALSE; + +- /* also copy audit data from the socket credentials +- */ + if (!_dbus_credentials_add_credential (auth->authorized_identity, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, + auth->credentials)) + return FALSE; +- ++ ++ if (!_dbus_credentials_add_credential (auth->authorized_identity, ++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, ++ auth->credentials)) ++ return FALSE; ++ + if (!send_ok (auth)) + return FALSE; + +diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h +index 2897404..64ef336 100644 +--- a/dbus/dbus-connection-internal.h ++++ b/dbus/dbus-connection-internal.h +@@ -107,6 +107,9 @@ void _dbus_connection_set_pending_fds_function (DBusConnectio + DBusPendingFdsChangeFunction callback, + void *data); + ++dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection, ++ char **label_p); ++ + /* if DBUS_ENABLE_STATS */ + void _dbus_connection_get_stats (DBusConnection *connection, + dbus_uint32_t *in_messages, +diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c +index b574207..8952b75 100644 +--- a/dbus/dbus-connection.c ++++ b/dbus/dbus-connection.c +@@ -5322,6 +5322,32 @@ dbus_connection_set_unix_user_function (DBusConnection *connection, + (* old_free_function) (old_data); + } + ++/* Same calling convention as dbus_connection_get_windows_user */ ++dbus_bool_t ++_dbus_connection_get_linux_security_label (DBusConnection *connection, ++ char **label_p) ++{ ++ dbus_bool_t result; ++ ++ _dbus_assert (connection != NULL); ++ _dbus_assert (label_p != NULL); ++ ++ CONNECTION_LOCK (connection); ++ ++ if (!_dbus_transport_try_to_authenticate (connection->transport)) ++ result = FALSE; ++ else ++ result = _dbus_transport_get_linux_security_label (connection->transport, ++ label_p); ++#ifndef __linux__ ++ _dbus_assert (!result); ++#endif ++ ++ CONNECTION_UNLOCK (connection); ++ ++ return result; ++} ++ + /** + * Gets the Windows user SID of the connection if known. Returns + * #TRUE if the ID is filled in. Always returns #FALSE on non-Windows +diff --git a/dbus/dbus-credentials.c b/dbus/dbus-credentials.c +index 7325125..151bb00 100644 +--- a/dbus/dbus-credentials.c ++++ b/dbus/dbus-credentials.c +@@ -50,6 +50,7 @@ struct DBusCredentials { + dbus_uid_t unix_uid; + dbus_pid_t pid; + char *windows_sid; ++ char *linux_security_label; + void *adt_audit_data; + dbus_int32_t adt_audit_data_size; + }; +@@ -79,6 +80,7 @@ _dbus_credentials_new (void) + creds->unix_uid = DBUS_UID_UNSET; + creds->pid = DBUS_PID_UNSET; + creds->windows_sid = NULL; ++ creds->linux_security_label = NULL; + creds->adt_audit_data = NULL; + creds->adt_audit_data_size = 0; + +@@ -133,6 +135,7 @@ _dbus_credentials_unref (DBusCredentials *credentials) + if (credentials->refcount == 0) + { + dbus_free (credentials->windows_sid); ++ dbus_free (credentials->linux_security_label); + dbus_free (credentials->adt_audit_data); + dbus_free (credentials); + } +@@ -193,6 +196,30 @@ _dbus_credentials_add_windows_sid (DBusCredentials *credentials, + } + + /** ++ * Add a Linux security label, as used by LSMs such as SELinux, Smack and ++ * AppArmor, to the credentials. ++ * ++ * @param credentials the object ++ * @param label the label ++ * @returns #FALSE if no memory ++ */ ++dbus_bool_t ++_dbus_credentials_add_linux_security_label (DBusCredentials *credentials, ++ const char *label) ++{ ++ char *copy; ++ ++ copy = _dbus_strdup (label); ++ if (copy == NULL) ++ return FALSE; ++ ++ dbus_free (credentials->linux_security_label); ++ credentials->linux_security_label = copy; ++ ++ return TRUE; ++} ++ ++/** + * Add ADT audit data to the credentials. + * + * @param credentials the object +@@ -236,6 +263,8 @@ _dbus_credentials_include (DBusCredentials *credentials, + return credentials->unix_uid != DBUS_UID_UNSET; + case DBUS_CREDENTIAL_WINDOWS_SID: + return credentials->windows_sid != NULL; ++ case DBUS_CREDENTIAL_LINUX_SECURITY_LABEL: ++ return credentials->linux_security_label != NULL; + case DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID: + return credentials->adt_audit_data != NULL; + } +@@ -284,6 +313,19 @@ _dbus_credentials_get_windows_sid (DBusCredentials *credentials) + } + + /** ++ * Gets the Linux security label (as used by LSMs) from the credentials, ++ * or #NULL if the credentials object doesn't contain a security label. ++ * ++ * @param credentials the object ++ * @returns the security label ++ */ ++const char * ++_dbus_credentials_get_linux_security_label (DBusCredentials *credentials) ++{ ++ return credentials->linux_security_label; ++} ++ ++/** + * Gets the ADT audit data in the credentials, or #NULL if + * the credentials object doesn't contain ADT audit data. + * +@@ -329,6 +371,10 @@ _dbus_credentials_are_superset (DBusCredentials *credentials, + (possible_subset->windows_sid == NULL || + (credentials->windows_sid && strcmp (possible_subset->windows_sid, + credentials->windows_sid) == 0)) && ++ (possible_subset->linux_security_label == NULL || ++ (credentials->linux_security_label != NULL && ++ strcmp (possible_subset->linux_security_label, ++ credentials->linux_security_label) == 0)) && + (possible_subset->adt_audit_data == NULL || + (credentials->adt_audit_data && memcmp (possible_subset->adt_audit_data, + credentials->adt_audit_data, +@@ -348,6 +394,7 @@ _dbus_credentials_are_empty (DBusCredentials *credentials) + credentials->pid == DBUS_PID_UNSET && + credentials->unix_uid == DBUS_UID_UNSET && + credentials->windows_sid == NULL && ++ credentials->linux_security_label == NULL && + credentials->adt_audit_data == NULL; + } + +@@ -388,6 +435,9 @@ _dbus_credentials_add_credentials (DBusCredentials *credentials, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, + other_credentials) && + _dbus_credentials_add_credential (credentials, ++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, ++ other_credentials) && ++ _dbus_credentials_add_credential (credentials, + DBUS_CREDENTIAL_WINDOWS_SID, + other_credentials); + } +@@ -427,6 +477,13 @@ _dbus_credentials_add_credential (DBusCredentials *credentials, + if (!_dbus_credentials_add_windows_sid (credentials, other_credentials->windows_sid)) + return FALSE; + } ++ else if (which == DBUS_CREDENTIAL_LINUX_SECURITY_LABEL && ++ other_credentials->linux_security_label != NULL) ++ { ++ if (!_dbus_credentials_add_linux_security_label (credentials, ++ other_credentials->linux_security_label)) ++ return FALSE; ++ } + else if (which == DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID && + other_credentials->adt_audit_data != NULL) + { +@@ -449,6 +506,8 @@ _dbus_credentials_clear (DBusCredentials *credentials) + credentials->unix_uid = DBUS_UID_UNSET; + dbus_free (credentials->windows_sid); + credentials->windows_sid = NULL; ++ dbus_free (credentials->linux_security_label); ++ credentials->linux_security_label = NULL; + dbus_free (credentials->adt_audit_data); + credentials->adt_audit_data = NULL; + credentials->adt_audit_data_size = 0; +@@ -540,6 +599,15 @@ _dbus_credentials_to_string_append (DBusCredentials *credentials, + else + join = FALSE; + ++ if (credentials->linux_security_label != NULL) ++ { ++ if (!_dbus_string_append_printf (string, "%slsm='%s'", ++ join ? " " : "", ++ credentials->linux_security_label)) ++ goto oom; ++ join = TRUE; ++ } ++ + return TRUE; + oom: + return FALSE; +diff --git a/dbus/dbus-credentials.h b/dbus/dbus-credentials.h +index abcc4bb..ab74eac 100644 +--- a/dbus/dbus-credentials.h ++++ b/dbus/dbus-credentials.h +@@ -34,6 +34,7 @@ typedef enum { + DBUS_CREDENTIAL_UNIX_PROCESS_ID, + DBUS_CREDENTIAL_UNIX_USER_ID, + DBUS_CREDENTIAL_ADT_AUDIT_DATA_ID, ++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL, + DBUS_CREDENTIAL_WINDOWS_SID + } DBusCredentialType; + +@@ -47,6 +48,8 @@ dbus_bool_t _dbus_credentials_add_unix_uid (DBusCredentials + dbus_uid_t uid); + dbus_bool_t _dbus_credentials_add_windows_sid (DBusCredentials *credentials, + const char *windows_sid); ++dbus_bool_t _dbus_credentials_add_linux_security_label (DBusCredentials *credentials, ++ const char *label); + dbus_bool_t _dbus_credentials_add_adt_audit_data (DBusCredentials *credentials, + void *audit_data, + dbus_int32_t size); +@@ -55,6 +58,7 @@ dbus_bool_t _dbus_credentials_include (DBusCredentials + dbus_pid_t _dbus_credentials_get_pid (DBusCredentials *credentials); + dbus_uid_t _dbus_credentials_get_unix_uid (DBusCredentials *credentials); + const char* _dbus_credentials_get_windows_sid (DBusCredentials *credentials); ++const char * _dbus_credentials_get_linux_security_label (DBusCredentials *credentials); + void * _dbus_credentials_get_adt_audit_data (DBusCredentials *credentials); + dbus_int32_t _dbus_credentials_get_adt_audit_data_size (DBusCredentials *credentials); + dbus_bool_t _dbus_credentials_are_superset (DBusCredentials *credentials, +diff --git a/dbus/dbus-sysdeps-unix.c b/dbus/dbus-sysdeps-unix.c +index fe891ab..61af423 100644 +--- a/dbus/dbus-sysdeps-unix.c ++++ b/dbus/dbus-sysdeps-unix.c +@@ -1639,6 +1639,105 @@ write_credentials_byte (int server_fd, + } + } + ++/* return FALSE on OOM, TRUE otherwise, even if no credentials were found */ ++static dbus_bool_t ++add_linux_security_label_to_credentials (int client_fd, ++ DBusCredentials *credentials) ++{ ++#if defined(__linux__) && defined(SO_PEERSEC) ++ DBusString buf; ++ socklen_t len = 1024; ++ dbus_bool_t oom = FALSE; ++ ++ if (!_dbus_string_init_preallocated (&buf, len) || ++ !_dbus_string_set_length (&buf, len)) ++ return FALSE; ++ ++ while (getsockopt (client_fd, SOL_SOCKET, SO_PEERSEC, ++ _dbus_string_get_data (&buf), &len) < 0) ++ { ++ int e = errno; ++ ++ _dbus_verbose ("getsockopt failed with %s, len now %lu\n", ++ _dbus_strerror (e), (unsigned long) len); ++ ++ if (e != ERANGE || len <= _dbus_string_get_length (&buf)) ++ { ++ _dbus_verbose ("Failed to getsockopt(SO_PEERSEC): %s\n", ++ _dbus_strerror (e)); ++ goto out; ++ } ++ ++ /* If not enough space, len is updated to be enough. ++ * Try again with a large enough buffer. */ ++ if (!_dbus_string_set_length (&buf, len)) ++ { ++ oom = TRUE; ++ goto out; ++ } ++ ++ _dbus_verbose ("will try again with %lu\n", (unsigned long) len); ++ } ++ ++ if (len <= 0) ++ { ++ _dbus_verbose ("getsockopt(SO_PEERSEC) yielded <= 0 bytes: %lu\n", ++ (unsigned long) len); ++ goto out; ++ } ++ ++ if (len > _dbus_string_get_length (&buf)) ++ { ++ _dbus_verbose ("%lu > %d", (unsigned long) len, ++ _dbus_string_get_length (&buf)); ++ _dbus_assert_not_reached ("getsockopt(SO_PEERSEC) overflowed"); ++ } ++ ++ if (_dbus_string_get_byte (&buf, len - 1) == 0) ++ { ++ /* the kernel included the trailing \0 in its count, ++ * but DBusString always has an extra \0 after the data anyway */ ++ _dbus_verbose ("subtracting trailing \\0\n"); ++ len--; ++ } ++ ++ if (!_dbus_string_set_length (&buf, len)) ++ { ++ _dbus_assert_not_reached ("shortening string should not lead to OOM"); ++ oom = TRUE; ++ goto out; ++ } ++ ++ if (strlen (_dbus_string_get_const_data (&buf)) != len) ++ { ++ /* LSM people on the linux-security-module@ mailing list say this ++ * should never happen: the label should be a bytestring with ++ * an optional trailing \0 */ ++ _dbus_verbose ("security label from kernel had an embedded \\0, " ++ "ignoring it\n"); ++ goto out; ++ } ++ ++ _dbus_verbose ("getsockopt(SO_PEERSEC): %lu bytes excluding \\0: %s\n", ++ (unsigned long) len, ++ _dbus_string_get_const_data (&buf)); ++ ++ if (!_dbus_credentials_add_linux_security_label (credentials, ++ _dbus_string_get_const_data (&buf))) ++ { ++ oom = TRUE; ++ goto out; ++ } ++ ++out: ++ _dbus_string_free (&buf); ++ return !oom; ++#else ++ /* no error */ ++ return TRUE; ++#endif ++} ++ + /** + * Reads a single byte which must be nul (an error occurs otherwise), + * and reads unix credentials if available. Clears the credentials +@@ -1922,6 +2021,12 @@ _dbus_read_credentials_socket (int client_fd, + } + } + ++ if (!add_linux_security_label_to_credentials (client_fd, credentials)) ++ { ++ _DBUS_SET_OOM (error); ++ return FALSE; ++ } ++ + return TRUE; + } + +diff --git a/dbus/dbus-transport.c b/dbus/dbus-transport.c +index e9dcc56..a43e7bb 100644 +--- a/dbus/dbus-transport.c ++++ b/dbus/dbus-transport.c +@@ -1425,6 +1425,33 @@ _dbus_transport_set_unix_user_function (DBusTransport *transport, + transport->free_unix_user_data = free_data_function; + } + ++dbus_bool_t ++_dbus_transport_get_linux_security_label (DBusTransport *transport, ++ char **label_p) ++{ ++ DBusCredentials *auth_identity; ++ ++ *label_p = NULL; ++ ++ if (!transport->authenticated) ++ return FALSE; ++ ++ auth_identity = _dbus_auth_get_identity (transport->auth); ++ ++ if (_dbus_credentials_include (auth_identity, ++ DBUS_CREDENTIAL_LINUX_SECURITY_LABEL)) ++ { ++ /* If no memory, we are supposed to return TRUE and set NULL */ ++ *label_p = _dbus_strdup (_dbus_credentials_get_linux_security_label (auth_identity)); ++ ++ return TRUE; ++ } ++ else ++ { ++ return FALSE; ++ } ++} ++ + /** + * See dbus_connection_get_windows_user(). + * +diff --git a/dbus/dbus-transport.h b/dbus/dbus-transport.h +index 39c74c4..843f231 100644 +--- a/dbus/dbus-transport.h ++++ b/dbus/dbus-transport.h +@@ -87,6 +87,9 @@ void _dbus_transport_set_unix_user_function (DBusTransport + DBusFreeFunction *old_free_data_function); + dbus_bool_t _dbus_transport_get_windows_user (DBusTransport *transport, + char **windows_sid_p); ++dbus_bool_t _dbus_transport_get_linux_security_label (DBusTransport *transport, ++ char **label_p); ++ + void _dbus_transport_set_windows_user_function (DBusTransport *transport, + DBusAllowWindowsUserFunction function, + void *data, +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch b/meta-security/recipes-core/dbus/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch new file mode 100644 index 000000000..70d5fc9d7 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0004-Integration-of-Cynara-asynchronous-security-checks.patch @@ -0,0 +1,2253 @@ +From 4dcfb02f17247ff9de966b62182cd2e08f301238 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 4/8] Integration of Cynara asynchronous security checks + +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. + +Change-Id: I9bcbce34577e5dc2a3cecf6233a0a2b0e43e1108 +--- + bus/Makefile.am | 6 + + bus/bus.c | 134 +++++--- + bus/bus.h | 58 ++-- + bus/check.c | 215 ++++++++++++ + bus/check.h | 68 ++++ + bus/config-parser-common.c | 6 + + bus/config-parser-common.h | 1 + + bus/config-parser.c | 71 +++- + bus/connection.c | 56 ++- + bus/connection.h | 5 + + bus/cynara.c | 374 +++++++++++++++++++++ + bus/cynara.h | 37 ++ + bus/dispatch.c | 51 ++- + bus/policy.c | 193 +++++++---- + bus/policy.h | 51 ++- + configure.ac | 13 + + test/Makefile.am | 1 + + test/data/invalid-config-files/badcheck-1.conf | 9 + + test/data/invalid-config-files/badcheck-2.conf | 9 + + test/data/valid-config-files/check-1.conf | 9 + + .../valid-config-files/debug-check-some.conf.in | 18 + + 22 files changed, 1211 insertions(+), 180 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 f335e30..b057d6b 100644 +--- a/bus/Makefile.am ++++ b/bus/Makefile.am +@@ -7,6 +7,7 @@ DBUS_BUS_LIBS = \ + $(THREAD_LIBS) \ + $(ADT_LIBS) \ + $(NETWORK_libs) \ ++ $(CYNARA_LIBS) \ + $(NULL) + + DBUS_LAUNCHER_LIBS = \ +@@ -21,6 +22,7 @@ AM_CPPFLAGS = \ + -DDBUS_SYSTEM_CONFIG_FILE=\""$(configdir)/system.conf"\" \ + -DDBUS_COMPILATION \ + -DDBUS_STATIC_BUILD \ ++ $(CYNARA_CFLAGS) \ + $(NULL) + + # if assertions are enabled, improve backtraces +@@ -60,12 +62,16 @@ BUS_SOURCES= \ + activation-exit-codes.h \ + bus.c \ + bus.h \ ++ check.c \ ++ check.h \ + config-parser.c \ + config-parser.h \ + config-parser-common.c \ + 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/bus.c b/bus/bus.c +index f0d980e..ac9ea8d 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -35,6 +35,7 @@ + #include "signals.h" + #include "selinux.h" + #include "dir-watch.h" ++#include "check.h" + #include <dbus/dbus-list.h> + #include <dbus/dbus-hash.h> + #include <dbus/dbus-credentials.h> +@@ -63,6 +64,7 @@ struct BusContext + BusRegistry *registry; + BusPolicy *policy; + BusMatchmaker *matchmaker; ++ BusCheck *check; + BusLimits limits; + DBusRLimit *initial_fd_limit; + unsigned int fork : 1; +@@ -962,6 +964,10 @@ bus_context_new (const DBusString *config_file, + #endif + } + ++ context->check = bus_check_new(context, error); ++ if (context->check == NULL) ++ goto failed; ++ + dbus_server_free_data_slot (&server_data_slot); + + return context; +@@ -1086,6 +1092,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); +@@ -1215,6 +1227,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) +@@ -1386,6 +1404,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; +@@ -1415,7 +1434,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)), +@@ -1426,7 +1446,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 */ +@@ -1450,14 +1471,15 @@ 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 +-bus_context_check_security_policy (BusContext *context, +- BusTransaction *transaction, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusConnection *proposed_recipient, +- DBusMessage *message, +- DBusError *error) ++BusResult ++bus_context_check_security_policy (BusContext *context, ++ BusTransaction *transaction, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ DBusMessage *message, ++ DBusError *error, ++ BusDeferredMessage **deferred_message) + { + const char *dest; + BusClientPolicy *sender_policy; +@@ -1466,6 +1488,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); + dest = dbus_message_get_destination (message); +@@ -1493,7 +1516,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; +@@ -1517,11 +1540,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; + } + + if (bus_connection_is_active (sender)) +@@ -1547,7 +1570,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; + } + } + } +@@ -1564,7 +1587,7 @@ bus_context_check_security_policy (BusContext *context, + { + _dbus_verbose ("security check allowing %s message\n", + "Hello"); +- return TRUE; ++ return BUS_RESULT_TRUE; + } + else + { +@@ -1575,7 +1598,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; + } + } + } +@@ -1624,20 +1647,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) + { +@@ -1646,23 +1678,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 */ +@@ -1672,10 +1710,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 +@@ -1692,11 +1730,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 dac6ea5..78084dd 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -30,19 +30,35 @@ + #include <dbus/dbus-pipe.h> + #include <dbus/dbus-sysdeps.h> + +-typedef struct BusActivation BusActivation; +-typedef struct BusConnections BusConnections; +-typedef struct BusContext BusContext; +-typedef struct BusPolicy BusPolicy; +-typedef struct BusClientPolicy BusClientPolicy; +-typedef struct BusPolicyRule BusPolicyRule; +-typedef struct BusRegistry BusRegistry; +-typedef struct BusSELinuxID BusSELinuxID; +-typedef struct BusService BusService; +-typedef struct BusOwner BusOwner; +-typedef struct BusTransaction BusTransaction; +-typedef struct BusMatchmaker BusMatchmaker; +-typedef struct BusMatchRule BusMatchRule; ++typedef struct BusActivation BusActivation; ++typedef struct BusConnections BusConnections; ++typedef struct BusContext BusContext; ++typedef struct BusPolicy BusPolicy; ++typedef struct BusClientPolicy BusClientPolicy; ++typedef struct BusPolicyRule BusPolicyRule; ++typedef struct BusRegistry BusRegistry; ++typedef struct BusSELinuxID BusSELinuxID; ++typedef struct BusService BusService; ++typedef struct BusOwner BusOwner; ++typedef struct BusTransaction BusTransaction; ++typedef struct BusMatchmaker BusMatchmaker; ++typedef struct BusMatchRule BusMatchRule; ++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 + { +@@ -96,6 +112,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, +@@ -121,13 +138,14 @@ void bus_context_log (BusContext + DBusSystemLogSeverity severity, + const char *msg, + ...); +-dbus_bool_t bus_context_check_security_policy (BusContext *context, +- BusTransaction *transaction, +- DBusConnection *sender, +- DBusConnection *addressed_recipient, +- DBusConnection *proposed_recipient, +- DBusMessage *message, +- DBusError *error); + void bus_context_check_all_watches (BusContext *context); ++BusResult bus_context_check_security_policy (BusContext *context, ++ BusTransaction *transaction, ++ DBusConnection *sender, ++ DBusConnection *addressed_recipient, ++ DBusConnection *proposed_recipient, ++ DBusMessage *message, ++ DBusError *error, ++ BusDeferredMessage **deferred_message); + + #endif /* BUS_BUS_H */ +diff --git a/bus/check.c b/bus/check.c +new file mode 100644 +index 0000000..d2f418a +--- /dev/null ++++ b/bus/check.c +@@ -0,0 +1,215 @@ ++/* -*- 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; ++ BusCynara *cynara; ++ 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 c522ff4..1cfe4c8 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; +@@ -155,6 +159,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 186bf4c..bff6fdb 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.c b/bus/config-parser.c +index ee2d4e7..73c9e6f 100644 +--- a/bus/config-parser.c ++++ b/bus/config-parser.c +@@ -1150,7 +1150,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; +@@ -1173,6 +1173,7 @@ append_rule_from_element (BusConfigParser *parser, + const char *own_prefix; + const char *user; + const char *group; ++ const char *privilege; + + BusPolicyRule *rule; + +@@ -1200,6 +1201,7 @@ append_rule_from_element (BusConfigParser *parser, + "user", &user, + "group", &group, + "log", &log, ++ "privilege", &privilege, + NULL)) + return FALSE; + +@@ -1208,6 +1210,7 @@ append_rule_from_element (BusConfigParser *parser, + receive_interface || receive_member || receive_error || receive_sender || + receive_type || receive_path || eavesdrop || + send_requested_reply || receive_requested_reply || ++ privilege || + own || own_prefix || user || group)) + { + dbus_set_error (error, DBUS_ERROR_FAILED, +@@ -1224,7 +1227,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: +@@ -1398,7 +1424,7 @@ append_rule_from_element (BusConfigParser *parser, + 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; + +@@ -1480,7 +1506,7 @@ append_rule_from_element (BusConfigParser *parser, + 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; + +@@ -1510,7 +1536,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; + +@@ -1536,7 +1562,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; + +@@ -1551,7 +1577,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; + +@@ -1568,7 +1594,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; + +@@ -1583,7 +1609,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; + +@@ -1607,6 +1633,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: +@@ -1681,7 +1711,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) +@@ -1696,7 +1726,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) +@@ -1707,6 +1737,21 @@ start_policy_child (BusConfigParser *parser, + + 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 + { + dbus_set_error (error, DBUS_ERROR_FAILED, +@@ -2066,6 +2111,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: +@@ -2365,6 +2411,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: +@@ -2829,6 +2876,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); +diff --git a/bus/connection.c b/bus/connection.c +index 7107434..a6d87e5 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -34,6 +34,10 @@ + #include <dbus/dbus-hash.h> + #include <dbus/dbus-timeout.h> + #include <dbus/dbus-connection-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 +@@ -105,6 +109,9 @@ typedef struct + #endif + int n_pending_unix_fds; + DBusTimeout *pending_unix_fds_timeout; ++#ifdef DBUS_ENABLE_CYNARA ++ char *cynara_session_id; ++#endif + } BusConnectionData; + + static dbus_bool_t bus_pending_reply_expired (BusExpireList *list, +@@ -118,8 +125,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; + +@@ -331,7 +338,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 +@@ -340,7 +347,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 +@@ -349,7 +356,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 +@@ -358,7 +365,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 +@@ -367,7 +374,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 +@@ -425,6 +432,10 @@ free_connection_data (void *data) + + dbus_free (d->name); + ++#ifdef DBUS_ENABLE_CYNARA ++ free (d->cynara_session_id); ++#endif ++ + dbus_free (d); + } + +@@ -984,6 +995,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, +@@ -2104,6 +2131,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + DBusConnection *connection, + DBusMessage *message) + { ++ BusResult res; + /* We have to set the sender to the driver, and have + * to check security policy since it was not done in + * dispatch.c +@@ -2132,10 +2160,18 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + /* If security policy doesn't allow the message, we silently + * eat it; the driver doesn't care about getting a reply. + */ +- if (!bus_context_check_security_policy (bus_transaction_get_context (transaction), +- transaction, +- NULL, connection, connection, message, NULL)) ++ res = bus_context_check_security_policy (bus_transaction_get_context (transaction), ++ transaction, ++ NULL, connection, connection, message, NULL, ++ NULL); ++ ++ if (res == BUS_RESULT_FALSE) + return TRUE; ++ else if (res == BUS_RESULT_LATER) ++ { ++ _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); ++ return TRUE; ++ } + + return bus_transaction_send (transaction, connection, message); + } +diff --git a/bus/connection.h b/bus/connection.h +index 6fbcd38..7433746 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); +@@ -116,6 +117,10 @@ dbus_bool_t bus_connection_get_unix_groups (DBusConnection *connecti + DBusError *error); + BusClientPolicy* bus_connection_get_policy (DBusConnection *connection); + ++#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 */ + + typedef void (* BusTransactionCancelFunction) (void *data); +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 7a61953..ce4076d 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" +@@ -56,13 +57,14 @@ send_one_message (DBusConnection *connection, + BusTransaction *transaction, + DBusError *error) + { +- if (!bus_context_check_security_policy (context, transaction, +- sender, +- addressed_recipient, +- connection, +- message, +- NULL)) +- return TRUE; /* silently don't send it */ ++ BusDeferredMessage *deferred_message; ++ BusResult result; ++ ++ result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient, ++ connection, message, NULL, &deferred_message); ++ ++ if (result != BUS_RESULT_TRUE) ++ return TRUE; /* silently don't send it */ + + if (dbus_message_contains_unix_fds(message) && + !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) +@@ -92,6 +94,7 @@ bus_dispatch_matches (BusTransaction *transaction, + BusMatchmaker *matchmaker; + DBusList *link; + BusContext *context; ++ BusDeferredMessage *deferred_message; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -107,11 +110,21 @@ 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, error)) ++ BusResult res; ++ res = bus_context_check_security_policy (context, transaction, ++ sender, addressed_recipient, ++ addressed_recipient, ++ message, 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, +@@ -273,12 +286,24 @@ bus_dispatch (DBusConnection *connection, + if (service_name && + strcmp (service_name, DBUS_SERVICE_DBUS) == 0) /* to bus driver */ + { +- if (!bus_context_check_security_policy (context, transaction, +- connection, NULL, NULL, message, &error)) ++ BusDeferredMessage *deferred_message; ++ BusResult res; ++ res = bus_context_check_security_policy (context, transaction, ++ connection, NULL, NULL, message, &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/policy.c b/bus/policy.c +index 082f385..ec888df 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" +@@ -32,7 +33,7 @@ + + BusPolicyRule* + bus_policy_rule_new (BusPolicyRuleType type, +- dbus_bool_t allow) ++ BusPolicyRuleAccess access) + { + BusPolicyRule *rule; + +@@ -42,7 +43,7 @@ bus_policy_rule_new (BusPolicyRuleType type, + + rule->type = type; + rule->refcount = 1; +- rule->allow = allow; ++ rule->access = access; + + switch (rule->type) + { +@@ -54,18 +55,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; +@@ -117,7 +119,8 @@ bus_policy_rule_unref (BusPolicyRule *rule) + case BUS_POLICY_RULE_GROUP: + break; + } +- ++ ++ dbus_free (rule->privilege); + dbus_free (rule); + } + } +@@ -427,7 +430,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; +@@ -862,18 +868,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 + */ +@@ -881,7 +892,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) + { +@@ -912,13 +923,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; + } + +@@ -926,7 +938,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; +@@ -949,13 +961,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)) +@@ -1029,33 +1043,63 @@ 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: ++ 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", ++ 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 && +@@ -1068,7 +1112,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) + { +@@ -1091,19 +1135,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; +@@ -1112,13 +1158,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; + } + +@@ -1126,7 +1173,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; +@@ -1149,13 +1196,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)) +@@ -1230,14 +1277,42 @@ 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: ++ 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", ++ 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; + } + + +@@ -1289,7 +1364,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 d1d3e72..e9f193a 100644 +--- a/bus/policy.h ++++ b/bus/policy.h +@@ -39,6 +39,14 @@ typedef enum + BUS_POLICY_RULE_GROUP + } BusPolicyRuleType; + ++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)) +@@ -49,8 +57,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 +@@ -106,7 +115,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); + +@@ -140,21 +149,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, +- BusRegistry *registry, +- dbus_bool_t requested_reply, +- DBusConnection *receiver, +- DBusMessage *message, +- dbus_int32_t *toggles, +- dbus_bool_t *log); +-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_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); ++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); + 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 eb803af..b131f30 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1748,6 +1748,18 @@ if test "x$enable_stats" = xyes; then + [Define to enable bus daemon usage statistics]) + fi + ++#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/versioninfo.rc +@@ -1778,6 +1790,7 @@ dbus-1.pc + dbus-1-uninstalled.pc + test/data/valid-config-files/debug-allow-all.conf + test/data/valid-config-files/debug-allow-all-sha1.conf ++test/data/valid-config-files/debug-check-some.conf + test/data/valid-config-files/incoming-limit.conf + test/data/valid-config-files-system/debug-allow-all-pass.conf + test/data/valid-config-files-system/debug-allow-all-fail.conf +diff --git a/test/Makefile.am b/test/Makefile.am +index e0ed3c8..ab63edc 100644 +--- a/test/Makefile.am ++++ b/test/Makefile.am +@@ -254,6 +254,7 @@ in_data = \ + data/valid-config-files-system/debug-allow-all-pass.conf.in \ + data/valid-config-files/debug-allow-all-sha1.conf.in \ + data/valid-config-files/debug-allow-all.conf.in \ ++ data/valid-config-files/debug-check-some.conf.in \ + data/valid-config-files/incoming-limit.conf.in \ + data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoExec.service.in \ + data/invalid-service-files-system/org.freedesktop.DBus.TestSuiteNoService.service.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.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch b/meta-security/recipes-core/dbus/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch new file mode 100644 index 000000000..ca787149e --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0005-Disable-message-dispatching-when-send-rule-result-is.patch @@ -0,0 +1,941 @@ +From b1b87ad9f20b2052c28431b48e81073078a745ce 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 5/8] Disable message dispatching when send rule result is not + known + +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. + +Change-Id: I57eccbf973525fd51369c7d4e58908292f44da80 +--- + bus/activation.c | 79 +++++++++++++++-- + bus/check.c | 109 ++++++++++++++++++++++-- + bus/check.h | 10 +++ + bus/cynara.c | 1 - + bus/dispatch.c | 183 ++++++++++++++++++++++++++++++++++++---- + bus/dispatch.h | 2 +- + bus/driver.c | 13 ++- + dbus/dbus-connection-internal.h | 9 ++ + dbus/dbus-connection.c | 125 +++++++++++++++++++++++++-- + dbus/dbus-list.c | 29 +++++++ + dbus/dbus-list.h | 2 + + dbus/dbus-shared.h | 3 +- + 12 files changed, 522 insertions(+), 43 deletions(-) + +diff --git a/bus/activation.c b/bus/activation.c +index ecd19bb..8c43941 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -31,6 +31,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> +@@ -91,6 +92,8 @@ struct BusPendingActivationEntry + DBusConnection *connection; + + dbus_bool_t auto_activation; ++ ++ dbus_bool_t is_put_back; + }; + + typedef struct +@@ -1180,20 +1183,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 +@@ -1205,9 +1211,40 @@ bus_activation_send_pending_auto_activation_messages (BusActivation *activation + bus_connection_send_oom_error (entry->connection, + entry->activation_message); + } ++ } ++ 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; ++ } + +- 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); ++ } + } + } + +@@ -1225,6 +1262,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; + } + +@@ -2009,13 +2059,24 @@ 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'", + service_name, + entry->systemd_service); + /* Wonderful, systemd is connected, let's just send the msg */ +- retval = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), +- message, error); ++ res = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), ++ message, error); ++ ++ if (res == BUS_RESULT_TRUE) ++ retval = TRUE; ++ else if (res == BUS_RESULT_FALSE) ++ retval = FALSE; ++ else if (res == BUS_RESULT_LATER) ++ { ++ _dbus_verbose("Unexpectedly need time to check message from bus driver to systemd - dropping the message.\n"); ++ retval = FALSE; ++ } + } + else + { +diff --git a/bus/check.c b/bus/check.c +index d2f418a..cd6a74b 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 ++dbus_bool_t (*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; + BusCynara *cynara; + DBusConnection *connection; +@@ -135,16 +186,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; + } +@@ -204,6 +293,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..f381789 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 dbus_bool_t (*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 ce4076d..6b0eadc 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -81,7 +81,7 @@ send_one_message (DBusConnection *connection, + return TRUE; + } + +-dbus_bool_t ++BusResult + bus_dispatch_matches (BusTransaction *transaction, + DBusConnection *sender, + DBusConnection *addressed_recipient, +@@ -117,13 +117,29 @@ bus_dispatch_matches (BusTransaction *transaction, + message, 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) && +@@ -134,14 +150,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; + } + } + +@@ -156,7 +172,7 @@ bus_dispatch_matches (BusTransaction *transaction, + &recipients)) + { + BUS_SET_OOM (error); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + link = _dbus_list_get_first_link (&recipients); +@@ -178,10 +194,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 +@@ -298,10 +314,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; + } + +@@ -366,8 +384,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)) +@@ -4714,9 +4738,132 @@ bus_dispatch_test_conf_fail (const DBusString *test_data_dir, + return TRUE; + } + ++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 dbus_bool_t ++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_all (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 11706f8..4dbce3d 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -97,6 +97,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); +@@ -129,7 +130,17 @@ bus_driver_send_service_owner_changed (const char *service_name, + + _dbus_assert (dbus_message_has_signature (message, "sss")); + +- 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 if (res == BUS_RESULT_FALSE) ++ retval = FALSE; ++ else if (res == BUS_RESULT_LATER) ++ { ++ /* should never happen */ ++ _dbus_assert_not_reached ("bus_dispatch_matches returned BUS_RESULT_LATER unexpectedly"); ++ retval = FALSE; ++ } + dbus_message_unref (message); + + return retval; +diff --git a/dbus/dbus-connection-internal.h b/dbus/dbus-connection-internal.h +index 64ef336..4fcd118 100644 +--- a/dbus/dbus-connection-internal.h ++++ b/dbus/dbus-connection-internal.h +@@ -109,6 +109,15 @@ void _dbus_connection_set_pending_fds_function (DBusConnectio + + dbus_bool_t _dbus_connection_get_linux_security_label (DBusConnection *connection, + char **label_p); ++void _dbus_connection_enable_dispatch (DBusConnection *connection); ++void _dbus_connection_disable_dispatch (DBusConnection *connection); ++dbus_bool_t _dbus_connection_putback_message (DBusConnection *connection, ++ DBusMessage *after_message, ++ DBusMessage *message, ++ DBusError *error); ++ ++dbus_bool_t _dbus_connection_remove_message (DBusConnection *connection, ++ DBusMessage *message); + + /* if DBUS_ENABLE_STATS */ + void _dbus_connection_get_stats (DBusConnection *connection, +diff --git a/dbus/dbus-connection.c b/dbus/dbus-connection.c +index 8952b75..5d8d943 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 +@@ -4068,6 +4102,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 +@@ -4251,8 +4361,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(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; +@@ -4689,6 +4800,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"); +@@ -4811,9 +4924,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 c4c1856..f84918b 100644 +--- a/dbus/dbus-list.c ++++ b/dbus/dbus-list.c +@@ -459,6 +459,35 @@ _dbus_list_remove_last (DBusList **list, + } + + /** ++ * 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. + * This is a linear-time operation. +diff --git a/dbus/dbus-list.h b/dbus/dbus-list.h +index 910d738..abe8331 100644 +--- a/dbus/dbus-list.h ++++ b/dbus/dbus-list.h +@@ -59,6 +59,8 @@ dbus_bool_t _dbus_list_remove_last (DBusList **list, + void *data); + void _dbus_list_remove_link (DBusList **list, + DBusList *link); ++DBusList* _dbus_list_find_first (DBusList **list, ++ void *data); + DBusList* _dbus_list_find_last (DBusList **list, + void *data); + void _dbus_list_clear (DBusList **list); +diff --git a/dbus/dbus-shared.h b/dbus/dbus-shared.h +index 6a57670..5371d88 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.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch b/meta-security/recipes-core/dbus/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch new file mode 100644 index 000000000..66f4e14e5 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0006-Handle-unavailability-of-policy-results-for-broadcas.patch @@ -0,0 +1,1071 @@ +From 1e231194610892dd4360224998d91336097b05a1 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 6/8] Handle unavailability of policy results for broadcasts + and receive rules + +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. + +Change-Id: Iecd5395f75a4c7811fa97247a37d8fc4d42e8814 +--- + bus/activation.c | 4 +- + bus/bus.c | 50 +++++++-- + bus/bus.h | 19 ++++ + bus/check.c | 307 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ + bus/check.h | 25 +++++ + bus/connection.c | 166 ++++++++++++++++++++++++++++-- + bus/connection.h | 19 +++- + bus/dispatch.c | 122 ++++++++++++++++++---- + bus/dispatch.h | 11 +- + bus/driver.c | 2 +- + bus/policy.c | 6 ++ + 11 files changed, 685 insertions(+), 46 deletions(-) + +diff --git a/bus/activation.c b/bus/activation.c +index 8c43941..308bf41 100644 +--- a/bus/activation.c ++++ b/bus/activation.c +@@ -1198,7 +1198,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 +@@ -2066,7 +2066,7 @@ bus_activation_activate_service (BusActivation *activation, + entry->systemd_service); + /* Wonderful, systemd is connected, let's just send the msg */ + res = bus_dispatch_matches (activation_transaction, NULL, bus_service_get_primary_owners_connection (service), +- message, error); ++ message, NULL, error); + + if (res == BUS_RESULT_TRUE) + retval = TRUE; +diff --git a/bus/bus.c b/bus/bus.c +index ac9ea8d..b478b8e 100644 +--- a/bus/bus.c ++++ b/bus/bus.c +@@ -1704,17 +1704,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 +@@ -1769,3 +1761,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 78084dd..27a5e49 100644 +--- a/bus/bus.h ++++ b/bus/bus.h +@@ -148,4 +148,23 @@ BusResult bus_context_check_security_policy (BusContext + DBusError *error, + BusDeferredMessage **deferred_message); + ++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 cd6a74b..733763a 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; +@@ -136,6 +139,89 @@ bus_check_enable_dispatch_callback (BusDeferredMessage *deferred_message, + } + + 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) + { + BusDeferredMessage *deferred_message = (BusDeferredMessage *)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 + dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, + const char *privilege); +@@ -257,6 +357,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; +@@ -293,12 +396,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, ++ &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) +@@ -308,3 +614,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 f381789..3c6b2a1 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 dbus_bool_t (*bus_check_test_override) (DBusConnection *connection, + const char *privilege); +diff --git a/bus/connection.c b/bus/connection.c +index a6d87e5..d2ebe82 100644 +--- a/bus/connection.c ++++ b/bus/connection.c +@@ -30,10 +30,12 @@ + #include "signals.h" + #include "expirelist.h" + #include "selinux.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-message-internal.h> + #ifdef DBUS_ENABLE_CYNARA + #include <stdlib.h> + #include <cynara-session.h> +@@ -95,6 +97,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; +@@ -256,6 +259,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 */ +@@ -2132,6 +2137,7 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + DBusMessage *message) + { + 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 + * dispatch.c +@@ -2163,23 +2169,25 @@ bus_transaction_send_from_driver (BusTransaction *transaction, + res = bus_context_check_security_policy (bus_transaction_get_context (transaction), + transaction, + NULL, connection, connection, message, NULL, +- NULL); ++ &deferred_message); + + if (res == BUS_RESULT_FALSE) + return TRUE; + else if (res == BUS_RESULT_LATER) + { +- _dbus_verbose ("Cannot delay sending message from bus driver, dropping it\n"); +- 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; +@@ -2205,7 +2213,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) + { +@@ -2457,6 +2486,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 7433746..8d49b25 100644 +--- a/bus/connection.h ++++ b/bus/connection.h +@@ -82,6 +82,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); +@@ -129,7 +145,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_send_from_driver (BusTransaction *transaction, + DBusConnection *connection, + DBusMessage *message); +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 6b0eadc..9972e76 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -33,8 +33,10 @@ + #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> + #include <dbus/dbus-misc.h> + #include <string.h> + +@@ -63,16 +65,26 @@ send_one_message (DBusConnection *connection, + result = bus_context_check_security_policy (context, transaction, sender, addressed_recipient, + connection, message, NULL, &deferred_message); + +- if (result != BUS_RESULT_TRUE) ++ if (result == BUS_RESULT_FALSE) + return TRUE; /* silently don't send it */ + + if (dbus_message_contains_unix_fds(message) && + !dbus_connection_can_send_type(connection, DBUS_TYPE_UNIX_FD)) + return TRUE; /* silently don't send it */ + ++ 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; +@@ -82,11 +94,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; +@@ -110,17 +123,78 @@ bus_dispatch_matches (BusTransaction *transaction, + /* First, send the message to the addressed_recipient, if there is one. */ + if (addressed_recipient != NULL) + { +- BusResult res; +- res = bus_context_check_security_policy (context, transaction, +- sender, addressed_recipient, +- addressed_recipient, +- message, error, +- &deferred_message); +- if (res == BUS_RESULT_FALSE) ++ 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, error, ++ &deferred_message); ++ ++ 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) +@@ -131,13 +205,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; + } + } +@@ -154,7 +233,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; +@@ -385,7 +465,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 4dbce3d..2fb1385 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -130,7 +130,7 @@ bus_driver_send_service_owner_changed (const char *service_name, + + _dbus_assert (dbus_message_has_signature (message, "sss")); + +- 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 if (res == BUS_RESULT_FALSE) +diff --git a/bus/policy.c b/bus/policy.c +index ec888df..448147f 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -1071,6 +1071,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; +@@ -1305,6 +1308,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.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch b/meta-security/recipes-core/dbus/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch new file mode 100644 index 000000000..e1b1e62f1 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0007-Add-own-rule-result-unavailability-handling.patch @@ -0,0 +1,1142 @@ +From 35ef89cd6777ea2430077fc621d21bd01df92349 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 7/8] Add own rule result unavailability handling + +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. + +Change-Id: I4c2cbd4585e41fccd8a30f825a8f0d342ab56755 +--- + bus/dispatch.c | 11 ++- + bus/driver.c | 227 ++++++++++++++++++++++++++++++--------------------------- + bus/driver.h | 2 +- + bus/policy.c | 51 ++++++++++--- + bus/policy.h | 6 +- + bus/services.c | 26 +++++-- + bus/services.h | 3 +- + bus/stats.c | 16 ++-- + 8 files changed, 204 insertions(+), 138 deletions(-) + +diff --git a/bus/dispatch.c b/bus/dispatch.c +index 9972e76..d3b970f 100644 +--- a/bus/dispatch.c ++++ b/bus/dispatch.c +@@ -404,8 +404,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 2fb1385..9708f49 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -297,7 +297,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, +@@ -305,7 +305,7 @@ bus_driver_handle_hello (DBusConnection *connection, + { + DBusString unique_name; + BusService *service; +- dbus_bool_t retval; ++ BusResult retval; + BusRegistry *registry; + BusConnections *connections; + +@@ -316,7 +316,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 +@@ -330,16 +330,16 @@ bus_driver_handle_hello (DBusConnection *connection, + error)) + { + _DBUS_ASSERT_ERROR_IS_SET (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); + +@@ -372,7 +372,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); +@@ -424,7 +424,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, +@@ -446,14 +446,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); +@@ -465,7 +465,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; + } + + { +@@ -477,7 +477,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; + } + } + +@@ -490,7 +490,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; + } +@@ -501,23 +501,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, +@@ -539,14 +539,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); +@@ -558,7 +558,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; + } + + { +@@ -570,7 +570,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; + } + } + +@@ -583,7 +583,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; + } +@@ -594,23 +594,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, +@@ -621,7 +621,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); +@@ -632,20 +633,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) +@@ -666,7 +671,7 @@ bus_driver_handle_acquire_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -674,7 +679,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, +@@ -684,7 +689,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); +@@ -694,11 +699,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); +@@ -727,7 +732,7 @@ bus_driver_handle_release_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -735,7 +740,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, +@@ -746,7 +751,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); +@@ -756,9 +761,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) + { +@@ -792,7 +797,7 @@ bus_driver_handle_service_exists (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + if (reply) +@@ -801,7 +806,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, +@@ -809,7 +814,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); +@@ -823,10 +828,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)) +@@ -836,7 +841,7 @@ bus_driver_handle_activate_service (DBusConnection *connection, + goto out; + } + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + return retval; +@@ -872,13 +877,13 @@ send_ack_reply (DBusConnection *connection, + 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; + DBusMessageIter iter; + DBusMessageIter dict_iter; +@@ -939,7 +944,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + + dbus_message_iter_recurse (&iter, &dict_iter); + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + /* Then loop through the sent dictionary, add the location of + * the environment keys and values to lists. The result will +@@ -1026,7 +1031,7 @@ bus_driver_handle_update_activation_environment (DBusConnection *connection, + message, error)) + goto out; + +- retval = TRUE; ++ retval = BUS_RESULT_TRUE; + + out: + _dbus_list_clear (&keys); +@@ -1034,7 +1039,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, +@@ -1093,16 +1098,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, +@@ -1146,16 +1151,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, +@@ -1225,7 +1230,7 @@ bus_driver_handle_get_service_owner (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1234,10 +1239,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, +@@ -1328,7 +1333,7 @@ bus_driver_handle_list_queued_owners (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1341,10 +1346,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, +@@ -1389,7 +1394,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); +@@ -1398,10 +1403,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, +@@ -1446,7 +1451,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); +@@ -1455,10 +1460,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, +@@ -1502,7 +1507,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); +@@ -1511,10 +1516,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, +@@ -1556,7 +1561,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); +@@ -1565,10 +1570,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, +@@ -1645,7 +1650,7 @@ bus_driver_handle_get_connection_credentials (DBusConnection *connection, + + dbus_message_unref (reply); + +- return TRUE; ++ return BUS_RESULT_TRUE; + + oom: + BUS_SET_OOM (error); +@@ -1659,10 +1664,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, +@@ -1687,7 +1692,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); +@@ -1696,10 +1701,10 @@ 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; + } + +-static dbus_bool_t ++static BusResult + bus_driver_handle_get_id (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -1715,7 +1720,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; +@@ -1741,7 +1746,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); +@@ -1751,7 +1756,7 @@ bus_driver_handle_get_id (DBusConnection *connection, + if (reply) + dbus_message_unref (reply); + _dbus_string_free (&uuid); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + typedef struct +@@ -1759,10 +1764,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); + } MessageHandler; + + /* For speed it might be useful to sort this in order of +@@ -1847,7 +1852,7 @@ static const MessageHandler dbus_message_handlers[] = { + { NULL, 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 introspectable_message_handlers[] = { +@@ -1973,7 +1978,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, +@@ -1993,13 +1998,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; + } + + if (!bus_driver_generate_introspect_string (&xml)) +@@ -2022,7 +2027,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); +@@ -2032,7 +2037,7 @@ bus_driver_handle_introspect (DBusConnection *connection, + + _dbus_string_free (&xml); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + /* +@@ -2067,7 +2072,7 @@ bus_driver_check_message_is_for_us (DBusMessage *message, + return TRUE; + } + +-dbus_bool_t ++BusResult + bus_driver_handle_message (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -2077,6 +2082,7 @@ bus_driver_handle_message (DBusConnection *connection, + const InterfaceHandler *ih; + const MessageHandler *mh; + dbus_bool_t found_interface = FALSE; ++ BusResult res; + + _DBUS_ASSERT_ERROR_IS_CLEAR (error); + +@@ -2085,13 +2091,13 @@ bus_driver_handle_message (DBusConnection *connection, + BusContext *context; + + context = bus_connection_get_context (connection); +- 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" */ +@@ -2133,20 +2139,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; + } + } + } +@@ -2158,7 +2171,7 @@ bus_driver_handle_message (DBusConnection *connection, + "%s does not understand message %s", + DBUS_SERVICE_DBUS, name); + +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + void +diff --git a/bus/driver.h b/bus/driver.h +index 201709c..3ff4ff1 100644 +--- a/bus/driver.h ++++ b/bus/driver.h +@@ -28,7 +28,7 @@ + #include "connection.h" + + 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 448147f..3672ff9 100644 +--- a/bus/policy.c ++++ b/bus/policy.c +@@ -1323,18 +1323,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) + { +@@ -1370,17 +1373,45 @@ 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; ++ 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 +@@ -1388,7 +1419,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); + } + #endif /* DBUS_ENABLE_EMBEDDED_TESTS */ + +diff --git a/bus/policy.h b/bus/policy.h +index e9f193a..1f23431 100644 +--- a/bus/policy.h ++++ b/bus/policy.h +@@ -170,8 +170,10 @@ BusResult bus_client_policy_check_can_receive (BusClientPolicy *polic + 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 584485b..f25fdf3 100644 +--- a/bus/services.c ++++ b/bus/services.c +@@ -374,24 +374,26 @@ 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; + BusActivation *activation; + BusSELinuxID *sid; + BusOwner *primary_owner; ++ BusResult res; + +- retval = FALSE; ++ retval = BUS_RESULT_FALSE; + + if (!_dbus_validate_bus_name (service_name, 0, + _dbus_string_get_length (service_name))) +@@ -459,7 +461,8 @@ bus_registry_acquire_service (BusRegistry *registry, + 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 " +@@ -470,6 +473,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; ++ } + + if (bus_connection_get_n_services_owned (connection) >= + bus_context_get_max_services_per_connection (registry->context)) +@@ -586,11 +594,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 20321e5..61dc428 100644 +--- a/bus/stats.c ++++ b/bus/stats.c +@@ -35,7 +35,7 @@ + + #ifdef DBUS_ENABLE_STATS + +-dbus_bool_t ++BusResult + bus_stats_handle_get_stats (DBusConnection *connection, + BusTransaction *transaction, + DBusMessage *message, +@@ -106,17 +106,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, +@@ -143,7 +143,7 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, + if (! dbus_message_get_args (message, error, + DBUS_TYPE_STRING, &bus_name, + DBUS_TYPE_INVALID)) +- return FALSE; ++ return BUS_RESULT_FALSE; + + _dbus_string_init_const (&bus_name_str, bus_name); + service = bus_registry_lookup (registry, &bus_name_str); +@@ -152,7 +152,7 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_connection, + { + dbus_set_error (error, DBUS_ERROR_NAME_HAS_NO_OWNER, + "Bus name '%s' has no owner", bus_name); +- return FALSE; ++ return BUS_RESULT_FALSE; + } + + stats_connection = bus_service_get_primary_owners_connection (service); +@@ -214,14 +214,14 @@ bus_stats_handle_get_connection_stats (DBusConnection *caller_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; + } + + #endif +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch b/meta-security/recipes-core/dbus/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch new file mode 100644 index 000000000..43a1ef658 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch @@ -0,0 +1,99 @@ +From 6c9997fb1cdff4281166e8c2fb8276018b1025dd Mon Sep 17 00:00:00 2001 +From: Jacek Bukarewicz <j.bukarewicz@samsung.com> +Date: Mon, 15 Jun 2015 11:46:47 +0200 +Subject: [PATCH 8/8] Add "GetConnectionSmackContext" D-Bus daemon method + +This method is used to obtain smack label of given D-Bus client. +Note that it is deprecated and is included only for compatilibity with +existing D-Bus users. GetConnectionCredentials should be used to obtain +client's credentials. + +Change-Id: Idf9648032ca5cbd9605ffab055e6384baa4eb9b4 +--- + bus/driver.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 63 insertions(+) + +diff --git a/bus/driver.c b/bus/driver.c +index 9708f49..4e76224 100644 +--- a/bus/driver.c ++++ b/bus/driver.c +@@ -1759,6 +1759,65 @@ bus_driver_handle_get_id (DBusConnection *connection, + return BUS_RESULT_FALSE; + } + ++static BusResult ++bus_driver_handle_get_connection_smack_context (DBusConnection *connection, ++ BusTransaction *transaction, ++ DBusMessage *message, ++ DBusError *error) ++{ ++ DBusConnection *conn; ++ DBusMessage *reply = NULL; ++ char *label = NULL; ++ const char *service; ++ ++ _DBUS_ASSERT_ERROR_IS_CLEAR (error); ++ ++ conn = bus_driver_get_conn_helper (connection, message, "credentials", ++ &service, error); ++ if (conn == NULL) ++ goto err; ++ ++ reply = dbus_message_new_method_return (message); ++ if (reply == NULL) ++ goto oom; ++ ++ if (!_dbus_connection_get_linux_security_label (conn, &label)) ++ { ++ dbus_set_error (error, DBUS_ERROR_FAILED, ++ "Failed to get smack label of connection", ++ conn); ++ goto err; ++ } ++ ++ if (label == NULL) ++ goto oom; ++ ++ if (!dbus_message_append_args (reply, ++ DBUS_TYPE_STRING, &label, ++ DBUS_TYPE_INVALID)) ++ goto oom; ++ ++ if (!bus_transaction_send_from_driver (transaction, connection, reply)) ++ goto oom; ++ ++ dbus_message_unref (reply); ++ dbus_free(label); ++ ++ return BUS_RESULT_TRUE; ++ ++oom: ++ BUS_SET_OOM (error); ++ ++err: ++ if (reply != NULL) ++ dbus_message_unref (reply); ++ ++ dbus_free(label); ++ ++ return BUS_RESULT_FALSE; ++} ++ ++ + typedef struct + { + const char *name; +@@ -1849,6 +1908,10 @@ static const MessageHandler dbus_message_handlers[] = { + bus_driver_handle_get_id }, + { "GetConnectionCredentials", "s", "a{sv}", + bus_driver_handle_get_connection_credentials }, ++ { "GetConnectionSmackContext", /* deprecated - you should use GetConnectionCredentials instead */ ++ DBUS_TYPE_STRING_AS_STRING, ++ DBUS_TYPE_STRING_AS_STRING, ++ bus_driver_handle_get_connection_smack_context }, + { NULL, NULL, NULL, NULL } + }; + +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch b/meta-security/recipes-core/dbus/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch new file mode 100644 index 000000000..e573fb3b3 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara/Perform-Cynara-runtime-policy-checks-by-default.patch @@ -0,0 +1,116 @@ +From e8610297cf7031e94eb314a2e8c11246f4405403 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] Perform Cynara runtime policy checks by default + +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. + +Change-Id: Ifb4a160bf6e0638404e0295a2e4fa3077efd881c +Signed-off-by: Jacek Bukarewicz <j.bukarewicz@samsung.com> +--- + bus/session.conf.in | 32 ++++++++++++++++++++++++++------ + bus/system.conf.in | 22 ++++++++++++++++------ + 2 files changed, 42 insertions(+), 12 deletions(-) + +diff --git a/bus/session.conf.in b/bus/session.conf.in +index 74d9d1f..fa5c232 100644 +--- a/bus/session.conf.in ++++ b/bus/session.conf.in +@@ -17,12 +17,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> + + <!-- Config files are placed here that among other things, +diff --git a/bus/system.conf.in b/bus/system.conf.in +index 92f4cc4..dd16947 100644 +--- a/bus/system.conf.in ++++ b/bus/system.conf.in +@@ -50,21 +50,31 @@ + <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 --> ++ <!-- 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 send_destination="org.freedesktop.DBus"/> +- <!-- But disallow some specific bus services --> ++ <allow receive_sender="org.freedesktop.DBus"/> ++ ++ <!-- Disallow some specific bus services --> + <deny send_destination="org.freedesktop.DBus" + send_interface="org.freedesktop.DBus" + send_member="UpdateActivationEnvironment"/> +-- +2.1.4 + diff --git a/meta-security/recipes-core/dbus/dbus-cynara_1.8.18.bb b/meta-security/recipes-core/dbus/dbus-cynara_1.8.18.bb new file mode 100644 index 000000000..bcff737cd --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-cynara_1.8.18.bb @@ -0,0 +1,58 @@ +require dbus-oe-core.inc +FILESEXTRAPATHS_prepend := "${COREBASE}/meta/recipes-core/dbus/dbus:${THISDIR}/dbus-cynara:" +S = "${WORKDIR}/dbus-${PV}" +libexecdir = "${libdir}/dbus" + +SRC_URI[md5sum] = "83e607e9ccb1c921d5b6bbea2376a36c" +SRC_URI[sha256sum] = "36f2eb9c777a3c71562573da36a147e900a642afcd44d2b0470d992a4898c4f2" + +# From https://review.tizen.org/gerrit/#/admin/projects/platform/upstream/dbus +# revision 6c9997fb1cdff4281166e8c2fb8276018b1025dd +# aka https://review.tizen.org/git/?p=platform%2Fupstream%2Fdbus.git;a=shortlog;h=refs%2Fheads%2Fsandbox%2Fjacekbe%2Fupgrade +# as announced in https://bugs.tizen.org/jira/browse/TC-2520 "D-Bus: local denial of service attack" +SRC_URI += " \ +file://0001-Fix-memleak-in-GetConnectionCredentials-handler.patch \ +file://0002-New-a-sv-helper-for-using-byte-arrays-as-the-variant.patch \ +file://0003-Add-LSM-agnostic-support-for-LinuxSecurityLabel-cred.patch \ +file://0004-Integration-of-Cynara-asynchronous-security-checks.patch \ +file://0005-Disable-message-dispatching-when-send-rule-result-is.patch \ +file://0006-Handle-unavailability-of-policy-results-for-broadcas.patch \ +file://0007-Add-own-rule-result-unavailability-handling.patch \ +" + +# Provides a legacy API which shouldn't be used in new code. It is +# still needed at the moment because cynara helper methods call it +# (creds-dbus-inner.cpp, creds-gdbus.cpp). +SRC_URI += "file://0008-Add-GetConnectionSmackContext-D-Bus-daemon-method.patch" + +# Depends on special Cynara rules which get installed in the +# security-manager-policy package. From patch set 5 in: +# https://review.tizen.org/gerrit/#/c/31310/ +SRC_URI += "file://Perform-Cynara-runtime-policy-checks-by-default.patch" + +DEPENDS += "cynara smack" +EXTRA_OECONF += "--enable-cynara" + +inherit distro_features_check +REQUIRED_DISTRO_FEATURES += "smack" + +# Only the main package gets created here, everything else remains in the +# normal dbus recipe. +do_install_append () { + for i in ${@' '.join([d.getVar('D', True) + x for x in (' '.join([d.getVar('FILES_${PN}-' + p, True) or '' for p in ['lib', 'dev', 'staticdev', 'doc', 'locale', 'ptest']])).split()])}; do + rm -rf $i + done + + # Try to remove empty directories, starting with the + # longest path (= deepest directory) first. + # Find needs a valid current directory. Somehow the directory + # we get called in is gone by the time that we get invoked. + ( cd ${D} + for i in `find . -type d | sort -r`; do + rmdir $i || true + done + ) +} + +# Avoid warning about dbus and dbus-cynara providing dbus-x11. +RPROVIDES_${PN}_remove = "${OLDPKGNAME}" diff --git a/meta-security/recipes-core/dbus/dbus-oe-core.inc b/meta-security/recipes-core/dbus/dbus-oe-core.inc new file mode 100644 index 000000000..3971081fd --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus-oe-core.inc @@ -0,0 +1,170 @@ +SUMMARY = "D-Bus message bus" +DESCRIPTION = "D-Bus is a message bus system, a simple way for applications to talk to one another. In addition to interprocess communication, D-Bus helps coordinate process lifecycle; it makes it simple and reliable to code a \"single instance\" application or daemon, and to launch applications and daemons on demand when their services are needed." +HOMEPAGE = "http://dbus.freedesktop.org" +SECTION = "base" +LICENSE = "AFL-2 | GPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=10dded3b58148f3f1fd804b26354af3e \ + file://dbus/dbus.h;beginline=6;endline=20;md5=7755c9d7abccd5dbd25a6a974538bb3c" +DEPENDS = "expat virtual/libintl" +RDEPENDS_dbus_class-native = "" +RDEPENDS_dbus_class-nativesdk = "" +PACKAGES += "${@bb.utils.contains('DISTRO_FEATURES', 'ptest', '${PN}-ptest', '', d)}" +ALLOW_EMPTY_dbus-ptest = "1" +RDEPENDS_dbus-ptest_class-target = "dbus-test-ptest" + +SRC_URI = "http://dbus.freedesktop.org/releases/dbus/dbus-${PV}.tar.gz \ + file://tmpdir.patch \ + file://dbus-1.init \ + file://os-test.patch \ + file://clear-guid_from_server-if-send_negotiate_unix_f.patch \ +" + +inherit useradd autotools pkgconfig gettext update-rc.d + +INITSCRIPT_NAME = "dbus-1" +INITSCRIPT_PARAMS = "start 02 5 3 2 . stop 20 0 1 6 ." + +python __anonymous() { + if not bb.utils.contains('DISTRO_FEATURES', 'sysvinit', True, False, d): + d.setVar("INHIBIT_UPDATERCD_BBCLASS", "1") +} + +USERADD_PACKAGES = "${PN}" +GROUPADD_PARAM_${PN} = "-r netdev" +USERADD_PARAM_${PN} = "--system --home ${localstatedir}/lib/dbus \ + --no-create-home --shell /bin/false \ + --user-group messagebus" + +CONFFILES_${PN} = "${sysconfdir}/dbus-1/system.conf ${sysconfdir}/dbus-1/session.conf" + +DEBIANNAME_${PN} = "dbus-1" + +PACKAGES =+ "${PN}-lib" + +OLDPKGNAME = "dbus-x11" +OLDPKGNAME_class-nativesdk = "" + +# for compatibility +RPROVIDES_${PN} = "${OLDPKGNAME}" +RREPLACES_${PN} += "${OLDPKGNAME}" + +FILES_${PN} = "${bindir}/dbus-daemon* \ + ${bindir}/dbus-uuidgen \ + ${bindir}/dbus-cleanup-sockets \ + ${bindir}/dbus-send \ + ${bindir}/dbus-monitor \ + ${bindir}/dbus-launch \ + ${bindir}/dbus-run-session \ + ${libexecdir}/dbus* \ + ${sysconfdir} \ + ${localstatedir} \ + ${datadir}/dbus-1/services \ + ${datadir}/dbus-1/system-services \ + ${systemd_unitdir}/system/" +FILES_${PN}-lib = "${libdir}/lib*.so.*" +RRECOMMENDS_${PN}-lib = "${PN}" +FILES_${PN}-dev += "${libdir}/dbus-1.0/include ${bindir}/dbus-glib-tool" + +pkg_postinst_dbus() { + # If both systemd and sysvinit are enabled, mask the dbus-1 init script + if ${@bb.utils.contains('DISTRO_FEATURES','systemd sysvinit','true','false',d)}; then + if [ -n "$D" ]; then + OPTS="--root=$D" + fi + systemctl $OPTS mask dbus-1.service + fi + + if [ -z "$D" ] && [ -e /etc/init.d/populate-volatile.sh ] ; then + /etc/init.d/populate-volatile.sh update + fi +} + +EXTRA_OECONF = "--disable-tests \ + --disable-xml-docs \ + --disable-doxygen-docs \ + --disable-libaudit \ + --disable-systemd \ + --without-dbus-glib" + +EXTRA_OECONF_append_class-native = " --disable-selinux" + +PACKAGECONFIG ??= "${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'systemd', '', d)} \ + ${@bb.utils.contains('DISTRO_FEATURES', 'x11', 'x11', '', d)}" +PACKAGECONFIG_class-native = "" +PACKAGECONFIG_class-nativesdk = "" + +# Would like to --enable-systemd but that's a circular build-dependency between +# systemd<->dbus +PACKAGECONFIG[systemd] = "--with-systemdsystemunitdir=${systemd_unitdir}/system/,--without-systemdsystemunitdir" +PACKAGECONFIG[x11] = "--with-x --enable-x11-autolaunch,--without-x --disable-x11-autolaunch, virtual/libx11 libsm" + +do_install() { + autotools_do_install + + if ${@bb.utils.contains('DISTRO_FEATURES', 'sysvinit', 'true', 'false', d)}; then + install -d ${D}${sysconfdir}/init.d + sed 's:@bindir@:${bindir}:' < ${WORKDIR}/dbus-1.init >${WORKDIR}/dbus-1.init.sh + install -m 0755 ${WORKDIR}/dbus-1.init.sh ${D}${sysconfdir}/init.d/dbus-1 + fi + + if ${@bb.utils.contains('DISTRO_FEATURES', 'systemd', 'true', 'false', d)}; then + for i in dbus.target.wants sockets.target.wants multi-user.target.wants; do \ + install -d ${D}${systemd_unitdir}/system/$i; done + install -m 0644 ${B}/bus/dbus.service ${B}/bus/dbus.socket ${D}${systemd_unitdir}/system/ + cd ${D}${systemd_unitdir}/system/dbus.target.wants/ + ln -fs ../dbus.socket ${D}${systemd_unitdir}/system/dbus.target.wants/dbus.socket + ln -fs ../dbus.socket ${D}${systemd_unitdir}/system/sockets.target.wants/dbus.socket + ln -fs ../dbus.service ${D}${systemd_unitdir}/system/multi-user.target.wants/dbus.service + fi + + install -d ${D}${sysconfdir}/default/volatiles + echo "d messagebus messagebus 0755 ${localstatedir}/run/dbus none" \ + > ${D}${sysconfdir}/default/volatiles/99_dbus + + + mkdir -p ${D}${localstatedir}/lib/dbus + + chown messagebus:messagebus ${D}${localstatedir}/lib/dbus + + chown root:messagebus ${D}${libexecdir}/dbus-daemon-launch-helper + chmod 4755 ${D}${libexecdir}/dbus-daemon-launch-helper + + # Remove Red Hat initscript + rm -rf ${D}${sysconfdir}/rc.d + + # Remove empty testexec directory as we don't build tests + rm -rf ${D}${libdir}/dbus-1.0/test + + # Remove /var/run as it is created on startup + rm -rf ${D}${localstatedir}/run +} + +do_install_class-native() { + autotools_do_install + + # for dbus-glib-native introspection generation + install -d ${D}${STAGING_DATADIR_NATIVE}/dbus/ + # N.B. is below install actually required? + install -m 0644 bus/session.conf ${D}${STAGING_DATADIR_NATIVE}/dbus/session.conf + + # dbus-glib-native and dbus-glib need this xml file + ./bus/dbus-daemon --introspect > ${D}${STAGING_DATADIR_NATIVE}/dbus/dbus-bus-introspect.xml + + # dbus-launch has no X support so lets not install it in case the host + # has a more featured and useful version + rm -f ${D}${bindir}/dbus-launch +} + +do_install_class-nativesdk() { + autotools_do_install + + # dbus-launch has no X support so lets not install it in case the host + # has a more featured and useful version + rm -f ${D}${bindir}/dbus-launch + + # Remove /var/run to avoid QA error + rm -rf ${D}${localstatedir}/run +} +BBCLASSEXTEND = "native nativesdk" + +INSANE_SKIP_${PN}-ptest += "build-deps" diff --git a/meta-security/recipes-core/dbus/dbus_%.bbappend b/meta-security/recipes-core/dbus/dbus_%.bbappend new file mode 100644 index 000000000..e352b4d05 --- /dev/null +++ b/meta-security/recipes-core/dbus/dbus_%.bbappend @@ -0,0 +1,27 @@ +# Optionally, compilation of the main package with the daemon gets moved into +# dbus-cynara. That is necessary to break a dependency cycle once the +# daemon gets compiled with Cynara support (dbus -> cynara -> systemd +# -> dbus). +do_install_append_class-target () { + if ${@bb.utils.contains('DISTRO_FEATURES', 'dbus-cynara', 'true', 'false', d)}; then + for i in ${@' '.join([d.getVar('D', True) + x for x in (d.getVar('FILES_${PN}', True) or '').split()])}; do + rm -rf $i + done + + # Try to remove empty directories, starting with the + # longest path (= deepest directory) first. + # Find needs a valid current directory. Somehow the directory + # we get called in is gone by the time that we get invoked. + ( cd ${D} + for i in `find . -type d | sort -r`; do + rmdir $i || true + done + ) + fi +} + +# The main package will be empty, but we want to have it created +# anyway because of the dependencies on it. Installing it will pull in +# the replacement dbus-cynara package. +ALLOW_EMPTY_${PN}_class-target = "1" +RDEPENDS_${PN}_append_class-target = "${@bb.utils.contains('DISTRO_FEATURES', 'dbus-cynara', ' dbus-cynara', '', d)}" diff --git a/meta-security/recipes-core/packagegroups/packagegroup-security-framework.bb b/meta-security/recipes-core/packagegroups/packagegroup-security-framework.bb new file mode 100644 index 000000000..c728da3b9 --- /dev/null +++ b/meta-security/recipes-core/packagegroups/packagegroup-security-framework.bb @@ -0,0 +1,22 @@ +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-userspace 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 = " \ + cynara \ + security-manager \ + security-manager-policy \ + smacknet \ +" diff --git a/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup-v216.patch b/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup-v216.patch new file mode 100644 index 000000000..2ff51f86b --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup-v216.patch @@ -0,0 +1,49 @@ +From da574755b8abe1d5fb9151f901ccea51d40d9509 Mon Sep 17 00:00:00 2001 +From: Michael Demeter <michael.demeter@intel.com> +Date: Fri, 30 Oct 2015 11:25:50 +0100 +Subject: [PATCH] tizen-smack: Handling of /run and /sys/fs/cgroup + +Make /run a transmuting directory to enable systemd +communications with services in the User domain. + +Upstream-Status: Pending + +Change-Id: I9e23b78d17a108d8e56ad85a9e839b6ccbe4feff +--- + src/core/mount-setup.c | 10 +++++++--- + 1 file changed, 7 insertions(+), 3 deletions(-) + +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index cc2633e..3dc7cd7 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -85,19 +85,23 @@ static const MountPoint mount_table[] = { + use_smack, MNT_FATAL }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + use_smack, MNT_FATAL }, +-#endif ++#else + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, ++#endif + { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, + NULL, MNT_IN_CONTAINER }, + #ifdef HAVE_SMACK +- { "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, ++ { "tmpfs", "/run", "tmpfs", "mode=755,smackfstransmute=System::Run", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + use_smack, MNT_FATAL }, +-#endif ++ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, ++ use_smack, MNT_IN_CONTAINER }, ++#else + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, ++#endif + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_IN_CONTAINER }, + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, +-- +2.1.4 + diff --git a/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup.patch b/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup.patch new file mode 100644 index 000000000..a4a3e50a6 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup.patch @@ -0,0 +1,50 @@ +From 831d552a9589bb2b99c042d01672409efa3d94fc Mon Sep 17 00:00:00 2001 +From: Michael Demeter <michael.demeter@intel.com> +Date: Fri, 11 Oct 2013 15:37:57 -0700 +Subject: [PATCH 3/9] tizen-smack: Handling of /run and /sys/fs/cgroup + +Make /run a transmuting directory to enable systemd +communications with services in the User domain. + +Upstream-Status: Pending + +Change-Id: I9e23b78d17a108d8e56ad85a9e839b6ccbe4feff +--- + src/core/mount-setup.c | 12 ++++++++---- + 1 file changed, 8 insertions(+), 4 deletions(-) + +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index 521545e..ba0867c 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -85,19 +85,23 @@ static const MountPoint mount_table[] = { + mac_smack_use, MNT_FATAL }, + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + mac_smack_use, MNT_FATAL }, +-#endif ++#else + { "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, ++#endif + { "devpts", "/dev/pts", "devpts", "mode=620,gid=" STRINGIFY(TTY_GID), MS_NOSUID|MS_NOEXEC, + NULL, MNT_IN_CONTAINER }, + #ifdef HAVE_SMACK +- { "tmpfs", "/run", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NODEV|MS_STRICTATIME, +- mac_smack_use, MNT_FATAL }, +-#endif ++ { "tmpfs", "/run", "tmpfs", "mode=755,smackfstransmute=System::Run", MS_NOSUID|MS_NODEV|MS_STRICTATIME, ++ mac_smack_use, MNT_FATAL }, ++ { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755,smackfsroot=*", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, ++ mac_smack_use, MNT_IN_CONTAINER }, ++#else + { "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, + { "tmpfs", "/sys/fs/cgroup", "tmpfs", "mode=755", MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_STRICTATIME, + NULL, MNT_FATAL|MNT_IN_CONTAINER }, ++#endif + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd,xattr", MS_NOSUID|MS_NOEXEC|MS_NODEV, + NULL, MNT_IN_CONTAINER }, + { "cgroup", "/sys/fs/cgroup/systemd", "cgroup", "none,name=systemd", MS_NOSUID|MS_NOEXEC|MS_NODEV, +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev-v216.patch b/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev-v216.patch new file mode 100644 index 000000000..88c100fed --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev-v216.patch @@ -0,0 +1,82 @@ +From 468ef790a7a0e53c390cec9c63090a0ae04a4d58 Mon Sep 17 00:00:00 2001 +From: Michael Demeter <michael.demeter@intel.com> +Date: Fri, 11 Oct 2013 15:37:57 -0700 +Subject: [PATCH 4/9] tizen-smack: Handling of /dev + +Smack enabled systems need /dev special devices correctly labeled + +- Add AC_DEFINE for HAVE_SMACK to configure.ac +- Add Check for smack in Makefile.am to include smack default rules +- Add smack default rules to label /dev/xxx correctly for access + +Upstream-Status: Inappropriate [configuration] + +Change-Id: Iebe2e349cbedb3013abdf32edb55e9310f1d17f5 +--- + configure.ac | 2 ++ + Makefile.am | 5 +++++ + rules/55-udev-smack-default.rules | 23 +++++++++++++++++++++++ + 3 files changed, 30 insertions(+) + create mode 100644 rules/55-udev-smack-default.rules + +diff --git a/configure.ac b/configure.ac +index 18b7198..05f49ed 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -635,6 +635,8 @@ if test "x${have_smack}" = xyes ; then + AC_DEFINE(HAVE_SMACK, 1, [Define if SMACK is available]) + fi + ++AM_CONDITIONAL([HAVE_SMACK], [test "x$have_smack" = "xyes"]) ++ + # ------------------------------------------------------------------------------ + AC_ARG_ENABLE([gcrypt], + AS_HELP_STRING([--disable-gcrypt],[Disable optional GCRYPT support]), +diff --git a/Makefile.am b/Makefile.am +index bf04d31..1a05607 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3108,6 +3108,11 @@ dist_udevrules_DATA += \ + nodist_udevrules_DATA += \ + rules/99-systemd.rules + ++if HAVE_SMACK ++dist_udevrules_DATA += \ ++ rules/55-udev-smack-default.rules ++endif ++ + dist_udevhwdb_DATA = \ + hwdb/20-pci-vendor-model.hwdb \ + hwdb/20-pci-classes.hwdb \ +diff --git a/rules/55-udev-smack-default.rules b/rules/55-udev-smack-default.rules +new file mode 100644 +index 0000000..3829019 +--- /dev/null ++++ b/rules/55-udev-smack-default.rules +@@ -0,0 +1,23 @@ ++# 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}="*" ++ ++SUBSYSTEM=="graphics", GROUP="video", SECLABEL{smack}="*" ++SUBSYSTEM=="drm", GROUP="video", SECLABEL{smack}="*" ++SUBSYSTEM=="dvb", GROUP="video", 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}="*" +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev.patch b/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev.patch new file mode 100644 index 000000000..b12caaec5 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0004-tizen-smack-Handling-of-dev.patch @@ -0,0 +1,68 @@ +From 468ef790a7a0e53c390cec9c63090a0ae04a4d58 Mon Sep 17 00:00:00 2001 +From: Michael Demeter <michael.demeter@intel.com> +Date: Fri, 11 Oct 2013 15:37:57 -0700 +Subject: [PATCH 4/9] tizen-smack: Handling of /dev + +Smack enabled systems need /dev special devices correctly labeled + +- Add AC_DEFINE for HAVE_SMACK to configure.ac +- Add Check for smack in Makefile.am to include smack default rules +- Add smack default rules to label /dev/xxx correctly for access + +Upstream-Status: Inappropriate [configuration] + +Change-Id: Iebe2e349cbedb3013abdf32edb55e9310f1d17f5 +--- + Makefile.am | 5 +++++ + rules/55-udev-smack-default.rules | 23 +++++++++++++++++++++++ + 2 files changed, 28 insertions(+) + create mode 100644 rules/55-udev-smack-default.rules + +diff --git a/Makefile.am b/Makefile.am +index bf04d31..1a05607 100644 +--- a/Makefile.am ++++ b/Makefile.am +@@ -3571,6 +3571,11 @@ dist_udevrules_DATA += \ + nodist_udevrules_DATA += \ + rules/99-systemd.rules + ++if HAVE_SMACK ++dist_udevrules_DATA += \ ++ rules/55-udev-smack-default.rules ++endif ++ + udevconfdir = $(sysconfdir)/udev + dist_udevconf_DATA = \ + src/udev/udev.conf +diff --git a/rules/55-udev-smack-default.rules b/rules/55-udev-smack-default.rules +new file mode 100644 +index 0000000..3829019 +--- /dev/null ++++ b/rules/55-udev-smack-default.rules +@@ -0,0 +1,23 @@ ++# 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}="*" ++ ++SUBSYSTEM=="graphics", GROUP="video", SECLABEL{smack}="*" ++SUBSYSTEM=="drm", GROUP="video", SECLABEL{smack}="*" ++SUBSYSTEM=="dvb", GROUP="video", 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}="*" +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v216.patch b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v216.patch new file mode 100644 index 000000000..3d69bb2a8 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v216.patch @@ -0,0 +1,107 @@ +From c257eade1a39ea00d26c4c297efd654b6ad4edb4 Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Fri, 8 Nov 2013 09:42:26 -0800 +Subject: [PATCH 5/9] tizen-smack: Handling network + +- Set Smack ambient to match run label +- Set Smack netlabel host rules + +Set Smack ambient to match run label +------------------------------------ +Set the Smack networking ambient label to match the +run label of systemd. System services may expect to +communicate with external services over IP. Setting +the ambient label assigns that label to IP packets +that do not include CIPSO headers. This allows systemd +and the services it spawns access to unlabeled IP +packets, and hence external services. + +A system may choose to restrict network access to +particular services later in the startup process. +This is easily done by resetting the ambient label +elsewhere. + +Set Smack netlabel host rules +----------------------------- +If SMACK_RUN_LABEL is defined set all other hosts to be +single label hosts at the specified label. Set the loopback +address to be a CIPSO host. + +If any netlabel host rules are defined in /etc/smack/netlabel.d +install them into the smackfs netlabel interface. + +Upstream-Status: Pending + +--- + src/core/smack-setup.c | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c +index 59f6832..33dc1ca 100644 +--- a/src/core/smack-setup.c ++++ b/src/core/smack-setup.c +@@ -42,6 +42,7 @@ + + #define SMACK_CONFIG "/etc/smack/accesses.d/" + #define CIPSO_CONFIG "/etc/smack/cipso.d/" ++#define NETLABEL_CONFIG "/etc/smack/netlabel.d/" + + #ifdef HAVE_SMACK + +@@ -146,6 +147,19 @@ int smack_setup(bool *loaded_policy) { + if (r) + log_warning("Failed to set SMACK label \"%s\" on self: %s", + SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL); ++ if (r) ++ log_warning("Failed to set SMACK ambient label \"%s\": %s", ++ SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", ++ "0.0.0.0/0 " SMACK_RUN_LABEL); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "0.0.0.0/0 " SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO"); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "127.0.0.1 -CIPSO", strerror(-r)); + #endif + + r = write_rules("/sys/fs/smackfs/cipso2", CIPSO_CONFIG); +@@ -155,14 +169,31 @@ int smack_setup(bool *loaded_policy) { + return 0; + case ENOENT: + log_debug("Smack/CIPSO access rules directory " CIPSO_CONFIG " not found"); +- return 0; ++ break; + case 0: + log_info("Successfully loaded Smack/CIPSO policies."); +- return 0; ++ break; + default: + log_warning("Failed to load Smack/CIPSO access rules: %s, ignoring.", + strerror(abs(r))); ++ break; ++ } ++ ++ r = write_rules("/sys/fs/smackfs/netlabel", NETLABEL_CONFIG); ++ switch(r) { ++ case -ENOENT: ++ log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; ++ case ENOENT: ++ log_debug("Smack network host rules directory " NETLABEL_CONFIG " not found"); ++ break; ++ case 0: ++ log_info("Successfully loaded Smack network host rules."); ++ break; ++ default: ++ log_warning("Failed to load Smack network host rules: %s, ignoring.", ++ strerror(abs(r))); ++ break; + } + + *loaded_policy = true; +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v225.patch b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v225.patch new file mode 100644 index 000000000..d5678f2e6 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v225.patch @@ -0,0 +1,191 @@ +From 513a8d943538643fabf0d31f1eed261677dfbddc Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Fri, 8 Nov 2013 09:42:26 -0800 +Subject: [PATCH] tizen-smack: Handling network + +- Set Smack ambient to match run label +- Set Smack netlabel host rules + +Set Smack ambient to match run label +------------------------------------ +Set the Smack networking ambient label to match the +run label of systemd. System services may expect to +communicate with external services over IP. Setting +the ambient label assigns that label to IP packets +that do not include CIPSO headers. This allows systemd +and the services it spawns access to unlabeled IP +packets, and hence external services. + +A system may choose to restrict network access to +particular services later in the startup process. +This is easily done by resetting the ambient label +elsewhere. + +Set Smack netlabel host rules +----------------------------- +If SMACK_RUN_LABEL is defined set all other hosts to be +single label hosts at the specified label. Set the loopback +address to be a CIPSO host. + +If any netlabel host rules are defined in /etc/smack/netlabel.d +install them into the smackfs netlabel interface. + +[Patrick Ohly: adapt to write_string_file() change in "fileio: consolidate write_string_file*()"] +[Patrick Ohly: create write_netlabel_rules() based on the original write_rules() that was removed in "smack: support smack access change-rule"] + +Upstream-Status: Pending +--- + src/core/smack-setup.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 106 insertions(+), 3 deletions(-) + +diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c +index cbe7d0b..b384aa0 100644 +--- a/src/core/smack-setup.c ++++ b/src/core/smack-setup.c +@@ -34,6 +34,9 @@ + #include "fileio.h" + #include "log.h" + ++#define CIPSO_CONFIG "/etc/smack/cipso.d/" ++#define NETLABEL_CONFIG "/etc/smack/netlabel.d/" ++ + #ifdef HAVE_SMACK + + static int write_access2_rules(const char* srcdir) { +@@ -193,6 +196,76 @@ static int write_cipso2_rules(const char* srcdir) { + return r; + } + ++static int write_netlabel_rules(const char* srcdir) { ++ _cleanup_fclose_ FILE *dst = NULL; ++ _cleanup_closedir_ DIR *dir = NULL; ++ struct dirent *entry; ++ char buf[NAME_MAX]; ++ int dfd = -1; ++ int r = 0; ++ static const char dstpath[] = "/sys/fs/smackfs/netlabel"; ++ ++ dst = fopen(dstpath, "we"); ++ if (!dst) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to open %s: %m", dstpath); ++ return -errno; /* negative error */ ++ } ++ ++ /* write rules to dst from every file in the directory */ ++ dir = opendir(srcdir); ++ if (!dir) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to opendir %s: %m", srcdir); ++ return errno; /* positive on purpose */ ++ } ++ ++ dfd = dirfd(dir); ++ assert(dfd >= 0); ++ ++ FOREACH_DIRENT(entry, dir, return 0) { ++ int fd; ++ _cleanup_fclose_ FILE *policy = NULL; ++ ++ fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); ++ if (fd < 0) { ++ if (r == 0) ++ r = -errno; ++ log_warning_errno(errno, "Failed to open %s: %m", entry->d_name); ++ continue; ++ } ++ ++ policy = fdopen(fd, "re"); ++ if (!policy) { ++ if (r == 0) ++ r = -errno; ++ safe_close(fd); ++ log_error_errno(errno, "Failed to open %s: %m", entry->d_name); ++ continue; ++ } ++ ++ /* load2 write rules in the kernel require a line buffered stream */ ++ FOREACH_LINE(buf, policy, ++ log_error_errno(errno, "Failed to read line from %s: %m", ++ entry->d_name)) { ++ if (!fputs(buf, dst)) { ++ if (r == 0) ++ r = -EINVAL; ++ log_error("Failed to write line to %s", dstpath); ++ break; ++ } ++ if (fflush(dst)) { ++ if (r == 0) ++ r = -errno; ++ log_error_errno(errno, "Failed to flush writes to %s: %m", dstpath); ++ break; ++ } ++ } ++ } ++ ++ return r; ++} ++ + #endif + + int mac_smack_setup(bool *loaded_policy) { +@@ -225,23 +298,53 @@ int mac_smack_setup(bool *loaded_policy) { + if (r) + log_warning("Failed to set SMACK label \"%s\" on self: %s", + SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0); ++ if (r) ++ log_warning("Failed to set SMACK ambient label \"%s\": %s", ++ SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", ++ "0.0.0.0/0 " SMACK_RUN_LABEL, 0); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "0.0.0.0/0 " SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "127.0.0.1 -CIPSO", strerror(-r)); + #endif + +- r = write_cipso2_rules("/etc/smack/cipso.d/"); ++ r = write_cipso2_rules(CIPSO_CONFIG); + switch(r) { + case -ENOENT: + log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; + case ENOENT: +- log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found"); +- return 0; ++ log_debug("Smack/CIPSO access rules directory " CIPSO_CONFIG " not found"); ++ break; + case 0: + log_info("Successfully loaded Smack/CIPSO policies."); + break; + default: + log_warning("Failed to load Smack/CIPSO access rules: %s, ignoring.", + strerror(abs(r))); ++ break; ++ } ++ ++ r = write_netlabel_rules(NETLABEL_CONFIG); ++ switch(r) { ++ case -ENOENT: ++ log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; ++ case ENOENT: ++ log_debug("Smack network host rules directory " NETLABEL_CONFIG " not found"); ++ break; ++ case 0: ++ log_info("Successfully loaded Smack network host rules."); ++ break; ++ default: ++ log_warning("Failed to load Smack network host rules: %s, ignoring.", ++ strerror(abs(r))); ++ break; + } + + *loaded_policy = true; +-- +2.1.4 + diff --git a/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v228.patch b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v228.patch new file mode 100644 index 000000000..bc6b97c8f --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network-v228.patch @@ -0,0 +1,179 @@ +From e714327016fb65a0bf977588efaecbaf41ac3cfc Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Fri, 8 Nov 2013 09:42:26 -0800 +Subject: [PATCH 4/6] tizen-smack: Handling network + +- Set Smack ambient to match run label +- Set Smack netlabel host rules + +Set Smack ambient to match run label +------------------------------------ +Set the Smack networking ambient label to match the +run label of systemd. System services may expect to +communicate with external services over IP. Setting +the ambient label assigns that label to IP packets +that do not include CIPSO headers. This allows systemd +and the services it spawns access to unlabeled IP +packets, and hence external services. + +A system may choose to restrict network access to +particular services later in the startup process. +This is easily done by resetting the ambient label +elsewhere. + +Set Smack netlabel host rules +----------------------------- +If SMACK_RUN_LABEL is defined set all other hosts to be +single label hosts at the specified label. Set the loopback +address to be a CIPSO host. + +If any netlabel host rules are defined in /etc/smack/netlabel.d +install them into the smackfs netlabel interface. + +[Patrick Ohly: copied from https://review.tizen.org/git/?p=platform/upstream/systemd.git;a=commit;h=db4f6c9a074644aa2bf] +[Patrick Ohly: adapt to write_string_file() change in "fileio: consolidate write_string_file*()"] +[Patrick Ohly: create write_netlabel_rules() based on the original write_rules() that was removed in "smack: support smack access change-rule"] +[Patrick Ohly: adapted to upstream code review feedback: error logging, string constants] + +Upstream-Status: Accepted [https://github.com/systemd/systemd/pull/2262] + +%% original patch: 0005-tizen-smack-Handling-network-v225.patch +--- + src/core/smack-setup.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++-- + 1 file changed, 98 insertions(+), 3 deletions(-) + +diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c +index 0661ff9..c9374ca 100644 +--- a/src/core/smack-setup.c ++++ b/src/core/smack-setup.c +@@ -197,6 +197,75 @@ static int write_cipso2_rules(const char* srcdir) { + return r; + } + ++static int write_netlabel_rules(const char* srcdir) { ++ _cleanup_fclose_ FILE *dst = NULL; ++ _cleanup_closedir_ DIR *dir = NULL; ++ struct dirent *entry; ++ char buf[NAME_MAX]; ++ int dfd = -1; ++ int r = 0; ++ ++ dst = fopen("/sys/fs/smackfs/netlabel", "we"); ++ if (!dst) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to open /sys/fs/smackfs/netlabel: %m"); ++ return -errno; /* negative error */ ++ } ++ ++ /* write rules to dst from every file in the directory */ ++ dir = opendir(srcdir); ++ if (!dir) { ++ if (errno != ENOENT) ++ log_warning_errno(errno, "Failed to opendir %s: %m", srcdir); ++ return errno; /* positive on purpose */ ++ } ++ ++ dfd = dirfd(dir); ++ assert(dfd >= 0); ++ ++ FOREACH_DIRENT(entry, dir, return 0) { ++ int fd; ++ _cleanup_fclose_ FILE *policy = NULL; ++ ++ fd = openat(dfd, entry->d_name, O_RDONLY|O_CLOEXEC); ++ if (fd < 0) { ++ if (r == 0) ++ r = -errno; ++ log_warning_errno(errno, "Failed to open %s: %m", entry->d_name); ++ continue; ++ } ++ ++ policy = fdopen(fd, "re"); ++ if (!policy) { ++ if (r == 0) ++ r = -errno; ++ safe_close(fd); ++ log_error_errno(errno, "Failed to open %s: %m", entry->d_name); ++ continue; ++ } ++ ++ /* load2 write rules in the kernel require a line buffered stream */ ++ FOREACH_LINE(buf, policy, ++ log_error_errno(errno, "Failed to read line from %s: %m", ++ entry->d_name)) { ++ if (!fputs(buf, dst)) { ++ if (r == 0) ++ r = -EINVAL; ++ log_error_errno(errno, "Failed to write line to /sys/fs/smackfs/netlabel"); ++ break; ++ } ++ if (fflush(dst)) { ++ if (r == 0) ++ r = -errno; ++ log_error_errno(errno, "Failed to flush writes to /sys/fs/smackfs/netlabel: %m"); ++ break; ++ } ++ } ++ } ++ ++ return r; ++} ++ + #endif + + int mac_smack_setup(bool *loaded_policy) { +@@ -225,8 +294,18 @@ int mac_smack_setup(bool *loaded_policy) { + + #ifdef SMACK_RUN_LABEL + r = write_string_file("/proc/self/attr/current", SMACK_RUN_LABEL, 0); +- if (r) +- log_warning_errno(r, "Failed to set SMACK label \"%s\" on self: %m", SMACK_RUN_LABEL); ++ if (r < 0) ++ log_warning_errno(r, "Failed to set SMACK label \"" SMACK_RUN_LABEL "\" on self: %m"); ++ r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL, 0); ++ if (r < 0) ++ log_warning_errno(r, "Failed to set SMACK ambient label \"" SMACK_RUN_LABEL "\": %m"); ++ r = write_string_file("/sys/fs/smackfs/netlabel", ++ "0.0.0.0/0 " SMACK_RUN_LABEL, 0); ++ if (r < 0) ++ log_warning_errno(r, "Failed to set SMACK netlabel rule \"0.0.0.0/0 " SMACK_RUN_LABEL "\": %m"); ++ r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO", 0); ++ if (r < 0) ++ log_warning_errno(r, "Failed to set SMACK netlabel rule \"127.0.0.1 -CIPSO\": %m"); + #endif + + r = write_cipso2_rules("/etc/smack/cipso.d/"); +@@ -236,13 +315,29 @@ int mac_smack_setup(bool *loaded_policy) { + return 0; + case ENOENT: + log_debug("Smack/CIPSO access rules directory '/etc/smack/cipso.d/' not found"); +- return 0; ++ break; + case 0: + log_info("Successfully loaded Smack/CIPSO policies."); + break; + default: + log_warning_errno(r, "Failed to load Smack/CIPSO access rules, ignoring: %m"); ++ break; ++ } ++ ++ r = write_netlabel_rules("/etc/smack/netlabel.d/"); ++ switch(r) { ++ case -ENOENT: ++ log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; ++ case ENOENT: ++ log_debug("Smack network host rules directory '/etc/smack/netlabel.d/' not found"); ++ break; ++ case 0: ++ log_info("Successfully loaded Smack network host rules."); ++ break; ++ default: ++ log_warning_errno(r, "Failed to load Smack network host rules: %m, ignoring."); ++ break; + } + + *loaded_policy = true; +-- +2.1.4 + diff --git a/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network.patch b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network.patch new file mode 100644 index 000000000..cd6a3c90b --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0005-tizen-smack-Handling-network.patch @@ -0,0 +1,106 @@ +From c257eade1a39ea00d26c4c297efd654b6ad4edb4 Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Fri, 8 Nov 2013 09:42:26 -0800 +Subject: [PATCH 5/9] tizen-smack: Handling network + +- Set Smack ambient to match run label +- Set Smack netlabel host rules + +Set Smack ambient to match run label +------------------------------------ +Set the Smack networking ambient label to match the +run label of systemd. System services may expect to +communicate with external services over IP. Setting +the ambient label assigns that label to IP packets +that do not include CIPSO headers. This allows systemd +and the services it spawns access to unlabeled IP +packets, and hence external services. + +A system may choose to restrict network access to +particular services later in the startup process. +This is easily done by resetting the ambient label +elsewhere. + +Set Smack netlabel host rules +----------------------------- +If SMACK_RUN_LABEL is defined set all other hosts to be +single label hosts at the specified label. Set the loopback +address to be a CIPSO host. + +If any netlabel host rules are defined in /etc/smack/netlabel.d +install them into the smackfs netlabel interface. + +Upstream-Status: Pending + +--- + src/core/smack-setup.c | 33 ++++++++++++++++++++++++++++++++- + 1 file changed, 32 insertions(+), 1 deletion(-) + +diff --git a/src/core/smack-setup.c b/src/core/smack-setup.c +index 59f6832..33dc1ca 100644 +--- a/src/core/smack-setup.c ++++ b/src/core/smack-setup.c +@@ -42,6 +42,7 @@ + + #define SMACK_CONFIG "/etc/smack/accesses.d/" + #define CIPSO_CONFIG "/etc/smack/cipso.d/" ++#define NETLABEL_CONFIG "/etc/smack/netlabel.d/" + + #ifdef HAVE_SMACK + +@@ -146,6 +147,19 @@ int mac_smack_setup(bool *loaded_policy) { + if (r) + log_warning("Failed to set SMACK label \"%s\" on self: %s", + SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/ambient", SMACK_RUN_LABEL); ++ if (r) ++ log_warning("Failed to set SMACK ambient label \"%s\": %s", ++ SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", ++ "0.0.0.0/0 " SMACK_RUN_LABEL); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "0.0.0.0/0 " SMACK_RUN_LABEL, strerror(-r)); ++ r = write_string_file("/sys/fs/smackfs/netlabel", "127.0.0.1 -CIPSO"); ++ if (r) ++ log_warning("Failed to set SMACK netlabel rule \"%s\": %s", ++ "127.0.0.1 -CIPSO", strerror(-r)); + #endif + + r = write_rules("/sys/fs/smackfs/cipso2", CIPSO_CONFIG); +@@ -155,14 +169,31 @@ int mac_smack_setup(bool *loaded_policy) { + return 0; + case ENOENT: + log_debug("Smack/CIPSO access rules directory " CIPSO_CONFIG " not found"); +- return 0; ++ break; + case 0: + log_info("Successfully loaded Smack/CIPSO policies."); + break; + default: + log_warning("Failed to load Smack/CIPSO access rules: %s, ignoring.", + strerror(abs(r))); ++ break; ++ } ++ ++ r = write_rules("/sys/fs/smackfs/netlabel", NETLABEL_CONFIG); ++ switch(r) { ++ case -ENOENT: ++ log_debug("Smack/CIPSO is not enabled in the kernel."); + return 0; ++ case ENOENT: ++ log_debug("Smack network host rules directory " NETLABEL_CONFIG " not found"); ++ break; ++ case 0: ++ log_info("Successfully loaded Smack network host rules."); ++ break; ++ default: ++ log_warning("Failed to load Smack network host rules: %s, ignoring.", ++ strerror(abs(r))); ++ break; + } + + *loaded_policy = true; +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with-v216.patch b/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with-v216.patch new file mode 100644 index 000000000..dd2c6542e --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with-v216.patch @@ -0,0 +1,41 @@ +From ccf384ca0f1cabe37e07e752df95ddb1e017a7ef Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Thu, 19 Dec 2013 16:49:28 -0800 +Subject: [PATCH 7/9] tizen-smack: Runs systemd-journald with ^ + +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. + +Upstream-Status: Inappropriate [configuration] + +Change-Id: Ic22633f0c9d99c04f873be8a346786ea577d0370 +Signed-off-by: Casey Schaufler <casey.schaufler@intel.com> +--- + units/systemd-journald.service.in | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in +index a3540c6..745dd84 100644 +--- a/units/systemd-journald.service.in ++++ b/units/systemd-journald.service.in +@@ -20,8 +20,10 @@ Restart=always + RestartSec=0 + NotifyAccess=all + StandardOutput=null ++SmackProcessLabel=^ +-CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID ++CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE + WatchdogSec=1min ++FileDescriptorStoreMax=1024 + + # Increase the default a bit in order to allow many simultaneous + # services being run since we keep one fd open per service. +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with.patch b/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with.patch new file mode 100644 index 000000000..27a9d0bc6 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/0007-tizen-smack-Runs-systemd-journald-with.patch @@ -0,0 +1,37 @@ +From ccf384ca0f1cabe37e07e752df95ddb1e017a7ef Mon Sep 17 00:00:00 2001 +From: Casey Schaufler <casey@schaufler-ca.com> +Date: Thu, 19 Dec 2013 16:49:28 -0800 +Subject: [PATCH 7/9] tizen-smack: Runs systemd-journald with ^ + +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. + +Upstream-Status: Inappropriate [configuration] + +Change-Id: Ic22633f0c9d99c04f873be8a346786ea577d0370 +Signed-off-by: Casey Schaufler <casey.schaufler@intel.com> +--- + units/systemd-journald.service.in | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/units/systemd-journald.service.in b/units/systemd-journald.service.in +index a3540c6..745dd84 100644 +--- a/units/systemd-journald.service.in ++++ b/units/systemd-journald.service.in +@@ -21,6 +21,7 @@ Restart=always + RestartSec=0 + NotifyAccess=all + StandardOutput=null ++SmackProcessLabel=^ + CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE CAP_SYSLOG CAP_AUDIT_CONTROL CAP_AUDIT_READ CAP_CHOWN CAP_DAC_READ_SEARCH CAP_FOWNER CAP_SETUID CAP_SETGID CAP_MAC_OVERRIDE + WatchdogSec=1min + FileDescriptorStoreMax=1024 +-- +1.8.4.5 + diff --git a/meta-security/recipes-core/systemd/systemd/mount-setup.c-fix-handling-of-symlink-Smack-labellin-v228.patch b/meta-security/recipes-core/systemd/systemd/mount-setup.c-fix-handling-of-symlink-Smack-labellin-v228.patch new file mode 100644 index 000000000..5a1baefed --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/mount-setup.c-fix-handling-of-symlink-Smack-labellin-v228.patch @@ -0,0 +1,58 @@ +From fd84be63d15fc94c1f396979c67e070c6cd7451b Mon Sep 17 00:00:00 2001 +From: Patrick Ohly <patrick.ohly@intel.com> +Date: Mon, 21 Dec 2015 14:56:00 +0100 +Subject: [PATCH] mount-setup.c: fix handling of symlink Smack labelling in + cgroup setup + +The code introduced in f8c1a81c51 (= systemd 227) failed for me with: + Failed to copy smack label from net_cls to /sys/fs/cgroup/net_cls: No such file or directory + +There is no need for a symlink in this case because source and target +are identical. The symlink() call is allowed to fail when the target +already exists. When that happens, copying the Smack label must be +skipped. + +But the code also failed when there is a symlink, like "cpu -> +cpu,cpuacct", because mac_smack_copy() got called with +src="cpu,cpuacct" which fails to find the entry because the current +directory is not inside /sys/fs/cgroup. The absolute path to the existing +entry must be used instead. + +Upstream-Status: Accepted [https://github.com/systemd/systemd/pull/2205] + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +--- + src/core/mount-setup.c | 15 ++++++++++----- + 1 file changed, 10 insertions(+), 5 deletions(-) + +diff --git a/src/core/mount-setup.c b/src/core/mount-setup.c +index 2b8d590..d73b319 100644 +--- a/src/core/mount-setup.c ++++ b/src/core/mount-setup.c +@@ -304,13 +304,18 @@ int mount_cgroup_controllers(char ***join_controllers) { + return log_oom(); + + r = symlink(options, t); +- if (r < 0 && errno != EEXIST) +- return log_error_errno(errno, "Failed to create symlink %s: %m", t); ++ if (r >= 0) { + #ifdef SMACK_RUN_LABEL +- r = mac_smack_copy(t, options); +- if (r < 0 && r != -EOPNOTSUPP) +- return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", options, t); ++ _cleanup_free_ char *src; ++ src = strappend("/sys/fs/cgroup/", options); ++ if (!src) ++ return log_oom(); ++ r = mac_smack_copy(t, src); ++ if (r < 0 && r != -EOPNOTSUPP) ++ return log_error_errno(r, "Failed to copy smack label from %s to %s: %m", src, t); + #endif ++ } else if (errno != EEXIST) ++ return log_error_errno(errno, "Failed to create symlink %s: %m", t); + } + } + } +-- +2.1.4 + diff --git a/meta-security/recipes-core/systemd/systemd/udev-smack-default.rules b/meta-security/recipes-core/systemd/systemd/udev-smack-default.rules new file mode 100644 index 000000000..3829019de --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd/udev-smack-default.rules @@ -0,0 +1,23 @@ +# 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}="*" + +SUBSYSTEM=="graphics", GROUP="video", SECLABEL{smack}="*" +SUBSYSTEM=="drm", GROUP="video", SECLABEL{smack}="*" +SUBSYSTEM=="dvb", GROUP="video", 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-security/recipes-core/systemd/systemd_%.bbappend b/meta-security/recipes-core/systemd/systemd_%.bbappend new file mode 100644 index 000000000..bea5a3731 --- /dev/null +++ b/meta-security/recipes-core/systemd/systemd_%.bbappend @@ -0,0 +1,120 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/${PN}:" + +# Most patches from sandbox/jobol/v219. Cannot be applied unconditionally +# because systemd panics when booted without Smack support: +# systemd[1]: Cannot determine cgroup we are running in: No such file or directory +# systemd[1]: Failed to allocate manager object: No such file or directory +# [!!!!!!] Failed to allocate manager object, freezing. +# +# There's a slight dependency on the base systemd in 0005-tizen-smack-Handling-network. +# We use the beginning of PV (unexpanded here to prevent a cyclic dependency +# during resolution apparently caused by ${SRCPV}) to pick the right set of +# patches. +# +# Patches are optional. Hopefully we won't need any for systemd >= 229. +SRC_URI_append_with-lsm-smack = " ${@d.getVar('SYSTEMD_SMACK_PATCHES_' + d.getVar('PV', False)[0:3], True) or ''}" + +SYSTEMD_SMACK_PATCHES_216 = " \ +file://0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup-v216.patch \ +file://0004-tizen-smack-Handling-of-dev-v216.patch \ +file://0005-tizen-smack-Handling-network-v216.patch \ +file://0007-tizen-smack-Runs-systemd-journald-with-v216.patch \ +" + +SYSTEMD_SMACK_PATCHES_219 = " \ +file://0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup.patch \ +file://0004-tizen-smack-Handling-of-dev.patch \ +file://0005-tizen-smack-Handling-network.patch \ +file://0007-tizen-smack-Runs-systemd-journald-with.patch \ +" +SYSTEMD_SMACK_PATCHES_225 = " \ +file://0003-tizen-smack-Handling-of-run-and-sys-fs-cgroup.patch \ +file://0004-tizen-smack-Handling-of-dev.patch \ +file://0005-tizen-smack-Handling-network-v225.patch \ +file://0007-tizen-smack-Runs-systemd-journald-with.patch \ +" + +SYSTEMD_SMACK_PATCHES_228 = " \ +file://0005-tizen-smack-Handling-network-v228.patch \ +file://mount-setup.c-fix-handling-of-symlink-Smack-labellin-v228.patch \ +" + +# From Tizen .spec file. +EXTRA_OECONF_append_with-lsm-smack = " --with-smack-run-label=System" + +install_file() { + install -d $(dirname $1) + cat >>$1 + chmod ${2:-0644} $1 +} + +# We need to emulate parts of the filesystem permissions from Tizen here. +# The part for regular files is in base-files.bbappend, but /var/log and +# /var/tmp point into /var/volatile (tmpfs) and get created anew during +# startup. We set these permissions directly after creating them via +# /etc/tmpfiles.d/00-create-volatile.conf +RDEPENDS_${PN}_append_with-lsm-smack = " smack-userspace" +do_install_append_with-lsm-smack() { + install_file ${D}${systemd_unitdir}/system/systemd-tmpfiles-setup.service.d/smack.conf <<EOF +[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)' +EOF + + # 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". + install_file ${D}${systemd_unitdir}/system/tmp.mount.d/smack.conf <<EOF +[Mount] +Options=smackfsroot=* +EOF + + # 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. + install_file ${D}${systemd_unitdir}/system/systemd-journald.service.d/smack.conf <<EOF +[Service] +SmackProcessLabel=^ +EOF +} + +# Will get installed in ${sysconfdir}/udev/rules.d/ by base systemd recipe. +SRC_URI += "file://udev-smack-default.rules" + +# A workaround for a missing space in a SRC_URI_append in a private layer elsewhere: +SRC_URI += "" + +# 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 +} diff --git a/meta-security/recipes-core/util-linux/util-linux_%.bbappend b/meta-security/recipes-core/util-linux/util-linux_%.bbappend new file mode 100644 index 000000000..05286f80d --- /dev/null +++ b/meta-security/recipes-core/util-linux/util-linux_%.bbappend @@ -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-security/recipes-devtools/e2fsprogs/e2fsprogs.inc b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs.inc new file mode 100644 index 000000000..09e4ea5bb --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs.inc @@ -0,0 +1,27 @@ +SUMMARY = "Ext2 Filesystem Utilities" +DESCRIPTION = "The Ext2 Filesystem Utilities (e2fsprogs) contain all of the standard utilities for creating, \ +fixing, configuring , and debugging ext2 filesystems." +HOMEPAGE = "http://e2fsprogs.sourceforge.net/" + +LICENSE = "GPLv2 & LGPLv2 & BSD & MIT" +LICENSE_e2fsprogs-e2fsck = "GPLv2" +LICENSE_e2fsprogs-mke2fs = "GPLv2" +LICENSE_e2fsprogs-fsck = "GPLv2" +LICENSE_e2fsprogs-tune2fs = "GPLv2" +LICENSE_e2fsprogs-badblocks = "GPLv2" +LIC_FILES_CHKSUM = "file://COPYING;md5=b48f21d765b875bd10400975d12c1ca2 \ + file://lib/ext2fs/ext2fs.h;beginline=1;endline=9;md5=596a8dedcb4e731c6b21c7a46fba6bef \ + file://lib/e2p/e2p.h;beginline=1;endline=7;md5=8a74ade8f9d65095d70ef2d4bf48e36a \ + file://lib/uuid/uuid.h.in;beginline=1;endline=32;md5=dbb8079e114a5f841934b99e59c8820a \ + file://lib/uuid/COPYING;md5=58dcd8452651fc8b07d1f65ce07ca8af \ + file://lib/et/et_name.c;beginline=1;endline=11;md5=ead236447dac7b980dbc5b4804d8c836 \ + file://lib/ss/ss.h;beginline=1;endline=20;md5=6e89ad47da6e75fecd2b5e0e81e1d4a6" +SECTION = "base" +DEPENDS = "util-linux" + +SRC_URI = "git://git.kernel.org/pub/scm/fs/ext2/e2fsprogs.git" +S = "${WORKDIR}/git" + +inherit autotools gettext texinfo pkgconfig multilib_header update-alternatives ptest + +BBCLASSEXTEND = "native nativesdk" diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/acinclude.m4 b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/acinclude.m4 new file mode 100644 index 000000000..c0bd7dbde --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/acinclude.m4 @@ -0,0 +1,135 @@ +# Extracted from the package's shipped aclocal.m4. Custom macros should be in +# acinclude.m4 so running aclocal doesn't blow them away. +# +# Signed-off-by: Ross Burton <ross.burton@intel.com> + +# from http://autoconf-archive.cryp.to/ax_tls.html +# +# This was licensed under the GPL with the following exception: +# +# As a special exception, the respective Autoconf Macro's copyright +# owner gives unlimited permission to copy, distribute and modify the +# configure scripts that are the output of Autoconf when processing +# the Macro. You need not follow the terms of the GNU General Public +# License when using or distributing such scripts, even though +# portions of the text of the Macro appear in them. The GNU General +# Public License (GPL) does govern all other use of the material that +# constitutes the Autoconf Macro. +# +# This special exception to the GPL applies to versions of the +# Autoconf Macro released by the Autoconf Macro Archive. When you make +# and distribute a modified version of the Autoconf Macro, you may +# extend this special exception to the GPL to apply to your modified +# version as well. +# +AC_DEFUN([AX_TLS], [ + AC_MSG_CHECKING(for thread local storage (TLS) class) + AC_CACHE_VAL(ac_cv_tls, [ + ax_tls_keywords="__thread __declspec(thread) none" + for ax_tls_keyword in $ax_tls_keywords; do + case $ax_tls_keyword in + none) ac_cv_tls=none ; break ;; + *) + AC_TRY_COMPILE( + [#include <stdlib.h> + static void + foo(void) { + static ] $ax_tls_keyword [ int bar; + exit(1); + }], + [], + [ac_cv_tls=$ax_tls_keyword ; break], + ac_cv_tls=none + ) + esac + done +]) + + if test "$ac_cv_tls" != "none"; then + dnl AC_DEFINE([TLS], [], [If the compiler supports a TLS storage class define it to that here]) + AC_DEFINE_UNQUOTED([TLS], $ac_cv_tls, [If the compiler supports a TLS storage class define it to that here]) + fi + AC_MSG_RESULT($ac_cv_tls) +]) + +# =========================================================================== +# http://www.nongnu.org/autoconf-archive/check_gnu_make.html +# =========================================================================== +# +# SYNOPSIS +# +# CHECK_GNU_MAKE() +# +# DESCRIPTION +# +# This macro searches for a GNU version of make. If a match is found, the +# makefile variable `ifGNUmake' is set to the empty string, otherwise it +# is set to "#". This is useful for including a special features in a +# Makefile, which cannot be handled by other versions of make. The +# variable _cv_gnu_make_command is set to the command to invoke GNU make +# if it exists, the empty string otherwise. +# +# Here is an example of its use: +# +# Makefile.in might contain: +# +# # A failsafe way of putting a dependency rule into a makefile +# $(DEPEND): +# $(CC) -MM $(srcdir)/*.c > $(DEPEND) +# +# @ifGNUmake@ ifeq ($(DEPEND),$(wildcard $(DEPEND))) +# @ifGNUmake@ include $(DEPEND) +# @ifGNUmake@ endif +# +# Then configure.in would normally contain: +# +# CHECK_GNU_MAKE() +# AC_OUTPUT(Makefile) +# +# Then perhaps to cause gnu make to override any other make, we could do +# something like this (note that GNU make always looks for GNUmakefile +# first): +# +# if ! test x$_cv_gnu_make_command = x ; then +# mv Makefile GNUmakefile +# echo .DEFAULT: > Makefile ; +# echo \ $_cv_gnu_make_command \$@ >> Makefile; +# fi +# +# Then, if any (well almost any) other make is called, and GNU make also +# exists, then the other make wraps the GNU make. +# +# LICENSE +# +# Copyright (c) 2008 John Darrington <j.darrington@elvis.murdoch.edu.au> +# +# Copying and distribution of this file, with or without modification, are +# permitted in any medium without royalty provided the copyright notice +# and this notice are preserved. +# +# Note: Modified by Ted Ts'o to add @ifNotGNUMake@ + +AC_DEFUN( + [CHECK_GNU_MAKE], [ AC_CACHE_CHECK( for GNU make,_cv_gnu_make_command, + _cv_gnu_make_command='' ; +dnl Search all the common names for GNU make + for a in "$MAKE" make gmake gnumake ; do + if test -z "$a" ; then continue ; fi ; + if ( sh -c "$a --version" 2> /dev/null | grep GNU 2>&1 > /dev/null ) ; then + _cv_gnu_make_command=$a ; + break; + fi + done ; + ) ; +dnl If there was a GNU version, then set @ifGNUmake@ to the empty string, '#' otherwise + if test "x$_cv_gnu_make_command" != "x" ; then + ifGNUmake='' ; + ifNotGNUmake='#' ; + else + ifGNUmake='#' ; + ifNotGNUmake='' ; + AC_MSG_RESULT("Not found"); + fi + AC_SUBST(ifGNUmake) + AC_SUBST(ifNotGNUmake) +] ) diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/mkdir.patch b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/mkdir.patch new file mode 100644 index 000000000..2a3aeff61 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/mkdir.patch @@ -0,0 +1,18 @@ +Upstream-Status: Inappropriate [configuration] + +Signed-off-by: Mei Lei <lei.mei@intel.com> + +diff --git a/configure.ac b/configure.ac +index c1fe224..f5ac628 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -1374,7 +1374,8 @@ if test -n "$WITH_DIET_LIBC" ; then + INCLUDES="$INCLUDES -D_REENTRANT" + fi + AC_SUBST(INCLUDES) +-AM_MKINSTALLDIRS ++MKINSTALLDIRS="mkdir -p" ++AC_SUBST(MKINSTALLDIRS) + dnl + dnl Build CFLAGS + dnl diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/ptest.patch b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/ptest.patch new file mode 100644 index 000000000..ef1ce5872 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/ptest.patch @@ -0,0 +1,67 @@ +diff --git a/tests/Makefile.in b/tests/Makefile.in +index 60cf655..ce220f1 100644 +--- a/tests/Makefile.in ++++ b/tests/Makefile.in +@@ -18,7 +18,7 @@ test_one: $(srcdir)/test_one.in Makefile mke2fs.conf + @echo "#!/bin/sh" > test_one + @echo "HTREE=y" >> test_one + @echo "QUOTA=y" >> test_one +- @echo "SRCDIR=@srcdir@" >> test_one ++ @echo "SRCDIR=/usr/lib/e2fsprogs/ptest/test" >> test_one + @echo "DIFF_OPTS=@UNI_DIFF_OPTS@" >> test_one + @cat $(srcdir)/test_one.in >> test_one + @chmod +x test_one +@@ -26,7 +26,7 @@ test_one: $(srcdir)/test_one.in Makefile mke2fs.conf + test_script: test_one test_script.in Makefile mke2fs.conf + @echo "Creating test_script..." + @echo "#!/bin/sh" > test_script +- @echo "SRCDIR=@srcdir@" >> test_script ++ @echo "SRCDIR=/usr/lib/e2fsprogs/ptest/test" >> test_script + @cat $(srcdir)/test_script.in >> test_script + @chmod +x test_script + +diff --git a/tests/test_config b/tests/test_config +index 7f39157..c815a44 100644 +--- a/tests/test_config ++++ b/tests/test_config +@@ -3,24 +3,24 @@ + # + + unset LANG LANGUAGE LC_ADDRESS LC_ALL LC_COLLATE LC_CTYPE LC_IDENTIFICATION LC_MEASUREMENT LC_MESSAGES LC_MONETARY LC_NAME LC_NUMERIC LC_PAPER LC_TELEPHONE LC_TIME PAGER +-FSCK="$USE_VALGRIND ../e2fsck/e2fsck" +-MKE2FS="$USE_VALGRIND ../misc/mke2fs" +-DUMPE2FS="$USE_VALGRIND ../misc/dumpe2fs" +-TUNE2FS="$USE_VALGRIND ../misc/tune2fs" +-CHATTR="$USE_VALGRIND../misc/chattr" +-LSATTR="$USE_VALGRIND ../misc/lsattr" +-E2IMAGE="$USE_VALGRIND ../misc/e2image" +-E2IMAGE_EXE="../misc/e2image" +-DEBUGFS="$USE_VALGRIND ../debugfs/debugfs" +-DEBUGFS_EXE="../debugfs/debugfs" +-TEST_BITS="../debugfs/debugfs" +-RESIZE2FS_EXE="../resize/resize2fs" ++FSCK="$USE_VALGRIND e2fsck" ++MKE2FS="$USE_VALGRIND mke2fs" ++DUMPE2FS="$USE_VALGRIND dumpe2fs" ++TUNE2FS="$USE_VALGRIND tune2fs" ++CHATTR="$USE_VALGRIND chattr" ++LSATTR="$USE_VALGRIND lsattr" ++E2IMAGE="$USE_VALGRIND e2image" ++E2IMAGE_EXE="/sbin/e2image" ++DEBUGFS="$USE_VALGRIND debugfs" ++DEBUGFS_EXE="/sbin/debugfs" ++TEST_BITS="/sbin/debugfs" ++RESIZE2FS_EXE="/sbin/resize2fs" + RESIZE2FS="$USE_VALGRIND $RESIZE2FS_EXE" +-E2UNDO_EXE="../misc/e2undo" ++E2UNDO_EXE="/sbin/e2undo" + E2UNDO="$USE_VALGRIND $E2UNDO_EXE" +-TEST_REL=../tests/progs/test_rel +-TEST_ICOUNT=../tests/progs/test_icount +-CRCSUM=../tests/progs/crcsum ++TEST_REL=./progs/test_rel ++TEST_ICOUNT=./progs/test_icount ++CRCSUM=./progs/crcsum + CLEAN_OUTPUT="sed -f $cmd_dir/filter.sed" + LD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss:${LD_LIBRARY_PATH} + DYLD_LIBRARY_PATH=../lib:../lib/ext2fs:../lib/e2p:../lib/et:../lib/ss:${DYLD_LIBRARY_PATH} diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/quiet-debugfs.patch b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/quiet-debugfs.patch new file mode 100644 index 000000000..830e9d57a --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/quiet-debugfs.patch @@ -0,0 +1,19 @@ +When executing a script don't echo every command, as we do this for entire +filesystems at rootfs time. + +Upstream-Status: Inappropriate +Signed-off-by: Ross Burton <ross.burton@intel.com> + +diff --git a/debugfs/debugfs.c b/debugfs/debugfs.c +index 5590295..ac57292 100644 +--- a/debugfs/debugfs.c ++++ b/debugfs/debugfs.c +@@ -2378,7 +2378,7 @@ static int source_file(const char *cmd_file, int ss_idx) + cp = strchr(buf, '\r'); + if (cp) + *cp = 0; +- printf("debugfs: %s\n", buf); ++ /*printf("debugfs: %s\n", buf);*/ + retval = ss_execute_line(ss_idx, buf); + if (retval) { + ss_perror(ss_idx, retval, buf); diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/remove.ldconfig.call.patch b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/remove.ldconfig.call.patch new file mode 100644 index 000000000..f3e6eb778 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/remove.ldconfig.call.patch @@ -0,0 +1,44 @@ +From b139e03ac2f72e644e547c7ee9b1514383af4d97 Mon Sep 17 00:00:00 2001 +From: Andrei Dinu <andrei.adrianx.dinu@intel.com> +Date: Wed, 30 Jan 2013 15:22:04 +0200 +Subject: [PATCH] When /etc/ld.so.cache is writeable by user running bitbake + then it creates invalid cache (in my case libstdc++.so + cannot be found after building zlib(-native) and I have to + call touch */libstdc++.so && /sbin/ldconfig to fix it. + +So remove ldconfig call from make install-libs + +Patch authored by Martin Jansa. + +Upstream-Status: Inappropriate [disable feature] + +Signed-off-by: Scott Garman <scott.a.garman@intel.com> +Signed-off-by: Andrei Dinu <andrei.adrianx.dinu@intel.com> +--- + lib/Makefile.elf-lib | 3 --- + 1 file changed, 3 deletions(-) + +diff --git a/lib/Makefile.elf-lib b/lib/Makefile.elf-lib +index 78479d3..4a4a5ac 100644 +--- a/lib/Makefile.elf-lib ++++ b/lib/Makefile.elf-lib +@@ -50,8 +50,6 @@ install-shlibs install:: $(ELF_LIB) installdirs-elf-lib $(DEP_INSTALL_SYMLINK) + $(E) " SYMLINK $(libdir)/$(ELF_IMAGE).so" + $(Q) $(INSTALL_SYMLINK) $(ELF_INSTALL_DIR)/$(ELF_SONAME) \ + $(libdir)/$(ELF_IMAGE).so $(DESTDIR) +- $(E) " LDCONFIG" +- $(Q) -$(LDCONFIG) + + install-strip: install + $(E) " STRIP-LIB $(ELF_INSTALL_DIR)/$(ELF_LIB)" +@@ -67,7 +65,6 @@ uninstall-shlibs uninstall:: + $(RM) -f $(DESTDIR)$(ELF_INSTALL_DIR)/$(ELF_LIB) \ + $(DESTDIR)$(ELF_INSTALL_DIR)/$(ELF_SONAME) \ + $(DESTDIR)$(libdir)/$(ELF_IMAGE).so +- -$(LDCONFIG) + + clean:: + $(RM) -rf elfshared +-- +1.7.9.5 + diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/run-ptest b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/run-ptest new file mode 100644 index 000000000..1ac251324 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs/run-ptest @@ -0,0 +1,11 @@ +#!/bin/sh + +cd ./test +./test_script &>../test.log +if [ $? -eq 0 ] +then + echo "PASS: e2fsprogs" + rm test.log +else + echo "FAIL: e2fsprogs" +fi diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_%.bbappend b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_%.bbappend new file mode 100644 index 000000000..35dd361d4 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_%.bbappend @@ -0,0 +1,14 @@ +FILESEXTRAPATHS_prepend := "${THISDIR}/files:" + +# Applying this patch is optional. Only some versions +# of e2fsprogs need it. So try to apply it, but if it fails, +# continue and hope the patch wasn't needed. If it is needed +# and got skipped, the oeqa Smack tests will catch the failure. +SRC_URI += "file://ext_attr.c-fix-adding-multiple-xattrs-during-image-c.patch;apply=no" + +do_patch[postfuncs] += "patch_xattr_support" +patch_xattr_support () { + cd ${S} + cp lib/ext2fs/ext_attr.c lib/ext2fs/ext_attr.c.orig + patch lib/ext2fs/ext_attr.c <${WORKDIR}/ext_attr.c-fix-adding-multiple-xattrs-during-image-c.patch && rm lib/ext2fs/ext_attr.c.orig || mv lib/ext2fs/ext_attr.c.orig lib/ext2fs/ext_attr.c +} diff --git a/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_git.bb b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_git.bb new file mode 100644 index 000000000..bc2d201a4 --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/e2fsprogs_git.bb @@ -0,0 +1,106 @@ +COREDIR = "${COREBASE}/meta/recipes-devtools/e2fsprogs" + +# This recipe is a copy of a e2fsprogs 1.42.99+1.43 from OE-core master and +# only meant to be used when the current OE-core does not have that version yet. +python () { + import os + upstream = os.path.join(d.getVar('COREDIR', True), 'e2fsprogs_1.42.9.bb') + if not os.path.exists(upstream): + raise bb.parse.SkipRecipe("This recipe replaces e2fsprogs 1.42.9 in OE-core. e2fsprogs from OE-core is something else and thus either recent enough to have xattr support or (less likely) something unexpected.") +} + + +require e2fsprogs.inc + +SRC_URI += "file://acinclude.m4 \ + file://remove.ldconfig.call.patch \ + file://quiet-debugfs.patch \ + file://run-ptest \ + file://ptest.patch \ + file://mkdir.patch \ +" + +SRCREV = "0f26747167cc9d82df849b0aad387bf824f04544" +PV = "1.42.99+1.43+git${SRCPV}" +UPSTREAM_CHECK_GITTAGREGEX = "v(?P<pver>\d+\.\d+(\.\d+)*)$" + +EXTRA_OECONF += "--libdir=${base_libdir} --sbindir=${base_sbindir} \ + --enable-elf-shlibs --disable-libuuid --disable-uuidd \ + --disable-libblkid --enable-verbose-makecmds" + +EXTRA_OECONF_darwin = "--libdir=${base_libdir} --sbindir=${base_sbindir} --enable-bsd-shlibs" + +PACKAGECONFIG ??= "" +PACKAGECONFIG[fuse] = '--enable-fuse2fs,--disable-fuse2fs,fuse' + +do_configure_prepend () { + cp ${WORKDIR}/acinclude.m4 ${S}/ +} + +do_install () { + oe_runmake 'DESTDIR=${D}' install + oe_runmake 'DESTDIR=${D}' install-libs + # We use blkid from util-linux now so remove from here + rm -f ${D}${base_libdir}/libblkid* + rm -rf ${D}${includedir}/blkid + rm -f ${D}${base_libdir}/pkgconfig/blkid.pc + rm -f ${D}${base_sbindir}/blkid + rm -f ${D}${base_sbindir}/fsck + rm -f ${D}${base_sbindir}/findfs + + # e2initrd_helper and the pkgconfig files belong in libdir + if [ ! ${D}${libdir} -ef ${D}${base_libdir} ]; then + install -d ${D}${libdir} + mv ${D}${base_libdir}/e2initrd_helper ${D}${libdir} + mv ${D}${base_libdir}/pkgconfig ${D}${libdir} + fi + + oe_multilib_header ext2fs/ext2_types.h + install -d ${D}${base_bindir} + mv ${D}${bindir}/chattr ${D}${base_bindir}/chattr.e2fsprogs + + install -v -m 755 ${S}/contrib/populate-extfs.sh ${D}${base_sbindir}/ +} + +do_install_append_class-target() { + # Clean host path in compile_et, mk_cmds + sed -i -e "s,ET_DIR=\"${S}/lib/et\",ET_DIR=\"${datadir}/et\",g" ${D}${bindir}/compile_et + sed -i -e "s,SS_DIR=\"${S}/lib/ss\",SS_DIR=\"${datadir}/ss\",g" ${D}${bindir}/mk_cmds +} + +RDEPENDS_e2fsprogs = "e2fsprogs-badblocks" +RRECOMMENDS_e2fsprogs = "e2fsprogs-mke2fs e2fsprogs-e2fsck" + +PACKAGES =+ "e2fsprogs-e2fsck e2fsprogs-mke2fs e2fsprogs-tune2fs e2fsprogs-badblocks e2fsprogs-resize2fs" +PACKAGES =+ "libcomerr libss libe2p libext2fs" + +FILES_e2fsprogs-resize2fs = "${base_sbindir}/resize2fs*" +FILES_e2fsprogs-e2fsck = "${base_sbindir}/e2fsck ${base_sbindir}/fsck.ext*" +FILES_e2fsprogs-mke2fs = "${base_sbindir}/mke2fs ${base_sbindir}/mkfs.ext* ${sysconfdir}/mke2fs.conf" +FILES_e2fsprogs-tune2fs = "${base_sbindir}/tune2fs ${base_sbindir}/e2label" +FILES_e2fsprogs-badblocks = "${base_sbindir}/badblocks" +FILES_libcomerr = "${base_libdir}/libcom_err.so.*" +FILES_libss = "${base_libdir}/libss.so.*" +FILES_libe2p = "${base_libdir}/libe2p.so.*" +FILES_libext2fs = "${libdir}/e2initrd_helper ${base_libdir}/libext2fs.so.*" +FILES_${PN}-dev += "${datadir}/*/*.awk ${datadir}/*/*.sed ${base_libdir}/*.so" + +ALTERNATIVE_${PN} = "chattr" +ALTERNATIVE_PRIORITY = "100" +ALTERNATIVE_LINK_NAME[chattr] = "${base_bindir}/chattr" +ALTERNATIVE_TARGET[chattr] = "${base_bindir}/chattr.e2fsprogs" + +ALTERNATIVE_${PN}-doc = "fsck.8" +ALTERNATIVE_LINK_NAME[fsck.8] = "${mandir}/man8/fsck.8" + +RDEPENDS_${PN}-ptest += "${PN} ${PN}-tune2fs coreutils procps bash" + +do_compile_ptest() { + oe_runmake -C ${B}/tests +} + +do_install_ptest() { + cp -a ${B}/tests ${D}${PTEST_PATH}/test + cp -a ${S}/tests/* ${D}${PTEST_PATH}/test + sed -e 's!../e2fsck/e2fsck!e2fsck!g' -i ${D}${PTEST_PATH}/test/*/expect* +} diff --git a/meta-security/recipes-devtools/e2fsprogs/files/ext_attr.c-fix-adding-multiple-xattrs-during-image-c.patch b/meta-security/recipes-devtools/e2fsprogs/files/ext_attr.c-fix-adding-multiple-xattrs-during-image-c.patch new file mode 100644 index 000000000..67b8b68fb --- /dev/null +++ b/meta-security/recipes-devtools/e2fsprogs/files/ext_attr.c-fix-adding-multiple-xattrs-during-image-c.patch @@ -0,0 +1,51 @@ +From 3b2b0922e031628f313f5480c4f1f9413c6656bf Mon Sep 17 00:00:00 2001 +From: Richard Purdie <richard.purdie@linuxfoundation.org> +Date: Wed, 10 Feb 2016 15:51:43 +0100 +Subject: [PATCH] ext_attr.c: fix adding multiple xattrs during image creation + +http://www.nongnu.org/ext2-doc/ext2.html#CONTRIB-EXTENDED-ATTRIBUTES +contains the small snippet that "The entry descriptors are sorted by +attribute name, so that two extended attribute blocks can be compared +efficiently". + +The libext2fs code in e2fsprogs needs to be taught about this minor +sorting detail. Otherwise creating an image with "mkfs.ext -d" from a +filesystem that reports xattrs in listxattr() in an order that does +not match the expected order will lead to an image where listxattr() +reports all xattrs, but reading some values fails with ENODATA. + +[Patch from RP, commit message from Patrick and RP] + +Upstream-Status: Pending [https://bugzilla.yoctoproject.org/show_bug.cgi?id=8992] +--- + lib/ext2fs/ext_attr.c | 7 ++++++- + 1 file changed, 6 insertions(+), 1 deletion(-) + +diff --git a/lib/ext2fs/ext_attr.c b/lib/ext2fs/ext_attr.c +index 0a4f8c0..be8f9c3 100644 +--- a/lib/ext2fs/ext_attr.c ++++ b/lib/ext2fs/ext_attr.c +@@ -258,6 +258,7 @@ static struct ea_name_index ea_names[] = { + static int attr_compare(const void *a, const void *b) + { + const struct ext2_xattr *xa = a, *xb = b; ++ size_t len; + + if (xa->name == NULL) + return +1; +@@ -267,7 +268,11 @@ static int attr_compare(const void *a, const void *b) + return -1; + else if (!strcmp(xb->name, "system.data")) + return +1; +- return 0; ++ len = strlen(xa->name) - strlen(xb->name); ++ if (len) ++ return len; ++ ++ return strcmp(xa->name, xb->name); + } + + static const char *find_ea_prefix(int index) +-- +2.1.4 + diff --git a/meta-security/recipes-kernel/linux/linux-%.bbappend b/meta-security/recipes-kernel/linux/linux-%.bbappend new file mode 100644 index 000000000..717d32e3a --- /dev/null +++ b/meta-security/recipes-kernel/linux/linux-%.bbappend @@ -0,0 +1,17 @@ +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}" + +SRC_URI_append_with-lsm-smack = "${SMACK_KERNEL_SRC_URI_${IS_KERNEL_RECIPE}}" diff --git a/meta-security/recipes-kernel/linux/linux/audit.cfg b/meta-security/recipes-kernel/linux/linux/audit.cfg new file mode 100644 index 000000000..214dbe33f --- /dev/null +++ b/meta-security/recipes-kernel/linux/linux/audit.cfg @@ -0,0 +1,2 @@ +CONFIG_AUDIT=y +CONFIG_AUDITSYSCALL=y diff --git a/meta-security/recipes-kernel/linux/linux/smack-default-lsm.cfg b/meta-security/recipes-kernel/linux/linux/smack-default-lsm.cfg new file mode 100644 index 000000000..b5c48454e --- /dev/null +++ b/meta-security/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-security/recipes-kernel/linux/linux/smack.cfg b/meta-security/recipes-kernel/linux/linux/smack.cfg new file mode 100644 index 000000000..62f465a45 --- /dev/null +++ b/meta-security/recipes-kernel/linux/linux/smack.cfg @@ -0,0 +1,8 @@ +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_TMPFS_XATTR=y diff --git a/meta-security/recipes-security/audit/audit/add-system-call-table-for-ARM.patch b/meta-security/recipes-security/audit/audit/add-system-call-table-for-ARM.patch new file mode 100644 index 000000000..ad94d11bd --- /dev/null +++ b/meta-security/recipes-security/audit/audit/add-system-call-table-for-ARM.patch @@ -0,0 +1,46 @@ +From 52ff74be2f01182ed9d4fcc3da059512fad63d72 Mon Sep 17 00:00:00 2001 +From: Han Chao <chan@windriver.com> +Date: Thu, 27 Feb 2014 14:58:57 +0800 +Subject: [PATCH] add system call table for ARM. + +This change enable audit system call on ARM. +Add arm System call table on machinetabs.h. +Audit system call need enable kernel config CONFIG_AUDITSYSCALL. + +Signed-off-by: Han Chao <chan@windriver.com> +--- + lib/machinetabs.h | 11 ++++++----- + 1 file changed, 6 insertions(+), 5 deletions(-) + +diff --git a/lib/machinetabs.h b/lib/machinetabs.h +index ec2d033..1c2e284 100644 +--- a/lib/machinetabs.h ++++ b/lib/machinetabs.h +@@ -1,10 +1,11 @@ +-/* This is a generated file, see Makefile.am for its inputs. */ +-static const char machine_strings[] = "i386\0i486\0i586\0i686\0ia64\0ppc\0ppc64\0s390\0s390x\0x86_64"; ++/* Such is aways generated file, see Makefile.am for its inputs. ++ * But this version is not generated file, which is for ARM. */ ++static const char machine_strings[] = "armeb\0armv5tejl\0armv5tel\0armv6l\0armv7l"; + static const unsigned machine_s2i_s[] = { +- 0,5,10,15,20,25,29,35,40,46, ++ 0,6,16,25,32, + }; + static const int machine_s2i_i[] = { +- 0,0,0,0,2,4,3,6,5,1, ++ 8,8,8,8,8, + }; + static int machine_s2i(const char *s, int *value) { + size_t len, i; +@@ -19,7 +20,7 @@ static int machine_s2i(const char *s, int *value) { + } + } + static const unsigned machine_i2s_direct[] = { +- 0,46,20,29,25,40,35, ++ 39,85,59,68,64, + }; + static const char *machine_i2s(int v) { + return i2s_direct__(machine_strings, machine_i2s_direct, 0, 6, v); +-- +1.7.9.5 + diff --git a/meta-security/recipes-security/audit/audit/audit-for-cross-compiling.patch b/meta-security/recipes-security/audit/audit/audit-for-cross-compiling.patch new file mode 100644 index 000000000..60a23a8a4 --- /dev/null +++ b/meta-security/recipes-security/audit/audit/audit-for-cross-compiling.patch @@ -0,0 +1,2938 @@ +From f73f654734c5f0d1a6568c6c8fba232b01f919f4 Mon Sep 17 00:00:00 2001 +From: Joe MacDonald <joe@deserted.net> +Date: Wed, 23 Oct 2013 16:02:34 -0400 +Subject: [PATCH] audit: use generated headers for cross compiling + +In the same vein as the patch for audit 2.2.1 (commit: 6c77455b), we generate +the headers which are inherently architecture specific but portable on a +convenient platform and use them for all platforms. + +Upstream-Status: Inappropriate [cross-compile specific] + +Signed-off-by: Joe MacDonald <joe@deserted.net> +--- + auparse/Makefile.am | 200 --------------------------------------------- + auparse/accesstabs.h | 6 ++ + auparse/captabs.h | 14 ++++ + auparse/clocktabs.h | 8 ++ + auparse/clone-flagtabs.h | 10 +++ + auparse/epoll_ctls.h | 8 ++ + auparse/famtabs.h | 14 ++++ + auparse/fcntl-cmdtabs.h | 17 ++++ + auparse/flagtabs.h | 6 ++ + auparse/icmptypetabs.h | 10 +++ + auparse/ip6optnametabs.h | 20 +++++ + auparse/ipccmdtabs.h | 6 ++ + auparse/ipctabs.h | 11 +++ + auparse/ipoptnametabs.h | 17 ++++ + auparse/mmaptabs.h | 8 ++ + auparse/mounttabs.h | 10 +++ + auparse/nfprototabs.h | 9 ++ + auparse/open-flagtabs.h | 8 ++ + auparse/persontabs.h | 17 ++++ + auparse/pktoptnametabs.h | 10 +++ + auparse/prctl_opttabs.h | 14 ++++ + auparse/prottabs.h | 6 ++ + auparse/ptracetabs.h | 17 ++++ + auparse/recvtabs.h | 8 ++ + auparse/rlimittabs.h | 10 +++ + auparse/schedtabs.h | 8 ++ + auparse/seccomptabs.h | 11 +++ + auparse/seektabs.h | 8 ++ + auparse/shm_modetabs.h | 6 ++ + auparse/signaltabs.h | 14 ++++ + auparse/sockleveltabs.h | 12 +++ + auparse/sockoptnametabs.h | 23 ++++++ + auparse/socktabs.h | 10 +++ + auparse/socktypetabs.h | 8 ++ + auparse/tcpoptnametabs.h | 12 +++ + auparse/typetabs.h | 35 ++++++++ + auparse/umounttabs.h | 6 ++ + lib/Makefile.am | 106 ------------------------ + lib/aarch64_tables.h | 125 ++++++++++++++++++++++++++++ + lib/actiontabs.h | 26 ++++++ + lib/alpha_tables.h | 196 ++++++++++++++++++++++++++++++++++++++++++++ + lib/armeb_tables.h | 165 +++++++++++++++++++++++++++++++++++++ + lib/errtabs.h | 78 ++++++++++++++++++ + lib/fieldtabs.h | 49 +++++++++++ + lib/flagtabs.h | 26 ++++++ + lib/ftypetabs.h | 29 +++++++ + lib/i386_tables.h | 163 ++++++++++++++++++++++++++++++++++++ + lib/ia64_tables.h | 147 +++++++++++++++++++++++++++++++++ + lib/machinetabs.h | 26 ++++++ + lib/msg_typetabs.h | 104 +++++++++++++++++++++++ + lib/optabs.h | 11 +++ + lib/ppc_tables.h | 163 ++++++++++++++++++++++++++++++++++++ + lib/s390_tables.h | 153 ++++++++++++++++++++++++++++++++++ + lib/s390x_tables.h | 144 ++++++++++++++++++++++++++++++++ + lib/x86_64_tables.h | 150 ++++++++++++++++++++++++++++++++++ + 55 files changed, 2172 insertions(+), 306 deletions(-) + create mode 100644 auparse/accesstabs.h + create mode 100644 auparse/captabs.h + create mode 100644 auparse/clocktabs.h + create mode 100644 auparse/clone-flagtabs.h + create mode 100644 auparse/epoll_ctls.h + create mode 100644 auparse/famtabs.h + create mode 100644 auparse/fcntl-cmdtabs.h + create mode 100644 auparse/flagtabs.h + create mode 100644 auparse/icmptypetabs.h + create mode 100644 auparse/ip6optnametabs.h + create mode 100644 auparse/ipccmdtabs.h + create mode 100644 auparse/ipctabs.h + create mode 100644 auparse/ipoptnametabs.h + create mode 100644 auparse/mmaptabs.h + create mode 100644 auparse/mounttabs.h + create mode 100644 auparse/nfprototabs.h + create mode 100644 auparse/open-flagtabs.h + create mode 100644 auparse/persontabs.h + create mode 100644 auparse/pktoptnametabs.h + create mode 100644 auparse/prctl_opttabs.h + create mode 100644 auparse/prottabs.h + create mode 100644 auparse/ptracetabs.h + create mode 100644 auparse/recvtabs.h + create mode 100644 auparse/rlimittabs.h + create mode 100644 auparse/schedtabs.h + create mode 100644 auparse/seccomptabs.h + create mode 100644 auparse/seektabs.h + create mode 100644 auparse/shm_modetabs.h + create mode 100644 auparse/signaltabs.h + create mode 100644 auparse/sockleveltabs.h + create mode 100644 auparse/sockoptnametabs.h + create mode 100644 auparse/socktabs.h + create mode 100644 auparse/socktypetabs.h + create mode 100644 auparse/tcpoptnametabs.h + create mode 100644 auparse/typetabs.h + create mode 100644 auparse/umounttabs.h + create mode 100644 lib/aarch64_tables.h + create mode 100644 lib/actiontabs.h + create mode 100644 lib/alpha_tables.h + create mode 100644 lib/armeb_tables.h + create mode 100644 lib/errtabs.h + create mode 100644 lib/fieldtabs.h + create mode 100644 lib/flagtabs.h + create mode 100644 lib/ftypetabs.h + create mode 100644 lib/i386_tables.h + create mode 100644 lib/ia64_tables.h + create mode 100644 lib/machinetabs.h + create mode 100644 lib/msg_typetabs.h + create mode 100644 lib/optabs.h + create mode 100644 lib/ppc_tables.h + create mode 100644 lib/s390_tables.h + create mode 100644 lib/s390x_tables.h + create mode 100644 lib/x86_64_tables.h + +diff --git a/auparse/Makefile.am b/auparse/Makefile.am +index f0ca18f..7d1527c 100644 +--- a/auparse/Makefile.am ++++ b/auparse/Makefile.am +@@ -53,203 +53,3 @@ BUILT_SOURCES = accesstabs.h captabs.h clocktabs.h clone-flagtabs.h \ + seektabs.h shm_modetabs.h signaltabs.h sockoptnametabs.h \ + socktabs.h sockleveltabs.h socktypetabs.h \ + tcpoptnametabs.h typetabs.h umounttabs.h +-noinst_PROGRAMS = gen_accesstabs_h gen_captabs_h gen_clock_h \ +- gen_clone-flagtabs_h \ +- gen_epoll_ctls_h gen_famtabs_h \ +- gen_fcntl-cmdtabs_h gen_flagtabs_h \ +- gen_icmptypetabs_h gen_ipctabs_h gen_ipccmdtabs_h\ +- gen_ipoptnametabs_h gen_ip6optnametabs_h gen_nfprototabs_h \ +- gen_mmaptabs_h gen_mounttabs_h \ +- gen_open-flagtabs_h gen_persontabs_h \ +- gen_prctl_opttabs_h gen_pktoptnametabs_h gen_prottabs_h \ +- gen_recvtabs_h gen_rlimit_h gen_ptracetabs_h \ +- gen_schedtabs_h gen_seccomptabs_h \ +- gen_seektabs_h gen_shm_modetabs_h gen_signals_h \ +- gen_sockoptnametabs_h gen_socktabs_h gen_sockleveltabs_h \ +- gen_socktypetabs_h gen_tcpoptnametabs_h gen_typetabs_h \ +- gen_umounttabs_h +- +-gen_accesstabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h accesstab.h +-gen_accesstabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="accesstab.h"' +-accesstabs.h: gen_accesstabs_h Makefile +- ./gen_accesstabs_h --i2s-transtab access > $@ +- +-gen_captabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h captab.h +-gen_captabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="captab.h"' +-captabs.h: gen_captabs_h Makefile +- ./gen_captabs_h --i2s cap > $@ +- +-gen_clock_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h clocktab.h +-gen_clock_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="clocktab.h"' +-clocktabs.h: gen_clock_h Makefile +- ./gen_clock_h --i2s clock > $@ +- +-gen_clone_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \ +- clone-flagtab.h +-gen_clone_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="clone-flagtab.h"' +-clone-flagtabs.h: gen_clone-flagtabs_h Makefile +- ./gen_clone-flagtabs_h --i2s-transtab clone_flag > $@ +- +-gen_epoll_ctls_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h epoll_ctl.h +-gen_epoll_ctls_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="epoll_ctl.h"' +-epoll_ctls.h: gen_epoll_ctls_h Makefile +- ./gen_epoll_ctls_h --i2s epoll_ctl > $@ +- +-gen_famtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h famtab.h +-gen_famtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="famtab.h"' +-famtabs.h: gen_famtabs_h Makefile +- ./gen_famtabs_h --i2s fam > $@ +- +-gen_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h flagtab.h +-# ../auparse/ is used to avoid using ../lib/flagtab.h +-gen_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="../auparse/flagtab.h"' +-flagtabs.h: gen_flagtabs_h Makefile +- ./gen_flagtabs_h --i2s-transtab flag > $@ +- +-gen_fcntl_cmdtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \ +- fcntl-cmdtab.h +-gen_fcntl_cmdtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="fcntl-cmdtab.h"' +-fcntl-cmdtabs.h: gen_fcntl-cmdtabs_h Makefile +- ./gen_fcntl-cmdtabs_h --i2s fcntl > $@ +- +-gen_icmptypetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h icmptypetab.h +-gen_icmptypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="icmptypetab.h"' +-icmptypetabs.h: gen_icmptypetabs_h Makefile +- ./gen_icmptypetabs_h --i2s icmptype > $@ +- +-gen_ipctabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipctab.h +-gen_ipctabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipctab.h"' +-ipctabs.h: gen_ipctabs_h Makefile +- ./gen_ipctabs_h --i2s ipc > $@ +- +-gen_ipccmdtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipccmdtab.h +-gen_ipccmdtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipccmdtab.h"' +-ipccmdtabs.h: gen_ipccmdtabs_h Makefile +- ./gen_ipccmdtabs_h --i2s-transtab ipccmd > $@ +- +-gen_ipoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ipoptnametab.h +-gen_ipoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ipoptnametab.h"' +-ipoptnametabs.h: gen_ipoptnametabs_h Makefile +- ./gen_ipoptnametabs_h --i2s ipoptname > $@ +- +-gen_ip6optnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ip6optnametab.h +-gen_ip6optnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ip6optnametab.h"' +-ip6optnametabs.h: gen_ip6optnametabs_h Makefile +- ./gen_ip6optnametabs_h --i2s ip6optname > $@ +- +-gen_mmaptabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h mmaptab.h +-gen_mmaptabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="mmaptab.h"' +-mmaptabs.h: gen_mmaptabs_h Makefile +- ./gen_mmaptabs_h --i2s-transtab mmap > $@ +- +-gen_mounttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h mounttab.h +-gen_mounttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="mounttab.h"' +-mounttabs.h: gen_mounttabs_h Makefile +- ./gen_mounttabs_h --i2s-transtab mount > $@ +- +-gen_nfprototabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h nfprototab.h +-gen_nfprototabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="nfprototab.h"' +-nfprototabs.h: gen_nfprototabs_h Makefile +- ./gen_nfprototabs_h --i2s nfproto > $@ +- +-gen_open_flagtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h \ +- open-flagtab.h +-gen_open_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="open-flagtab.h"' +-open-flagtabs.h: gen_open-flagtabs_h Makefile +- ./gen_open-flagtabs_h --i2s-transtab open_flag > $@ +- +-gen_persontabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h persontab.h +-gen_persontabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="persontab.h"' +-persontabs.h: gen_persontabs_h Makefile +- ./gen_persontabs_h --i2s person > $@ +- +-gen_ptracetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h ptracetab.h +-gen_ptracetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ptracetab.h"' +-ptracetabs.h: gen_ptracetabs_h Makefile +- ./gen_ptracetabs_h --i2s ptrace > $@ +- +-gen_prctl_opttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h prctl-opt-tab.h +-gen_prctl_opttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="prctl-opt-tab.h"' +-prctl_opttabs.h: gen_prctl_opttabs_h Makefile +- ./gen_prctl_opttabs_h --i2s prctl_opt > $@ +- +-gen_pktoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h pktoptnametab.h +-gen_pktoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="pktoptnametab.h"' +-pktoptnametabs.h: gen_pktoptnametabs_h Makefile +- ./gen_pktoptnametabs_h --i2s pktoptname > $@ +- +-gen_prottabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h prottab.h +-gen_prottabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="prottab.h"' +-prottabs.h: gen_prottabs_h Makefile +- ./gen_prottabs_h --i2s-transtab prot > $@ +- +-gen_recvtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h recvtab.h +-gen_recvtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="recvtab.h"' +-recvtabs.h: gen_recvtabs_h Makefile +- ./gen_recvtabs_h --i2s-transtab recv > $@ +- +-gen_rlimit_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h rlimittab.h +-gen_rlimit_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="rlimittab.h"' +-rlimittabs.h: gen_rlimit_h Makefile +- ./gen_rlimit_h --i2s rlimit > $@ +- +-gen_schedtabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h schedtab.h +-gen_schedtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="schedtab.h"' +-schedtabs.h: gen_schedtabs_h Makefile +- ./gen_schedtabs_h --i2s sched > $@ +- +-gen_seccomptabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h seccomptab.h +-gen_seccomptabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="seccomptab.h"' +-seccomptabs.h: gen_seccomptabs_h Makefile +- ./gen_seccomptabs_h --i2s seccomp > $@ +- +-gen_seektabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h seektab.h +-gen_seektabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="seektab.h"' +-seektabs.h: gen_seektabs_h Makefile +- ./gen_seektabs_h --i2s seek > $@ +- +-gen_shm_modetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h shm_modetab.h +-gen_shm_modetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="shm_modetab.h"' +-shm_modetabs.h: gen_shm_modetabs_h Makefile +- ./gen_shm_modetabs_h --i2s-transtab shm_mode > $@ +- +-gen_signals_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h signaltab.h +-gen_signals_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="signaltab.h"' +-signaltabs.h: gen_signals_h Makefile +- ./gen_signals_h --i2s signal > $@ +- +-gen_sockleveltabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h sockleveltab.h +-gen_sockleveltabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="sockleveltab.h"' +-sockleveltabs.h: gen_sockleveltabs_h Makefile +- ./gen_sockleveltabs_h --i2s socklevel > $@ +- +-gen_sockoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h sockoptnametab.h +-gen_sockoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="sockoptnametab.h"' +-sockoptnametabs.h: gen_sockoptnametabs_h Makefile +- ./gen_sockoptnametabs_h --i2s sockoptname > $@ +- +-gen_socktabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h socktab.h +-gen_socktabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="socktab.h"' +-socktabs.h: gen_socktabs_h Makefile +- ./gen_socktabs_h --i2s sock > $@ +- +-gen_socktypetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h socktypetab.h +-gen_socktypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="socktypetab.h"' +-socktypetabs.h: gen_socktypetabs_h Makefile +- ./gen_socktypetabs_h --i2s sock_type > $@ +- +-gen_tcpoptnametabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h tcpoptnametab.h +-gen_tcpoptnametabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="tcpoptnametab.h"' +-tcpoptnametabs.h: gen_tcpoptnametabs_h Makefile +- ./gen_tcpoptnametabs_h --i2s tcpoptname > $@ +- +-gen_typetabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h typetab.h +-gen_typetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="typetab.h"' +-typetabs.h: gen_typetabs_h Makefile +- ./gen_typetabs_h --s2i type > $@ +- +-gen_umounttabs_h_SOURCES = ../lib/gen_tables.c ../lib/gen_tables.h umounttab.h +-gen_umounttabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="umounttab.h"' +-umounttabs.h: gen_umounttabs_h Makefile +- ./gen_umounttabs_h --i2s-transtab umount > $@ +- +diff --git a/auparse/accesstabs.h b/auparse/accesstabs.h +new file mode 100644 +index 0000000..867d99c +--- /dev/null ++++ b/auparse/accesstabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char access_strings[] = "R_OK\0W_OK\0X_OK"; ++static const struct transtab access_table[] = { ++ {1,10},{2,5},{4,0}, ++}; ++#define ACCESS_NUM_ENTRIES (sizeof(access_table) / sizeof(*access_table)) +diff --git a/auparse/captabs.h b/auparse/captabs.h +new file mode 100644 +index 0000000..9267466 +--- /dev/null ++++ b/auparse/captabs.h +@@ -0,0 +1,14 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char cap_strings[] = "audit_control\0audit_write\0block_suspend\0chown\0compromise_kernel\0dac_override\0dac_read_search\0fowner\0fsetid\0ipc_lock\0" ++ "ipc_owner\0kill\0lease\0linux_immutable\0mac_admin\0mac_override\0mknod\0net_admin\0net_bind_service\0net_broadcast\0" ++ "net_raw\0setfcap\0setgid\0setpcap\0setuid\0sys_admin\0sys_boot\0sys_chroot\0sys_module\0sys_nice\0" ++ "sys_pacct\0sys_ptrace\0sys_rawio\0sys_resource\0sys_time\0sys_tty_config\0syslog\0wake_alarm"; ++static const unsigned cap_i2s_direct[] = { ++ 40,64,77,93,100,126,239,254,246,137, ++ 192,209,182,223,107,116,291,332,280,321, ++ 311,261,271,302,342,355,364,176,131,14, ++ 0,231,163,153,379,386,26,46, ++}; ++static const char *cap_i2s(int v) { ++ return i2s_direct__(cap_strings, cap_i2s_direct, 0, 37, v); ++} +diff --git a/auparse/clocktabs.h b/auparse/clocktabs.h +new file mode 100644 +index 0000000..03f9f09 +--- /dev/null ++++ b/auparse/clocktabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char clock_strings[] = "CLOCK_BOOTTIME\0CLOCK_BOOTTIME_ALARM\0CLOCK_MONOTONIC\0CLOCK_MONOTONIC_COARSE\0CLOCK_MONOTONIC_RAW\0CLOCK_PROCESS_CPUTIME_ID\0CLOCK_REALTIME\0CLOCK_REALTIME_ALARM\0CLOCK_REALTIME_COARSE\0CLOCK_THREAD_CPUTIME_ID"; ++static const unsigned clock_i2s_direct[] = { ++ 120,36,95,178,75,156,52,0,135,15, ++}; ++static const char *clock_i2s(int v) { ++ return i2s_direct__(clock_strings, clock_i2s_direct, 0, 9, v); ++} +diff --git a/auparse/clone-flagtabs.h b/auparse/clone-flagtabs.h +new file mode 100644 +index 0000000..b8f815d +--- /dev/null ++++ b/auparse/clone-flagtabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char clone_flag_strings[] = "CLONE_CHILD_CLEARTID\0CLONE_CHILD_SETTID\0CLONE_DETACHED\0CLONE_FILES\0CLONE_FS\0CLONE_IO\0CLONE_NEWIPC\0CLONE_NEWNET\0CLONE_NEWNS\0CLONE_NEWPID\0" ++ "CLONE_NEWUSER\0CLONE_NEWUTS\0CLONE_PARENT\0CLONE_PARENT_SETTID\0CLONE_PTRACE\0CLONE_SETTLS\0CLONE_SIGHAND\0CLONE_STOPPED\0CLONE_SYSVSEM\0CLONE_THREAD\0" ++ "CLONE_UNTRACED\0CLONE_VFORK\0CLONE_VM"; ++static const struct transtab clone_flag_table[] = { ++ {256,304},{512,67},{1024,55},{2048,222},{8192,196},{16384,292},{32768,163},{65536,264},{131072,111},{262144,250}, ++ {524288,209},{1048576,176},{2097152,0},{4194304,40},{8388608,277},{16777216,21},{33554432,236},{67108864,150},{134217728,85},{268435456,136}, ++ {536870912,123},{1073741824,98},{-2147483648,76}, ++}; ++#define CLONE_FLAG_NUM_ENTRIES (sizeof(clone_flag_table) / sizeof(*clone_flag_table)) +diff --git a/auparse/epoll_ctls.h b/auparse/epoll_ctls.h +new file mode 100644 +index 0000000..2787c18 +--- /dev/null ++++ b/auparse/epoll_ctls.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char epoll_ctl_strings[] = "EPOLL_CTL_ADD\0EPOLL_CTL_DEL\0EPOLL_CTL_MOD"; ++static const unsigned epoll_ctl_i2s_direct[] = { ++ 0,14,28, ++}; ++static const char *epoll_ctl_i2s(int v) { ++ return i2s_direct__(epoll_ctl_strings, epoll_ctl_i2s_direct, 1, 3, v); ++} +diff --git a/auparse/famtabs.h b/auparse/famtabs.h +new file mode 100644 +index 0000000..cae396b +--- /dev/null ++++ b/auparse/famtabs.h +@@ -0,0 +1,14 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char fam_strings[] = "alg\0appletalk\0ash\0atmpvc\0atmsvc\0ax25\0bluetooth\0bridge\0caif\0can\0" ++ "decnet\0econet\0ieee802154\0inet\0inet6\0ipx\0irda\0isdn\0iucv\0key\0" ++ "llc\0local\0netbeui\0netlink\0netrom\0nfc\0packet\0phonet\0pppox\0rds\0" ++ "rose\0rxrpc\0security\0sna\0tipc\0vsock\0wanpipe\0x25"; ++static const unsigned fam_i2s_direct[] = { ++ 126,88,32,99,4,148,47,18,226,93, ++ 183,63,132,194,118,140,159,14,70,25, ++ 179,203,103,173,218,122,-1u,-1u,59,207, ++ 37,113,188,108,166,77,54,0,155,212, ++}; ++static const char *fam_i2s(int v) { ++ return i2s_direct__(fam_strings, fam_i2s_direct, 1, 40, v); ++} +diff --git a/auparse/fcntl-cmdtabs.h b/auparse/fcntl-cmdtabs.h +new file mode 100644 +index 0000000..18c6cc7 +--- /dev/null ++++ b/auparse/fcntl-cmdtabs.h +@@ -0,0 +1,17 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char fcntl_strings[] = "F_CANCELLK\0F_DUPFD\0F_DUPFD_CLOEXEC\0F_GETFD\0F_GETFL\0F_GETLEASE\0F_GETLK\0F_GETLK64\0F_GETOWN\0F_GETOWNER_UIDS\0" ++ "F_GETOWN_EX\0F_GETPIPE_SZ\0F_GETSIG\0F_NOTIFY\0F_SETFD\0F_SETFL\0F_SETLEASE\0F_SETLK\0F_SETLK64\0F_SETLKW\0" ++ "F_SETLKW64\0F_SETOWN\0F_SETOWN_EX\0F_SETPIPE_SZ\0F_SETSIG"; ++static const int fcntl_i2s_i[] = { ++ 0,1,2,3,4,5,6,7,8,9, ++ 10,11,12,13,14,15,16,17,1024,1025, ++ 1026,1029,1030,1031,1032, ++}; ++static const unsigned fcntl_i2s_s[] = { ++ 11,35,148,43,156,62,175,193,213,80, ++ 247,130,70,183,202,222,105,89,164,51, ++ 139,0,19,234,117, ++}; ++static const char *fcntl_i2s(int v) { ++ return i2s_bsearch__(fcntl_strings, fcntl_i2s_i, fcntl_i2s_s, 25, v); ++} +diff --git a/auparse/flagtabs.h b/auparse/flagtabs.h +new file mode 100644 +index 0000000..5f57e14 +--- /dev/null ++++ b/auparse/flagtabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char flag_strings[] = "access\0atomic\0continue\0create\0directory\0follow\0noalt\0open\0parent"; ++static const struct transtab flag_table[] = { ++ {1,40},{2,30},{4,14},{16,58},{32,47},{64,7},{256,53},{512,23},{1024,0}, ++}; ++#define FLAG_NUM_ENTRIES (sizeof(flag_table) / sizeof(*flag_table)) +diff --git a/auparse/icmptypetabs.h b/auparse/icmptypetabs.h +new file mode 100644 +index 0000000..49b44bf +--- /dev/null ++++ b/auparse/icmptypetabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char icmptype_strings[] = "address-mask-reply\0address-mask-request\0destination-unreachable\0echo\0echo-reply\0info-reply\0info-request\0parameter-problem\0redirect\0source-quench\0" ++ "time-exceeded\0timestamp-reply\0timestamp-request"; ++static const unsigned icmptype_i2s_direct[] = { ++ 69,-1u,-1u,40,131,122,-1u,-1u,64,-1u, ++ -1u,145,104,175,159,91,80,19,0, ++}; ++static const char *icmptype_i2s(int v) { ++ return i2s_direct__(icmptype_strings, icmptype_i2s_direct, 0, 18, v); ++} +diff --git a/auparse/ip6optnametabs.h b/auparse/ip6optnametabs.h +new file mode 100644 +index 0000000..4af11c2 +--- /dev/null ++++ b/auparse/ip6optnametabs.h +@@ -0,0 +1,20 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ip6optname_strings[] = "IP6T_SO_GET_REVISION_MATCH\0IP6T_SO_GET_REVISION_TARGET\0IP6T_SO_ORIGINAL_DST\0IP6T_SO_SET_ADD_COUNTERS\0IP6T_SO_SET_REPLACE\0IPV6_2292DSTOPTS\0IPV6_2292HOPLIMIT\0IPV6_2292HOPOPTS\0IPV6_2292PKTINFO\0IPV6_2292PKTOPTIONS\0" ++ "IPV6_2292RTHDR\0IPV6_ADDRFORM\0IPV6_ADDR_PREFERENCES\0IPV6_ADD_MEMBERSHIP\0IPV6_AUTHHDR\0IPV6_CHECKSUM\0IPV6_DONTFRAG\0IPV6_DROP_MEMBERSHIP\0IPV6_DSTOPTS\0IPV6_FLOWINFO\0" ++ "IPV6_FLOWINFO_SEND\0IPV6_FLOWLABEL_MGR\0IPV6_HOPLIMIT\0IPV6_HOPOPTS\0IPV6_IPSEC_POLICY\0IPV6_JOIN_ANYCAST\0IPV6_LEAVE_ANYCAST\0IPV6_MINHOPCOUNT\0IPV6_MTU\0IPV6_MTU_DISCOVER\0" ++ "IPV6_MULTICAST_HOPS\0IPV6_MULTICAST_IF\0IPV6_MULTICAST_LOOP\0IPV6_NEXTHOP\0IPV6_ORIGDSTADDR\0IPV6_PATHMTU\0IPV6_PKTINFO\0IPV6_RECVDSTOPTS\0IPV6_RECVERR\0IPV6_RECVHOPLIMIT\0" ++ "IPV6_RECVHOPOPTS\0IPV6_RECVPATHMTU\0IPV6_RECVPKTINFO\0IPV6_RECVRTHDR\0IPV6_RECVTCLASS\0IPV6_ROUTER_ALERT\0IPV6_RTHDR\0IPV6_RTHDRDSTOPTS\0IPV6_TCLASS\0IPV6_TRANSPARENT\0" ++ "IPV6_UNICAST_HOPS\0IPV6_UNICAST_IF\0IPV6_USE_MIN_MTU\0IPV6_V6ONLY\0IPV6_XFRM_POLICY"; ++static const unsigned ip6optname_i2s_direct[] = { ++ 225,173,156,121,210,190,294,138,592,281, ++ 356,-1u,-1u,-1u,-1u,854,554,534,572,261, ++ 322,778,516,507,665,905,453,471,-1u,-1u, ++ -1u,389,370,435,917,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,730,635, ++ 678,408,696,422,807,747,796,648,343,713, ++ 622,308,888,101,76,762,825,0,27,-1u, ++ -1u,239,490,605,837,872,-1u,-1u,-1u,55, ++}; ++static const char *ip6optname_i2s(int v) { ++ return i2s_direct__(ip6optname_strings, ip6optname_i2s_direct, 1, 80, v); ++} +diff --git a/auparse/ipccmdtabs.h b/auparse/ipccmdtabs.h +new file mode 100644 +index 0000000..ff43dbb +--- /dev/null ++++ b/auparse/ipccmdtabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ipccmd_strings[] = "IPC_CREAT\0IPC_EXCL\0IPC_NOWAIT"; ++static const struct transtab ipccmd_table[] = { ++ {512,0},{1024,10},{2048,19}, ++}; ++#define IPCCMD_NUM_ENTRIES (sizeof(ipccmd_table) / sizeof(*ipccmd_table)) +diff --git a/auparse/ipctabs.h b/auparse/ipctabs.h +new file mode 100644 +index 0000000..4bf3bcd +--- /dev/null ++++ b/auparse/ipctabs.h +@@ -0,0 +1,11 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ipc_strings[] = "msgctl\0msgget\0msgrcv\0msgsnd\0semctl\0semget\0semop\0semtimedop\0shmat\0shmctl\0" ++ "shmdt\0shmget"; ++static const unsigned ipc_i2s_direct[] = { ++ 42,35,28,48,-1u,-1u,-1u,-1u,-1u,-1u, ++ 21,14,7,0,-1u,-1u,-1u,-1u,-1u,-1u, ++ 59,72,78,65, ++}; ++static const char *ipc_i2s(int v) { ++ return i2s_direct__(ipc_strings, ipc_i2s_direct, 1, 24, v); ++} +diff --git a/auparse/ipoptnametabs.h b/auparse/ipoptnametabs.h +new file mode 100644 +index 0000000..fb0b8b7 +--- /dev/null ++++ b/auparse/ipoptnametabs.h +@@ -0,0 +1,17 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ipoptname_strings[] = "IPT_SO_GET_REVISION_TARGET\0IPT_SO_SET_ADD_COUNTERS\0IPT_SO_SET_REPLACE\0IP_ADD_MEMBERSHIP\0IP_ADD_SOURCE_MEMBERSHIP\0IP_BLOCK_SOURCE\0IP_DROP_MEMBERSHIP\0IP_DROP_SOURCE_MEMBERSHIP\0IP_FREEBIND\0IP_HDRINCL\0" ++ "IP_IPSEC_POLICY\0IP_MINTTL\0IP_MSFILTER\0IP_MTU\0IP_MTU_DISCOVER\0IP_MULTICAST_ALL\0IP_MULTICAST_IF\0IP_MULTICAST_LOOP\0IP_MULTICAST_TTL\0IP_NODEFRAG\0" ++ "IP_OPTIONS\0IP_ORIGDSTADDR\0IP_PASSSEC\0IP_PKTINFO\0IP_PKTOPTIONS\0IP_RECVERR\0IP_RECVOPTS\0IP_RECVTTL\0IP_RETOPTS\0IP_ROUTER_ALERT\0" ++ "IP_TOS\0IP_TRANSPARENT\0IP_TTL\0IP_UNBLOCK_SOURCE\0IP_UNICAST_IF\0IP_XFRM_POLICY"; ++static const unsigned ipoptname_i2s_direct[] = { ++ 461,483,186,338,445,411,434,375,386,242, ++ 400,423,-1u,235,174,197,522,364,468,349, ++ 213,326,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,275,309,291,70,129,490,113,88,148, ++ 223,-1u,-1u,-1u,-1u,-1u,-1u,-1u,258,508, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,51,27,0, ++}; ++static const char *ipoptname_i2s(int v) { ++ return i2s_direct__(ipoptname_strings, ipoptname_i2s_direct, 1, 66, v); ++} +diff --git a/auparse/mmaptabs.h b/auparse/mmaptabs.h +new file mode 100644 +index 0000000..386833c +--- /dev/null ++++ b/auparse/mmaptabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char mmap_strings[] = "MAP_32BIT\0MAP_ANONYMOUS\0MAP_DENYWRITE\0MAP_EXECUTABLE\0MAP_FIXED\0MAP_GROWSDOWN\0MAP_HUGETLB\0MAP_LOCKED\0MAP_NONBLOCK\0MAP_NORESERVE\0" ++ "MAP_POPULATE\0MAP_PRIVATE\0MAP_SHARED\0MAP_STACK"; ++static const struct transtab mmap_table[] = { ++ {1,152},{2,140},{16,53},{32,10},{64,0},{256,63},{2048,24},{4096,38},{8192,89},{16384,113}, ++ {32768,127},{65536,100},{131072,163},{262144,77}, ++}; ++#define MMAP_NUM_ENTRIES (sizeof(mmap_table) / sizeof(*mmap_table)) +diff --git a/auparse/mounttabs.h b/auparse/mounttabs.h +new file mode 100644 +index 0000000..ca66885 +--- /dev/null ++++ b/auparse/mounttabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char mount_strings[] = "MS_ACTIVE\0MS_BIND\0MS_BORN\0MS_DIRSYNC\0MS_I_VERSION\0MS_KERNMOUNT\0MS_MANDLOCK\0MS_MOVE\0MS_NOATIME\0MS_NODEV\0" ++ "MS_NODIRATIME\0MS_NOEXEC\0MS_NOSEC\0MS_NOSUID\0MS_NOUSER\0MS_POSIXACL\0MS_PRIVATE\0MS_RDONLY\0MS_REC\0MS_RELATIME\0" ++ "MS_REMOUNT\0MS_SHARED\0MS_SILENT\0MS_SLAVE\0MS_SNAP_STABLE\0MS_STRICTATIME\0MS_SYNCHRONOUS\0MS_UNBINDABLE"; ++static const struct transtab mount_table[] = { ++ {1,179},{2,136},{4,94},{8,117},{16,278},{32,208},{64,63},{128,26},{1024,83},{2048,103}, ++ {4096,10},{8192,75},{16384,189},{32768,229},{65536,156},{131072,293},{262144,168},{524288,239},{1048576,219},{2097152,196}, ++ {4194304,50},{8388608,37},{16777216,263},{134217728,248},{268435456,127},{536870912,18},{1073741824,0},{-2147483648,146}, ++}; ++#define MOUNT_NUM_ENTRIES (sizeof(mount_table) / sizeof(*mount_table)) +diff --git a/auparse/nfprototabs.h b/auparse/nfprototabs.h +new file mode 100644 +index 0000000..9bb2723 +--- /dev/null ++++ b/auparse/nfprototabs.h +@@ -0,0 +1,9 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char nfproto_strings[] = "arp\0bridge\0decnet\0ipv4\0ipv6\0unspecified"; ++static const unsigned nfproto_i2s_direct[] = { ++ 28,-1u,18,0,-1u,-1u,-1u,4,-1u,-1u, ++ 23,-1u,11, ++}; ++static const char *nfproto_i2s(int v) { ++ return i2s_direct__(nfproto_strings, nfproto_i2s_direct, 0, 12, v); ++} +diff --git a/auparse/open-flagtabs.h b/auparse/open-flagtabs.h +new file mode 100644 +index 0000000..5e3c3eb +--- /dev/null ++++ b/auparse/open-flagtabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char open_flag_strings[] = "O_APPEND\0O_ASYNC\0O_CLOEXEC\0O_CREAT\0O_DIRECT\0O_DIRECTORY\0O_DSYNC\0O_EXCL\0O_NOATIME\0O_NOCTTY\0" ++ "O_NOFOLLOW\0O_NONBLOCK\0O_PATH\0O_RDWR\0O_TRUNC\0O_WRONLY\0__O_SYNC"; ++static const struct transtab open_flag_table[] = { ++ {1,134},{2,119},{64,27},{128,64},{256,81},{512,126},{1024,0},{2048,101},{4096,56},{8192,9}, ++ {16384,35},{65536,44},{131072,90},{262144,71},{524288,17},{1048576,143},{2097152,112}, ++}; ++#define OPEN_FLAG_NUM_ENTRIES (sizeof(open_flag_table) / sizeof(*open_flag_table)) +diff --git a/auparse/persontabs.h b/auparse/persontabs.h +new file mode 100644 +index 0000000..d099839 +--- /dev/null ++++ b/auparse/persontabs.h +@@ -0,0 +1,17 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char person_strings[] = "PER_BSD\0PER_HPUX\0PER_IRIX32\0PER_IRIX64\0PER_IRIXN32\0PER_ISCR4\0PER_LINUX\0PER_LINUX32\0PER_LINUX32_3GB\0PER_LINUX_32BIT\0" ++ "PER_OSF4\0PER_OSR5\0PER_RISCOS\0PER_SCOSVR3\0PER_SOLARIS\0PER_SUNOS\0PER_SVR3\0PER_SVR4\0PER_UW7\0PER_WYSEV386\0" ++ "PER_XENIX"; ++static const int person_i2s_i[] = { ++ 0,6,8,12,15,16,8388608,67108869,67108870,67108873, ++ 67108874,67108875,67108877,68157441,68157454,83886082,83886084,83886087,100663299,117440515, ++ 134217736, ++}; ++static const unsigned person_i2s_s[] = { ++ 61,0,71,133,115,8,99,51,168,17, ++ 39,28,156,187,196,178,204,217,124,144, ++ 83, ++}; ++static const char *person_i2s(int v) { ++ return i2s_bsearch__(person_strings, person_i2s_i, person_i2s_s, 21, v); ++} +diff --git a/auparse/pktoptnametabs.h b/auparse/pktoptnametabs.h +new file mode 100644 +index 0000000..4613372 +--- /dev/null ++++ b/auparse/pktoptnametabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char pktoptname_strings[] = "PACKET_ADD_MEMBERSHIP\0PACKET_AUXDATA\0PACKET_COPY_THRESH\0PACKET_DROP_MEMBERSHIP\0PACKET_FANOUT\0PACKET_HDRLEN\0PACKET_LOSS\0PACKET_ORIGDEV\0PACKET_RECV_OUTPUT\0PACKET_RESERVE\0" ++ "PACKET_RX_RING\0PACKET_STATISTICS\0PACKET_TIMESTAMP\0PACKET_TX_HAS_OFF\0PACKET_TX_RING\0PACKET_TX_TIMESTAMP\0PACKET_VERSION\0PACKET_VNET_HDR"; ++static const unsigned pktoptname_i2s_direct[] = { ++ 0,56,134,-1u,168,183,37,22,119,271, ++ 93,153,236,107,286,251,201,79,218, ++}; ++static const char *pktoptname_i2s(int v) { ++ return i2s_direct__(pktoptname_strings, pktoptname_i2s_direct, 1, 19, v); ++} +diff --git a/auparse/prctl_opttabs.h b/auparse/prctl_opttabs.h +new file mode 100644 +index 0000000..03707a8 +--- /dev/null ++++ b/auparse/prctl_opttabs.h +@@ -0,0 +1,14 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char prctl_opt_strings[] = "PR_CAPBSET_DROP\0PR_CAPBSET_READ\0PR_GET_CHILD_SUBREAPER\0PR_GET_DUMPABLE\0PR_GET_ENDIAN\0PR_GET_FPEMU\0PR_GET_FPEXC\0PR_GET_KEEPCAPS\0PR_GET_NAME\0PR_GET_NO_NEW_PRIVS\0" ++ "PR_GET_PDEATHSIG\0PR_GET_SECCOMP\0PR_GET_SECUREBITS\0PR_GET_TID_ADDRESS\0PR_GET_TIMERSLACK\0PR_GET_TIMING\0PR_GET_TSC\0PR_GET_UNALIGN\0PR_MCE_KILL\0PR_MCE_KILL_GET\0" ++ "PR_SET_CHILD_SUBREAPER\0PR_SET_DUMPABLE\0PR_SET_ENDIAN\0PR_SET_FPEMU\0PR_SET_FPEXC\0PR_SET_KEEPCAPS\0PR_SET_MM\0PR_SET_NAME\0PR_SET_NO_NEW_PRIVS\0PR_SET_PDEATHSIG\0" ++ "PR_SET_SECCOMP\0PR_SET_SECUREBITS\0PR_SET_TIMERSLACK\0PR_SET_TIMING\0PR_SET_TSC\0PR_SET_UNALIGN\0PR_TASK_PERF_EVENTS_DISABLE\0PR_TASK_PERF_EVENTS_ENABLE"; ++static const unsigned prctl_opt_i2s_direct[] = { ++ 451,159,55,337,271,544,111,393,85,367, ++ 98,380,246,519,419,127,-1u,-1u,71,353, ++ 176,468,16,0,260,533,191,483,501,228, ++ 559,587,286,298,409,314,32,431,139,209, ++}; ++static const char *prctl_opt_i2s(int v) { ++ return i2s_direct__(prctl_opt_strings, prctl_opt_i2s_direct, 1, 40, v); ++} +diff --git a/auparse/prottabs.h b/auparse/prottabs.h +new file mode 100644 +index 0000000..1727f43 +--- /dev/null ++++ b/auparse/prottabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char prot_strings[] = "PROT_EXEC\0PROT_READ\0PROT_SEM\0PROT_WRITE"; ++static const struct transtab prot_table[] = { ++ {1,10},{2,29},{4,0},{8,20}, ++}; ++#define PROT_NUM_ENTRIES (sizeof(prot_table) / sizeof(*prot_table)) +diff --git a/auparse/ptracetabs.h b/auparse/ptracetabs.h +new file mode 100644 +index 0000000..6bbfc9b +--- /dev/null ++++ b/auparse/ptracetabs.h +@@ -0,0 +1,17 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ptrace_strings[] = "PTRACE_ATTACH\0PTRACE_CONT\0PTRACE_DETACH\0PTRACE_GETEVENTMSG\0PTRACE_GETFPREGS\0PTRACE_GETFPXREGS\0PTRACE_GETREGS\0PTRACE_GETREGSET\0PTRACE_GETSIGINFO\0PTRACE_INTERRUPT\0" ++ "PTRACE_KILL\0PTRACE_LISTEN\0PTRACE_PEEKDATA\0PTRACE_PEEKTEXT\0PTRACE_PEEKUSER\0PTRACE_POKEDATA\0PTRACE_POKETEXT\0PTRACE_POKEUSER\0PTRACE_SEIZE\0PTRACE_SETFPREGS\0" ++ "PTRACE_SETFPXREGS\0PTRACE_SETOPTIONS\0PTRACE_SETREGS\0PTRACE_SETREGSET\0PTRACE_SETSIGINFO\0PTRACE_SINGLESTEP\0PTRACE_SYSCALL\0PTRACE_TRACEME"; ++static const int ptrace_i2s_i[] = { ++ 0,1,2,3,4,5,6,7,8,9, ++ 12,13,14,15,16,17,18,19,24,16896, ++ 16897,16898,16899,16900,16901,16902,16903,16904, ++}; ++static const unsigned ptrace_i2s_s[] = { ++ 432,203,187,219,251,235,267,14,161,399, ++ 94,349,59,296,0,26,76,313,417,331, ++ 40,126,381,109,364,283,144,173, ++}; ++static const char *ptrace_i2s(int v) { ++ return i2s_bsearch__(ptrace_strings, ptrace_i2s_i, ptrace_i2s_s, 28, v); ++} +diff --git a/auparse/recvtabs.h b/auparse/recvtabs.h +new file mode 100644 +index 0000000..9cab5a3 +--- /dev/null ++++ b/auparse/recvtabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char recv_strings[] = "MSG_CMSG_CLOEXEC\0MSG_CONFIRM\0MSG_CTRUNC\0MSG_DONTROUTE\0MSG_DONTWAIT\0MSG_EOR\0MSG_ERRQUEUE\0MSG_FASTOPEN\0MSG_FIN\0MSG_MORE\0" ++ "MSG_NOSIGNAL\0MSG_OOB\0MSG_PEEK\0MSG_PROXY\0MSG_RST\0MSG_SENDPAGE_NOTLAST\0MSG_SYN\0MSG_TRUNC\0MSG_WAITALL\0MSG_WAITFORONE"; ++static const struct transtab recv_table[] = { ++ {1,131},{2,139},{4,40},{8,29},{16,148},{32,195},{64,54},{128,67},{256,205},{512,101}, ++ {1024,187},{2048,17},{4096,158},{8192,75},{16384,118},{32768,109},{65536,217},{131072,166},{536870912,88},{1073741824,0}, ++}; ++#define RECV_NUM_ENTRIES (sizeof(recv_table) / sizeof(*recv_table)) +diff --git a/auparse/rlimittabs.h b/auparse/rlimittabs.h +new file mode 100644 +index 0000000..364ad69 +--- /dev/null ++++ b/auparse/rlimittabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char rlimit_strings[] = "RLIMIT_AS\0RLIMIT_CORE\0RLIMIT_CPU\0RLIMIT_DATA\0RLIMIT_FSIZE\0RLIMIT_LOCKS\0RLIMIT_MEMLOCK\0RLIMIT_MSGQUEUE\0RLIMIT_NICE\0RLIMIT_NOFILE\0" ++ "RLIMIT_NPROC\0RLIMIT_RSS\0RLIMIT_RTPRIO\0RLIMIT_RTTIME\0RLIMIT_SIGPENDING\0RLIMIT_STACK"; ++static const unsigned rlimit_i2s_direct[] = { ++ 22,45,33,198,10,141,128,114,71,0, ++ 58,180,86,102,152,166, ++}; ++static const char *rlimit_i2s(int v) { ++ return i2s_direct__(rlimit_strings, rlimit_i2s_direct, 0, 15, v); ++} +diff --git a/auparse/schedtabs.h b/auparse/schedtabs.h +new file mode 100644 +index 0000000..875317f +--- /dev/null ++++ b/auparse/schedtabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char sched_strings[] = "SCHED_BATCH\0SCHED_FIFO\0SCHED_IDLE\0SCHED_OTHER\0SCHED_RR"; ++static const unsigned sched_i2s_direct[] = { ++ 34,12,46,0,-1u,23, ++}; ++static const char *sched_i2s(int v) { ++ return i2s_direct__(sched_strings, sched_i2s_direct, 0, 5, v); ++} +diff --git a/auparse/seccomptabs.h b/auparse/seccomptabs.h +new file mode 100644 +index 0000000..5c6c911 +--- /dev/null ++++ b/auparse/seccomptabs.h +@@ -0,0 +1,11 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char seccomp_strings[] = "allow\0errno\0kill\0trace\0trap"; ++static const int seccomp_i2s_i[] = { ++ 0,196608,327680,2146435072,2147418112, ++}; ++static const unsigned seccomp_i2s_s[] = { ++ 12,23,6,17,0, ++}; ++static const char *seccomp_i2s(int v) { ++ return i2s_bsearch__(seccomp_strings, seccomp_i2s_i, seccomp_i2s_s, 5, v); ++} +diff --git a/auparse/seektabs.h b/auparse/seektabs.h +new file mode 100644 +index 0000000..0d0f542 +--- /dev/null ++++ b/auparse/seektabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char seek_strings[] = "SEEK_CUR\0SEEK_DATA\0SEEK_END\0SEEK_HOLE\0SEEK_SET"; ++static const unsigned seek_i2s_direct[] = { ++ 38,0,19,9,28, ++}; ++static const char *seek_i2s(int v) { ++ return i2s_direct__(seek_strings, seek_i2s_direct, 0, 4, v); ++} +diff --git a/auparse/shm_modetabs.h b/auparse/shm_modetabs.h +new file mode 100644 +index 0000000..ddd414d +--- /dev/null ++++ b/auparse/shm_modetabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char shm_mode_strings[] = "SHM_DEST\0SHM_HUGETLB\0SHM_LOCKED\0SHM_NORESERVE"; ++static const struct transtab shm_mode_table[] = { ++ {512,0},{1024,21},{2048,9},{4096,32}, ++}; ++#define SHM_MODE_NUM_ENTRIES (sizeof(shm_mode_table) / sizeof(*shm_mode_table)) +diff --git a/auparse/signaltabs.h b/auparse/signaltabs.h +new file mode 100644 +index 0000000..91ce38e +--- /dev/null ++++ b/auparse/signaltabs.h +@@ -0,0 +1,14 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char signal_strings[] = "IGPWR\0SIG0\0SIGABRT\0SIGALRM\0SIGBUS\0SIGCHLD\0SIGCONT\0SIGFPE\0SIGHUP\0SIGILL\0" ++ "SIGINT\0SIGIO\0SIGKILL\0SIGPIPE\0SIGPROF\0SIGQUIT\0SIGSEGV\0SIGSTKFLT\0SIGSTOP\0SIGSYS\0" ++ "SIGTERM\0SIGTRAP\0SIGTSTP\0SIGTTIN\0SIGTTOU\0SIGURG\0SIGUSR1\0SIGUSR2\0SIGVTALRM\0SIGWINCH\0" ++ "SIGXCPU\0SIGXFSZ"; ++static const unsigned signal_i2s_direct[] = { ++ 6,57,71,108,64,157,11,27,50,84, ++ 196,116,204,92,19,149,124,34,42,134, ++ 165,173,181,189,231,239,212,100,222,78, ++ 0,142, ++}; ++static const char *signal_i2s(int v) { ++ return i2s_direct__(signal_strings, signal_i2s_direct, 0, 31, v); ++} +diff --git a/auparse/sockleveltabs.h b/auparse/sockleveltabs.h +new file mode 100644 +index 0000000..4473d8c +--- /dev/null ++++ b/auparse/sockleveltabs.h +@@ -0,0 +1,12 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char socklevel_strings[] = "SOL_AAL\0SOL_ALG\0SOL_ATALK\0SOL_ATM\0SOL_AX25\0SOL_BLUETOOTH\0SOL_CAIF\0SOL_DCCP\0SOL_DECNET\0SOL_IPX\0" ++ "SOL_IRDA\0SOL_IUCV\0SOL_LLC\0SOL_NETBEUI\0SOL_NETLINK\0SOL_NETROM\0SOL_PACKET\0SOL_PNPIPE\0SOL_PPPOL2TP\0SOL_RAW\0" ++ "SOL_RDS\0SOL_ROSE\0SOL_RXRPC\0SOL_TIPC"; ++static const unsigned socklevel_i2s_direct[] = { ++ 190,86,34,16,144,206,75,-1u,155,26, ++ 0,94,120,112,66,132,225,215,177,43, ++ 166,198,103,57,8, ++}; ++static const char *socklevel_i2s(int v) { ++ return i2s_direct__(socklevel_strings, socklevel_i2s_direct, 255, 279, v); ++} +diff --git a/auparse/sockoptnametabs.h b/auparse/sockoptnametabs.h +new file mode 100644 +index 0000000..831a030 +--- /dev/null ++++ b/auparse/sockoptnametabs.h +@@ -0,0 +1,23 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char sockoptname_strings[] = "SO_ACCEPTCONN\0SO_ATTACH_FILTER\0SO_BINDTODEVICE\0SO_BROADCAST\0SO_BSDCOMPAT\0SO_DEBUG\0SO_DETACH_FILTER\0SO_DOMAIN\0SO_DONTROUTE\0SO_ERROR\0" ++ "SO_KEEPALIVE\0SO_LINGER\0SO_LOCK_FILTER\0SO_MARK\0SO_NOFCS\0SO_NO_CHECK\0SO_OOBINLINE\0SO_PASSCRED\0SO_PASSCRED\0SO_PASSSEC\0" ++ "SO_PEEK_OFF\0SO_PEERCRED\0SO_PEERCRED\0SO_PEERNAME\0SO_PEERSEC\0SO_PRIORITY\0SO_PROTOCOL\0SO_RCVBUF\0SO_RCVBUFFORCE\0SO_RCVLOWAT\0" ++ "SO_RCVLOWAT\0SO_RCVTIMEO\0SO_RCVTIMEO\0SO_REUSEADDR\0SO_REUSEPORT\0SO_RXQ_OVFL\0SO_SECURITY_AUTHENTICATION\0SO_SECURITY_ENCRYPTION_NETWORK\0SO_SECURITY_ENCRYPTION_TRANSPORT\0SO_SNDBUF\0" ++ "SO_SNDBUFFORCE\0SO_SNDLOWAT\0SO_SNDLOWAT\0SO_SNDTIMEO\0SO_SNDTIMEO\0SO_TIMESTAMP\0SO_TIMESTAMPING\0SO_TIMESTAMPNS\0SO_TYPE\0SO_WIFI_STATUS"; ++static const int sockoptname_i2s_i[] = { ++ 1,2,3,4,5,6,7,8,9,10, ++ 11,12,13,14,15,16,17,18,19,20, ++ 21,22,23,24,25,26,27,28,29,30, ++ 31,32,33,34,35,36,37,38,39,40, ++ 41,42,43,44,116,117,118,119,120,121, ++}; ++static const unsigned sockoptname_i2s_s[] = { ++ 73,402,648,122,109,47,531,329,131,198, ++ 186,305,144,60,415,211,258,354,556,378, ++ 580,440,498,467,31,14,82,282,604,0, ++ 294,541,339,235,633,169,617,317,99,428, ++ 656,246,177,154,366,568,390,592,223,270, ++}; ++static const char *sockoptname_i2s(int v) { ++ return i2s_bsearch__(sockoptname_strings, sockoptname_i2s_i, sockoptname_i2s_s, 50, v); ++} +diff --git a/auparse/socktabs.h b/auparse/socktabs.h +new file mode 100644 +index 0000000..66a8235 +--- /dev/null ++++ b/auparse/socktabs.h +@@ -0,0 +1,10 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char sock_strings[] = "accept\0accept4\0bind\0connect\0getpeername\0getsockname\0getsockopt\0listen\0recv\0recvfrom\0" ++ "recvmmsg\0recvmsg\0send\0sendmmsg\0sendmsg\0sendto\0setsockopt\0shutdown\0socket\0socketpair"; ++static const unsigned sock_i2s_direct[] = { ++ 150,15,20,63,0,40,28,157,101,70, ++ 123,75,141,130,52,115,93,7,84,106, ++}; ++static const char *sock_i2s(int v) { ++ return i2s_direct__(sock_strings, sock_i2s_direct, 1, 20, v); ++} +diff --git a/auparse/socktypetabs.h b/auparse/socktypetabs.h +new file mode 100644 +index 0000000..05e8d36 +--- /dev/null ++++ b/auparse/socktypetabs.h +@@ -0,0 +1,8 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char sock_type_strings[] = "SOCK_DCCP\0SOCK_DGRAM\0SOCK_PACKET\0SOCK_RAW\0SOCK_RDM\0SOCK_SEQPACKET\0SOCK_STREAM"; ++static const unsigned sock_type_i2s_direct[] = { ++ 66,10,33,42,51,0,-1u,-1u,-1u,21, ++}; ++static const char *sock_type_i2s(int v) { ++ return i2s_direct__(sock_type_strings, sock_type_i2s_direct, 1, 10, v); ++} +diff --git a/auparse/tcpoptnametabs.h b/auparse/tcpoptnametabs.h +new file mode 100644 +index 0000000..061db3f +--- /dev/null ++++ b/auparse/tcpoptnametabs.h +@@ -0,0 +1,12 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char tcpoptname_strings[] = "TCP_CONGESTION\0TCP_COOKIE_TRANSACTIONS\0TCP_CORK\0TCP_DEFER_ACCEPT\0TCP_FASTOPEN\0TCP_INFO\0TCP_KEEPCNT\0TCP_KEEPIDLE\0TCP_KEEPINTVL\0TCP_LINGER2\0" ++ "TCP_MAXSEG\0TCP_MD5SIG\0TCP_NODELAY\0TCP_QUEUE_SEQ\0TCP_QUICKACK\0TCP_REPAIR\0TCP_REPAIR_OPTIONS\0TCP_REPAIR_QUEUE\0TCP_SYNCNT\0TCP_THIN_DUPACK\0" ++ "TCP_THIN_LINEAR_TIMEOUTS\0TCP_TIMESTAMP\0TCP_USER_TIMEOUT\0TCP_WINDOW_CLAMP"; ++static const unsigned tcpoptname_i2s_direct[] = { ++ 160,138,39,99,112,87,246,126,48,329, ++ 78,186,0,149,15,273,257,312,199,229, ++ 172,210,65,298, ++}; ++static const char *tcpoptname_i2s(int v) { ++ return i2s_direct__(tcpoptname_strings, tcpoptname_i2s_direct, 1, 24, v); ++} +diff --git a/auparse/typetabs.h b/auparse/typetabs.h +new file mode 100644 +index 0000000..a99d398 +--- /dev/null ++++ b/auparse/typetabs.h +@@ -0,0 +1,35 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char type_strings[] = "a0\0a1\0a2\0a3\0acct\0addr\0arch\0auid\0cap_fi\0cap_fp\0" ++ "cap_pe\0cap_pi\0cap_pp\0capability\0cgroup\0cmd\0code\0comm\0cwd\0data\0" ++ "device\0dir\0egid\0euid\0exe\0exit\0family\0fe\0fi\0file\0" ++ "flags\0fp\0fsgid\0fsuid\0gid\0icmptype\0id\0igid\0inode_gid\0inode_uid\0" ++ "iuid\0key\0list\0mode\0name\0new-disk\0new-fs\0new-rng\0new_gid\0new_pe\0" ++ "new_pi\0new_pp\0oauid\0obj_gid\0obj_uid\0ocomm\0oflag\0ogid\0old-disk\0old-fs\0" ++ "old-rng\0old_pe\0old_pi\0old_pp\0old_prom\0ouid\0path\0per\0perm\0perm_mask\0" ++ "prom\0proto\0res\0result\0saddr\0sauid\0ses\0sgid\0sig\0sigev_signo\0" ++ "suid\0syscall\0uid\0vm\0watch"; ++static const unsigned type_s2i_s[] = { ++ 0,3,6,9,12,17,22,27,32,39, ++ 46,53,60,67,78,85,89,94,99,103, ++ 108,115,119,124,129,133,138,145,148,151, ++ 156,162,165,171,177,181,190,193,198,208, ++ 218,223,227,232,237,242,251,258,266,274, ++ 281,288,295,301,309,317,323,329,334,343, ++ 350,358,365,372,379,388,393,398,402,407, ++ 417,422,428,432,439,445,451,455,460,464, ++ 476,481,489,493,496, ++}; ++static const int type_s2i_i[] = { ++ 14,15,16,17,6,26,4,1,22,22, ++ 22,22,22,12,6,6,28,6,6,20, ++ 6,6,2,1,6,5,23,22,22,6, ++ 30,22,2,1,2,24,1,2,2,1, ++ 1,6,19,8,6,6,6,6,2,22, ++ 22,22,1,2,1,6,29,2,6,6, ++ 6,22,22,22,11,1,6,27,7,7, ++ 11,25,13,13,9,1,21,2,18,18, ++ 1,3,1,6,6, ++}; ++static int type_s2i(const char *s, int *value) { ++ return s2i__(type_strings, type_s2i_s, type_s2i_i, 85, s, value); ++} +diff --git a/auparse/umounttabs.h b/auparse/umounttabs.h +new file mode 100644 +index 0000000..e98118f +--- /dev/null ++++ b/auparse/umounttabs.h +@@ -0,0 +1,6 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char umount_strings[] = "MNT_DETACH\0MNT_EXPIRE\0MNT_FORCE\0UMOUNT_NOFOLLOW\0UMOUNT_UNUSED"; ++static const struct transtab umount_table[] = { ++ {1,22},{2,0},{4,11},{8,32},{-2147483647,48}, ++}; ++#define UMOUNT_NUM_ENTRIES (sizeof(umount_table) / sizeof(*umount_table)) +diff --git a/lib/Makefile.am b/lib/Makefile.am +index 5e9f966..5a7d12b 100644 +--- a/lib/Makefile.am ++++ b/lib/Makefile.am +@@ -50,109 +50,3 @@ endif + if USE_AARCH64 + BUILT_SOURCES += aarch64_tables.h + endif +-noinst_PROGRAMS = gen_actiontabs_h gen_errtabs_h gen_fieldtabs_h \ +- gen_flagtabs_h gen_ftypetabs_h gen_i386_tables_h \ +- gen_ia64_tables_h gen_machinetabs_h gen_msg_typetabs_h \ +- gen_optabs_h gen_ppc_tables_h gen_s390_tables_h \ +- gen_s390x_tables_h gen_x86_64_tables_h +-if USE_ALPHA +-noinst_PROGRAMS += gen_alpha_tables_h +-endif +-if USE_ARMEB +-noinst_PROGRAMS += gen_armeb_tables_h +-endif +-if USE_AARCH64 +-noinst_PROGRAMS += gen_aarch64_tables_h +-endif +-gen_actiontabs_h_SOURCES = gen_tables.c gen_tables.h actiontab.h +-gen_actiontabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="actiontab.h"' +-actiontabs.h: gen_actiontabs_h Makefile +- ./gen_actiontabs_h --lowercase --i2s --s2i action > $@ +- +-if USE_ALPHA +-gen_alpha_tables_h_SOURCES = gen_tables.c gen_tables.h alpha_table.h +-gen_alpha_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="alpha_table.h"' +-alpha_tables.h: gen_alpha_tables_h Makefile +- ./gen_alpha_tables_h --lowercase --i2s --s2i alpha_syscall > $@ +-endif +- +-if USE_ARMEB +-gen_armeb_tables_h_SOURCES = gen_tables.c gen_tables.h armeb_table.h +-gen_armeb_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="armeb_table.h"' +-armeb_tables.h: gen_armeb_tables_h Makefile +- ./gen_armeb_tables_h --lowercase --i2s --s2i armeb_syscall > $@ +-endif +- +-if USE_AARCH64 +-gen_aarch64_tables_h_SOURCES = gen_tables.c gen_tables.h aarch64_table.h +-gen_aarch64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="aarch64_table.h"' +-aarch64_tables.h: gen_aarch64_tables_h Makefile +- ./gen_aarch64_tables_h --lowercase --i2s --s2i aarch64_syscall > $@ +-endif +- +-gen_errtabs_h_SOURCES = gen_tables.c gen_tables.h errtab.h +-gen_errtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="errtab.h"' +-errtabs.h: gen_errtabs_h Makefile +- ./gen_errtabs_h --duplicate-ints --uppercase --i2s --s2i err > $@ +- +-gen_fieldtabs_h_SOURCES = gen_tables.c gen_tables.h fieldtab.h +-gen_fieldtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="fieldtab.h"' +-fieldtabs.h: gen_fieldtabs_h Makefile +- ./gen_fieldtabs_h --duplicate-ints --lowercase --i2s --s2i field > $@ +- +-gen_flagtabs_h_SOURCES = gen_tables.c gen_tables.h flagtab.h +-gen_flagtabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="flagtab.h"' +-flagtabs.h: gen_flagtabs_h Makefile +- ./gen_flagtabs_h --lowercase --i2s --s2i flag > $@ +- +-gen_ftypetabs_h_SOURCES = gen_tables.c gen_tables.h ftypetab.h +-gen_ftypetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ftypetab.h"' +-ftypetabs.h: gen_ftypetabs_h Makefile +- ./gen_ftypetabs_h --lowercase --i2s --s2i ftype > $@ +- +-gen_i386_tables_h_SOURCES = gen_tables.c gen_tables.h i386_table.h +-gen_i386_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="i386_table.h"' +-i386_tables.h: gen_i386_tables_h Makefile +- ./gen_i386_tables_h --duplicate-ints --lowercase --i2s --s2i \ +- i386_syscall > $@ +- +-gen_ia64_tables_h_SOURCES = gen_tables.c gen_tables.h ia64_table.h +-gen_ia64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ia64_table.h"' +-ia64_tables.h: gen_ia64_tables_h Makefile +- ./gen_ia64_tables_h --lowercase --i2s --s2i ia64_syscall > $@ +- +-gen_machinetabs_h_SOURCES = gen_tables.c gen_tables.h machinetab.h +-gen_machinetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="machinetab.h"' +-machinetabs.h: gen_machinetabs_h Makefile +- ./gen_machinetabs_h --duplicate-ints --lowercase --i2s --s2i machine \ +- > $@ +- +-gen_msg_typetabs_h_SOURCES = gen_tables.c gen_tables.h msg_typetab.h +-gen_msg_typetabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="msg_typetab.h"' +-msg_typetabs.h: gen_msg_typetabs_h Makefile +- ./gen_msg_typetabs_h --uppercase --i2s --s2i msg_type > $@ +- +-gen_optabs_h_SOURCES = gen_tables.c gen_tables.h optab.h +-gen_optabs_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="optab.h"' +-optabs.h: gen_optabs_h Makefile +- ./gen_optabs_h --i2s op > $@ +- +-gen_ppc_tables_h_SOURCES = gen_tables.c gen_tables.h ppc_table.h +-gen_ppc_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="ppc_table.h"' +-ppc_tables.h: gen_ppc_tables_h Makefile +- ./gen_ppc_tables_h --lowercase --i2s --s2i ppc_syscall > $@ +- +-gen_s390_tables_h_SOURCES = gen_tables.c gen_tables.h s390_table.h +-gen_s390_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="s390_table.h"' +-s390_tables.h: gen_s390_tables_h Makefile +- ./gen_s390_tables_h --lowercase --i2s --s2i s390_syscall > $@ +- +-gen_s390x_tables_h_SOURCES = gen_tables.c gen_tables.h s390x_table.h +-gen_s390x_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="s390x_table.h"' +-s390x_tables.h: gen_s390x_tables_h Makefile +- ./gen_s390x_tables_h --lowercase --i2s --s2i s390x_syscall > $@ +- +-gen_x86_64_tables_h_SOURCES = gen_tables.c gen_tables.h x86_64_table.h +-gen_x86_64_tables_h_CFLAGS = $(AM_CFLAGS) '-DTABLE_H="x86_64_table.h"' +-x86_64_tables.h: gen_x86_64_tables_h Makefile +- ./gen_x86_64_tables_h --lowercase --i2s --s2i x86_64_syscall > $@ +diff --git a/lib/aarch64_tables.h b/lib/aarch64_tables.h +new file mode 100644 +index 0000000..571d6ee +--- /dev/null ++++ b/lib/aarch64_tables.h +@@ -0,0 +1,125 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char aarch64_syscall_strings[] = "accept\0accept4\0acct\0add_key\0adjtimex\0bind\0brk\0capget\0capset\0chdir\0" ++ "chroot\0clock_adjtime\0clock_getres\0clock_gettime\0clock_nanosleep\0clock_settime\0clone\0close\0connect\0delete_module\0" ++ "dup\0dup3\0epoll_create1\0epoll_ctl\0epoll_pwait\0eventfd2\0execve\0exit\0exit_group\0faccessat\0" ++ "fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0fchownat\0fdatasync\0fgetxattr\0" ++ "finit_module\0flistxattr\0flock\0fremovexattr\0fsetxattr\0fsync\0futex\0get_mempolicy\0get_robust_list\0getcpu\0" ++ "getcwd\0getdents64\0getegid\0geteuid\0getgid\0getgroups\0getitimer\0getpeername\0getpgid\0getpid\0" ++ "getppid\0getpriority\0getresgid\0getresuid\0getrlimit\0getrusage\0getsid\0getsockname\0getsockopt\0gettid\0" ++ "gettimeofday\0getuid\0getxattr\0init_module\0inotify_add_watch\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0" ++ "io_setup\0io_submit\0ioctl\0ioprio_get\0ioprio_set\0kcmp\0kexec_load\0keyctl\0kill\0lgetxattr\0" ++ "linkat\0listen\0listxattr\0llistxattr\0lookup_dcookie\0lremovexattr\0lsetxattr\0madvise\0mbind\0migrate_pages\0" ++ "mincore\0mkdirat\0mknodat\0mlock\0mlockall\0mount\0move_pages\0mprotect\0mq_getsetattr\0mq_notify\0" ++ "mq_open\0mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msgctl\0msgget\0msgrcv\0msgsnd\0msync\0" ++ "munlock\0munlockall\0munmap\0name_to_handle_at\0nanosleep\0nfsservctl\0open_by_handle_at\0openat\0perf_event_open\0personality\0" ++ "pipe2\0pivot_root\0ppoll\0prctl\0pread64\0preadv\0prlimit64\0process_vm_readv\0process_vm_writev\0pselect6\0" ++ "ptrace\0pwrite64\0pwritev\0quotactl\0read\0readahead\0readlinkat\0readv\0reboot\0recvfrom\0" ++ "recvmmsg\0recvmsg\0remap_file_pages\0removexattr\0renameat\0request_key\0restart_syscall\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0" ++ "rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0" ++ "sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0sched_yield\0semctl\0semget\0semop\0semtimedop\0sendmmsg\0" ++ "sendmsg\0sendto\0set_mempolicy\0set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsuid\0setgid\0setgroups\0" ++ "sethostname\0setitimer\0setns\0setpgid\0setpriority\0setregid\0setresgid\0setresuid\0setreuid\0setrlimit\0" ++ "setsid\0setsockopt\0settimeofday\0setuid\0setxattr\0shmat\0shmctl\0shmdt\0shmget\0shutdown\0" ++ "sigaltstack\0signalfd4\0socket\0socketpair\0splice\0swapoff\0swapon\0symlinkat\0sync\0sync_file_range\0" ++ "syncfs\0sysinfo\0syslog\0tee\0tgkill\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0" ++ "timerfd_create\0timerfd_gettime\0timerfd_settime\0times\0tkill\0umask\0umount2\0uname\0unlinkat\0unshare\0" ++ "utimensat\0vhangup\0vmsplice\0wait4\0waitid\0write\0writev"; ++static const unsigned aarch64_syscall_s2i_s[] = { ++ 0,7,15,20,28,37,42,46,53,60, ++ 66,73,87,100,114,130,144,150,156,164, ++ 178,182,187,201,211,223,232,239,244,255, ++ 265,275,289,303,310,317,326,333,342,352, ++ 362,375,386,392,405,415,421,427,441,457, ++ 464,471,482,490,498,505,515,525,537,545, ++ 552,560,572,582,592,602,612,619,631,642, ++ 649,662,669,678,690,708,722,739,749,760, ++ 773,782,792,798,809,820,825,836,843,848, ++ 858,865,872,882,893,908,921,931,939,945, ++ 959,967,975,983,989,998,1004,1015,1024,1038, ++ 1048,1056,1072,1085,1095,1102,1109,1116,1123,1130, ++ 1136,1144,1155,1162,1180,1190,1201,1219,1226,1242, ++ 1254,1260,1271,1277,1283,1291,1298,1308,1325,1343, ++ 1352,1359,1368,1376,1385,1390,1400,1411,1417,1424, ++ 1433,1442,1450,1467,1479,1488,1500,1516,1529,1543, ++ 1558,1574,1587,1601,1617,1635,1658,1681,1699,1714, ++ 1733,1755,1773,1788,1807,1819,1826,1833,1839,1850, ++ 1859,1867,1874,1888,1904,1920,1934,1943,1952,1959, ++ 1969,1981,1991,1997,2005,2017,2026,2036,2046,2055, ++ 2065,2072,2083,2096,2103,2112,2118,2125,2131,2138, ++ 2147,2159,2169,2176,2187,2194,2202,2209,2219,2224, ++ 2240,2247,2255,2262,2266,2273,2286,2299,2316,2330, ++ 2344,2359,2375,2391,2397,2403,2409,2417,2423,2432, ++ 2440,2450,2458,2467,2473,2480,2486, ++}; ++static const int aarch64_syscall_s2i_i[] = { ++ 202,242,89,217,171,200,214,90,91,49, ++ 51,266,114,113,115,112,220,57,203,106, ++ 23,24,20,21,22,19,221,93,94,48, ++ 47,262,263,50,52,53,55,54,83,10, ++ 273,13,32,16,7,82,98,236,100,168, ++ 17,61,177,175,176,158,102,205,155,172, ++ 173,141,150,148,163,165,156,204,209,178, ++ 169,174,8,105,27,26,28,3,1,4, ++ 0,2,29,31,30,272,104,219,129,9, ++ 37,201,11,12,18,15,6,233,235,238, ++ 232,34,33,228,230,40,239,226,185,184, ++ 180,183,182,181,216,187,186,188,189,227, ++ 229,231,215,264,101,42,265,56,241,92, ++ 59,41,73,167,67,69,261,270,271,72, ++ 117,68,70,60,63,213,78,65,142,207, ++ 243,212,234,14,38,218,128,134,136,135, ++ 138,139,133,137,240,125,126,123,121,120, ++ 127,122,118,119,124,191,190,193,192,269, ++ 211,206,237,99,96,162,152,151,144,159, ++ 161,103,268,154,140,143,149,147,145,164, ++ 157,208,170,146,5,196,195,197,194,210, ++ 132,74,198,199,76,225,224,36,81,84, ++ 267,179,116,77,131,107,111,109,108,110, ++ 85,87,86,153,130,166,39,160,35,97, ++ 88,58,75,260,95,64,66, ++}; ++static int aarch64_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(aarch64_syscall_strings, aarch64_syscall_s2i_s, aarch64_syscall_s2i_i, 247, copy, value); ++ } ++} ++static const unsigned aarch64_syscall_i2s_direct[] = { ++ 773,749,782,739,760,2103,921,405,669,848, ++ 352,872,882,375,1467,908,392,464,893,223, ++ 187,201,211,178,182,-1u,708,690,722,792, ++ 809,798,386,975,967,2423,2209,858,1479,2409, ++ 998,1260,1190,-1u,-1u,-1u,-1u,265,255,60, ++ 303,66,310,317,333,326,1219,150,2450,1254, ++ 1376,471,-1u,1385,2480,1411,2486,1283,1359,1291, ++ 1368,-1u,1343,1271,2159,2458,2187,2262,1400,-1u, ++ -1u,2219,415,342,2224,2344,2375,2359,2440,15, ++ 46,53,1242,239,244,2473,1904,2432,421,1888, ++ 441,1180,515,1981,825,678,164,2273,2316,2299, ++ 2330,2286,130,100,87,114,2255,1352,1773,1788, ++ 1714,1699,1755,1681,1807,1635,1658,1733,1500,843, ++ 2397,2266,2147,1587,1516,1543,1529,1601,1558,1574, ++ 2005,560,1417,2017,1952,2046,2096,2036,582,2026, ++ 572,1943,1934,2391,1997,537,612,2065,505,1959, ++ 2417,1969,1920,592,2055,602,2403,1277,457,649, ++ 2083,28,545,552,662,490,498,482,642,2247, ++ 1048,1085,1072,1056,1038,1024,1109,1102,1116,1123, ++ 1826,1819,1839,1833,2131,2118,2112,2125,2169,2176, ++ 37,865,0,156,619,525,1867,1424,2072,631, ++ 2138,1859,1442,1390,42,1155,1095,20,1488,836, ++ 144,232,-1u,-1u,2202,2194,1015,1130,983,1136, ++ 989,1144,959,931,1450,939,427,1874,945,1004, ++ 1617,1226,7,1433,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ 2467,1298,275,289,1162,1201,73,2240,1991,1850, ++ 1308,1325,820,362, ++}; ++static const char *aarch64_syscall_i2s(int v) { ++ return i2s_direct__(aarch64_syscall_strings, aarch64_syscall_i2s_direct, 0, 273, v); ++} +diff --git a/lib/actiontabs.h b/lib/actiontabs.h +new file mode 100644 +index 0000000..a7a9e62 +--- /dev/null ++++ b/lib/actiontabs.h +@@ -0,0 +1,26 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char action_strings[] = "always\0never\0possible"; ++static const unsigned action_s2i_s[] = { ++ 0,7,13, ++}; ++static const int action_s2i_i[] = { ++ 2,0,1, ++}; ++static int action_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(action_strings, action_s2i_s, action_s2i_i, 3, copy, value); ++ } ++} ++static const unsigned action_i2s_direct[] = { ++ 7,13,0, ++}; ++static const char *action_i2s(int v) { ++ return i2s_direct__(action_strings, action_i2s_direct, 0, 2, v); ++} +diff --git a/lib/alpha_tables.h b/lib/alpha_tables.h +new file mode 100644 +index 0000000..b57e54c +--- /dev/null ++++ b/lib/alpha_tables.h +@@ -0,0 +1,196 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char alpha_syscall_strings[] = "_sysctl\0accept\0accept4\0access\0acct\0add_key\0adjtimex\0afs_syscall\0bdflush\0bind\0" ++ "brk\0capget\0capset\0chdir\0chmod\0chown\0chroot\0clock_adjtime\0clone\0close\0" ++ "connect\0create_module\0delete_module\0dipc\0dup\0dup2\0dup3\0epoll_create\0epoll_create1\0epoll_ctl\0" ++ "epoll_pwait\0epoll_wait\0eventfd\0eventfd2\0exec_with_loader\0execve\0exit\0exit_group\0faccessat\0fadvise64\0" ++ "fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0fchownat\0fcntl\0fdatasync\0" ++ "fgetxattr\0flistxattr\0flock\0fork\0fremovexattr\0fsetxattr\0fstat\0fstat64\0fstatat64\0fstatfs\0" ++ "fsync\0ftruncate\0futex\0futimesat\0get_kernel_syms\0get_mempolicy\0get_robust_list\0getcpu\0getcwd\0getdents\0" ++ "getdents64\0getdtablesize\0getgroups\0gethostname\0getitimer\0getpagesize\0getpeername\0getpgid\0getpgrp\0getpriority\0" ++ "getresgid\0getresuid\0getrlimit\0getrusage\0getsid\0getsockname\0getsockopt\0gettid\0gettimeofday\0getxattr\0" ++ "getxgid\0getxpid\0getxuid\0init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0" ++ "io_getevents\0io_setup\0io_submit\0ioctl\0ioprio_get\0ioprio_set\0kexec_load\0keyctl\0kill\0lchown\0" ++ "lgetxattr\0link\0linkat\0listen\0listxattr\0llistxattr\0lookup_dcookie\0lremovexattr\0lseek\0lsetxattr\0" ++ "lstat\0lstat64\0madvise\0mbind\0migrate_pages\0mincore\0mkdir\0mkdirat\0mknod\0mknodat\0" ++ "mlock\0mlockall\0mmap\0mount\0move_pages\0mprotect\0mq_getsetattr\0mq_notify\0mq_open\0mq_timedreceive\0" ++ "mq_timedsend\0mq_unlink\0mremap\0msgctl\0msgget\0msgrcv\0msgsnd\0msync\0munlock\0munlockall\0" ++ "munmap\0name_to_handle_at\0nanosleep\0nfsservctl\0old_adjtimex\0oldumount\0open\0open_by_handle_at\0openat\0osf_adjtime\0" ++ "osf_afs_syscall\0osf_alt_plock\0osf_alt_setsid\0osf_alt_sigpending\0osf_asynch_daemon\0osf_audcntl\0osf_audgen\0osf_chflags\0osf_execve\0osf_exportfs\0" ++ "osf_fchflags\0osf_fdatasync\0osf_fpathconf\0osf_fstatfs\0osf_fuser\0osf_getaddressconf\0osf_getdirentries\0osf_getdomainname\0osf_getfh\0osf_getfsstat\0" ++ "osf_gethostid\0osf_getitimer\0osf_getlogin\0osf_getmnt\0osf_getrusage\0osf_getsysinfo\0osf_gettimeofday\0osf_kloadcall\0osf_kmodcall\0osf_memcntl\0" ++ "osf_mincore\0osf_mount\0osf_mremap\0osf_msfs_syscall\0osf_msleep\0osf_mvalid\0osf_mwakeup\0osf_naccept\0osf_nfssvc\0osf_ngetpeername\0" ++ "osf_ngetsockname\0osf_nrecvfrom\0osf_nrecvmsg\0osf_nsendmsg\0osf_ntp_adjtime\0osf_ntp_gettime\0osf_old_creat\0osf_old_fstat\0osf_old_getpgrp\0osf_old_killpg\0" ++ "osf_old_lstat\0osf_old_open\0osf_old_sigaction\0osf_old_sigblock\0osf_old_sigreturn\0osf_old_sigsetmask\0osf_old_sigvec\0osf_old_stat\0osf_old_vadvise\0osf_old_vtrace\0" ++ "osf_old_wait\0osf_oldquota\0osf_pathconf\0osf_pid_block\0osf_pid_unblock\0osf_plock\0osf_priocntlset\0osf_profil\0osf_proplist_syscall\0osf_reboot\0" ++ "osf_revoke\0osf_sbrk\0osf_security\0osf_select\0osf_set_program_attributes\0osf_set_speculative\0osf_sethostid\0osf_setitimer\0osf_setlogin\0osf_setsysinfo\0" ++ "osf_settimeofday\0osf_shmat\0osf_signal\0osf_sigprocmask\0osf_sigsendset\0osf_sigstack\0osf_sigwaitprim\0osf_sstk\0osf_statfs\0osf_subsys_info\0" ++ "osf_swapctl\0osf_swapon\0osf_syscall\0osf_sysinfo\0osf_table\0osf_uadmin\0osf_usleep_thread\0osf_uswitch\0osf_utc_adjtime\0osf_utc_gettime\0" ++ "osf_utimes\0osf_utsname\0osf_wait4\0osf_waitid\0pciconfig_iobase\0pciconfig_read\0pciconfig_write\0perf_event_open\0personality\0pipe\0" ++ "pipe2\0pivot_root\0poll\0ppoll\0prctl\0pread\0preadv\0prlimit64\0process_vm_readv\0process_vm_writev\0" ++ "pselect6\0ptrace\0pwrite\0pwritev\0query_module\0quotactl\0read\0readahead\0readlink\0readlinkat\0" ++ "readv\0reboot\0recv\0recvfrom\0recvmmsg\0recvmsg\0remap_file_pages\0removexattr\0rename\0renameat\0" ++ "request_key\0restart_syscall\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0" ++ "rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0" ++ "sched_yield\0select\0semctl\0semget\0semop\0send\0sendfile\0sendmmsg\0sendmsg\0sendto\0" ++ "set_mempolicy\0set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsuid\0setgid\0setgroups\0sethae\0sethostname\0" ++ "setitimer\0setns\0setpgid\0setpgrp\0setpriority\0setregid\0setresgid\0setresuid\0setreuid\0setrlimit\0" ++ "setsid\0setsockopt\0settimeofday\0setuid\0setxattr\0shmctl\0shmdt\0shmget\0shutdown\0sigaction\0" ++ "sigaltstack\0signalfd\0signalfd4\0sigpending\0sigreturn\0sigsuspend\0socket\0socketpair\0splice\0stat\0" ++ "stat64\0statfs\0swapoff\0swapon\0symlink\0symlinkat\0sync\0sync_file_range\0syncfs\0sysfs\0" ++ "sysinfo\0syslog\0tee\0tgkill\0timerfd\0timerfd_create\0timerfd_gettime\0timerfd_settime\0times\0tkill\0" ++ "truncate\0tuxcall\0umask\0umount\0uname\0unlink\0unlinkat\0unshare\0uselib\0ustat\0" ++ "utimensat\0utimes\0vfork\0vhangup\0vmsplice\0vserver\0wait4\0waitid\0write\0writev"; ++static const unsigned alpha_syscall_s2i_s[] = { ++ 0,8,15,23,30,35,43,52,64,72, ++ 77,81,88,95,101,107,113,120,134,140, ++ 146,154,168,182,187,191,196,201,214,228, ++ 238,250,261,269,278,295,302,307,318,328, ++ 338,348,362,376,383,390,399,406,415,421, ++ 431,441,452,458,463,476,486,492,500,510, ++ 518,524,534,540,550,566,580,596,603,610, ++ 619,630,644,654,666,676,688,700,708,716, ++ 728,738,748,758,768,775,787,798,805,818, ++ 827,835,843,851,863,881,894,908,925,935, ++ 946,959,968,978,984,995,1006,1017,1024,1029, ++ 1036,1046,1051,1058,1065,1075,1086,1101,1114,1120, ++ 1130,1136,1144,1152,1158,1172,1180,1186,1194,1200, ++ 1208,1214,1223,1228,1234,1245,1254,1268,1278,1286, ++ 1302,1315,1325,1332,1339,1346,1353,1360,1366,1374, ++ 1385,1392,1410,1420,1431,1444,1454,1459,1477,1484, ++ 1496,1512,1526,1541,1560,1578,1590,1601,1613,1624, ++ 1637,1650,1664,1678,1690,1700,1719,1737,1755,1765, ++ 1779,1793,1807,1820,1831,1845,1860,1877,1891,1904, ++ 1916,1928,1938,1949,1966,1977,1988,2000,2012,2023, ++ 2040,2057,2071,2084,2097,2113,2129,2143,2157,2173, ++ 2188,2202,2215,2233,2250,2268,2287,2302,2315,2331, ++ 2346,2359,2372,2385,2399,2415,2425,2441,2452,2473, ++ 2484,2495,2504,2517,2528,2555,2575,2589,2603,2616, ++ 2631,2648,2658,2669,2685,2700,2713,2729,2738,2749, ++ 2765,2777,2788,2800,2812,2822,2833,2851,2863,2879, ++ 2895,2906,2918,2928,2939,2956,2971,2987,3003,3015, ++ 3020,3026,3037,3042,3048,3054,3060,3067,3077,3094, ++ 3112,3121,3128,3135,3143,3156,3165,3170,3180,3189, ++ 3200,3206,3213,3218,3227,3236,3244,3261,3273,3280, ++ 3289,3301,3317,3323,3336,3350,3365,3381,3394,3408, ++ 3424,3442,3465,3488,3506,3521,3540,3562,3580,3595, ++ 3614,3626,3633,3640,3647,3653,3658,3667,3676,3684, ++ 3691,3705,3721,3737,3751,3760,3769,3776,3786,3793, ++ 3805,3815,3821,3829,3837,3849,3858,3868,3878,3887, ++ 3897,3904,3915,3928,3935,3944,3951,3957,3964,3973, ++ 3983,3995,4004,4014,4025,4035,4046,4053,4064,4071, ++ 4076,4083,4090,4098,4105,4113,4123,4128,4144,4151, ++ 4157,4165,4172,4176,4183,4191,4206,4222,4238,4244, ++ 4250,4259,4267,4273,4280,4286,4293,4302,4310,4317, ++ 4323,4333,4340,4346,4354,4363,4371,4377,4384,4390, ++}; ++static const int alpha_syscall_s2i_i[] = { ++ 319,99,502,33,51,439,366,338,300,104, ++ 17,368,369,12,15,16,61,499,312,6, ++ 98,306,308,373,41,90,487,407,486,408, ++ 474,409,478,485,25,59,1,405,462,413, ++ 480,494,495,13,124,461,123,453,92,447, ++ 387,390,131,2,393,384,91,427,455,329, ++ 95,130,394,454,309,430,467,473,367,305, ++ 377,89,79,87,361,64,141,233,63,100, ++ 372,344,144,364,234,150,118,378,359,385, ++ 47,20,24,307,445,444,489,446,402,399, ++ 400,398,401,54,443,442,448,441,37,208, ++ 386,9,458,106,388,389,406,392,19,383, ++ 68,426,75,429,449,375,136,451,14,452, ++ 314,316,71,302,472,74,437,436,432,435, ++ 434,433,341,200,201,202,203,217,315,317, ++ 73,497,340,342,303,321,45,498,450,140, ++ 258,181,188,187,163,252,253,34,11,169, ++ 35,261,248,161,243,214,159,165,164,18, ++ 142,86,49,184,117,256,116,223,77,260, ++ 78,21,65,240,215,213,216,30,158,31, ++ 32,29,27,28,245,246,8,62,81,146, ++ 40,5,46,109,139,110,108,38,72,115, ++ 84,149,247,153,154,107,237,44,244,55, ++ 56,69,222,93,43,239,143,83,50,257, ++ 122,209,218,48,238,112,157,70,160,255, ++ 259,199,0,241,85,242,251,250,220,219, ++ 138,207,7,236,376,345,346,493,324,42, ++ 488,374,94,464,348,349,490,496,504,505, ++ 463,26,350,491,347,148,3,379,58,460, ++ 120,311,102,125,479,113,410,391,128,457, ++ 440,412,137,352,354,353,356,351,357,355, ++ 492,335,336,396,331,333,337,395,330,332, ++ 334,358,204,205,206,101,370,503,114,133, ++ 431,466,411,166,326,325,132,80,301,88, ++ 362,501,39,82,96,127,371,343,126,145, ++ 147,105,360,23,382,210,211,212,134,156, ++ 235,476,484,52,103,111,97,135,468,67, ++ 425,328,304,322,57,459,36,469,500,254, ++ 318,310,470,424,477,481,483,482,323,381, ++ 129,397,60,22,339,10,456,465,313,327, ++ 475,363,66,76,471,428,365,438,4,121, ++}; ++static int alpha_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(alpha_syscall_strings, alpha_syscall_s2i_s, alpha_syscall_s2i_i, 410, copy, value); ++ } ++} ++static const unsigned alpha_syscall_i2s_direct[] = { ++ 2788,302,458,3165,4384,2202,140,2918,2129,1046, ++ 4286,1613,95,376,1194,101,107,77,1765,1114, ++ 835,1928,4273,3928,843,278,3121,2071,2084,2057, ++ 2000,2023,2040,23,1601,1637,4123,1024,2302,3821, ++ 2188,187,3015,2528,2441,1454,2215,827,2669,1807, ++ 2603,30,4014,-1u,978,2473,2484,4105,3180,295, ++ 4267,113,2143,708,676,1938,4340,4071,1130,2495, ++ 2729,1223,2315,1385,1245,1144,4346,1891,1916,644, ++ 3776,2157,3829,2589,2346,2812,1793,654,3793,630, ++ 191,486,415,2517,3037,518,3837,4046,146,8, ++ 716,3653,3213,4025,72,3904,1058,2415,2287,2233, ++ 2268,4035,2700,3236,3676,2331,1860,1831,787,-1u, ++ 3200,4390,2631,399,383,3218,3878,3849,3273,4250, ++ 524,452,3769,3684,3964,4053,1180,3317,2895,2250, ++ 1484,688,1779,2575,748,3887,2173,3897,3156,2359, ++ 775,-1u,-1u,2385,2399,-1u,3973,2713,2012,1719, ++ 2738,1678,-1u,1560,1755,1737,3737,-1u,-1u,1624, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,1512,-1u,-1u,1820,-1u,-1u,1541,1526,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,2777, ++ 1332,1339,1346,1353,3633,3640,3647,2906,1029,2648, ++ 3944,3951,3957,1977,1700,1966,1988,1360,2658,2879, ++ 2863,-1u,2504,1877,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,700,768,3983,2928,2425,2685,2555, ++ 1949,2800,2822,1690,2452,2097,2113,2372,1664,-1u, ++ 2851,2833,1578,1590,4151,2749,1845,2616,1496,2765, ++ 1904,1650,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u,-1u, ++ 64,3786,1228,1431,4090,610,154,851,168,550, ++ 4165,3206,134,4310,1208,1366,1214,1374,4157,0, ++ -1u,1444,4098,4238,3003,3760,3751,4317,4083,510, ++ 3580,3506,3595,3521,3614,3442,3465,3540,52,4280, ++ 1410,1325,1420,3868,738,2956,2971,3143,3048,3054, ++ 3128,3381,3323,3350,3336,3408,3365,3394,3626,805, ++ 3915,666,3805,4333,758,4371,43,603,81,88, ++ 3658,3858,728,182,3026,1172,2939,619,798,3170, ++ -1u,4244,3935,1120,476,818,1036,431,1065,1075, ++ 441,3261,1101,463,534,3562,3488,4259,959,935, ++ 946,968,925,-1u,-1u,307,1086,201,228,250, ++ 3244,3721,3301,328,-1u,-1u,-1u,-1u,-1u,-1u, ++ -1u,-1u,-1u,-1u,4176,4076,1136,492,4363,1152, ++ 566,3691,1278,1315,1302,1286,1268,1254,4377,35, ++ 3289,1017,995,984,881,863,908,421,1006,1158, ++ 1477,1186,1200,406,540,500,4293,3280,1051,4113, ++ 3189,390,318,3112,3042,4302,3705,580,4064,4128, ++ 4172,4354,1234,596,238,4323,3995,4183,261,3227, ++ 338,4191,4222,4206,4004,269,214,196,3020,894, ++ 3060,3135,3424,2987,348,362,3067,1392,1459,120, ++ 4144,3815,15,3667,3077,3094, ++}; ++static const char *alpha_syscall_i2s(int v) { ++ return i2s_direct__(alpha_syscall_strings, alpha_syscall_i2s_direct, 0, 505, v); ++} +diff --git a/lib/armeb_tables.h b/lib/armeb_tables.h +new file mode 100644 +index 0000000..dd2bf5f +--- /dev/null ++++ b/lib/armeb_tables.h +@@ -0,0 +1,165 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char armeb_syscall_strings[] = "accept\0accept4\0access\0acct\0add_key\0adjtimex\0alarm\0bdflush\0bind\0brk\0" ++ "capget\0capset\0chdir\0chmod\0chown\0chown32\0chroot\0clock_adjtime\0clock_getres\0clock_gettime\0" ++ "clock_nanosleep\0clock_settime\0clone\0close\0connect\0creat\0delete_module\0dup\0dup2\0dup3\0" ++ "epoll_create\0epoll_create1\0epoll_ctl\0epoll_wait\0eventfd\0eventfd2\0execve\0exit\0exit_group\0faccessat\0" ++ "fadvise64_64\0fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0fchown32\0fchownat\0" ++ "fcntl\0fcntl64\0fdatasync\0fgetxattr\0finit_module\0flistxattr\0flock\0fork\0fremovexattr\0fsetxattr\0" ++ "fstat\0fstat64\0fstatat64\0fstatfs\0fstatfs64\0fsync\0ftruncate\0ftruncate64\0futex\0futimesat\0" ++ "get_mempolicy\0get_robust_list\0getcpu\0getcwd\0getdents\0getdents64\0getegid\0getegid32\0geteuid\0geteuid32\0" ++ "getgid\0getgid32\0getgroups\0getgroups32\0getitimer\0getpeername\0getpgid\0getpgrp\0getpid\0getppid\0" ++ "getpriority\0getresgid\0getresgid32\0getresuid\0getresuid32\0getrlimit\0getrusage\0getsid\0getsockname\0getsockopt\0" ++ "gettid\0gettimeofday\0getuid\0getuid32\0getxattr\0init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0" ++ "io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0ioctl\0ioprio_get\0ioprio_set\0ipc\0kcmp\0" ++ "kexec_load\0keyctl\0kill\0lchown\0lchown32\0lgetxattr\0link\0linkat\0listen\0listxattr\0" ++ "llistxattr\0llseek\0lookup_dcookie\0lremovexattr\0lseek\0lsetxattr\0lstat\0lstat64\0madvise\0mbind\0" ++ "mincore\0mkdir\0mkdirat\0mknod\0mknodat\0mlock\0mlockall\0mmap\0mmap2\0mount\0" ++ "move_pages\0mprotect\0mq_getsetattr\0mq_notify\0mq_open\0mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msgctl\0" ++ "msgget\0msgrcv\0msgsnd\0msync\0munlock\0munlockall\0munmap\0name_to_handle_at\0nanosleep\0newselect\0" ++ "nfsservctl\0nice\0open\0open_by_handle_at\0openat\0pause\0pciconfig_iobase\0pciconfig_read\0pciconfig_write\0perf_event_open\0" ++ "personality\0pipe\0pipe2\0pivot_root\0poll\0prctl\0pread64\0preadv\0prlimit64\0process_vm_readv\0" ++ "process_vm_writev\0ptrace\0pwrite64\0pwritev\0quotactl\0read\0readahead\0readdir\0readlink\0readlinkat\0" ++ "readv\0reboot\0recv\0recvfrom\0recvmmsg\0recvmsg\0remap_file_pages\0removexattr\0rename\0renameat\0" ++ "request_key\0restart_syscall\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0" ++ "rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0" ++ "sched_yield\0select\0semctl\0semget\0semop\0semtimedop\0send\0sendfile\0sendfile64\0sendmmsg\0" ++ "sendmsg\0sendto\0set_mempolicy\0set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsgid32\0setfsuid\0setfsuid32\0" ++ "setgid\0setgid32\0setgroups\0setgroups32\0sethostname\0setitimer\0setns\0setpgid\0setpriority\0setregid\0" ++ "setregid32\0setresgid\0setresgid32\0setresuid\0setresuid32\0setreuid\0setreuid32\0setrlimit\0setsid\0setsockopt\0" ++ "settimeofday\0setuid\0setuid32\0setxattr\0shmat\0shmctl\0shmdt\0shmget\0shutdown\0sigaction\0" ++ "sigaltstack\0signalfd\0signalfd4\0sigpending\0sigprocmask\0sigreturn\0sigsuspend\0socket\0socketcall\0socketpair\0" ++ "splice\0stat\0stat64\0statfs\0statfs64\0stime\0swapoff\0swapon\0symlink\0symlinkat\0" ++ "sync\0sync_file_range\0syncfs\0syscall\0sysctl\0sysfs\0sysinfo\0syslog\0tee\0tgkill\0" ++ "time\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd_create\0timerfd_gettime\0timerfd_settime\0times\0" ++ "tkill\0truncate\0truncate64\0ugetrlimit\0umask\0umount\0umount2\0uname\0unlink\0unlinkat\0" ++ "unshare\0uselib\0ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0vmsplice\0vserver\0" ++ "wait4\0waitid\0write\0writev"; ++static const unsigned armeb_syscall_s2i_s[] = { ++ 0,7,15,22,27,35,44,50,58,63, ++ 67,74,81,87,93,99,107,114,128,141, ++ 155,171,185,191,197,205,211,225,229,234, ++ 239,252,266,276,287,295,304,311,316,327, ++ 337,350,360,374,388,395,402,411,418,427, ++ 436,442,450,460,470,483,494,500,505,518, ++ 528,534,542,552,560,570,576,586,598,604, ++ 614,628,644,651,658,667,678,686,696,704, ++ 714,721,730,740,752,762,774,782,790,797, ++ 805,817,827,839,849,861,871,881,888,900, ++ 911,918,931,938,947,956,968,986,999,1013, ++ 1030,1040,1051,1064,1073,1083,1089,1100,1111,1115, ++ 1120,1131,1138,1143,1150,1159,1169,1174,1181,1188, ++ 1198,1209,1216,1231,1244,1250,1260,1266,1274,1282, ++ 1288,1296,1302,1310,1316,1324,1330,1339,1344,1350, ++ 1356,1367,1376,1390,1400,1408,1424,1437,1447,1454, ++ 1461,1468,1475,1482,1488,1496,1507,1514,1532,1542, ++ 1552,1563,1568,1573,1591,1598,1604,1621,1636,1652, ++ 1668,1680,1685,1691,1702,1707,1713,1721,1728,1738, ++ 1755,1773,1780,1789,1797,1806,1811,1821,1829,1838, ++ 1849,1855,1862,1867,1876,1885,1893,1910,1922,1929, ++ 1938,1950,1966,1972,1985,1999,2014,2030,2043,2057, ++ 2073,2091,2114,2137,2155,2170,2189,2211,2229,2244, ++ 2263,2275,2282,2289,2296,2302,2313,2318,2327,2338, ++ 2347,2355,2362,2376,2392,2408,2422,2431,2442,2451, ++ 2462,2469,2478,2488,2500,2512,2522,2528,2536,2548, ++ 2557,2568,2578,2590,2600,2612,2621,2632,2642,2649, ++ 2660,2673,2680,2689,2698,2704,2711,2717,2724,2733, ++ 2743,2755,2764,2774,2785,2797,2807,2818,2825,2836, ++ 2847,2854,2859,2866,2873,2882,2888,2896,2903,2911, ++ 2921,2926,2942,2949,2957,2964,2970,2978,2985,2989, ++ 2996,3001,3014,3027,3044,3058,3072,3087,3103,3119, ++ 3125,3131,3140,3151,3162,3168,3175,3183,3189,3196, ++ 3205,3213,3220,3226,3232,3242,3249,3255,3263,3272, ++ 3280,3286,3293,3299, ++}; ++static const int armeb_syscall_s2i_i[] = { ++ 285,366,33,51,309,124,27,134,282,45, ++ 184,185,12,15,182,212,61,372,264,263, ++ 265,262,120,6,283,8,129,41,63,358, ++ 250,357,251,252,351,356,11,1,248,334, ++ 270,352,367,368,133,94,333,95,207,325, ++ 55,221,148,231,379,234,143,2,237,228, ++ 108,197,327,100,267,118,93,194,240,326, ++ 320,339,345,183,141,217,50,202,49,201, ++ 47,200,80,205,105,287,132,65,20,64, ++ 96,171,211,165,209,76,77,147,286,295, ++ 224,78,24,199,229,128,317,316,360,318, ++ 247,244,245,243,246,54,315,314,117,378, ++ 347,311,37,16,198,230,9,330,284,232, ++ 233,140,249,236,19,227,107,196,220,319, ++ 219,39,323,14,324,150,152,90,192,21, ++ 344,125,279,278,274,277,276,275,163,304, ++ 303,302,301,144,151,153,91,370,162,142, ++ 169,34,5,371,322,29,271,272,273,364, ++ 136,42,359,218,168,172,180,361,369,376, ++ 377,26,181,362,131,3,225,89,85,332, ++ 145,88,291,292,365,297,253,235,38,329, ++ 310,0,40,174,176,175,178,173,179,177, ++ 363,159,160,242,155,157,161,241,154,156, ++ 158,82,300,299,298,312,289,187,239,374, ++ 296,290,321,338,256,121,139,216,138,215, ++ 46,214,81,206,74,104,375,57,97,71, ++ 204,170,210,164,208,70,203,75,66,294, ++ 79,23,213,226,305,308,306,307,293,67, ++ 186,349,355,73,126,119,72,281,102,288, ++ 340,106,195,99,266,25,115,87,83,331, ++ 36,341,373,113,149,135,116,103,342,268, ++ 13,257,261,260,259,258,350,354,353,43, ++ 238,92,193,191,60,22,52,122,10,328, ++ 337,86,62,30,348,269,190,111,343,313, ++ 114,280,4,146, ++}; ++static int armeb_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(armeb_syscall_strings, armeb_syscall_s2i_s, armeb_syscall_s2i_i, 344, copy, value); ++ } ++} ++static const unsigned armeb_syscall_i2s_direct[] = { ++ 1950,311,500,1806,3293,1568,191,-1u,205,1169, ++ 3189,304,81,2996,1310,87,1143,-1u,-1u,1244, ++ 790,1350,3168,2673,931,2882,1773,44,-1u,1598, ++ 3226,-1u,-1u,15,1563,-1u,2921,1138,1922,1296, ++ 1966,225,1680,3119,-1u,63,2462,714,-1u,696, ++ 678,22,3175,-1u,1083,436,-1u,2528,-1u,-1u, ++ 3162,107,3220,229,797,782,2642,2733,-1u,-1u, ++ 2612,2548,2807,2774,2500,2632,861,871,918,2660, ++ 730,2478,2275,2903,-1u,1829,3213,2896,1855,1821, ++ 1339,1507,3131,576,395,411,805,2536,-1u,2866, ++ 552,-1u,2825,2978,2512,752,2854,1260,528,-1u, ++ -1u,3255,-1u,2949,3280,2888,2970,1111,570,2797, ++ 185,2408,3183,-1u,35,1367,2785,-1u,956,211, ++ -1u,1797,774,388,50,2964,1668,-1u,2442,2422, ++ 1209,658,1542,494,1482,1849,3299,881,450,2957, ++ 1324,1488,1330,1496,2229,2155,2244,2170,2263,2091, ++ 2114,2189,1532,1447,2590,839,-1u,-1u,1702,1552, ++ 2568,817,1707,2030,1972,1999,1985,2057,2014,2043, ++ 1713,1780,93,651,67,74,2743,2318,-1u,-1u, ++ 3249,3151,1344,3140,586,2859,1266,534,1150,938, ++ 721,704,686,2621,2557,740,2488,418,2600,849, ++ 2578,827,99,2680,2469,2451,2431,667,1691,1288, ++ 1274,442,-1u,-1u,911,1811,2689,1250,518,947, ++ 1159,460,1188,1198,483,1910,1231,505,3125,2327, ++ 598,2211,2137,1064,1040,1051,1073,1030,316,1216, ++ 239,266,276,1893,-1u,-1u,2392,3001,3058,3044, ++ 3027,3014,171,141,128,155,2873,560,2989,3242, ++ 337,1604,1621,1636,1400,1437,1424,1408,1390,1376, ++ 3286,2818,58,197,1181,0,888,762,2836,2313, ++ 2355,1862,1867,2724,2649,900,2347,1885,2296,2289, ++ 2282,1475,1468,1461,1454,2698,2711,2717,2704,27, ++ 1938,1131,2302,3272,1100,1089,986,968,1013,1282, ++ 614,2362,1591,1302,1316,427,604,542,3196,1929, ++ 1174,2911,1838,402,327,-1u,-1u,3205,2376,628, ++ 2847,2926,2985,3263,1356,644,-1u,1120,3232,2755, ++ 3072,287,350,3103,3087,2764,295,252,234,1685, ++ 999,1721,1789,2073,1652,1876,7,360,374,1728, ++ 1514,1573,114,2942,2338,2522,1738,1755,1115,470, ++}; ++static const char *armeb_syscall_i2s(int v) { ++ return i2s_direct__(armeb_syscall_strings, armeb_syscall_i2s_direct, 0, 379, v); ++} +diff --git a/lib/errtabs.h b/lib/errtabs.h +new file mode 100644 +index 0000000..53deac2 +--- /dev/null ++++ b/lib/errtabs.h +@@ -0,0 +1,78 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char err_strings[] = "E2BIG\0EACCES\0EADDRINUSE\0EADDRNOTAVAIL\0EADV\0EAFNOSUPPORT\0EAGAIN\0EALREADY\0EBADE\0EBADF\0" ++ "EBADFD\0EBADMSG\0EBADR\0EBADRQC\0EBADSLT\0EBFONT\0EBUSY\0ECANCELED\0ECHILD\0ECHRNG\0" ++ "ECOMM\0ECONNABORTED\0ECONNREFUSED\0ECONNRESET\0EDEADLK\0EDEADLOCK\0EDESTADDRREQ\0EDOM\0EDOTDOT\0EDQUOT\0" ++ "EEXIST\0EFAULT\0EFBIG\0EHOSTDOWN\0EHOSTUNREACH\0EIDRM\0EILSEQ\0EINPROGRESS\0EINTR\0EINVAL\0" ++ "EIO\0EISCONN\0EISDIR\0EISNAM\0EKEYEXPIRED\0EKEYREJECTED\0EKEYREVOKED\0EL2HLT\0EL2NSYNC\0EL3HLT\0" ++ "EL3RST\0ELIBACC\0ELIBBAD\0ELIBEXEC\0ELIBMAX\0ELIBSCN\0ELNRNG\0ELOOP\0EMEDIUMTYPE\0EMFILE\0" ++ "EMLINK\0EMSGSIZE\0EMULTIHOP\0ENAMETOOLONG\0ENAVAIL\0ENETDOWN\0ENETRESET\0ENETUNREACH\0ENFILE\0ENOANO\0" ++ "ENOBUFS\0ENOCSI\0ENODATA\0ENODEV\0ENOENT\0ENOEXEC\0ENOKEY\0ENOLCK\0ENOLINK\0ENOMEDIUM\0" ++ "ENOMEM\0ENOMSG\0ENONET\0ENOPKG\0ENOPROTOOPT\0ENOSPC\0ENOSR\0ENOSTR\0ENOSYS\0ENOTBLK\0" ++ "ENOTCONN\0ENOTDIR\0ENOTEMPTY\0ENOTNAM\0ENOTRECOVERABLE\0ENOTSOCK\0ENOTTY\0ENOTUNIQ\0ENXIO\0EOPNOTSUPP\0" ++ "EOVERFLOW\0EOWNERDEAD\0EPERM\0EPFNOSUPPORT\0EPIPE\0EPROTO\0EPROTONOSUPPORT\0EPROTOTYPE\0ERANGE\0EREMCHG\0" ++ "EREMOTE\0EREMOTEIO\0ERESTART\0EROFS\0ESHUTDOWN\0ESOCKTNOSUPPORT\0ESPIPE\0ESRCH\0ESRMNT\0ESTALE\0" ++ "ESTRPIPE\0ETIME\0ETIMEDOUT\0ETOOMANYREFS\0ETXTBSY\0EUCLEAN\0EUNATCH\0EUSERS\0EWOULDBLOCK\0EXDEV\0" ++ "EXFULL"; ++static const unsigned err_s2i_s[] = { ++ 0,6,13,24,38,43,56,63,72,78, ++ 84,91,99,105,113,121,128,134,144,151, ++ 158,164,177,190,201,209,219,232,237,245, ++ 252,259,266,272,282,295,301,308,320,326, ++ 333,337,345,352,359,371,384,396,403,412, ++ 419,426,434,442,451,459,467,474,480,492, ++ 499,506,515,525,538,546,555,565,577,584, ++ 591,599,606,614,621,628,636,643,650,658, ++ 668,675,682,689,696,708,715,721,728,735, ++ 743,752,760,770,778,794,803,810,819,825, ++ 836,846,857,863,876,882,889,905,916,923, ++ 931,939,949,958,964,974,990,997,1003,1010, ++ 1017,1026,1032,1042,1055,1063,1071,1079,1086,1098, ++ 1104, ++}; ++static const int err_s2i_i[] = { ++ 7,13,98,99,68,97,11,114,52,9, ++ 77,74,53,56,57,59,16,125,10,44, ++ 70,103,111,104,35,35,89,33,73,122, ++ 17,14,27,112,113,43,84,115,4,22, ++ 5,106,21,120,127,129,128,51,45,46, ++ 47,79,80,83,82,81,48,40,124,24, ++ 31,90,72,36,119,100,102,101,23,55, ++ 105,50,61,19,2,8,126,37,67,123, ++ 12,42,64,65,92,28,63,60,38,15, ++ 107,20,39,118,131,88,25,76,6,95, ++ 75,130,1,96,32,71,93,91,34,78, ++ 66,121,85,30,108,94,29,3,69,116, ++ 86,62,110,109,26,117,49,87,11,18, ++ 54, ++}; ++static int err_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISLOWER(c) ? c - 'a' + 'A' : c; ++ } ++ copy[i] = 0; ++ return s2i__(err_strings, err_s2i_s, err_s2i_i, 131, copy, value); ++ } ++} ++static const unsigned err_i2s_direct[] = { ++ 857,621,997,320,333,819,0,628,78,144, ++ 56,668,6,259,735,128,252,1098,614,752, ++ 345,326,577,492,803,1055,266,708,990,958, ++ 499,876,232,916,201,525,643,728,760,474, ++ -1u,675,295,151,403,412,419,467,1071,599, ++ 396,72,99,1104,584,105,113,-1u,121,721, ++ 606,1026,715,682,689,931,650,38,1003,158, ++ 882,515,237,91,836,810,84,923,426,434, ++ 459,451,442,301,949,1017,1079,794,219,506, ++ 905,696,889,974,825,863,43,13,24,546, ++ 565,555,164,190,591,337,743,964,1042,1032, ++ 177,272,282,63,308,1010,1063,770,538,352, ++ 939,245,658,480,134,636,359,384,371,846, ++ 778, ++}; ++static const char *err_i2s(int v) { ++ return i2s_direct__(err_strings, err_i2s_direct, 1, 131, v); ++} +diff --git a/lib/fieldtabs.h b/lib/fieldtabs.h +new file mode 100644 +index 0000000..fb50e08 +--- /dev/null ++++ b/lib/fieldtabs.h +@@ -0,0 +1,49 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char field_strings[] = "a0\0a1\0a2\0a3\0arch\0auid\0devmajor\0devminor\0dir\0egid\0" ++ "euid\0exit\0field_compare\0filetype\0fsgid\0fsuid\0gid\0inode\0key\0loginuid\0" ++ "msgtype\0obj_gid\0obj_lev_high\0obj_lev_low\0obj_role\0obj_type\0obj_uid\0obj_user\0path\0perm\0" ++ "pers\0pid\0ppid\0sgid\0subj_clr\0subj_role\0subj_sen\0subj_type\0subj_user\0success\0" ++ "suid\0uid"; ++static const unsigned field_s2i_s[] = { ++ 0,3,6,9,12,17,22,31,40,44, ++ 49,54,59,73,82,88,94,98,104,108, ++ 117,125,133,146,158,167,176,184,193,198, ++ 203,208,212,217,222,231,241,250,260,270, ++ 278,283, ++}; ++static const int field_s2i_i[] = { ++ 200,201,202,203,11,9,100,101,107,6, ++ 2,103,111,108,8,4,5,102,210,9, ++ 12,110,23,22,20,21,109,19,105,106, ++ 10,0,18,7,17,14,16,15,13,104, ++ 3,1, ++}; ++static int field_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(field_strings, field_s2i_s, field_s2i_i, 42, copy, value); ++ } ++} ++static const int field_i2s_i[] = { ++ 0,1,2,3,4,5,6,7,8,9, ++ 10,11,12,13,14,15,16,17,18,19, ++ 20,21,22,23,100,101,102,103,104,105, ++ 106,107,108,109,110,111,200,201,202,203, ++ 210, ++}; ++static const unsigned field_i2s_s[] = { ++ 208,283,49,278,88,94,44,217,82,17, ++ 203,12,117,260,231,250,241,222,212,184, ++ 158,167,146,133,22,31,98,54,270,193, ++ 198,40,73,176,125,59,0,3,6,9, ++ 104, ++}; ++static const char *field_i2s(int v) { ++ return i2s_bsearch__(field_strings, field_i2s_i, field_i2s_s, 41, v); ++} +diff --git a/lib/flagtabs.h b/lib/flagtabs.h +new file mode 100644 +index 0000000..e191db3 +--- /dev/null ++++ b/lib/flagtabs.h +@@ -0,0 +1,26 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char flag_strings[] = "entry\0exclude\0exit\0task\0user"; ++static const unsigned flag_s2i_s[] = { ++ 0,6,14,19,24, ++}; ++static const int flag_s2i_i[] = { ++ 2,5,4,1,0, ++}; ++static int flag_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(flag_strings, flag_s2i_s, flag_s2i_i, 5, copy, value); ++ } ++} ++static const unsigned flag_i2s_direct[] = { ++ 24,19,0,-1u,14,6, ++}; ++static const char *flag_i2s(int v) { ++ return i2s_direct__(flag_strings, flag_i2s_direct, 0, 5, v); ++} +diff --git a/lib/ftypetabs.h b/lib/ftypetabs.h +new file mode 100644 +index 0000000..04aaa46 +--- /dev/null ++++ b/lib/ftypetabs.h +@@ -0,0 +1,29 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ftype_strings[] = "block\0character\0dir\0fifo\0file\0link\0socket"; ++static const unsigned ftype_s2i_s[] = { ++ 0,6,16,20,25,30,35, ++}; ++static const int ftype_s2i_i[] = { ++ 24576,8192,16384,4096,32768,40960,49152, ++}; ++static int ftype_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(ftype_strings, ftype_s2i_s, ftype_s2i_i, 7, copy, value); ++ } ++} ++static const int ftype_i2s_i[] = { ++ 4096,8192,16384,24576,32768,40960,49152, ++}; ++static const unsigned ftype_i2s_s[] = { ++ 20,6,16,0,25,30,35, ++}; ++static const char *ftype_i2s(int v) { ++ return i2s_bsearch__(ftype_strings, ftype_i2s_i, ftype_i2s_s, 7, v); ++} +diff --git a/lib/i386_tables.h b/lib/i386_tables.h +new file mode 100644 +index 0000000..6703ffc +--- /dev/null ++++ b/lib/i386_tables.h +@@ -0,0 +1,163 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char i386_syscall_strings[] = "_llseek\0_newselect\0_sysctl\0access\0acct\0add_key\0adjtimex\0afs_syscall\0alarm\0bdflush\0" ++ "break\0brk\0capget\0capset\0chdir\0chmod\0chown\0chown32\0chroot\0clock_adjtime\0" ++ "clock_getres\0clock_gettime\0clock_nanosleep\0clock_settime\0clone\0close\0creat\0create_module\0delete_module\0dup\0" ++ "dup2\0dup3\0epoll_create\0epoll_create1\0epoll_ctl\0epoll_pwait\0epoll_wait\0eventfd\0eventfd2\0execve\0" ++ "exit\0exit_group\0faccessat\0fadvise64\0fadvise64_64\0fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0" ++ "fchmodat\0fchown\0fchown32\0fchownat\0fcntl\0fcntl64\0fdatasync\0fgetxattr\0finit_module\0flistxattr\0" ++ "flock\0fork\0fremovexattr\0fsetxattr\0fstat\0fstat64\0fstatat64\0fstatfs\0fstatfs64\0fsync\0" ++ "ftime\0ftruncate\0ftruncate64\0futex\0futimesat\0get_kernel_syms\0get_mempolicy\0get_robust_list\0get_thread_area\0getcpu\0" ++ "getcwd\0getdents\0getdents64\0getegid\0getegid32\0geteuid\0geteuid32\0getgid\0getgid32\0getgroups\0" ++ "getgroups32\0getitimer\0getpgid\0getpgrp\0getpid\0getpmsg\0getppid\0getpriority\0getresgid\0getresgid32\0" ++ "getresuid\0getresuid32\0getrlimit\0getrusage\0getsid\0gettid\0gettimeofday\0getuid\0getuid32\0getxattr\0" ++ "gtty\0idle\0init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0" ++ "io_setup\0io_submit\0ioctl\0ioperm\0iopl\0ioprio_get\0ioprio_set\0ipc\0kcmp\0keyctl\0" ++ "kill\0lchown\0lchown32\0lgetxattr\0link\0linkat\0listxattr\0llistxattr\0lock\0lookup_dcookie\0" ++ "lremovexattr\0lseek\0lsetxattr\0lstat\0lstat64\0madvise\0madvise1\0mbind\0migrate_pages\0mincore\0" ++ "mkdir\0mkdirat\0mknod\0mknodat\0mlock\0mlockall\0mmap\0mmap2\0modify_ldt\0mount\0" ++ "move_pages\0mprotect\0mpx\0mq_getsetattr\0mq_notify\0mq_open\0mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0" ++ "msync\0munlock\0munlockall\0munmap\0name_to_handle_at\0nanosleep\0nfsservctl\0nice\0oldfstat\0oldlstat\0" ++ "oldolduname\0oldstat\0olduname\0open\0open_by_handle_at\0openat\0pause\0perf_event_open\0personality\0pipe\0" ++ "pipe2\0pivot_root\0poll\0ppoll\0prctl\0pread64\0preadv\0prlimit64\0process_vm_readv\0process_vm_writev\0" ++ "prof\0profil\0pselect6\0ptrace\0putpmsg\0pwrite64\0pwritev\0query_module\0quotactl\0read\0" ++ "readahead\0readdir\0readlink\0readlinkat\0readv\0reboot\0recvmmsg\0remap_file_pages\0removexattr\0rename\0" ++ "renameat\0request_key\0restart_syscall\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0" ++ "rt_sigtimedwait\0rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0" ++ "sched_setscheduler\0sched_yield\0select\0sendfile\0sendfile64\0sendmmsg\0set_mempolicy\0set_robust_list\0set_thread_area\0set_tid_address\0" ++ "setdomainname\0setfsgid\0setfsgid32\0setfsuid\0setfsuid32\0setgid\0setgid32\0setgroups\0setgroups32\0sethostname\0" ++ "setitimer\0setns\0setpgid\0setpriority\0setregid\0setregid32\0setresgid\0setresgid32\0setresuid\0setresuid32\0" ++ "setreuid\0setreuid32\0setrlimit\0setsid\0settimeofday\0setuid\0setuid32\0setxattr\0sgetmask\0sigaction\0" ++ "sigaltstack\0signal\0signalfd\0signalfd4\0sigpending\0sigprocmask\0sigreturn\0sigsuspend\0socketcall\0splice\0" ++ "ssetmask\0stat\0stat64\0statfs\0statfs64\0stime\0stty\0swapoff\0swapon\0symlink\0" ++ "symlinkat\0sync\0sync_file_range\0syncfs\0sys_kexec_load\0sysfs\0sysinfo\0syslog\0tee\0tgkill\0" ++ "time\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd\0timerfd_gettime\0timerfd_settime\0times\0" ++ "tkill\0truncate\0truncate64\0ugetrlimit\0ulimit\0umask\0umount\0umount2\0uname\0unlink\0" ++ "unlinkat\0unshare\0uselib\0ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0vm86\0" ++ "vm86old\0vmsplice\0vserver\0wait4\0waitid\0waitpid\0write\0writev"; ++static const unsigned i386_syscall_s2i_s[] = { ++ 0,8,19,27,34,39,47,56,68,74, ++ 82,88,92,99,106,112,118,124,132,139, ++ 153,166,180,196,210,216,222,228,242,256, ++ 260,265,270,283,297,307,319,330,338,347, ++ 354,359,370,380,390,403,413,427,441,448, ++ 455,464,471,480,489,495,503,513,523,536, ++ 547,553,558,571,581,587,595,605,613,623, ++ 629,635,645,657,663,673,689,703,719,735, ++ 742,749,758,769,777,787,795,805,812,821, ++ 831,843,853,861,869,876,884,892,904,914, ++ 926,936,948,958,968,975,982,995,1002,1011, ++ 1020,1025,1030,1042,1060,1073,1087,1104,1114,1125, ++ 1138,1147,1157,1163,1170,1175,1186,1197,1201,1206, ++ 1213,1218,1225,1234,1244,1249,1256,1266,1277,1282, ++ 1297,1310,1316,1326,1332,1340,1348,1357,1363,1377, ++ 1385,1391,1399,1405,1413,1419,1428,1433,1439,1450, ++ 1456,1467,1476,1480,1494,1504,1512,1528,1541,1551, ++ 1558,1564,1572,1583,1590,1608,1618,1629,1634,1643, ++ 1652,1664,1672,1681,1686,1704,1711,1717,1733,1745, ++ 1750,1756,1767,1772,1778,1784,1792,1799,1809,1826, ++ 1844,1849,1856,1865,1872,1880,1889,1897,1910,1919, ++ 1924,1934,1942,1951,1962,1968,1975,1984,2001,2013, ++ 2020,2029,2041,2057,2063,2076,2090,2105,2121,2134, ++ 2148,2164,2182,2205,2228,2246,2261,2280,2302,2320, ++ 2335,2354,2366,2373,2382,2393,2402,2416,2432,2448, ++ 2464,2478,2487,2498,2507,2518,2525,2534,2544,2556, ++ 2568,2578,2584,2592,2604,2613,2624,2634,2646,2656, ++ 2668,2677,2688,2698,2705,2718,2725,2734,2743,2752, ++ 2762,2774,2781,2790,2800,2811,2823,2833,2844,2855, ++ 2862,2871,2876,2883,2890,2899,2905,2910,2918,2925, ++ 2933,2943,2948,2964,2971,2986,2992,3000,3007,3011, ++ 3018,3023,3036,3049,3066,3080,3094,3102,3118,3134, ++ 3140,3146,3155,3166,3177,3184,3190,3197,3205,3211, ++ 3218,3227,3235,3242,3248,3254,3264,3271,3277,3285, ++ 3290,3298,3307,3315,3321,3328,3336,3342, ++}; ++static const int i386_syscall_s2i_i[] = { ++ 140,142,149,33,51,286,124,137,27,134, ++ 17,45,184,185,12,15,182,212,61,343, ++ 266,265,267,264,120,6,8,127,129,41, ++ 63,330,254,329,255,319,256,323,328,11, ++ 1,252,307,250,272,324,338,339,133,94, ++ 306,95,207,298,55,221,148,231,350,234, ++ 143,2,237,228,108,197,300,100,269,118, ++ 35,93,194,240,299,130,275,312,244,318, ++ 183,141,220,50,202,49,201,47,200,80, ++ 205,105,132,65,20,188,64,96,171,211, ++ 165,209,76,77,147,224,78,24,199,229, ++ 32,112,128,292,291,332,293,249,246,247, ++ 245,248,54,101,110,290,289,117,349,288, ++ 37,16,198,230,9,303,232,233,53,253, ++ 236,19,227,107,196,219,219,274,294,218, ++ 39,296,14,297,150,152,90,192,123,21, ++ 317,125,56,282,281,277,280,279,278,163, ++ 144,151,153,91,341,162,169,34,28,84, ++ 59,18,109,5,342,295,29,336,136,42, ++ 331,217,168,309,172,180,333,340,347,348, ++ 44,98,308,26,189,181,334,167,131,3, ++ 225,89,85,305,145,88,337,257,235,38, ++ 302,287,0,40,174,176,175,178,173,179, ++ 177,335,159,160,242,155,157,161,241,154, ++ 156,158,82,187,239,345,276,311,243,258, ++ 121,139,216,138,215,46,214,81,206,74, ++ 104,346,57,97,71,204,170,210,164,208, ++ 70,203,75,66,79,23,213,226,68,67, ++ 186,48,321,327,73,126,119,72,102,313, ++ 69,106,195,99,268,25,31,115,87,83, ++ 304,36,314,344,283,135,116,103,315,270, ++ 13,259,263,262,261,260,322,326,325,43, ++ 238,92,193,191,58,60,22,52,122,10, ++ 301,310,86,62,30,320,271,190,111,166, ++ 113,316,273,114,284,7,4,146, ++}; ++static int i386_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(i386_syscall_strings, i386_syscall_s2i_s, i386_syscall_s2i_i, 348, copy, value); ++ } ++} ++static const unsigned i386_syscall_i2s_direct[] = { ++ 2041,354,553,1919,3336,1681,216,3328,222,1244, ++ 3211,347,106,3018,1399,112,1218,82,1664,1310, ++ 869,1450,3190,2718,995,2899,1865,68,1634,1711, ++ 3248,2905,1020,27,1629,629,2943,1213,2013,1385, ++ 2057,256,1745,3134,1844,88,2518,805,2774,787, ++ 769,34,3197,1277,1157,489,1476,2584,3177,1652, ++ 3184,132,3242,260,884,861,2698,2752,2743,2862, ++ 2668,2604,2833,2800,2556,2688,948,958,982,2705, ++ 821,2534,2366,2925,1643,1942,3235,2918,1968,1934, ++ 1428,1583,3146,635,448,464,892,2592,1849,2883, ++ 605,1163,2844,3000,2568,843,2871,1326,581,1672, ++ 1170,3277,1025,3290,3315,2910,2992,1197,623,2823, ++ 210,2464,3205,1439,47,1467,2811,228,1030,242, ++ 673,1910,853,441,74,2986,1733,56,2498,2478, ++ 0,749,8,547,1558,1962,3342,968,503,19, ++ 1413,1564,1419,1572,2320,2246,2335,2261,2354,2182, ++ 2205,2280,1608,1551,2646,926,3285,1897,1767,1618, ++ 2624,904,1778,2121,2063,2090,2076,2148,2105,2134, ++ 1784,1880,118,742,92,99,2762,2373,876,1872, ++ 3271,3166,1433,3155,645,2876,1332,587,1225,1002, ++ 812,795,777,2677,2613,831,2544,471,2656,936, ++ 2634,914,124,2725,2525,2507,2487,1756,1377,1340, ++ 758,495,-1u,-1u,975,1924,2734,1316,571,1011, ++ 1234,513,1256,1266,536,2001,1297,558,3140,2382, ++ 657,2302,2228,2432,719,1138,1114,1125,1147,1104, ++ 380,-1u,359,1282,270,297,319,1984,2448,3023, ++ 3080,3066,3049,3036,196,166,153,180,2890,613, ++ 3011,3264,390,3307,1357,689,2402,1504,1541,1528, ++ 1512,1494,1480,2971,3321,-1u,39,2029,1206,1186, ++ 1175,1060,1042,1087,1363,1704,1391,1405,480,663, ++ 595,3218,2020,1249,2933,1951,455,370,1856,1772, ++ 3227,2416,703,2855,2948,3007,3298,1456,735,307, ++ 3254,2781,3094,330,403,3118,3102,2790,338,283, ++ 265,1750,1073,1792,1889,2164,1717,1975,413,427, ++ 1799,1590,1686,139,2964,2393,2578,1809,1826,1201, ++ 523, ++}; ++static const char *i386_syscall_i2s(int v) { ++ return i2s_direct__(i386_syscall_strings, i386_syscall_i2s_direct, 0, 350, v); ++} +diff --git a/lib/ia64_tables.h b/lib/ia64_tables.h +new file mode 100644 +index 0000000..9e127a0 +--- /dev/null ++++ b/lib/ia64_tables.h +@@ -0,0 +1,147 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ia64_syscall_strings[] = "_sysctl\0accept\0accept4\0access\0acct\0add_key\0adjtimex\0afs_syscall\0bdflush\0bind\0" ++ "brk\0capget\0capset\0chdir\0chmod\0chown\0chroot\0clock_adjtime\0clock_getres\0clock_gettime\0" ++ "clock_nanosleep\0clock_settime\0clone\0clone2\0close\0connect\0creat\0delete_module\0dup\0dup2\0" ++ "dup3\0epoll_create\0epoll_create1\0epoll_ctl\0epoll_pwait\0epoll_wait\0eventfd\0eventfd2\0execve\0exit\0" ++ "exit_group\0faccessat\0fadvise64\0fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0" ++ "fchownat\0fcntl\0fdatasync\0fgetxattr\0finit_module\0flistxattr\0flock\0fremovexattr\0fsetxattr\0fstat\0" ++ "fstatfs\0fstatfs64\0fsync\0ftruncate\0futex\0futimesat\0get_mempolicy\0get_robust_list\0getcpu\0getcwd\0" ++ "getdents\0getdents64\0getegid\0geteuid\0getgid\0getgroups\0getitimer\0getpeername\0getpgid\0getpid\0" ++ "getpmsg\0getppid\0getpriority\0getresgid\0getresuid\0getrlimit\0getrusage\0getsid\0getsockname\0getsockopt\0" ++ "gettid\0gettimeofday\0getuid\0getunwind\0getxattr\0init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0" ++ "io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0ioctl\0ioprio_get\0ioprio_set\0kexec_load\0keyctl\0" ++ "kill\0lchown\0lgetxattr\0link\0linkat\0listen\0listxattr\0llistxattr\0lookup_dcookie\0lremovexattr\0" ++ "lseek\0lsetxattr\0lstat\0madvise\0mbind\0migrate_pages\0mincore\0mkdir\0mkdirat\0mknod\0" ++ "mknodat\0mlock\0mlockall\0mmap\0mmap2\0mount\0mprotect\0mq_getsetattr\0mq_notify\0mq_open\0" ++ "mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msgctl\0msgget\0msgrcv\0msgsnd\0msync\0munlock\0" ++ "munlockall\0munmap\0name_to_handle_at\0nanosleep\0newfstatat\0nfsservctl\0ni_syscall\0open\0open_by_handle_at\0openat\0" ++ "pciconfig_read\0pciconfig_write\0perfmonctl\0personality\0pipe\0pipe2\0pivot_root\0poll\0ppoll\0prctl\0" ++ "pread64\0preadv\0prlimit64\0process_vm_readv\0process_vm_writev\0pselect\0ptrace\0putpmsg\0pwrite64\0pwritev\0" ++ "quotactl\0read\0readahead\0readlink\0readlinkat\0readv\0reboot\0recv\0recvfrom\0recvmmsg\0" ++ "recvmsg\0remap_file_pages\0removexattr\0rename\0renameat\0request_key\0restart_syscall\0rmdir\0rt_sigaction\0rt_sigpending\0" ++ "rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0" ++ "sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0sched_yield\0select\0semctl\0semget\0semop\0" ++ "semtimedop\0send\0sendfile\0sendmmsg\0sendmsg\0sendto\0set_mempolicy\0set_robust_list\0set_tid_address\0set_zone_reclaim\0" ++ "setdomainname\0setfsgid\0setfsuid\0setgid\0setgroups\0sethostname\0setitimer\0setns\0setpgid\0setpriority\0" ++ "setregid\0setresgid\0setresuid\0setreuid\0setrlimit\0setsid\0setsockopt\0settimeofday\0setuid\0setxattr\0" ++ "shmat\0shmctl\0shmdt\0shmget\0shutdown\0sigaltstack\0signalfd\0signalfd4\0socket\0socketpair\0" ++ "splice\0stat\0statfs\0statfs64\0swapoff\0swapon\0symlink\0symlinkat\0sync\0sync_file_range\0" ++ "syncfs\0sysfs\0sysinfo\0syslog\0tee\0tgkill\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0" ++ "timer_settime\0timerfd\0timerfd_create\0timerfd_gettime\0timerfd_settime\0times\0tkill\0truncate\0tux\0umask\0" ++ "umount\0uname\0unlink\0unlinkat\0unshare\0uselib\0ustat\0utimensat\0utimes\0vhangup\0" ++ "vmsplice\0vserver\0wait4\0waitid\0write\0writev"; ++static const unsigned ia64_syscall_s2i_s[] = { ++ 0,8,15,23,30,35,43,52,64,72, ++ 77,81,88,95,101,107,113,120,134,147, ++ 161,177,191,197,204,210,218,224,238,242, ++ 247,252,265,279,289,301,312,320,329,336, ++ 341,352,362,372,382,396,410,417,424,433, ++ 440,449,455,465,475,488,499,505,518,528, ++ 534,542,552,558,568,574,584,598,614,621, ++ 628,637,648,656,664,671,681,691,703,711, ++ 718,726,734,746,756,766,776,786,793,805, ++ 816,823,836,843,853,862,874,892,905,919, ++ 936,946,957,970,979,989,995,1006,1017,1028, ++ 1035,1040,1047,1057,1062,1069,1076,1086,1097,1112, ++ 1125,1131,1141,1147,1155,1161,1175,1183,1189,1197, ++ 1203,1211,1217,1226,1231,1237,1243,1252,1266,1276, ++ 1284,1300,1313,1323,1330,1337,1344,1351,1358,1364, ++ 1372,1383,1390,1408,1418,1429,1440,1451,1456,1474, ++ 1481,1496,1512,1523,1535,1540,1546,1557,1562,1568, ++ 1574,1582,1589,1599,1616,1634,1642,1649,1657,1666, ++ 1674,1683,1688,1698,1707,1718,1724,1731,1736,1745, ++ 1754,1762,1779,1791,1798,1807,1819,1835,1841,1854, ++ 1868,1883,1899,1912,1926,1942,1960,1983,2006,2024, ++ 2039,2058,2080,2098,2113,2132,2144,2151,2158,2165, ++ 2171,2182,2187,2196,2205,2213,2220,2234,2250,2266, ++ 2283,2297,2306,2315,2322,2332,2344,2354,2360,2368, ++ 2380,2389,2399,2409,2418,2428,2435,2446,2459,2466, ++ 2475,2481,2488,2494,2501,2510,2522,2531,2541,2548, ++ 2559,2566,2571,2578,2587,2595,2602,2610,2620,2625, ++ 2641,2648,2654,2662,2669,2673,2680,2693,2706,2723, ++ 2737,2751,2759,2774,2790,2806,2812,2818,2827,2831, ++ 2837,2844,2850,2857,2866,2874,2881,2887,2897,2904, ++ 2912,2921,2929,2935,2942,2948, ++}; ++static const int ia64_syscall_s2i_i[] = { ++ 1150,1194,1334,1049,1064,1271,1131,1141,1138,1191, ++ 1060,1185,1186,1034,1038,1039,1068,1328,1255,1254, ++ 1256,1253,1128,1213,1029,1192,1030,1134,1057,1070, ++ 1316,1243,1315,1244,1305,1245,1309,1314,1033,1025, ++ 1236,1293,1234,1303,1323,1324,1035,1099,1292,1100, ++ 1284,1066,1052,1222,1335,1225,1145,1228,1219,1212, ++ 1104,1257,1051,1098,1230,1285,1260,1299,1304,1184, ++ 1144,1214,1063,1047,1062,1077,1119,1196,1079,1041, ++ 1188,1042,1101,1075,1073,1085,1086,1082,1195,1204, ++ 1105,1087,1046,1215,1220,1133,1278,1277,1318,1279, ++ 1242,1239,1240,1238,1241,1065,1275,1274,1268,1273, ++ 1053,1124,1221,1031,1289,1193,1223,1224,1237,1227, ++ 1040,1218,1211,1209,1259,1280,1208,1055,1282,1037, ++ 1283,1153,1154,1151,1172,1043,1155,1267,1266,1262, ++ 1265,1264,1263,1156,1112,1109,1111,1110,1157,1158, ++ 1159,1152,1326,1168,1286,1169,1024,1028,1327,1281, ++ 1173,1174,1175,1140,1058,1317,1207,1090,1295,1170, ++ 1148,1319,1325,1332,1333,1294,1048,1189,1149,1320, ++ 1137,1026,1216,1092,1291,1146,1096,1200,1201,1322, ++ 1206,1125,1226,1054,1288,1272,1246,1056,1177,1178, ++ 1179,1180,1181,1182,1183,1321,1165,1166,1232,1160, ++ 1162,1167,1231,1161,1163,1164,1089,1108,1106,1107, ++ 1247,1198,1187,1331,1205,1199,1261,1298,1233,1276, ++ 1129,1143,1142,1061,1078,1083,1118,1330,1080,1102, ++ 1072,1076,1074,1071,1084,1081,1203,1088,1045,1217, ++ 1114,1116,1115,1113,1202,1176,1307,1313,1190,1197, ++ 1297,1210,1103,1258,1095,1094,1091,1290,1050,1300, ++ 1329,1139,1127,1117,1301,1235,1248,1252,1251,1250, ++ 1249,1308,1310,1312,1311,1059,1229,1097,1120,1067, ++ 1044,1130,1032,1287,1296,1093,1069,1306,1036,1123, ++ 1302,1269,1126,1270,1027,1147, ++}; ++static int ia64_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(ia64_syscall_strings, ia64_syscall_s2i_s, ia64_syscall_s2i_i, 306, copy, value); ++ } ++} ++static const unsigned ia64_syscall_i2s_direct[] = { ++ 1440,336,1683,2942,1451,204,218,1057,2850,329, ++ 95,410,2897,1197,101,107,1125,711,726,1237, ++ 2837,2459,836,656,1642,23,2620,552,455,1035, ++ 1791,1183,1835,238,1535,2806,77,2315,664,648, ++ 30,989,449,2831,113,2881,242,2409,2380,756, ++ 2399,746,2389,671,2322,703,2360,2428,786,2332, ++ 2418,766,776,823,2446,2144,1557,2602,1698,2874, ++ 2595,2587,1724,2818,558,417,433,734,2368,2571, ++ 534,816,2158,2165,2151,1337,1351,1344,1330,2494, ++ 2475,2488,2481,2662,2344,681,2827,-1u,-1u,2904, ++ 1040,1762,2929,2654,191,2283,2844,43,-1u,862, ++ 224,-1u,-1u,1674,64,2648,1523,52,2306,2297, ++ 628,499,1718,2948,1574,1657,0,1226,1383,1211, ++ 1217,1243,1323,1358,1364,1372,2024,2098,2039,2113, ++ 2132,1960,1983,2058,1408,1429,1568,-1u,1231,1481, ++ 1496,1512,2510,1841,1854,1868,1883,1899,1912,1926, ++ 621,81,88,2187,718,1649,2541,72,210,1069, ++ 8,793,691,2548,2182,2213,1731,1736,2501,2435, ++ 805,2205,1754,1546,1175,1147,2566,1141,528,197, ++ 637,843,1688,2466,1131,518,853,1047,465,1076, ++ 1086,488,1779,1112,505,2812,568,2080,2006,2250, ++ 362,2673,341,1097,970,946,957,979,936,252, ++ 279,301,1819,2171,2680,2737,2723,2706,2693,177, ++ 147,134,161,542,2578,1155,584,2220,1276,1313, ++ 1300,1284,1266,1252,1017,2921,2935,35,1807,1028, ++ 1006,995,2266,892,874,919,1161,1474,1189,1203, ++ 440,574,1418,2857,1798,1062,2610,1707,424,352, ++ 1634,1562,2866,2559,2234,598,2625,2669,2912,372, ++ 614,289,2887,2522,2751,312,2759,2790,2774,2531, ++ 320,265,247,1540,905,1582,1666,1942,1745,382, ++ 396,1589,1390,1456,120,2641,2354,2196,1599,1616, ++ 15,475, ++}; ++static const char *ia64_syscall_i2s(int v) { ++ return i2s_direct__(ia64_syscall_strings, ia64_syscall_i2s_direct, 1024, 1335, v); ++} +diff --git a/lib/machinetabs.h b/lib/machinetabs.h +new file mode 100644 +index 0000000..ec2d033 +--- /dev/null ++++ b/lib/machinetabs.h +@@ -0,0 +1,26 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char machine_strings[] = "i386\0i486\0i586\0i686\0ia64\0ppc\0ppc64\0s390\0s390x\0x86_64"; ++static const unsigned machine_s2i_s[] = { ++ 0,5,10,15,20,25,29,35,40,46, ++}; ++static const int machine_s2i_i[] = { ++ 0,0,0,0,2,4,3,6,5,1, ++}; ++static int machine_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(machine_strings, machine_s2i_s, machine_s2i_i, 10, copy, value); ++ } ++} ++static const unsigned machine_i2s_direct[] = { ++ 0,46,20,29,25,40,35, ++}; ++static const char *machine_i2s(int v) { ++ return i2s_direct__(machine_strings, machine_i2s_direct, 0, 6, v); ++} +diff --git a/lib/msg_typetabs.h b/lib/msg_typetabs.h +new file mode 100644 +index 0000000..770ec21 +--- /dev/null ++++ b/lib/msg_typetabs.h +@@ -0,0 +1,104 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char msg_type_strings[] = "ADD_GROUP\0ADD_USER\0ANOM_ABEND\0ANOM_ACCESS_FS\0ANOM_ADD_ACCT\0ANOM_AMTU_FAIL\0ANOM_CRYPTO_FAIL\0ANOM_DEL_ACCT\0ANOM_EXEC\0ANOM_LINK\0" ++ "ANOM_LOGIN_ACCT\0ANOM_LOGIN_FAILURES\0ANOM_LOGIN_LOCATION\0ANOM_LOGIN_SESSIONS\0ANOM_LOGIN_TIME\0ANOM_MAX_DAC\0ANOM_MAX_MAC\0ANOM_MK_EXEC\0ANOM_MOD_ACCT\0ANOM_PROMISCUOUS\0" ++ "ANOM_RBAC_FAIL\0ANOM_RBAC_INTEGRITY_FAIL\0ANOM_ROOT_TRANS\0AVC\0AVC_PATH\0BPRM_FCAPS\0CAPSET\0CHGRP_ID\0CHUSER_ID\0CONFIG_CHANGE\0" ++ "CRED_ACQ\0CRED_DISP\0CRED_REFR\0CRYPTO_FAILURE_USER\0CRYPTO_KEY_USER\0CRYPTO_LOGIN\0CRYPTO_LOGOUT\0CRYPTO_PARAM_CHANGE_USER\0CRYPTO_REPLAY_USER\0CRYPTO_SESSION\0" ++ "CRYPTO_TEST_USER\0CWD\0DAC_CHECK\0DAEMON_ABORT\0DAEMON_ACCEPT\0DAEMON_CLOSE\0DAEMON_CONFIG\0DAEMON_END\0DAEMON_RESUME\0DAEMON_ROTATE\0" ++ "DAEMON_START\0DEL_GROUP\0DEL_USER\0DEV_ALLOC\0DEV_DEALLOC\0EOE\0EXECVE\0FD_PAIR\0FS_RELABEL\0GRP_AUTH\0" ++ "INTEGRITY_DATA\0INTEGRITY_HASH\0INTEGRITY_METADATA\0INTEGRITY_PCR\0INTEGRITY_RULE\0INTEGRITY_STATUS\0IPC\0IPC_SET_PERM\0KERNEL\0KERNEL_OTHER\0" ++ "LABEL_LEVEL_CHANGE\0LABEL_OVERRIDE\0LIST_RULES\0LOGIN\0MAC_CIPSOV4_ADD\0MAC_CIPSOV4_DEL\0MAC_CONFIG_CHANGE\0MAC_IPSEC_ADDSA\0MAC_IPSEC_ADDSPD\0MAC_IPSEC_DELSA\0" ++ "MAC_IPSEC_DELSPD\0MAC_IPSEC_EVENT\0MAC_MAP_ADD\0MAC_MAP_DEL\0MAC_POLICY_LOAD\0MAC_STATUS\0MAC_UNLBL_ALLOW\0MAC_UNLBL_STCADD\0MAC_UNLBL_STCDEL\0MMAP\0" ++ "MQ_GETSETATTR\0MQ_NOTIFY\0MQ_OPEN\0MQ_SENDRECV\0NETFILTER_CFG\0NETFILTER_PKT\0OBJ_PID\0PATH\0RESP_ACCT_LOCK\0RESP_ACCT_LOCK_TIMED\0" ++ "RESP_ACCT_REMOTE\0RESP_ACCT_UNLOCK_TIMED\0RESP_ALERT\0RESP_ANOMALY\0RESP_EXEC\0RESP_HALT\0RESP_KILL_PROC\0RESP_SEBOOL\0RESP_SINGLE\0RESP_TERM_ACCESS\0" ++ "RESP_TERM_LOCK\0ROLE_ASSIGN\0ROLE_MODIFY\0ROLE_REMOVE\0SECCOMP\0SELINUX_ERR\0SERVICE_START\0SERVICE_STOP\0SOCKADDR\0SOCKETCALL\0" ++ "SYSCALL\0SYSTEM_BOOT\0SYSTEM_RUNLEVEL\0SYSTEM_SHUTDOWN\0TEST\0TRUSTED_APP\0TTY\0TTY_GET\0TTY_SET\0USER\0" ++ "USER_ACCT\0USER_AUTH\0USER_AVC\0USER_CHAUTHTOK\0USER_CMD\0USER_END\0USER_ERR\0USER_LABELED_EXPORT\0USER_LOGIN\0USER_LOGOUT\0" ++ "USER_MAC_POLICY_LOAD\0USER_MGMT\0USER_ROLE_CHANGE\0USER_SELINUX_ERR\0USER_START\0USER_TTY\0USER_UNLABELED_EXPORT\0USYS_CONFIG\0VIRT_CONTROL\0VIRT_MACHINE_ID\0" ++ "VIRT_RESOURCE"; ++static const unsigned msg_type_s2i_s[] = { ++ 0,10,19,30,45,59,74,91,105,115, ++ 125,141,161,181,201,217,230,243,256,270, ++ 287,302,327,343,347,356,367,374,383,393, ++ 407,416,426,436,456,472,485,499,524,543, ++ 558,575,579,589,602,616,629,643,654,668, ++ 682,695,705,714,724,736,740,747,755,766, ++ 775,790,805,824,838,853,870,874,887,894, ++ 907,926,941,952,958,974,990,1008,1024,1041, ++ 1057,1074,1090,1102,1114,1130,1141,1157,1174,1191, ++ 1196,1210,1220,1228,1240,1254,1268,1276,1281,1296, ++ 1317,1334,1357,1368,1381,1391,1401,1416,1428,1440, ++ 1457,1472,1484,1496,1508,1516,1528,1542,1555,1564, ++ 1575,1583,1595,1611,1627,1632,1644,1648,1656,1664, ++ 1669,1679,1689,1698,1713,1722,1731,1740,1760,1771, ++ 1783,1804,1814,1831,1848,1859,1868,1890,1902,1915, ++ 1931, ++}; ++static const int msg_type_s2i_i[] = { ++ 1116,1114,1701,2111,2114,2107,2110,2115,2112,1702, ++ 2103,2100,2104,2102,2101,2105,2106,2113,2116,1700, ++ 2108,2109,2117,1400,1402,1321,1322,1119,1125,1305, ++ 1103,1104,1110,2405,2404,2402,2403,2401,2406,2407, ++ 2400,1307,1118,1202,1207,1208,1203,1201,1206,1205, ++ 1200,1117,1115,2307,2308,1320,1309,1317,2309,1126, ++ 1800,1803,1801,1804,1805,1802,1303,1311,2000,1316, ++ 2304,2303,1013,1006,1407,1408,1405,1411,1413,1412, ++ 1414,1415,1409,1410,1403,1404,1406,1416,1417,1323, ++ 1315,1314,1312,1313,1325,1324,1318,1302,2207,2205, ++ 2204,2206,2201,2200,2210,2212,2202,2209,2211,2203, ++ 2208,2301,2311,2302,1326,1401,1130,1131,1306,1304, ++ 1300,1127,1129,1128,1120,1121,1319,1016,1017,1005, ++ 1101,1100,1107,1108,1123,1106,1109,2305,1112,1113, ++ 2310,1102,2300,1122,1105,1124,2306,1111,2500,2502, ++ 2501, ++}; ++static int msg_type_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISLOWER(c) ? c - 'a' + 'A' : c; ++ } ++ copy[i] = 0; ++ return s2i__(msg_type_strings, msg_type_s2i_s, msg_type_s2i_i, 151, copy, value); ++ } ++} ++static const int msg_type_i2s_i[] = { ++ 1005,1006,1013,1016,1017,1100,1101,1102,1103,1104, ++ 1105,1106,1107,1108,1109,1110,1111,1112,1113,1114, ++ 1115,1116,1117,1118,1119,1120,1121,1122,1123,1124, ++ 1125,1126,1127,1128,1129,1130,1131,1200,1201,1202, ++ 1203,1205,1206,1207,1208,1300,1302,1303,1304,1305, ++ 1306,1307,1309,1311,1312,1313,1314,1315,1316,1317, ++ 1318,1319,1320,1321,1322,1323,1324,1325,1326,1400, ++ 1401,1402,1403,1404,1405,1406,1407,1408,1409,1410, ++ 1411,1412,1413,1414,1415,1416,1417,1700,1701,1702, ++ 1800,1801,1802,1803,1804,1805,2000,2100,2101,2102, ++ 2103,2104,2105,2106,2107,2108,2109,2110,2111,2112, ++ 2113,2114,2115,2116,2117,2200,2201,2202,2203,2204, ++ 2205,2206,2207,2208,2209,2210,2211,2212,2300,2301, ++ 2302,2303,2304,2305,2306,2307,2308,2309,2310,2311, ++ 2400,2401,2402,2403,2404,2405,2406,2407,2500,2501, ++ 2502, ++}; ++static const unsigned msg_type_i2s_s[] = { ++ 1664,952,941,1648,1656,1679,1669,1804,407,416, ++ 1848,1722,1689,1698,1731,426,1890,1760,1771,10, ++ 705,0,695,579,374,1627,1632,1831,1713,1859, ++ 383,766,1583,1611,1595,1528,1542,682,643,589, ++ 629,668,654,602,616,1575,1276,870,1564,393, ++ 1555,575,740,874,1220,1228,1210,1196,894,747, ++ 1268,1644,736,356,367,1191,1254,1240,1508,343, ++ 1516,347,1114,1130,990,1141,958,974,1090,1102, ++ 1008,1041,1024,1057,1074,1157,1174,270,19,115, ++ 775,805,853,790,824,838,887,141,201,181, ++ 125,161,217,230,59,287,302,74,30,105, ++ 243,45,91,256,327,1368,1357,1401,1440,1317, ++ 1296,1334,1281,1457,1416,1381,1428,1391,1814,1472, ++ 1496,926,907,1740,1868,714,724,755,1783,1484, ++ 558,499,472,485,456,436,524,543,1902,1931, ++ 1915, ++}; ++static const char *msg_type_i2s(int v) { ++ return i2s_bsearch__(msg_type_strings, msg_type_i2s_i, msg_type_i2s_s, 151, v); ++} +diff --git a/lib/optabs.h b/lib/optabs.h +new file mode 100644 +index 0000000..d79b665 +--- /dev/null ++++ b/lib/optabs.h +@@ -0,0 +1,11 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char op_strings[] = "!=\0&\0&=\0<\0<=\0=\0>\0>="; ++static const int op_i2s_i[] = { ++ 134217728,268435456,536870912,805306368,1073741824,1207959552,1342177280,1610612736, ++}; ++static const unsigned op_i2s_s[] = { ++ 3,8,15,0,13,5,10,17, ++}; ++static const char *op_i2s(int v) { ++ return i2s_bsearch__(op_strings, op_i2s_i, op_i2s_s, 8, v); ++} +diff --git a/lib/ppc_tables.h b/lib/ppc_tables.h +new file mode 100644 +index 0000000..778fae3 +--- /dev/null ++++ b/lib/ppc_tables.h +@@ -0,0 +1,163 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char ppc_syscall_strings[] = "_llseek\0_newselect\0_sysctl\0accept\0accept4\0access\0acct\0add_key\0adjtimex\0afs_syscall\0" ++ "alarm\0bdflush\0bind\0break\0brk\0capget\0capset\0chdir\0chmod\0chown\0" ++ "chroot\0clock_adjtime\0clock_getres\0clock_gettime\0clock_nanosleep\0clock_settime\0clone\0close\0connect\0creat\0" ++ "create_module\0delete_module\0dup\0dup2\0dup3\0epoll_create\0epoll_create1\0epoll_ctl\0epoll_pwait\0epoll_wait\0" ++ "eventfd\0eventfd2\0execve\0exit\0exit_group\0faccessat\0fadvise64\0fadvise64_64\0fallocate\0fanotify_init\0" ++ "fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0fchownat\0fcntl\0fcntl64\0fdatasync\0fgetxattr\0" ++ "finit_module\0flistxattr\0flock\0fork\0fremovexattr\0fsetxattr\0fstat\0fstat64\0fstatat\0fstatfs\0" ++ "fstatfs64\0fsync\0ftime\0ftruncate\0ftruncate64\0futex\0futimesat\0get_kernel_syms\0get_robust_list\0getcpu\0" ++ "getcwd\0getdents\0getdents64\0getegid\0geteuid\0getgid\0getgroups\0getitimer\0getpeername\0getpgid\0" ++ "getpgrp\0getpid\0getpmsg\0getppid\0getpriority\0getresgid\0getresuid\0getrlimit\0getrusage\0getsid\0" ++ "getsockname\0getsockopt\0gettid\0gettimeofday\0getuid\0getxattr\0gtty\0idle\0init_module\0inotify_add_watch\0" ++ "inotify_init\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0ioctl\0ioperm\0" ++ "iopl\0ioprio_get\0ioprio_set\0ipc\0kcmp\0kexec_load\0keyctl\0kill\0lchown\0lgetxattr\0" ++ "link\0linkat\0listen\0listxattr\0llistxattr\0lock\0lookup_dcookie\0lremovexattr\0lseek\0lsetxattr\0" ++ "lstat\0lstat64\0madvise\0mincore\0mkdir\0mkdirat\0mknod\0mknodat\0mlock\0mlockall\0" ++ "mmap\0mmap2\0modify_ldt\0mount\0move_pages\0mprotect\0mpx\0mq_getsetattr\0mq_notify\0mq_open\0" ++ "mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msync\0multiplexer\0munlock\0munlockall\0munmap\0name_to_handle_at\0" ++ "nanosleep\0nfsservctl\0nice\0oldfstat\0oldlstat\0oldolduname\0oldstat\0olduname\0open\0open_by_handle_at\0" ++ "openat\0pause\0pciconfig_iobase\0pciconfig_read\0pciconfig_write\0perf_counter_open\0personality\0pipe\0pipe2\0pivot_root\0" ++ "poll\0ppoll\0prctl\0pread\0preadv\0prlimit64\0process_vm_readv\0process_vm_writev\0prof\0profil\0" ++ "pselect6\0ptrace\0putpmsg\0pwrite\0pwritev\0query_module\0quotactl\0read\0readahead\0readdir\0" ++ "readlink\0readlinkat\0readv\0reboot\0recv\0recvfrom\0recvmmsg\0recvmsg\0remap_file_pages\0removexattr\0" ++ "rename\0renameat\0request_key\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0" ++ "rt_sigtimedwait\0rt_tgsigqueueinfo\0rtas\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0" ++ "sched_setparam\0sched_setscheduler\0sched_yield\0select\0send\0sendfile\0sendfile64\0sendmmsg\0sendmsg\0sendto\0" ++ "set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsuid\0setgid\0setgroups\0sethostname\0setitimer\0setns\0" ++ "setpgid\0setpriority\0setregid\0setresgid\0setresuid\0setreuid\0setrlimit\0setsid\0setsockopt\0settimeofday\0" ++ "setuid\0setxattr\0sgetmask\0shutdown\0sigaction\0sigaltstack\0signal\0signalfd\0signalfd4\0sigpending\0" ++ "sigprocmask\0sigreturn\0sigsuspend\0socket\0socketcall\0socketpair\0splice\0spu_create\0spu_run\0ssetmask\0" ++ "stat\0stat64\0statfs\0statfs64\0stime\0stty\0subpage_prot\0swapcontext\0swapoff\0swapon\0" ++ "symlink\0symlinkat\0sync\0sync_file_range2\0syncfs\0sysfs\0sysinfo\0syslog\0tee\0tgkill\0" ++ "time\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd\0timerfd_gettime\0timerfd_settime\0times\0" ++ "tkill\0truncate\0truncate64\0tuxcall\0ugetrlimit\0ulimit\0umask\0umount\0umount2\0uname\0" ++ "unlink\0unlinkat\0unshare\0uselib\0ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0" ++ "vm86\0vmsplice\0wait4\0waitid\0waitpid\0write\0writev"; ++static const unsigned ppc_syscall_s2i_s[] = { ++ 0,8,19,27,34,42,49,54,62,71, ++ 83,89,97,102,108,112,119,126,132,138, ++ 144,151,165,178,192,208,222,228,234,242, ++ 248,262,276,280,285,290,303,317,327,339, ++ 350,358,367,374,379,390,400,410,423,433, ++ 447,461,468,475,484,491,500,506,514,524, ++ 534,547,558,564,569,582,592,598,606,614, ++ 622,632,638,644,654,666,672,682,698,714, ++ 721,728,737,748,756,764,771,781,791,803, ++ 811,819,826,834,842,854,864,874,884,894, ++ 901,913,924,931,944,951,960,965,970,982, ++ 1000,1013,1027,1044,1054,1065,1078,1087,1097,1103, ++ 1110,1115,1126,1137,1141,1146,1157,1164,1169,1176, ++ 1186,1191,1198,1205,1215,1226,1231,1246,1259,1265, ++ 1275,1281,1289,1297,1305,1311,1319,1325,1333,1339, ++ 1348,1353,1359,1370,1376,1387,1396,1400,1414,1424, ++ 1432,1448,1461,1471,1478,1484,1496,1504,1515,1522, ++ 1540,1550,1561,1566,1575,1584,1596,1604,1613,1618, ++ 1636,1643,1649,1666,1681,1697,1715,1727,1732,1738, ++ 1749,1754,1760,1766,1772,1779,1789,1806,1824,1829, ++ 1836,1845,1852,1860,1867,1875,1888,1897,1902,1912, ++ 1920,1929,1940,1946,1953,1958,1967,1976,1984,2001, ++ 2013,2020,2029,2041,2047,2060,2074,2089,2105,2118, ++ 2132,2148,2166,2171,2194,2217,2235,2250,2269,2291, ++ 2309,2324,2343,2355,2362,2367,2376,2387,2396,2404, ++ 2411,2427,2443,2457,2466,2475,2482,2492,2504,2514, ++ 2520,2528,2540,2549,2559,2569,2578,2588,2595,2606, ++ 2619,2626,2635,2644,2653,2663,2675,2682,2691,2701, ++ 2712,2724,2734,2745,2752,2763,2774,2781,2792,2800, ++ 2809,2814,2821,2828,2837,2843,2848,2861,2873,2881, ++ 2888,2896,2906,2911,2928,2935,2941,2949,2956,2960, ++ 2967,2972,2985,2998,3015,3029,3043,3051,3067,3083, ++ 3089,3095,3104,3115,3123,3134,3141,3147,3154,3162, ++ 3168,3175,3184,3192,3199,3205,3211,3221,3228,3234, ++ 3242,3247,3256,3262,3269,3277,3283, ++}; ++static const int ppc_syscall_s2i_i[] = { ++ 140,142,149,330,344,33,51,269,124,137, ++ 27,134,327,17,45,183,184,12,15,181, ++ 61,347,247,246,248,245,120,6,328,8, ++ 127,129,41,63,316,236,315,237,303,238, ++ 307,314,11,1,234,298,233,254,309,323, ++ 324,133,94,297,95,289,55,204,148,214, ++ 353,217,143,2,220,211,108,197,291,100, ++ 253,118,35,93,194,221,290,130,299,302, ++ 182,141,202,50,49,47,80,105,332,132, ++ 65,20,187,64,96,170,165,76,77,147, ++ 331,340,207,78,24,212,32,112,128,276, ++ 275,318,277,231,228,229,227,230,54,101, ++ 110,274,273,117,354,268,271,37,16,213, ++ 9,294,329,215,216,53,235,219,19,210, ++ 107,196,205,206,39,287,14,288,150,152, ++ 90,192,123,21,301,125,56,267,266,262, ++ 265,264,263,163,144,201,151,153,91,345, ++ 162,168,34,28,84,59,18,109,5,346, ++ 286,29,200,198,199,319,136,42,317,203, ++ 167,281,171,179,320,325,351,352,44,98, ++ 280,26,188,180,321,166,131,3,191,89, ++ 85,296,145,88,336,337,343,342,239,218, ++ 38,293,270,40,173,175,174,177,172,178, ++ 176,322,255,159,160,223,155,157,161,222, ++ 154,156,158,82,334,186,226,349,341,335, ++ 300,232,121,139,138,46,81,74,104,350, ++ 57,97,71,169,164,70,75,66,339,79, ++ 23,209,68,338,67,185,48,305,313,73, ++ 126,119,72,326,102,333,283,279,278,69, ++ 106,195,99,252,25,31,310,249,115,87, ++ 83,295,36,308,348,135,116,103,284,250, ++ 13,240,244,243,242,241,306,312,311,43, ++ 208,92,193,225,190,58,60,22,52,122, ++ 10,292,282,86,62,30,304,251,189,111, ++ 113,285,114,272,7,4,146, ++}; ++static int ppc_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(ppc_syscall_strings, ppc_syscall_s2i_s, ppc_syscall_s2i_i, 347, copy, value); ++ } ++} ++static const unsigned ppc_syscall_i2s_direct[] = { ++ 374,564,1897,3277,1613,228,3269,242,1186,3168, ++ 367,126,2967,1319,132,1169,102,1596,1259,819, ++ 1370,3147,2619,944,2837,1845,83,1566,1643,3205, ++ 2843,960,42,1561,638,2906,1164,2013,1305,2041, ++ 276,1727,3083,1824,108,2475,764,2675,756,748, ++ 49,3154,1226,1097,500,1396,2520,3134,1584,3141, ++ 144,3199,280,834,811,2588,2653,2635,2800,2569, ++ 2540,2734,2701,2492,2578,874,884,931,2606,771, ++ 2482,2355,2888,1575,1920,3192,2881,1946,1912,1348, ++ 1515,3095,644,468,484,842,2528,1829,2821,614, ++ 1103,2752,2949,2504,781,2809,1275,592,1604,1110, ++ 3234,965,3242,3256,2873,2941,1137,632,2724,222, ++ 2443,3162,1359,62,1387,2712,248,970,262,682, ++ 1888,803,461,89,2935,1715,71,2466,2457,0, ++ 728,8,558,1478,1940,3283,894,514,19,1333, ++ 1496,1339,1504,2309,2235,2324,2250,2343,2171,2194, ++ 2269,1540,1471,2559,864,1875,1749,1550,2549,854, ++ 1760,2105,2047,2074,2060,2132,2089,2118,1766,1860, ++ 138,721,112,119,2663,2367,826,1852,3228,3123, ++ 1902,1353,3104,654,2814,1281,598,1666,1681,1649, ++ 1484,737,1738,506,1289,1297,924,3089,2626,1265, ++ 582,951,1176,524,1205,1215,547,2001,1246,569, ++ 666,2291,2217,-1u,3115,2376,1078,1054,1065,1087, ++ 1044,2427,400,379,1231,290,317,339,1984,2972, ++ 3029,3015,2998,2985,208,178,165,192,2861,2960, ++ 3221,2828,622,410,2166,-1u,-1u,-1u,-1u,-1u, ++ -1u,1424,1461,1448,1432,1414,1400,1146,54,2029, ++ 1157,3262,1126,1115,1000,982,1027,2792,2781,1836, ++ 1754,3184,2774,2956,3247,1636,1311,1325,491,672, ++ 606,3175,2020,1191,2896,1929,475,390,698,2411, ++ 1376,714,327,3211,2682,3043,350,2911,423,2848, ++ 3067,3051,2691,358,303,285,1732,1013,1697,1772, ++ 1867,2148,433,447,1779,2745,97,234,1198,27, ++ 901,791,2763,2362,2404,1953,1958,2644,2595,913, ++ 2396,1976,1967,34,1522,1618,151,2928,2387,2514, ++ 1789,1806,534,1141, ++}; ++static const char *ppc_syscall_i2s(int v) { ++ return i2s_direct__(ppc_syscall_strings, ppc_syscall_i2s_direct, 1, 354, v); ++} +diff --git a/lib/s390_tables.h b/lib/s390_tables.h +new file mode 100644 +index 0000000..218482e +--- /dev/null ++++ b/lib/s390_tables.h +@@ -0,0 +1,153 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char s390_syscall_strings[] = "_llseek\0_newselect\0_sysctl\0access\0acct\0add_key\0adjtimex\0afs_syscall\0alarm\0bdflush\0" ++ "brk\0capget\0capset\0chdir\0chmod\0chown\0chown32\0chroot\0clock_adjtime\0clock_getres\0" ++ "clock_gettime\0clock_nanosleep\0clock_settime\0clone\0close\0creat\0create_module\0delete_module\0dup\0dup2\0" ++ "dup3\0epoll_create\0epoll_create1\0epoll_ctl\0epoll_pwait\0epoll_wait\0eventfd\0eventfd2\0execve\0exit\0" ++ "exit_group\0faccessat\0fadvise64\0fadvise64_64\0fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0" ++ "fchown\0fchown32\0fchownat\0fcntl\0fcntl64\0fdatasync\0fgetxattr\0finit_module\0flistxattr\0flock\0" ++ "fork\0fremovexattr\0fsetxattr\0fstat\0fstat64\0fstatat\0fstatfs\0fstatfs64\0fsync\0ftruncate\0" ++ "ftruncate64\0futex\0futimesat\0get_kernel_syms\0get_robust_list\0getcpu\0getcwd\0getdents\0getdents64\0getegid\0" ++ "getegid32\0geteuid\0geteuid32\0getgid\0getgid32\0getgroups\0getgroups32\0getitimer\0getpgid\0getpgrp\0" ++ "getpid\0getpmsg\0getppid\0getpriority\0getresgid\0getresgid32\0getresuid\0getresuid32\0getrlimit\0getrusage\0" ++ "getsid\0gettid\0gettimeofday\0getuid\0getuid32\0getxattr\0idle\0init_module\0inotify_add_watch\0inotify_init\0" ++ "inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0ioctl\0ioperm\0ioprio_get\0" ++ "ioprio_set\0ipc\0kcmp\0kexec_load\0keyctl\0kill\0lchown\0lchown32\0lgetxattr\0link\0" ++ "linkat\0listxattr\0llistxattr\0lremovexattr\0lseek\0lsetxattr\0lstat\0lstat64\0madvise\0mincore\0" ++ "mkdir\0mkdirat\0mknod\0mknodat\0mlock\0mlockall\0mmap\0mmap2\0mount\0mprotect\0" ++ "mq_getsetattr\0mq_notify\0mq_open\0mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msync\0munlock\0munlockall\0" ++ "munmap\0name_to_handle_at\0nanosleep\0nfsservctl\0nice\0open\0open_by_handle_at\0openat\0pause\0perf_event_open\0" ++ "personality\0pipe\0pipe2\0pivot_root\0poll\0ppoll\0prctl\0pread\0preadv\0prlimit64\0" ++ "process_vm_readv\0process_vm_writev\0pselect6\0ptrace\0putpmsg\0pwrite\0pwritev\0query_module\0quotactl\0read\0" ++ "readahead\0readdir\0readlink\0readlinkat\0readv\0reboot\0remap_file_pages\0removexattr\0rename\0renameat\0" ++ "request_key\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0rt_tgsigqueueinfo\0" ++ "s390_runtime_instr\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0" ++ "sched_yield\0sendfile\0sendfile64\0set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsgid32\0setfsuid\0setfsuid32\0" ++ "setgid\0setgid32\0setgroups\0setgroups32\0sethostname\0setitimer\0setns\0setpgid\0setpriority\0setregid\0" ++ "setregid32\0setresgid\0setresgid32\0setresuid\0setresuid32\0setreuid\0setreuid32\0setrlimit\0setsid\0settimeofday\0" ++ "setuid\0setuid32\0setxattr\0sigaction\0sigaltstack\0signal\0signalfd\0signalfd4\0sigpending\0sigprocmask\0" ++ "sigreturn\0sigsuspend\0socketcall\0splice\0stat\0stat64\0statfs\0statfs64\0stime\0swapoff\0" ++ "swapon\0symlink\0symlinkat\0sync\0sync_file_range\0syncfs\0sysfs\0sysinfo\0syslog\0tee\0" ++ "tgkill\0time\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd\0timerfd_create\0timerfd_gettime\0" ++ "timerfd_settime\0times\0tkill\0truncate\0truncate64\0ugetrlimit\0umask\0umount\0umount2\0uname\0" ++ "unlink\0unlinkat\0unshare\0uselib\0ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0" ++ "vmsplice\0wait4\0waitid\0write\0writev"; ++static const unsigned s390_syscall_s2i_s[] = { ++ 0,8,19,27,34,39,47,56,68,74, ++ 82,86,93,100,106,112,118,126,133,147, ++ 160,174,190,204,210,216,222,236,250,254, ++ 259,264,277,291,301,313,324,332,341,348, ++ 353,364,374,384,397,407,421,435,442,449, ++ 458,465,474,483,489,497,507,517,530,541, ++ 547,552,565,575,581,589,597,605,615,621, ++ 631,643,649,659,675,691,698,705,714,725, ++ 733,743,751,761,768,777,787,799,809,817, ++ 825,832,840,848,860,870,882,892,904,914, ++ 924,931,938,951,958,967,976,981,993,1011, ++ 1024,1038,1055,1065,1076,1089,1098,1108,1114,1121, ++ 1132,1143,1147,1152,1163,1170,1175,1182,1191,1201, ++ 1206,1213,1223,1234,1247,1253,1263,1269,1277,1285, ++ 1293,1299,1307,1313,1321,1327,1336,1341,1347,1353, ++ 1362,1376,1386,1394,1410,1423,1433,1440,1446,1454, ++ 1465,1472,1490,1500,1511,1516,1521,1539,1546,1552, ++ 1568,1580,1585,1591,1602,1607,1613,1619,1625,1632, ++ 1642,1659,1677,1686,1693,1701,1708,1716,1729,1738, ++ 1743,1753,1761,1770,1781,1787,1794,1811,1823,1830, ++ 1839,1851,1857,1870,1884,1899,1915,1928,1942,1958, ++ 1976,1995,2018,2041,2059,2074,2093,2115,2133,2148, ++ 2167,2179,2188,2199,2215,2231,2245,2254,2265,2274, ++ 2285,2292,2301,2311,2323,2335,2345,2351,2359,2371, ++ 2380,2391,2401,2413,2423,2435,2444,2455,2465,2472, ++ 2485,2492,2501,2510,2520,2532,2539,2548,2558,2569, ++ 2581,2591,2602,2613,2620,2625,2632,2639,2648,2654, ++ 2662,2669,2677,2687,2692,2708,2715,2721,2729,2736, ++ 2740,2747,2752,2765,2778,2795,2809,2823,2831,2846, ++ 2862,2878,2884,2890,2899,2910,2921,2927,2934,2942, ++ 2948,2955,2964,2972,2979,2985,2991,3001,3008,3014, ++ 3022,3031,3037,3044,3050, ++}; ++static const int s390_syscall_s2i_i[] = { ++ 140,142,149,33,51,278,124,137,27,134, ++ 45,184,185,12,15,182,212,61,337,261, ++ 260,262,259,120,6,8,127,129,41,63, ++ 326,249,327,250,312,251,318,323,11,1, ++ 248,300,253,264,314,332,333,133,94,299, ++ 95,207,291,55,221,148,229,344,232,143, ++ 2,235,226,108,197,293,100,266,118,93, ++ 194,238,292,130,305,311,183,141,220,50, ++ 202,49,201,47,200,80,205,105,132,65, ++ 20,188,64,96,171,211,165,209,76,77, ++ 147,236,78,24,199,227,112,128,285,284, ++ 324,286,247,244,245,243,246,54,101,283, ++ 282,117,343,277,280,37,16,198,228,9, ++ 296,230,231,234,19,225,107,196,219,218, ++ 39,289,14,290,150,152,90,192,21,125, ++ 276,275,271,274,273,272,163,144,151,153, ++ 91,335,162,169,34,5,336,288,29,331, ++ 136,42,325,217,168,302,172,180,328,334, ++ 340,341,301,26,189,181,329,167,131,3, ++ 222,89,85,298,145,88,267,233,38,295, ++ 279,40,174,176,175,178,173,179,177,330, ++ 342,159,160,240,155,157,161,239,154,156, ++ 158,187,223,304,252,121,139,216,138,215, ++ 46,214,81,206,74,104,339,57,97,71, ++ 204,170,210,164,208,70,203,75,66,79, ++ 23,213,224,67,186,48,316,322,73,126, ++ 119,72,102,306,106,195,99,265,25,115, ++ 87,83,297,36,307,338,135,116,103,308, ++ 241,13,254,258,257,256,255,317,319,321, ++ 320,43,237,92,193,191,60,22,52,122, ++ 10,294,303,86,62,30,315,313,190,111, ++ 309,114,281,4,146, ++}; ++static int s390_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(s390_syscall_strings, s390_syscall_s2i_s, s390_syscall_s2i_i, 315, copy, value); ++ } ++} ++static const unsigned s390_syscall_i2s_direct[] = { ++ 348,547,1738,3044,1516,210,-1u,216,1201,2948, ++ 341,100,2747,1307,106,1175,-1u,-1u,1247,825, ++ 1347,2927,2485,951,2648,1686,68,-1u,1546,2985, ++ -1u,-1u,27,1511,-1u,2687,1170,1823,1293,1851, ++ 250,1580,2878,-1u,82,2285,761,2532,743,725, ++ 34,2934,-1u,1108,483,-1u,2351,-1u,-1u,2921, ++ 126,2979,254,840,817,2465,2510,-1u,-1u,2435, ++ 2371,2591,2558,2323,2455,904,914,938,2472,777, ++ 2301,-1u,2669,-1u,1761,2972,2662,1787,1753,1336, ++ 1465,2890,621,442,458,848,2359,-1u,2632,597, ++ 1114,2602,2729,2335,799,2620,1263,575,-1u,-1u, ++ 3014,976,-1u,3031,2654,2721,1143,615,2581,204, ++ 2231,2942,-1u,47,1353,2569,222,981,236,659, ++ 1729,809,435,74,2715,1568,56,2265,2245,0, ++ 705,8,541,1440,1781,3050,924,497,19,1321, ++ 1446,1327,1454,2133,2059,2148,2074,2167,1995,2018, ++ 2093,1490,1433,2413,882,-1u,1716,1602,1500,2391, ++ 860,1613,1915,1857,1884,1870,1942,1899,1928,1619, ++ 1701,112,698,86,93,2520,2179,832,1693,3008, ++ 2910,1341,2899,631,2625,1269,581,1182,958,768, ++ 751,733,2444,2380,787,2311,465,2423,892,2401, ++ 870,118,2492,2292,2274,2254,1591,1285,1277,714, ++ 489,1743,2188,2501,1253,565,967,1191,507,1213, ++ 1223,530,1811,1234,552,931,2884,643,2115,2041, ++ 2740,-1u,1089,1065,1076,1098,1055,353,264,291, ++ 313,2215,374,2752,2809,2795,2778,2765,190,160, ++ 147,174,-1u,384,2639,605,1794,-1u,-1u,-1u, ++ 1386,1423,1410,1394,1376,1362,1152,39,1839,1163, ++ 3037,1132,1121,1011,993,1038,-1u,1539,1299,1313, ++ 474,649,589,2955,1830,1206,2677,1770,449,364, ++ 1677,1607,2964,2199,675,2613,2692,2736,3022,-1u, ++ 691,301,3001,397,2991,2539,2823,324,2831,2862, ++ 2846,2548,332,1024,1585,259,277,1625,1708,1958, ++ 1552,407,421,1632,1472,1521,133,2708,2345,1642, ++ 1659,1976,1147,517, ++}; ++static const char *s390_syscall_i2s(int v) { ++ return i2s_direct__(s390_syscall_strings, s390_syscall_i2s_direct, 1, 344, v); ++} +diff --git a/lib/s390x_tables.h b/lib/s390x_tables.h +new file mode 100644 +index 0000000..36099fc +--- /dev/null ++++ b/lib/s390x_tables.h +@@ -0,0 +1,144 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char s390x_syscall_strings[] = "_sysctl\0access\0acct\0add_key\0adjtimex\0afs_syscall\0alarm\0bdflush\0brk\0capget\0" ++ "capset\0chdir\0chmod\0chown\0chroot\0clock_adjtime\0clock_getres\0clock_gettime\0clock_nanosleep\0clock_settime\0" ++ "clone\0close\0creat\0create_module\0delete_module\0dup\0dup2\0dup3\0epoll_create\0epoll_create1\0" ++ "epoll_ctl\0epoll_pwait\0epoll_wait\0eventfd\0eventfd2\0execve\0exit\0exit_group\0faccessat\0fadvise64\0" ++ "fallocate\0fanotify_init\0fanotify_mark\0fchdir\0fchmod\0fchmodat\0fchown\0fchownat\0fcntl\0fdatasync\0" ++ "fgetxattr\0finit_module\0flistxattr\0flock\0fork\0fremovexattr\0fsetxattr\0fstat\0fstatfs\0fstatfs64\0" ++ "fsync\0ftruncate\0futex\0futimesat\0get_kernel_syms\0get_robust_list\0getcpu\0getcwd\0getdents\0getegid\0" ++ "geteuid\0getgid\0getgroups\0getitimer\0getpgid\0getpgrp\0getpid\0getpmsg\0getppid\0getpriority\0" ++ "getresgid\0getresuid\0getrlimit\0getrusage\0getsid\0gettid\0gettimeofday\0getuid\0getxattr\0idle\0" ++ "init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0" ++ "ioctl\0ioprio_get\0ioprio_set\0ipc\0kcmp\0kexec_load\0keyctl\0kill\0lchown\0lgetxattr\0" ++ "link\0linkat\0listxattr\0llistxattr\0lremovexattr\0lseek\0lsetxattr\0lstat\0madvise\0mincore\0" ++ "mkdir\0mkdirat\0mknod\0mknodat\0mlock\0mlockall\0mmap\0mount\0mprotect\0mq_getsetattr\0" ++ "mq_notify\0mq_open\0mq_timedreceive\0mq_timedsend\0mq_unlink\0mremap\0msync\0munlock\0munlockall\0munmap\0" ++ "name_to_handle_at\0nanosleep\0newfstatat\0nfsservctl\0nice\0open\0open_by_handle_at\0openat\0pause\0perf_event_open\0" ++ "personality\0pipe\0pipe2\0pivot_root\0poll\0ppoll\0prctl\0pread\0preadv\0prlimit64\0" ++ "process_vm_readv\0process_vm_writev\0pselect6\0ptrace\0putpmsg\0pwrite\0pwritev\0query_module\0quotactl\0read\0" ++ "readahead\0readdir\0readlink\0readlinkat\0readv\0reboot\0remap_file_pages\0removexattr\0rename\0renameat\0" ++ "request_key\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0rt_sigsuspend\0rt_sigtimedwait\0rt_tgsigqueueinfo\0" ++ "s390_runtime_instr\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0sched_setparam\0sched_setscheduler\0" ++ "sched_yield\0select\0sendfile\0set_robust_list\0set_tid_address\0setdomainname\0setfsgid\0setfsuid\0setgid\0setgroups\0" ++ "sethostname\0setitimer\0setns\0setpgid\0setpriority\0setregid\0setresgid\0setresuid\0setreuid\0setrlimit\0" ++ "setsid\0settimeofday\0setuid\0setxattr\0sigaction\0sigaltstack\0signal\0signalfd\0signalfd4\0sigpending\0" ++ "sigprocmask\0sigreturn\0sigsuspend\0socketcall\0splice\0stat\0statfs\0statfs64\0swapoff\0swapon\0" ++ "symlink\0symlinkat\0sync\0sync_file_range\0syncfs\0sysfs\0sysinfo\0syslog\0tee\0tgkill\0" ++ "timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd\0timerfd_create\0timerfd_gettime\0timerfd_settime\0times\0" ++ "tkill\0truncate\0umask\0umount\0umount2\0uname\0unlink\0unlinkat\0unshare\0uselib\0" ++ "ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0vmsplice\0wait4\0waitid\0write\0" ++ "writev"; ++static const unsigned s390x_syscall_s2i_s[] = { ++ 0,8,15,20,28,37,49,55,63,67, ++ 74,81,87,93,99,106,120,133,147,163, ++ 177,183,189,195,209,223,227,232,237,250, ++ 264,274,286,297,305,314,321,326,337,347, ++ 357,367,381,395,402,409,418,425,434,440, ++ 450,460,473,484,490,495,508,518,524,532, ++ 542,548,558,564,574,590,606,613,620,629, ++ 637,645,652,662,672,680,688,695,703,711, ++ 723,733,743,753,763,770,777,790,797,806, ++ 811,823,841,854,868,885,895,906,919,928, ++ 938,944,955,966,970,975,986,993,998,1005, ++ 1015,1020,1027,1037,1048,1061,1067,1077,1083,1091, ++ 1099,1105,1113,1119,1127,1133,1142,1147,1153,1162, ++ 1176,1186,1194,1210,1223,1233,1240,1246,1254,1265, ++ 1272,1290,1300,1311,1322,1327,1332,1350,1357,1363, ++ 1379,1391,1396,1402,1413,1418,1424,1430,1436,1443, ++ 1453,1470,1488,1497,1504,1512,1519,1527,1540,1549, ++ 1554,1564,1572,1581,1592,1598,1605,1622,1634,1641, ++ 1650,1662,1668,1681,1695,1710,1726,1739,1753,1769, ++ 1787,1806,1829,1852,1870,1885,1904,1926,1944,1959, ++ 1978,1990,1997,2006,2022,2038,2052,2061,2070,2077, ++ 2087,2099,2109,2115,2123,2135,2144,2154,2164,2173, ++ 2183,2190,2203,2210,2219,2229,2241,2248,2257,2267, ++ 2278,2290,2300,2311,2322,2329,2334,2341,2350,2358, ++ 2365,2373,2383,2388,2404,2411,2417,2425,2432,2436, ++ 2443,2456,2469,2486,2500,2514,2522,2537,2553,2569, ++ 2575,2581,2590,2596,2603,2611,2617,2624,2633,2641, ++ 2648,2654,2660,2670,2677,2683,2691,2700,2706,2713, ++ 2719, ++}; ++static const int s390x_syscall_s2i_i[] = { ++ 149,33,51,278,124,137,27,134,45,184, ++ 185,12,15,212,61,337,261,260,262,259, ++ 120,6,8,127,129,41,63,326,249,327, ++ 250,312,251,318,323,11,1,248,300,253, ++ 314,332,333,133,94,299,207,291,55,148, ++ 229,344,232,143,2,235,226,108,100,266, ++ 118,93,238,292,130,305,311,183,141,202, ++ 201,200,205,105,132,65,20,188,64,96, ++ 211,209,191,77,147,236,78,199,227,112, ++ 128,285,284,324,286,247,244,245,243,246, ++ 54,283,282,117,343,277,280,37,198,228, ++ 9,296,230,231,234,19,225,107,219,218, ++ 39,289,14,290,150,152,90,21,125,276, ++ 275,271,274,273,272,163,144,151,153,91, ++ 335,162,293,169,34,5,336,288,29,331, ++ 136,42,325,217,168,302,172,180,328,334, ++ 340,341,301,26,189,181,329,167,131,3, ++ 222,89,85,298,145,88,267,233,38,295, ++ 279,40,174,176,175,178,173,179,177,330, ++ 342,159,160,240,155,157,161,239,154,156, ++ 158,142,187,304,252,121,216,215,214,206, ++ 74,104,339,57,97,204,210,208,203,75, ++ 66,79,213,224,67,186,48,316,322,73, ++ 126,119,72,102,306,106,99,265,115,87, ++ 83,297,36,307,338,135,116,103,308,241, ++ 254,258,257,256,255,317,319,321,320,43, ++ 237,92,60,22,52,122,10,294,303,86, ++ 62,30,315,313,190,111,309,114,281,4, ++ 146, ++}; ++static int s390x_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(s390x_syscall_strings, s390x_syscall_s2i_s, s390x_syscall_s2i_i, 281, copy, value); ++ } ++} ++static const unsigned s390x_syscall_i2s_direct[] = { ++ 321,490,1549,2713,1327,183,-1u,189,1015,2617, ++ 314,81,-1u,1113,87,-1u,-1u,-1u,1061,688, ++ 1147,2596,-1u,-1u,-1u,1497,49,-1u,1357,2654, ++ -1u,-1u,8,1322,-1u,2383,993,1634,1099,1662, ++ 223,1391,2569,-1u,63,-1u,-1u,2241,-1u,-1u, ++ 15,2603,-1u,938,434,-1u,2115,-1u,-1u,2590, ++ 99,2648,227,703,680,2183,2219,-1u,-1u,-1u, ++ -1u,2300,2267,2087,2173,-1u,753,777,2190,-1u, ++ -1u,-1u,2365,-1u,1572,2641,2358,1598,1564,1142, ++ 1265,2581,548,402,-1u,711,2123,-1u,2334,524, ++ -1u,2311,2425,2099,662,2329,1077,518,-1u,-1u, ++ 2683,806,-1u,2700,2350,2417,966,542,2290,177, ++ 2038,2611,-1u,28,1153,2278,195,811,209,574, ++ 1540,672,395,55,2411,1379,37,-1u,-1u,-1u, ++ 620,1990,484,1240,1592,2719,763,440,0,1127, ++ 1246,1133,1254,1944,1870,1959,1885,1978,1806,1829, ++ 1904,1290,1233,-1u,-1u,-1u,1527,1413,1311,-1u, ++ -1u,1424,1726,1668,1695,1681,1753,1710,1739,1430, ++ 1512,-1u,613,67,74,2229,1997,695,1504,2677, ++ 743,-1u,-1u,-1u,-1u,-1u,-1u,998,790,645, ++ 637,629,2164,2135,652,2077,418,2154,733,2144, ++ 723,93,2203,2070,2061,2052,1402,1091,1083,-1u, ++ -1u,1554,-1u,2210,1067,508,797,1005,450,1027, ++ 1037,473,1622,1048,495,770,2575,558,1926,1852, ++ 2436,-1u,919,895,906,928,885,326,237,264, ++ 286,2022,347,2443,2500,2486,2469,2456,163,133, ++ 120,147,-1u,-1u,2341,532,1605,-1u,-1u,-1u, ++ 1186,1223,1210,1194,1176,1162,975,20,1650,986, ++ 2706,955,944,841,823,868,-1u,1350,1105,1119, ++ 425,564,1300,2624,1641,1020,2373,1581,409,337, ++ 1488,1418,2633,2006,590,2322,2388,2432,2691,-1u, ++ 606,274,2670,357,2660,2248,2514,297,2522,2553, ++ 2537,2257,305,854,1396,232,250,1436,1519,1769, ++ 1363,367,381,1443,1272,1332,106,2404,2109,1453, ++ 1470,1787,970,460, ++}; ++static const char *s390x_syscall_i2s(int v) { ++ return i2s_direct__(s390x_syscall_strings, s390x_syscall_i2s_direct, 1, 344, v); ++} +diff --git a/lib/x86_64_tables.h b/lib/x86_64_tables.h +new file mode 100644 +index 0000000..d2a5673 +--- /dev/null ++++ b/lib/x86_64_tables.h +@@ -0,0 +1,150 @@ ++/* This is a generated file, see Makefile.am for its inputs. */ ++static const char x86_64_syscall_strings[] = "_sysctl\0accept\0accept4\0access\0acct\0add_key\0adjtimex\0afs_syscall\0alarm\0arch_prctl\0" ++ "bind\0brk\0capget\0capset\0chdir\0chmod\0chown\0chroot\0clock_adjtime\0clock_getres\0" ++ "clock_gettime\0clock_nanosleep\0clock_settime\0clone\0close\0connect\0creat\0create_module\0delete_module\0dup\0" ++ "dup2\0dup3\0epoll_create\0epoll_create1\0epoll_ctl\0epoll_ctl_old\0epoll_pwait\0epoll_wait\0epoll_wait_old\0eventfd\0" ++ "eventfd2\0execve\0exit\0exit_group\0faccessat\0fadvise64\0fallocate\0fanotify_init\0fanotify_mark\0fchdir\0" ++ "fchmod\0fchmodat\0fchown\0fchownat\0fcntl\0fdatasync\0fgetxattr\0finit_module\0flistxattr\0flock\0" ++ "fork\0fremovexattr\0fsetxattr\0fstat\0fstatfs\0fsync\0ftruncate\0futex\0futimesat\0get_kernel_syms\0" ++ "get_mempolicy\0get_robust_list\0get_thread_area\0getcpu\0getcwd\0getdents\0getdents64\0getegid\0geteuid\0getgid\0" ++ "getgroups\0getitimer\0getpeername\0getpgid\0getpgrp\0getpid\0getpmsg\0getppid\0getpriority\0getresgid\0" ++ "getresuid\0getrlimit\0getrusage\0getsid\0getsockname\0getsockopt\0gettid\0gettimeofday\0getuid\0getxattr\0" ++ "init_module\0inotify_add_watch\0inotify_init\0inotify_init1\0inotify_rm_watch\0io_cancel\0io_destroy\0io_getevents\0io_setup\0io_submit\0" ++ "ioctl\0ioperm\0iopl\0ioprio_get\0ioprio_set\0kcmp\0kexec_load\0keyctl\0kill\0lchown\0" ++ "lgetxattr\0link\0linkat\0listen\0listxattr\0llistxattr\0lookup_dcookie\0lremovexattr\0lseek\0lsetxattr\0" ++ "lstat\0madvise\0mbind\0migrate_pages\0mincore\0mkdir\0mkdirat\0mknod\0mknodat\0mlock\0" ++ "mlockall\0mmap\0modify_ldt\0mount\0move_pages\0mprotect\0mq_getsetattr\0mq_notify\0mq_open\0mq_timedreceive\0" ++ "mq_timedsend\0mq_unlink\0mremap\0msgctl\0msgget\0msgrcv\0msgsnd\0msync\0munlock\0munlockall\0" ++ "munmap\0name_to_handle_at\0nanosleep\0newfstatat\0nfsservctl\0open\0open_by_handle_at\0openat\0pause\0perf_event_open\0" ++ "personality\0pipe\0pipe2\0pivot_root\0poll\0ppoll\0prctl\0pread\0preadv\0prlimit64\0" ++ "process_vm_readv\0process_vm_writev\0pselect6\0ptrace\0putpmsg\0pwrite\0pwritev\0query_module\0quotactl\0read\0" ++ "readahead\0readlink\0readlinkat\0readv\0reboot\0recvfrom\0recvmmsg\0recvmsg\0remap_file_pages\0removexattr\0" ++ "rename\0renameat\0request_key\0restart_syscall\0rmdir\0rt_sigaction\0rt_sigpending\0rt_sigprocmask\0rt_sigqueueinfo\0rt_sigreturn\0" ++ "rt_sigsuspend\0rt_sigtimedwait\0rt_tgsigqueueinfo\0sched_get_priority_max\0sched_get_priority_min\0sched_getaffinity\0sched_getparam\0sched_getscheduler\0sched_rr_get_interval\0sched_setaffinity\0" ++ "sched_setparam\0sched_setscheduler\0sched_yield\0security\0select\0semctl\0semget\0semop\0semtimedop\0sendfile\0" ++ "sendmmsg\0sendmsg\0sendto\0set_mempolicy\0set_robust_list\0set_thread_area\0set_tid_address\0setdomainname\0setfsgid\0setfsuid\0" ++ "setgid\0setgroups\0sethostname\0setitimer\0setns\0setpgid\0setpriority\0setregid\0setresgid\0setresuid\0" ++ "setreuid\0setrlimit\0setsid\0setsockopt\0settimeofday\0setuid\0setxattr\0shmat\0shmctl\0shmdt\0" ++ "shmget\0shutdown\0sigaltstack\0signalfd\0signalfd4\0socket\0socketpair\0splice\0stat\0statfs\0" ++ "swapoff\0swapon\0symlink\0symlinkat\0sync\0sync_file_range\0syncfs\0sysfs\0sysinfo\0syslog\0" ++ "tee\0tgkill\0time\0timer_create\0timer_delete\0timer_getoverrun\0timer_gettime\0timer_settime\0timerfd\0timerfd_gettime\0" ++ "timerfd_settime\0times\0tkill\0truncate\0tuxcall\0umask\0umount2\0uname\0unlink\0unlinkat\0" ++ "unshare\0uselib\0ustat\0utime\0utimensat\0utimes\0vfork\0vhangup\0vmsplice\0vserver\0" ++ "wait4\0waitid\0write\0writev"; ++static const unsigned x86_64_syscall_s2i_s[] = { ++ 0,8,15,23,30,35,43,52,64,70, ++ 81,86,90,97,104,110,116,122,129,143, ++ 156,170,186,200,206,212,220,226,240,254, ++ 258,263,268,281,295,305,319,331,342,357, ++ 365,374,381,386,397,407,417,427,441,455, ++ 462,469,478,485,494,500,510,520,533,544, ++ 550,555,568,578,584,592,598,608,614,624, ++ 640,654,670,686,693,700,709,720,728,736, ++ 743,753,763,775,783,791,798,806,814,826, ++ 836,846,856,866,873,885,896,903,916,923, ++ 932,944,962,975,989,1006,1016,1027,1040,1049, ++ 1059,1065,1072,1077,1088,1099,1104,1115,1122,1127, ++ 1134,1144,1149,1156,1163,1173,1184,1199,1212,1218, ++ 1228,1234,1242,1248,1262,1270,1276,1284,1290,1298, ++ 1304,1313,1318,1329,1335,1346,1355,1369,1379,1387, ++ 1403,1416,1426,1433,1440,1447,1454,1461,1467,1475, ++ 1486,1493,1511,1521,1532,1543,1548,1566,1573,1579, ++ 1595,1607,1612,1618,1629,1634,1640,1646,1652,1659, ++ 1669,1686,1704,1713,1720,1728,1735,1743,1756,1765, ++ 1770,1780,1789,1800,1806,1813,1822,1831,1839,1856, ++ 1868,1875,1884,1896,1912,1918,1931,1945,1960,1976, ++ 1989,2003,2019,2037,2060,2083,2101,2116,2135,2157, ++ 2175,2190,2209,2221,2230,2237,2244,2251,2257,2268, ++ 2277,2286,2294,2301,2315,2331,2347,2363,2377,2386, ++ 2395,2402,2412,2424,2434,2440,2448,2460,2469,2479, ++ 2489,2498,2508,2515,2526,2539,2546,2555,2561,2568, ++ 2574,2581,2590,2602,2611,2621,2628,2639,2646,2651, ++ 2658,2666,2673,2681,2691,2696,2712,2719,2725,2733, ++ 2740,2744,2751,2756,2769,2782,2799,2813,2827,2835, ++ 2851,2867,2873,2879,2888,2896,2902,2910,2916,2923, ++ 2932,2940,2947,2953,2959,2969,2976,2982,2990,2999, ++ 3007,3013,3020,3026, ++}; ++static const int x86_64_syscall_s2i_i[] = { ++ 156,43,288,21,163,248,159,183,37,158, ++ 49,12,125,126,80,90,92,161,305,229, ++ 228,230,227,56,3,42,85,174,176,32, ++ 33,292,213,291,233,214,281,232,215,284, ++ 290,59,60,231,269,221,285,300,301,81, ++ 91,268,93,260,72,75,193,313,196,73, ++ 57,199,190,5,138,74,77,202,261,177, ++ 239,274,211,309,79,78,217,108,107,104, ++ 115,36,52,121,111,39,181,110,140,120, ++ 118,97,98,124,51,55,186,96,102,191, ++ 175,254,253,294,255,210,207,208,206,209, ++ 16,173,172,252,251,312,246,250,62,94, ++ 192,86,265,50,194,195,212,198,8,189, ++ 6,28,237,256,27,83,258,133,259,149, ++ 151,9,154,165,279,10,245,244,240,243, ++ 242,241,25,71,68,70,69,26,150,152, ++ 11,303,35,262,180,2,304,257,34,298, ++ 135,22,293,155,7,271,157,17,295,302, ++ 310,311,270,101,182,18,296,178,179,0, ++ 187,89,267,19,169,45,299,47,216,197, ++ 82,264,249,219,84,13,127,14,129,15, ++ 130,128,297,146,147,204,143,145,148,203, ++ 142,144,24,185,23,66,64,65,220,40, ++ 307,46,44,238,273,205,218,171,123,122, ++ 106,116,170,38,308,109,141,114,119,117, ++ 113,160,112,54,164,105,188,30,31,67, ++ 29,48,131,282,289,41,53,275,4,137, ++ 168,167,88,266,162,277,306,139,99,103, ++ 276,234,201,222,226,225,224,223,283,287, ++ 286,100,200,76,184,95,166,63,87,263, ++ 272,134,136,132,280,235,58,153,278,236, ++ 61,247,1,20, ++}; ++static int x86_64_syscall_s2i(const char *s, int *value) { ++ size_t len, i; ++ len = strlen(s); ++ { char copy[len + 1]; ++ for (i = 0; i < len; i++) { ++ char c = s[i]; ++ copy[i] = GT_ISUPPER(c) ? c - 'A' + 'a' : c; ++ } ++ copy[i] = 0; ++ return s2i__(x86_64_syscall_strings, x86_64_syscall_s2i_s, x86_64_syscall_s2i_i, 314, copy, value); ++ } ++} ++static const unsigned x86_64_syscall_i2s_direct[] = { ++ 1765,3020,1543,206,2646,578,1228,1629,1212,1313, ++ 1346,1486,86,1918,1945,1976,1059,1646,1728,1800, ++ 3026,23,1607,2230,2209,1426,1461,1262,1234,2574, ++ 2555,2561,254,258,1573,1511,753,64,2424,791, ++ 2268,2621,212,8,2294,1813,2286,1831,2581,81, ++ 1156,873,763,2628,2515,885,200,550,2976,374, ++ 381,3007,1122,2910,2244,2251,2237,2568,1440,1454, ++ 1447,1433,494,544,592,500,2879,598,700,693, ++ 104,455,1868,1270,1912,220,1144,2916,2673,1780, ++ 110,462,116,478,1127,2896,903,846,856,2725, ++ 2867,1713,916,2733,736,2539,2395,728,720,2440, ++ 806,783,2508,2489,2460,743,2402,2479,836,2469, ++ 826,775,2386,2377,866,90,97,1931,2003,1960, ++ 1989,2590,2953,1284,2940,1595,2947,2651,584,2719, ++ 814,2448,2175,2101,2190,2116,2037,2060,2135,1298, ++ 1467,1304,1475,2982,1318,1618,0,1640,70,43, ++ 2498,122,2691,30,2526,1329,2902,2666,2658,1806, ++ 2412,2363,1072,1065,226,932,240,624,1743,1756, ++ 1532,798,1720,52,2888,2221,896,1770,2546,1218, ++ 568,923,1134,510,1163,1173,533,1856,1199,555, ++ 2873,2751,608,2157,2083,2331,1040,1016,1027,1049, ++ 1006,670,1184,268,305,342,1839,709,2347,1896, ++ 2257,407,2756,2813,2799,2782,2769,186,156,143, ++ 170,386,331,295,2744,2969,2999,1242,2301,640, ++ 1379,1416,1403,1387,1369,1355,1104,3013,35,1884, ++ 1115,1088,1077,962,944,989,1248,1566,1276,1290, ++ 485,614,1521,2923,1875,1149,2681,1789,469,397, ++ 1704,1634,2932,2315,654,2639,2740,2696,2990,1335, ++ 2959,319,2602,2827,357,417,2851,2835,15,2611, ++ 365,281,263,1612,975,1652,1735,2019,1579,1822, ++ 427,441,1659,1493,1548,129,2712,2277,2434,686, ++ 1669,1686,1099,520, ++}; ++static const char *x86_64_syscall_i2s(int v) { ++ return i2s_direct__(x86_64_syscall_strings, x86_64_syscall_i2s_direct, 0, 313, v); ++} +-- +1.7.9.5 + diff --git a/meta-security/recipes-security/audit/audit/audit-python-configure.patch b/meta-security/recipes-security/audit/audit/audit-python-configure.patch new file mode 100644 index 000000000..f90e21330 --- /dev/null +++ b/meta-security/recipes-security/audit/audit/audit-python-configure.patch @@ -0,0 +1,27 @@ +From cace630b0eb42418dea4f3d98c69d0d777bfc1be Mon Sep 17 00:00:00 2001 +From: Xin Ouyang <Xin.Ouyang@windriver.com> +Date: Wed, 20 Jun 2012 16:34:19 +0800 +Subject: [PATCH] audit: python cross-compile + +Signed-off-by: Xin Ouyang <Xin.Ouyang@windriver.com> +--- + configure.ac | 3 ++- + 1 files changed, 2 insertions(+), 1 deletions(-) + +diff --git a/configure.ac b/configure.ac +index 3db7d45..9a07db6 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -90,7 +90,8 @@ if test x$use_python = xno ; then + else + AC_MSG_RESULT(testing) + AM_PATH_PYTHON +-if test -f /usr/include/python${am_cv_python_version}/Python.h ; then ++PY_PREFIX=`$PYTHON -c 'import sys ; print sys.prefix'` ++if test -f $PY_PREFIX/include/python${am_cv_python_version}/Python.h ; then + python_found="yes" + AC_MSG_NOTICE(Python bindings will be built) + else +-- +1.7.7 + diff --git a/meta-security/recipes-security/audit/audit/audit-python.patch b/meta-security/recipes-security/audit/audit/audit-python.patch new file mode 100644 index 000000000..78fce0199 --- /dev/null +++ b/meta-security/recipes-security/audit/audit/audit-python.patch @@ -0,0 +1,31 @@ +Remove hard coded python include directory + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> + +diff -ur audit-2.1.3.orig/bindings/python/Makefile.am audit-2.1.3/bindings/python/Makefile.am +--- audit-2.1.3.orig/bindings/python/Makefile.am 2011-08-15 12:31:01.000000000 -0500 ++++ audit-2.1.3/bindings/python/Makefile.am 2012-01-30 12:19:54.533959225 -0600 +@@ -25,7 +25,9 @@ + + pyexec_LTLIBRARIES = auparse.la + ++PYINC ?= /usr/include/python$(PYTHON_VERSION) ++ + auparse_la_SOURCES = auparse_python.c +-auparse_la_CPPFLAGS = -I$(top_srcdir)/auparse $(AM_CPPFLAGS) -I/usr/include/python$(PYTHON_VERSION) -fno-strict-aliasing ++auparse_la_CPPFLAGS = -I$(top_srcdir)/auparse $(AM_CPPFLAGS) -I$(PYINC) -fno-strict-aliasing + auparse_la_LDFLAGS = -module -avoid-version -Wl,-z,relro + auparse_la_LIBADD = ../../auparse/libauparse.la ../../lib/libaudit.la +diff -ur audit-2.1.3.orig/swig/Makefile.am audit-2.1.3/swig/Makefile.am +--- audit-2.1.3.orig/swig/Makefile.am 2011-08-15 12:31:03.000000000 -0500 ++++ audit-2.1.3/swig/Makefile.am 2012-01-30 12:28:09.574834697 -0600 +@@ -23,7 +23,8 @@ + CONFIG_CLEAN_FILES = *.loT *.rej *.orig + AM_CFLAGS = -fPIC -DPIC -fno-strict-aliasing + PYLIBVER ?= python$(PYTHON_VERSION) +-INCLUDES = -I. -I$(top_builddir) -I${top_srcdir}/lib -I/usr/include/$(PYLIBVER) ++PYINC ?= /usr/include/$(PYLIBVER) ++INCLUDES = -I. -I$(top_builddir) -I${top_srcdir}/lib -I$(PYINC) + LIBS = $(top_builddir)/lib/libaudit.la + pyexec_PYTHON = audit.py + pyexec_LTLIBRARIES = _audit.la diff --git a/meta-security/recipes-security/audit/audit/audit-volatile.conf b/meta-security/recipes-security/audit/audit/audit-volatile.conf new file mode 100644 index 000000000..9cbe1547a --- /dev/null +++ b/meta-security/recipes-security/audit/audit/audit-volatile.conf @@ -0,0 +1 @@ +d /var/log/audit 0750 root root - diff --git a/meta-security/recipes-security/audit/audit/auditd b/meta-security/recipes-security/audit/audit/auditd new file mode 100755 index 000000000..fcd96c9df --- /dev/null +++ b/meta-security/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-security/recipes-security/audit/audit/auditd.service b/meta-security/recipes-security/audit/audit/auditd.service new file mode 100644 index 000000000..ebc079897 --- /dev/null +++ b/meta-security/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-security/recipes-security/audit/audit/disable-ldap.patch b/meta-security/recipes-security/audit/audit/disable-ldap.patch new file mode 100644 index 000000000..1d683c29e --- /dev/null +++ b/meta-security/recipes-security/audit/audit/disable-ldap.patch @@ -0,0 +1,59 @@ +Disable LDAP support + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> + +Disable LDAP support + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> + +Index: audit-2.3.2/audisp/plugins/Makefile.am +=================================================================== +--- audit-2.3.2.orig/audisp/plugins/Makefile.am ++++ audit-2.3.2/audisp/plugins/Makefile.am +@@ -22,8 +22,10 @@ + + CONFIG_CLEAN_FILES = *.loT *.rej *.orig + +-SUBDIRS = builtins zos-remote remote +-#SUBDIRS = builtins zos-remote ++SUBDIRS = builtins remote ++if HAVE_LDAP ++SUBDIRS += zos-remote ++endif + if HAVE_PRELUDE + SUBDIRS += prelude + endif +Index: audit-2.3.2/configure.ac +=================================================================== +--- audit-2.3.2.orig/configure.ac ++++ audit-2.3.2/configure.ac +@@ -241,6 +241,12 @@ else + fi + AM_CONDITIONAL(HAVE_PRELUDE, test x$have_prelude = xyes) + ++AC_ARG_WITH(ldap, ++AS_HELP_STRING([--with-ldap],[enable zos-remote plugin, which requires ldap]), ++use_ldap=$withval, ++use_ldap=no) ++AM_CONDITIONAL(HAVE_LDAP, test x$have_ldap = xyes) ++ + AC_MSG_CHECKING(whether to use libwrap) + AC_ARG_WITH(libwrap, + [ --with-libwrap[=PATH] Compile in libwrap (tcp_wrappers) support.], +Index: audit-2.3.2/docs/Makefile.am +=================================================================== +--- audit-2.3.2.orig/docs/Makefile.am ++++ audit-2.3.2/docs/Makefile.am +@@ -53,7 +53,9 @@ ausearch_add_expression.3 ausearch_add_t + ausearch_clear.3 \ + ausearch_next_event.3 ausearch_set_stop.3 \ + autrace.8 get_auditfail_action.3 set_aumessage_mode.3 \ +-audispd.8 audispd.conf.5 audispd-zos-remote.8 libaudit.conf.5 \ +-augenrules.8 \ +-zos-remote.conf.5 ++audispd.8 audispd.conf.5 libaudit.conf.5 \ ++augenrules.8 + ++if HAVE_LDAP ++man_MANS += audispd-zos-remote.8 zos-remote.conf.5 ++endif diff --git a/meta-security/recipes-security/audit/audit/fix-swig-host-contamination.patch b/meta-security/recipes-security/audit/audit/fix-swig-host-contamination.patch new file mode 100644 index 000000000..16bb173ad --- /dev/null +++ b/meta-security/recipes-security/audit/audit/fix-swig-host-contamination.patch @@ -0,0 +1,48 @@ +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: pending + +Signed-off-by: Anders Hedlund <anders.hedlund@windriver.com> +Signed-off-by: Joe Slater <jslater@windriver.com> + +Index: audit-2.2.1/swig/Makefile.am +=================================================================== +--- audit-2.2.1.orig/swig/Makefile.am ++++ audit-2.2.1/swig/Makefile.am +@@ -25,6 +25,7 @@ AM_CFLAGS = -fPIC -DPIC -fno-strict-alia + PYLIBVER ?= python$(PYTHON_VERSION) + PYINC ?= /usr/include/$(PYLIBVER) + INCLUDES = -I. -I$(top_builddir) -I${top_srcdir}/lib -I$(PYINC) ++STDINC ?= /usr/include + LIBS = $(top_builddir)/lib/libaudit.la + pyexec_PYTHON = audit.py + pyexec_LTLIBRARIES = _audit.la +@@ -34,7 +35,7 @@ _audit_la_HEADERS: $(top_builddir)/confi + _audit_la_DEPENDENCIES =${top_srcdir}/lib/libaudit.h ${top_builddir}/lib/libaudit.la + nodist__audit_la_SOURCES = audit_wrap.c + audit.py audit_wrap.c: ${srcdir}/auditswig.i +- swig -o audit_wrap.c -python ${INCLUDES} ${srcdir}/auditswig.i ++ swig -o audit_wrap.c -python ${INCLUDES} -I$(STDINC) ${srcdir}/auditswig.i + + CLEANFILES = audit.py* audit_wrap.c *~ + +Index: audit-2.2.1/swig/auditswig.i +=================================================================== +--- audit-2.2.1.orig/swig/auditswig.i ++++ audit-2.2.1/swig/auditswig.i +@@ -37,8 +37,8 @@ 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 "/usr/include/stdint.h" ++%include "stdint.h" + %include "../lib/libaudit.h" + diff --git a/meta-security/recipes-security/audit/audit_2.3.2.bb b/meta-security/recipes-security/audit/audit_2.3.2.bb new file mode 100644 index 000000000..1d7ea0f0a --- /dev/null +++ b/meta-security/recipes-security/audit/audit_2.3.2.bb @@ -0,0 +1,102 @@ +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" +PR = "r8" +LICENSE = "GPLv2+ & LGPLv2+" +LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f" + +SRC_URI = "http://people.redhat.com/sgrubb/audit/audit-${PV}.tar.gz \ + file://disable-ldap.patch \ + file://audit-python.patch \ + file://audit-python-configure.patch \ + file://audit-for-cross-compiling.patch \ + file://auditd \ + file://fix-swig-host-contamination.patch \ + file://auditd.service \ + file://audit-volatile.conf \ +" +SRC_URI_append_arm = "file://add-system-call-table-for-ARM.patch" + +inherit autotools pythonnative update-rc.d systemd + +UPDATERCPN = "auditd" +INITSCRIPT_NAME = "auditd" +INITSCRIPT_PARAMS = "defaults" + +SYSTEMD_SERVICE_${PN} = "auditd.service" + +SRC_URI[md5sum] = "4e8d065b5cc16b77b9b61e93a9ed160e" +SRC_URI[sha256sum] = "8872e0b5392888789061db8034164305ef0e1b34543e1e7004d275f039081d29" + +DEPENDS += "python tcp-wrappers libcap-ng linux-libc-headers (>= 2.6.30)" + +EXTRA_OECONF += "--without-prelude \ + --with-libwrap \ + --enable-gssapi-krb5=no \ + --without-ldap \ + --with-libcap-ng=yes \ + --with-python=yes \ + --libdir=${base_libdir} \ + --sbindir=${base_sbindir} \ + " +EXTRA_OECONF_append_arm = " --with-armeb=yes" + +EXTRA_OEMAKE += "PYLIBVER='python${PYTHON_BASEVERSION}' \ + PYINC='${STAGING_INCDIR}/$(PYLIBVER)' \ + pyexecdir=${libdir}/python${PYTHON_BASEVERSION}/site-packages \ + STDINC='${STAGING_INCDIR}' \ + " + +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}" +FILES_${PN}-dev += "${base_libdir}/*.so ${base_libdir}/*.la" + +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 ${S}/../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 + + 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-security/recipes-security/cynara/cynara.inc b/meta-security/recipes-security/cynara/cynara.inc new file mode 100644 index 000000000..0e823edcc --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara.inc @@ -0,0 +1,158 @@ +DESCRIPTION = "Cynara service with client libraries" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327;beginline=3" + +DEPENDS = " \ +dbus \ +glib-2.0 \ +systemd \ +zip \ +" + +# For testing: +# DEPENDS += "gmock" + +PACKAGECONFIG ??= "" +# Use debug mode to increase logging. Beware, also compiles with less optimization +# and thus has to disable FORTIFY_SOURCE below. +PACKAGECONFIG[debug] = "-DCMAKE_BUILD_TYPE=DEBUG,-DCMAKE_BUILD_TYPE=RELEASE,libunwind elfutils" + +inherit cmake + +CXXFLAGS_append = " \ +-DCYNARA_STATE_PATH=\\\\\"${localstatedir}/cynara/\\\\\" \ +-DCYNARA_LIB_PATH=\\\\\"${prefix}/lib/cynara/\\\\\" \ +-DCYNARA_TESTS_DIR=\\\\\"${prefix}/share/cynara/tests/\\\\\" \ +-DCYNARA_CONFIGURATION_DIR=\\\\\"${sysconfdir}/cynara/\\\\\" \ +${@bb.utils.contains('PACKAGECONFIG', 'debug', '-Wp,-U_FORTIFY_SOURCE', '', d)} \ +" + +EXTRA_OECMAKE += " \ +-DCMAKE_VERBOSE_MAKEFILE=ON \ +-DBUILD_WITH_SYSTEMD=ON \ +-DSYSTEMD_UNIT_DIR=${systemd_unitdir}/system \ +-DSOCKET_DIR=/run/cynara \ +" + +# Explicitly package empty directory. Otherwise Cynara prints warnings +# at runtime: +# cyad[198]: Couldn't scan for plugins in </usr/lib/cynara/plugin/service/> : <No such file or directory> +FILES_${PN}_append = " \ +${libdir}/cynara/plugin/service \ +${libdir}/cynara/plugin/client \ +" + +# Testing depends on gmock and gtest. They can be found in meta-oe +# and are not necessarily available, so this feature is off by default. +# If gmock from meta-oe is used, then a workaround is needed to avoid +# a link error (libgmock.a calls pthread functions without libpthread +# being listed in the .pc file). +PACKAGECONFIG[tests] = "-DBUILD_TESTS:BOOL=ON,-DBUILD_TESTS:BOOL=OFF,gmock gtest," +SRC_URI_append = "${@bb.utils.contains('PACKAGECONFIG', 'tests', ' file://gmock-pthread-linking.patch file://run-ptest', '', d)}" + +# Will be empty if no tests were built. +inherit ptest +FILES_${PN}-ptest += "${bindir}/cynara-tests ${bindir}/cynara-db-migration-tests ${datadir}/cynara/tests" +do_install_ptest () { + if ${@bb.utils.contains('PACKAGECONFIG', 'tests', 'true', 'false', d)}; then + mkdir -p ${D}/${datadir}/cynara/tests + cp -r ${S}/test/db/* ${D}/${datadir}/cynara/tests + fi +} + +do_compile_prepend () { + # en_US.UTF8 is not available, causing cynara-tests parser.getKeyAndValue to fail. + # Submitted upstream: https://github.com/Samsung/cynara/issues/10 + sed -i -e 's/std::locale("en_US.UTF8")/std::locale::classic()/g' ${S}/test/credsCommons/parser/Parser.cpp +} + +inherit useradd +USERADD_PACKAGES = "${PN}" +GROUPADD_PARAM_${PN} = "-r cynara" +USERADD_PARAM_${PN} = "\ +--system --home ${localstatedir}/lib/empty \ +--no-create-home --shell /bin/false \ +--gid cynara cynara \ +" + +# Causes deadlock during booting, see workaround in postinst below. +#inherit systemd +#SYSTEMD_SERVICE_${PN} = "cynara.service" + +do_install_append () { + chmod a+rx ${D}/${sbindir}/cynara-db-migration + + install -d ${D}${sysconfdir}/cynara/ + install -m 644 ${S}/conf/creds.conf ${D}/${sysconfdir}/cynara/creds.conf + + # No need to create empty directories except for those which + # Cynara expects to find. + # install -d ${D}${localstatedir}/cynara/ + # install -d ${D}${prefix}/share/cynara/tests/empty_db + install -d ${D}${libdir}/cynara/plugin/client + install -d ${D}${libdir}/cynara/plugin/service + + # install db* ${D}${prefix}/share/cynara/tests/ + + install -d ${D}${systemd_unitdir}/system/sockets.target.wants + ln -s ../cynara.socket ${D}${systemd_unitdir}/system/sockets.target.wants/cynara.socket + ln -s ../cynara-admin.socket ${D}${systemd_unitdir}/system/sockets.target.wants/cynara-admin.socket + ln -s ../cynara-agent.socket ${D}${systemd_unitdir}/system/sockets.target.wants/cynara-agent.socket +} + +FILES_${PN} += "${systemd_unitdir}/system" + +# Cynara itself has no dependency on Smack. Only its installation +# is Smack-aware in the sense that it sets Smack labels. Do not +# depend on smack userspace unless we really need Smack labels. +# +# The Tizen .spec file calls cynara-db-migration in a %pre section. +# That only works when cynara-db-migration is packaged separately +# (overly complex) and does not seem necessary: perhaps there is a +# time window where cynara might already get activated before +# the postinst completes, but that is a general problem. It gets +# avoided entirely when calling this script while building the +# rootfs. +RDEPENDS_${PN}_append_with-lsm-smack = " smack-userspace" +DEPENDS_append_with-lsm-smack = " smack-userspace-native" +CHSMACK_with-lsm-smack = "chsmack" +CHSMACK = "true" +pkg_postinst_${PN} () { + # Fail on error. + set -e + + # It would be nice to run the code below while building an image, + # but currently the calls to cynara-db-chsgen (a binary) in + # cynara-db-migration (a script) prevent that. Rely instead + # on OE's support for running failed postinst scripts at first boot. + if [ x"$D" != "x" ]; then + exit 1 + fi + + mkdir -p $D${sysconfdir}/cynara + ${CHSMACK} -a System $D${sysconfdir}/cynara + + # Strip git patch level information, the version comparison code + # in cynara-db-migration only expect major.minor.patch version numbers. + VERSION=${@bb.data.getVar('PV',d,1).split('+git')[0]} + if [ -d $D${localstatedir}/cynara ] ; then + # upgrade + echo "NOTE: updating cynara DB to version $VERSION" + $D${sbindir}/cynara-db-migration upgrade -f 0.0.0 -t $VERSION + else + # install + echo "NOTE: creating cynara DB for version $VERSION" + mkdir -p $D${localstatedir}/cynara + ${CHSMACK} -a System $D${localstatedir}/cynara + $D${sbindir}/cynara-db-migration install -t $VERSION + fi + + # Workaround for systemd.bbclass issue: it would call + # "systemctl start" without "--no-block", but because + # the service is not ready to run at the time when + # this scripts gets executed by run-postinsts.service, + # booting deadlocks. + echo "NOTE: enabling and starting cynara service" + systemctl enable cynara + systemctl start --no-block cynara +} diff --git a/meta-security/recipes-security/cynara/cynara/cmake-Improves-directories-and-libsystemd.patch b/meta-security/recipes-security/cynara/cynara/cmake-Improves-directories-and-libsystemd.patch new file mode 100644 index 000000000..7ad94ed40 --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara/cmake-Improves-directories-and-libsystemd.patch @@ -0,0 +1,119 @@ +From 9d1ba2f7c5d72436b17d0f3982a00380c72a58f8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jose.bollo@iot.bzh> +Date: Mon, 4 Jul 2016 13:54:59 +0200 +Subject: [PATCH] cmake: Improves directories and libsystemd +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +The previous implementation was not fully compliant with +standards. It was missing some of the predefined variable +DATAROOTDIR, it was missing specificity of +CMAKE_INSTALL_FULL_SYSCONFDIR. It also was not compatible +with yocto build system bitbake. + +The library systemd is changing. The previous previous +pkg-config files 'libsystemd-daemon' and 'libsystemd-journal' +are now deprecated in favour of 'libsystemd'. + +Upstream-status: Submitted [https://github.com/Samsung/cynara/pull/16] + +Signed-off-by: José Bollo <jose.bollo@iot.bzh> +--- + CMakeLists.txt | 46 ++++++++++++++++++++-------------------------- + 1 file changed, 20 insertions(+), 26 deletions(-) + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index b0ee75f..6a439e2 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -43,66 +43,60 @@ ENDIF (NOT BUILD_COMMONS AND NOT BUILD_SERVICE AND NOT BUILD_DBUS) + + ########################## search for packages ################################ + +-#1st case. User choose to build with systemd. +-IF (DEFINED BUILD_WITH_SYSTEMD AND BUILD_WITH_SYSTEMD) +- PKG_CHECK_MODULES(SYSTEMD_DEP +- REQUIRED +- libsystemd-daemon +- libsystemd-journal +- ) +-ENDIF (DEFINED BUILD_WITH_SYSTEMD AND BUILD_WITH_SYSTEMD) ++#Search the new libsystemd package ++PKG_CHECK_MODULES(SYSTEMD_DEP QUIET libsystemd) + +-#2nd case. User choose not to build with systemd. Noting to do in this case. +-#IF (DEFINED BUILD_WITH_SYSTEMD AND NOT BUILD_WITH_SYSTEMD) +-#ENDIF (DEFINED BUILD_WITH_SYSTEMD AND NOT BUILD_WITH_SYSTEMD) +- +-#3rd case. User did not choose. If we can we will use systemd. +-IF (NOT DEFINED BUILD_WITH_SYSTEMD) ++#Fallback ot the oldest libsystemd packages ++IF(NOT SYSTEMD_DEP_FOUND) + PKG_CHECK_MODULES(SYSTEMD_DEP + QUIET + libsystemd-daemon + libsystemd-journal + ) +- +- IF (SYSTEMD_DEP_FOUND) +- SET(BUILD_WITH_SYSTEMD ON) +- ENDIF (SYSTEMD_DEP_FOUND) +-ENDIF (NOT DEFINED BUILD_WITH_SYSTEMD) ++ENDIF(NOT SYSTEMD_DEP_FOUND) ++ ++#Enforce and check ++IF(SYSTEMD_DEP_FOUND) ++ #Enforce use of systemd if present ++ SET(BUILD_WITH_SYSTEMD ON) ++ELSEIF(BUILD_WITH_SYSTEMD) ++ MESSAGE(FATAL_ERROR "Can't find libsystemd") ++ENDIF() + + ######################## directory configuration ############################ + + SET(LIB_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}" ++ "${CMAKE_INSTALL_FULL_LIBDIR}" + CACHE PATH + "Object code libraries directory") + + SET(BIN_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_BINDIR}" ++ "${CMAKE_INSTALL_FULL_BINDIR}" + CACHE PATH + "User executables directory") + + SET(SBIN_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SBINDIR}" ++ "${CMAKE_INSTALL_FULL_SBINDIR}" + CACHE PATH + "System admin executables directory") + + SET(SYS_CONFIG_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_SYSCONFDIR}" ++ "${CMAKE_INSTALL_FULL_SYSCONFDIR}" + CACHE PATH + "Read-only single-machine data directory") + + SET(INCLUDE_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_INCLUDEDIR}" ++ "${CMAKE_INSTALL_FULL_INCLUDEDIR}" + CACHE PATH + "Header files directory") + + SET(LOCAL_STATE_DIR +- "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LOCALSTATEDIR}" ++ "${CMAKE_INSTALL_FULL_LOCALSTATEDIR}" + CACHE PATH + "Modifiable single-machine data directory") + + SET(DATA_ROOT_DIR +- "${CMAKE_INSTALL_PREFIX}/share" ++ "${CMAKE_INSTALL_FULL_DATAROOTDIR}" + CACHE PATH + "Read-only architecture-independent data root directory") + +-- +2.5.5 + diff --git a/meta-security/recipes-security/cynara/cynara/cynara-db-migration-abort-on-errors.patch b/meta-security/recipes-security/cynara/cynara/cynara-db-migration-abort-on-errors.patch new file mode 100644 index 000000000..cbf372ad9 --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara/cynara-db-migration-abort-on-errors.patch @@ -0,0 +1,31 @@ +From 297774fa4d01156c0327d6e6380a7ecae30bf875 Mon Sep 17 00:00:00 2001 +From: Patrick Ohly <patrick.ohly@intel.com> +Date: Mon, 23 Mar 2015 15:01:39 -0700 +Subject: [PATCH 1/2] cynara-db-migration.in: abort on errors + +"set -e" enables error checking for all commands invoked by the script. +Previously, errors were silently ignored. + +Upstream-status: Submitted [https://github.com/Samsung/cynara/pull/8] + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +--- + migration/cynara-db-migration | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/migration/cynara-db-migration.in b/migration/cynara-db-migration.in +index ff9bd61..f6e7f94 100644 +--- a/migration/cynara-db-migration.in ++++ b/migration/cynara-db-migration.in +@@ -19,6 +19,8 @@ + # @brief Migration tool for Cynara's database + # + ++set -e ++ + ##### Constants (these must not be modified by shell) + + STATE_PATH='@LOCAL_STATE_DIR@/@PROJECT_NAME@' +-- +1.8.4.5 + diff --git a/meta-security/recipes-security/cynara/cynara/gmock-pthread-linking.patch b/meta-security/recipes-security/cynara/cynara/gmock-pthread-linking.patch new file mode 100644 index 000000000..1a204eb14 --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara/gmock-pthread-linking.patch @@ -0,0 +1,31 @@ +From 80cc04091410d6a322fee1a2922fdf867395f00a Mon Sep 17 00:00:00 2001 +From: Patrick Ohly <patrick.ohly@intel.com> +Date: Fri, 29 May 2015 10:21:57 +0200 +Subject: [PATCH] work around gmock pthread dependency + +In meta-oe, gmock's .pc file does not declare that users of +gmock must link against pthread. Let's work around that +here by always linking tests against libpthread. + +Upstream-status: Inappropriate [embedded specific] + +Signed-off-by: Patrick Ohly <patrick.ohly@intel.com> +--- + test/CMakeLists.txt | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt +index 25a70db..f490a24 100644 +--- a/test/CMakeLists.txt ++++ b/test/CMakeLists.txt +@@ -138,6 +138,7 @@ ADD_EXECUTABLE(${TARGET_CYNARA_TESTS} + TARGET_LINK_LIBRARIES(${TARGET_CYNARA_TESTS} + ${PKGS_LDFLAGS} + ${PKGS_LIBRARIES} ++ pthread + crypt + ) + INSTALL(TARGETS ${TARGET_CYNARA_TESTS} DESTINATION ${BIN_INSTALL_DIR}) +-- +2.1.4 + diff --git a/meta-security/recipes-security/cynara/cynara/run-ptest b/meta-security/recipes-security/cynara/cynara/run-ptest new file mode 100755 index 000000000..f8dd5d8b4 --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara/run-ptest @@ -0,0 +1,4 @@ +#!/bin/sh + +cynara-tests | sed -e 's/^\[ *OK *\] \(\S*\)$/PASS: \1/' -e 's/^\[ *FAILED *\] \(\S*\)$/FAIL: \1/' +sh /usr/bin/cynara-db-migration-tests | sed -e 's/^Test .*(\([^)]*\)).*passed.*/PASS: \1/' -e 's/^Test .*(\([^)]*\)).*failed.*/FAIL: \1/' diff --git a/meta-security/recipes-security/cynara/cynara_git.bb b/meta-security/recipes-security/cynara/cynara_git.bb new file mode 100644 index 000000000..6e387d41e --- /dev/null +++ b/meta-security/recipes-security/cynara/cynara_git.bb @@ -0,0 +1,11 @@ +require cynara.inc + +PV = "0.11.0+git${SRCPV}" +SRCREV = "973765e329f8a84c1549cb2b0c65ccb1cce3c2d3" +SRC_URI = "git://github.com/Samsung/cynara.git" +S = "${WORKDIR}/git" + +SRC_URI += " \ +file://cynara-db-migration-abort-on-errors.patch \ +file://cmake-Improves-directories-and-libsystemd.patch \ +" diff --git a/meta-security/recipes-security/keyutils/keyutils/keyutils-arm-remove-m32-m64.patch b/meta-security/recipes-security/keyutils/keyutils/keyutils-arm-remove-m32-m64.patch new file mode 100644 index 000000000..a049fd23f --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils/keyutils-arm-remove-m32-m64.patch @@ -0,0 +1,19 @@ +Index: keyutils-1.5.5/Makefile +=================================================================== +--- keyutils-1.5.5.orig/Makefile 2011-12-20 11:05:10.000000000 +0200 ++++ keyutils-1.5.5/Makefile 2011-12-20 11:06:27.000000000 +0200 +@@ -58,12 +58,12 @@ + LNS := ln -sf + + ifeq ($(BUILDFOR),32-bit) +-CFLAGS += -m32 ++#CFLAGS += -m32 + LIBDIR := /usr/lib + USRLIBDIR := /usr/lib + else + ifeq ($(BUILDFOR),64-bit) +-CFLAGS += -m64 ++#CFLAGS += -m64 + LIBDIR := /usr/lib + USRLIBDIR := /usr/lib + endif diff --git a/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_library_install.patch b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_library_install.patch new file mode 100644 index 000000000..adf064304 --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_library_install.patch @@ -0,0 +1,30 @@ +Index: keyutils-1.5.5/Makefile +=================================================================== +--- keyutils-1.5.5.orig/Makefile 2011-11-30 17:27:43.000000000 +0200 ++++ keyutils-1.5.5/Makefile 2011-12-21 16:05:53.000000000 +0200 +@@ -59,13 +59,13 @@ + + ifeq ($(BUILDFOR),32-bit) + CFLAGS += -m32 +-LIBDIR := /lib ++LIBDIR := /usr/lib + USRLIBDIR := /usr/lib + else + ifeq ($(BUILDFOR),64-bit) + CFLAGS += -m64 +-LIBDIR := /lib64 +-USRLIBDIR := /usr/lib64 ++LIBDIR := /usr/lib ++USRLIBDIR := /usr/lib + endif + endif + +@@ -152,7 +152,7 @@ + $(INSTALL) -D $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(LIBNAME) + $(LNS) $(LIBNAME) $(DESTDIR)$(LIBDIR)/$(SONAME) + mkdir -p $(DESTDIR)$(USRLIBDIR) +- $(LNS) $(LIBDIR)/$(SONAME) $(DESTDIR)$(USRLIBDIR)/$(DEVELLIB) ++ $(LNS) $(SONAME) $(DESTDIR)$(USRLIBDIR)/$(DEVELLIB) + $(INSTALL) -D keyctl $(DESTDIR)$(BINDIR)/keyctl + $(INSTALL) -D request-key $(DESTDIR)$(SBINDIR)/request-key + $(INSTALL) -D request-key-debug.sh $(DESTDIR)$(SHAREDIR)/request-key-debug.sh diff --git a/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86-64_cflags.patch b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86-64_cflags.patch new file mode 100644 index 000000000..8dd224505 --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86-64_cflags.patch @@ -0,0 +1,13 @@ +Index: git/Makefile +=================================================================== +--- git.orig/Makefile 2012-11-16 15:40:05.258723425 +0200 ++++ git/Makefile 2012-11-16 15:41:08.978725491 +0200 +@@ -53,7 +53,7 @@ + ############################################################################### + LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') + USRLIBDIR := $(patsubst /lib/%,/usr/lib/%,$(LIBDIR)) +-BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit ++BUILDFOR := 64-bit + + LNS := ln -sf + diff --git a/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86_cflags.patch b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86_cflags.patch new file mode 100644 index 000000000..573c429b8 --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils/keyutils_fix_x86_cflags.patch @@ -0,0 +1,13 @@ +Index: git/Makefile +=================================================================== +--- git.orig/Makefile 2012-11-16 15:40:05.258723425 +0200 ++++ git/Makefile 2012-11-16 15:41:08.978725491 +0200 +@@ -53,7 +53,7 @@ + ############################################################################### + LIBDIR := $(shell ldd /usr/bin/make | grep '\(/libc\)' | sed -e 's!.*\(/.*\)/libc[.].*!\1!') + USRLIBDIR := $(patsubst /lib/%,/usr/lib/%,$(LIBDIR)) +-BUILDFOR := $(shell file /usr/bin/make | sed -e 's!.*ELF \(32\|64\)-bit.*!\1!')-bit ++BUILDFOR := 32-bit + + LNS := ln -sf + diff --git a/meta-security/recipes-security/keyutils/keyutils_1.5.8.bb b/meta-security/recipes-security/keyutils/keyutils_1.5.8.bb new file mode 100644 index 000000000..46b2b622a --- /dev/null +++ b/meta-security/recipes-security/keyutils/keyutils_1.5.8.bb @@ -0,0 +1,44 @@ +SUMMARY = "Linux Key Management Utilities" +DESCRIPTION = "Keyutils is a set of utilities for managing the key retention \ +facility in the kernel, which can be used by filesystems, block devices and \ +more to gain and retain the authorization and encryption keys required to \ +perform secure operations." +SECTION = "base" +LICENSE = "GPLv2" +LIC_FILES_CHKSUM = "file://LICENCE.GPL;md5=5f6e72824f5da505c1f4a7197f004b45" + +PR = "r1" + +SRCREV = "dd64114721edca5808872190e7e2e927ee2e994c" + +SRC_URI = "git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/keyutils.git;protocol=git \ + file://keyutils_fix_library_install.patch \ + " +SRC_URI_append_arm = " file://keyutils-arm-remove-m32-m64.patch" +SRC_URI_append_x86 = " file://keyutils_fix_x86_cflags.patch" +SRC_URI_append_x86-64 = " file://keyutils_fix_x86-64_cflags.patch" + +S = "${WORKDIR}/git" + +INSTALL_FLAGS = " \ +BINDIR=${bindir} \ +SBINDIR=${sbindir} \ +INCLUDEDIR=${includedir} \ +ETCDIR=${sysconfdir} \ +LIBDIR=${libdir} \ +USRLIBDIR=${libdir} \ +SHAREDIR=${datadir} \ +MAN1=${mandir}/man1 \ +MAN3=${mandir}/man3 \ +MAN5=${mandir}/man5 \ +MAN8=${mandir}/man8 \ +DESTDIR=${D}" + +do_install() { + cd ${S} && oe_runmake ${INSTALL_FLAGS} install + + # Debugging script of unknown value, not packaged. + rm -f "${D}${datadir}/request-key-debug.sh" +} + +BBCLASSEXTEND = "native" diff --git a/meta-security/recipes-security/libcap-ng/libcap-ng/CVE-2014-3215.patch b/meta-security/recipes-security/libcap-ng/libcap-ng/CVE-2014-3215.patch new file mode 100644 index 000000000..d7a868d2c --- /dev/null +++ b/meta-security/recipes-security/libcap-ng/libcap-ng/CVE-2014-3215.patch @@ -0,0 +1,79 @@ +Upstream-Status: Pending + +diff --git a/docs/capng_lock.3 b/docs/capng_lock.3 +index 7683119..a070c1e 100644 +--- a/docs/capng_lock.3 ++++ b/docs/capng_lock.3 +@@ -8,12 +8,13 @@ int capng_lock(void); + + .SH "DESCRIPTION" + +-capng_lock will take steps to prevent children of the current process to regain full privileges if the uid is 0. This should be called while possessing the CAP_SETPCAP capability in the kernel. This function will do the following if permitted by the kernel: Set the NOROOT option on for PR_SET_SECUREBITS, set the NOROOT_LOCKED option to on for PR_SET_SECUREBITS, set the PR_NO_SETUID_FIXUP option on for PR_SET_SECUREBITS, and set the PR_NO_SETUID_FIXUP_LOCKED option on for PR_SET_SECUREBITS. ++capng_lock will take steps to prevent children of the current process from gaining privileges by executing setuid programs. This should be called while possessing the CAP_SETPCAP capability in the kernel. + ++This function will do the following if permitted by the kernel: If the kernel supports PR_SET_NO_NEW_PRIVS, it will use it. Otherwise it will set the NOROOT option on for PR_SET_SECUREBITS, set the NOROOT_LOCKED option to on for PR_SET_SECUREBITS, set the PR_NO_SETUID_FIXUP option on for PR_SET_SECUREBITS, and set the PR_NO_SETUID_FIXUP_LOCKED option on for PR_SET_SECUREBITS. If both fail, it will return an error. + + .SH "RETURN VALUE" + +-This returns 0 on success and a negative number on failure. -1 means a failure setting any of the PR_SET_SECUREBITS options. ++This returns 0 on success and a negative number on failure. -1 means a failure to use PR_SET_NO_NEW_PRIVS and a failure setting any of the PR_SET_SECUREBITS options. + + .SH "SEE ALSO" + +diff --git a/src/cap-ng.c b/src/cap-ng.c +index bd105ba..422f2bc 100644 +--- a/src/cap-ng.c ++++ b/src/cap-ng.c +@@ -45,6 +45,7 @@ + * 2.6.24 kernel XATTR_NAME_CAPS + * 2.6.25 kernel PR_CAPBSET_DROP, CAPABILITY_VERSION_2 + * 2.6.26 kernel PR_SET_SECUREBITS, SECURE_*_LOCKED, VERSION_3 ++ * 3.5 kernel PR_SET_NO_NEW_PRIVS + */ + + /* External syscall prototypes */ +@@ -122,6 +123,14 @@ extern int capget(cap_user_header_t header, const cap_user_data_t data); + #define SECURE_NO_SETUID_FIXUP_LOCKED 3 /* make bit-2 immutable */ + #endif + ++/* prctl values that we use */ ++#ifndef PR_SET_SECUREBITS ++#define PR_SET_SECUREBITS 28 ++#endif ++#ifndef PR_SET_NO_NEW_PRIVS ++#define PR_SET_NO_NEW_PRIVS 38 ++#endif ++ + // States: new, allocated, initted, updated, applied + typedef enum { CAPNG_NEW, CAPNG_ERROR, CAPNG_ALLOCATED, CAPNG_INIT, + CAPNG_UPDATED, CAPNG_APPLIED } capng_states_t; +@@ -663,15 +672,22 @@ int capng_change_id(int uid, int gid, capng_flags_t flag) + + int capng_lock(void) + { +-#ifdef PR_SET_SECUREBITS +- int rc = prctl(PR_SET_SECUREBITS, +- 1 << SECURE_NOROOT | +- 1 << SECURE_NOROOT_LOCKED | +- 1 << SECURE_NO_SETUID_FIXUP | +- 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0); ++ int rc; ++ ++ // On Linux 3.5 and up, we can directly prevent ourselves and ++ // our descendents from gaining privileges. ++ if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == 0) ++ return 0; ++ ++ // This kernel is too old or otherwise doesn't support ++ // PR_SET_NO_NEW_PRIVS. Fall back to using securebits. ++ rc = prctl(PR_SET_SECUREBITS, ++ 1 << SECURE_NOROOT | ++ 1 << SECURE_NOROOT_LOCKED | ++ 1 << SECURE_NO_SETUID_FIXUP | ++ 1 << SECURE_NO_SETUID_FIXUP_LOCKED, 0, 0, 0); + if (rc) + return -1; +-#endif + + return 0; + } diff --git a/meta-security/recipes-security/libcap-ng/libcap-ng/python.patch b/meta-security/recipes-security/libcap-ng/libcap-ng/python.patch new file mode 100644 index 000000000..d82ceb454 --- /dev/null +++ b/meta-security/recipes-security/libcap-ng/libcap-ng/python.patch @@ -0,0 +1,39 @@ +configure.ac - Avoid an incorrect check for python. +Makefile.am - avoid hard coded host include paths. + +Signed-off-by: Mark Hatle <mark.hatle@windriver.com> + +--- libcap-ng-0.6.5/configure.ac.orig 2012-01-17 13:59:03.645898989 -0600 ++++ libcap-ng-0.6.5/configure.ac 2012-01-17 13:59:46.353959252 -0600 +@@ -120,17 +120,8 @@ + else + AC_MSG_RESULT(testing) + AM_PATH_PYTHON +-if test -f /usr/include/python${am_cv_python_version}/Python.h ; then +- python_found="yes" +- AC_MSG_NOTICE(Python bindings will be built) +-else +- python_found="no" +- if test x$use_python = xyes ; then +- AC_MSG_ERROR([Python explicitly required and python headers found]) +- else +- AC_MSG_WARN("Python headers not found - python bindings will not be made") +- fi +-fi ++python_found="yes" ++AC_MSG_NOTICE(Python bindings will be built) + fi + AM_CONDITIONAL(HAVE_PYTHON, test ${python_found} = "yes") + +--- libcap-ng-0.6.5/bindings/python/Makefile.am.orig 2010-11-03 12:31:59.000000000 -0500 ++++ libcap-ng-0.6.5/bindings/python/Makefile.am 2012-01-17 14:05:50.199834467 -0600 +@@ -24,7 +24,8 @@ + CONFIG_CLEAN_FILES = *.loT *.rej *.orig + AM_CFLAGS = -fPIC -DPIC + PYLIBVER ?= python$(PYTHON_VERSION) +-INCLUDES = -I. -I$(top_builddir) -I/usr/include/$(PYLIBVER) ++PYINC ?= /usr/include/$(PYLIBVER) ++INCLUDES = -I. -I$(top_builddir) -I$(PYINC) + LIBS = $(top_builddir)/src/libcap-ng.la + pyexec_PYTHON = capng.py + pyexec_LTLIBRARIES = _capng.la diff --git a/meta-security/recipes-security/libcap-ng/libcap-ng_0.7.3.bb b/meta-security/recipes-security/libcap-ng/libcap-ng_0.7.3.bb new file mode 100644 index 000000000..e729518e9 --- /dev/null +++ b/meta-security/recipes-security/libcap-ng/libcap-ng_0.7.3.bb @@ -0,0 +1,39 @@ +SUMMARY = "An alternate posix capabilities library" +DESCRIPTION = "The libcap-ng library is intended to make programming \ +with POSIX capabilities much easier than the traditional libcap library." +HOMEPAGE = "http://freecode.com/projects/libcap-ng" +SECTION = "base" +LICENSE = "GPLv2+ & LGPLv2.1+" +LIC_FILES_CHKSUM = "file://COPYING;md5=94d55d512a9ba36caa9b7df079bae19f \ + file://COPYING.LIB;md5=e3eda01d9815f8d24aae2dbd89b68b06" + +SRC_URI = "http://people.redhat.com/sgrubb/libcap-ng/libcap-ng-${PV}.tar.gz \ + file://python.patch \ + file://CVE-2014-3215.patch \ + " + +inherit lib_package autotools pythonnative + +SRC_URI[md5sum] = "610afb774f80a8032b711281df126283" +SRC_URI[sha256sum] = "5ca441c8d3a1e4cfe8a8151907977662679457311ccaa7eaac91447c33a35bb1" + +DEPENDS += "swig-native python" + +EXTRA_OEMAKE += "PYLIBVER='python${PYTHON_BASEVERSION}' PYINC='${STAGING_INCDIR}/${PYLIBVER}'" + +PACKAGES += "${PN}-python" + +FILES_${PN}-dbg += "${libdir}/python${PYTHON_BASEVERSION}/*/.debug" +FILES_${PN}-python = "${libdir}/python${PYTHON_BASEVERSION}" + +BBCLASSEXTEND = "native" + +do_install_append() { + # Moving libcap-ng to base_libdir + if [ ! ${D}${libdir} -ef ${D}${base_libdir} ]; then + mkdir -p ${D}/${base_libdir}/ + mv -f ${D}${libdir}/libcap-ng.so.* ${D}${base_libdir}/ + relpath=${@os.path.relpath("${base_libdir}", "${libdir}")} + ln -sf ${relpath}/libcap-ng.so.0.0.0 ${D}${libdir}/libcap-ng.so + fi +} diff --git a/meta-security/recipes-security/security-manager/security-manager.inc b/meta-security/recipes-security/security-manager/security-manager.inc new file mode 100644 index 000000000..ee749a8fb --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager.inc @@ -0,0 +1,98 @@ +DESCRIPTION = "Security manager and utilities" +LICENSE = "Apache-2.0" +LIC_FILES_CHKSUM = "file://LICENSE;md5=86d3f3a95c324c9479bd8986968f4327;beginline=3" + +inherit cmake + +# Out-of-tree build is broken ("sqlite3 .security-manager.db <db.sql" where db.sql is in $S/db). +B = "${S}" + +DEPENDS = " \ +attr \ +boost \ +cynara \ +icu \ +libcap \ +smack \ +sqlite3 \ +sqlite3-native \ +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 distro_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} += "smack" +pkg_postinst_${PN} () { + set -e + chsmack -a System $D${TZ_SYS_DB}/.security-manager.db + chsmack -a System $D${TZ_SYS_DB}/.security-manager.db-journal +} + +FILES_${PN} += " \ +${systemd_unitdir} \ +${TZ_SYS_DB} \ +" + +PACKAGES =+ "${PN}-policy" +FILES_${PN}-policy = " \ + ${datadir}/${PN} \ + ${bindir}/security-manager-policy-reload \ +" +RDEPENDS_${PN}-policy += "sqlite3 cynara" +pkg_postinst_${PN}-policy () { + if [ x"$D" = "x" ] && ${bindir}/security-manager-policy-reload; then + exit 0 + else + exit 1 + fi +} diff --git a/meta-security/recipes-security/security-manager/security-manager/0001-Smack-rules-create-two-new-functions.patch b/meta-security/recipes-security/security-manager/security-manager/0001-Smack-rules-create-two-new-functions.patch new file mode 100644 index 000000000..b0e11afe4 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/0001-Smack-rules-create-two-new-functions.patch @@ -0,0 +1,116 @@ +From d130a7384428a96f31ad5950ffbffadc0aa29a15 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 1/2] 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. + +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..f9fa438 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; +@@ -75,6 +77,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. + * + * Function loads package-specific smack rules, revokes them from the kernel +diff --git a/src/common/smack-rules.cpp b/src/common/smack-rules.cpp +index 3629e0f..d834e42 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.1.0 + diff --git a/meta-security/recipes-security/security-manager/security-manager/0002-app-install-implement-multiple-set-of-smack-rules.patch b/meta-security/recipes-security/security-manager/security-manager/0002-app-install-implement-multiple-set-of-smack-rules.patch new file mode 100644 index 000000000..d60096a15 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/0002-app-install-implement-multiple-set-of-smack-rules.patch @@ -0,0 +1,34 @@ +From 19688cbe2ca10921a499f3fa265928dca54cf98d 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 2/2] 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.1.0 + diff --git a/meta-security/recipes-security/security-manager/security-manager/Removing-tizen-platform-config.patch b/meta-security/recipes-security/security-manager/security-manager/Removing-tizen-platform-config.patch new file mode 100644 index 000000000..4baea6572 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/Removing-tizen-platform-config.patch @@ -0,0 +1,196 @@ +From 72e66d0e42f3bb6efd689ce33b1df407d94b3c60 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] Removing tizen-platform-config + +Change-Id: Ic832a2b75229517b09faba969c27fb1a4b490121 +--- + policy/security-manager-policy-reload | 2 +- + 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 ++++------- + 6 files changed, 19 insertions(+), 42 deletions(-) + +diff --git a/policy/security-manager-policy-reload b/policy/security-manager-policy-reload +index 6f211c6..ed8047a 100755 +--- a/policy/security-manager-policy-reload ++++ b/policy/security-manager-policy-reload +@@ -2,7 +2,7 @@ + + POLICY_PATH=/usr/share/security-manager/policy + PRIVILEGE_GROUP_MAPPING=$POLICY_PATH/privilege-group.list +-DB_FILE=`tzplatform-get TZ_SYS_DB | cut -d= -f2`/.security-manager.db ++DB_FILE=/usr/dbspace/.security-manager.db + + # Create default buckets + while read bucket default_policy +diff --git a/src/common/file-lock.cpp b/src/common/file-lock.cpp +index 6f3996c..1dada17 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 = "/var/run/lock/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 4d73d90..03c6680 100644 +--- a/src/common/include/privilege_db.h ++++ b/src/common/include/privilege_db.h +@@ -34,14 +34,13 @@ + #include <string> + + #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 = "/usr/dbspace/.security-manager.db"; + + enum class QueryType { + EGetPkgPrivileges, +diff --git a/src/common/service_impl.cpp b/src/common/service_impl.cpp +index ae305d3..65cc8b5 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("userapp", &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 d834e42..8b5728b 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 = "/usr/share/security-manager/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 "/etc/smack/accesses.d/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 "/etc/smack/accesses.d/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 = "/usr/share/security-manager/policy/" + privilege + "-template.smack"; + if( stat(path.c_str(), &buffer) == 0) + smackRules.addFromTemplateFile(appId, pkgId, path); + } +-- +2.1.4 + diff --git a/meta-security/recipes-security/security-manager/security-manager/c-11-replace-depracated-auto_ptr.patch b/meta-security/recipes-security/security-manager/security-manager/c-11-replace-depracated-auto_ptr.patch new file mode 100644 index 000000000..c312a9e72 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/c-11-replace-depracated-auto_ptr.patch @@ -0,0 +1,32 @@ +From 6abeec29a0e704f4bf7084b29275b99fea0a78de 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 2/2] c++11: replace depracated 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.1.4 + diff --git a/meta-security/recipes-security/security-manager/security-manager/include-linux-xattr.patch b/meta-security/recipes-security/security-manager/security-manager/include-linux-xattr.patch new file mode 100644 index 000000000..33fbc025e --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/include-linux-xattr.patch @@ -0,0 +1,24 @@ +From: José Bollo <jose.bollo@iot.bzh> +Date: Tue, 30 Oct 2015 14:32:03 -0100 +Subject: [PATCH] include linux xattr + +adds a #include <linux/xattr.h> in source. + +--- + src/client/client-security-manager.cpp | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/client/client-security-manager.cpp b/src/client/client-security-manager.cpp +index 74a6b30..641790b 100644 +--- a/src/client/client-security-manager.cpp ++++ b/src/client/client-security-manager.cpp +@@ -34,6 +34,7 @@ + #include <sys/types.h> + #include <sys/stat.h> + #include <sys/xattr.h> ++#include <linux/xattr.h> + #include <sys/smack.h> + #include <sys/capability.h> + +-- +2.1.4 diff --git a/meta-security/recipes-security/security-manager/security-manager/libcap-without-pkgconfig.patch b/meta-security/recipes-security/security-manager/security-manager/libcap-without-pkgconfig.patch new file mode 100644 index 000000000..a948343f8 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/libcap-without-pkgconfig.patch @@ -0,0 +1,32 @@ +From: José Bollo <jose.bollo@iot.bzh> +Date: Tue, 30 Oct 2015 14:32:03 -0100 +Subject: [PATCH] libcap without pkgconfig + +Handles libcap that isn't distributed for pkg-config + +--- + src/client/CMakeLists.txt | 1 - + 1 file changed, 1 deletion(-) + +diff --git a/src/client/CMakeLists.txt b/src/client/CMakeLists.txt +index 5399a55..0250ce2 100644 +--- a/src/client/CMakeLists.txt ++++ b/src/client/CMakeLists.txt +@@ -1,7 +1,6 @@ + PKG_CHECK_MODULES(CLIENT_DEP + REQUIRED + libsmack +- libcap + ) + + SET(CLIENT_VERSION_MAJOR 1) +@@ -37,6 +36,7 @@ SET_TARGET_PROPERTIES(${TARGET_CLIENT} + TARGET_LINK_LIBRARIES(${TARGET_CLIENT} + ${TARGET_COMMON} + ${CLIENT_DEP_LIBRARIES} ++ cap + ) + + INSTALL(TARGETS ${TARGET_CLIENT} DESTINATION ${LIB_INSTALL_DIR}) +-- +2.1.4 diff --git a/meta-security/recipes-security/security-manager/security-manager/removes-dependency-to-libslp-db-utils.patch b/meta-security/recipes-security/security-manager/security-manager/removes-dependency-to-libslp-db-utils.patch new file mode 100644 index 000000000..f94973074 --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/removes-dependency-to-libslp-db-utils.patch @@ -0,0 +1,78 @@ +From 1e2f8f58d4320afa1d83a6f94822e53346108ee8 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] removes dependency to libslp-db-utils + +Change-Id: I90471e77d20e04bae58cc42eb2639e4aef97fdec +--- + src/common/CMakeLists.txt | 1 ++- + src/dpl/db/src/sql_connection.cpp | 17 +---------------- + 2 files changed, 3 additions(+), 17 deletions(-) + +diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt +index 968c7c1..d1fe644 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..1fb97be 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.1.4 + diff --git a/meta-security/recipes-security/security-manager/security-manager/security-manager-policy-reload-do-not-depend-on-GNU-.patch b/meta-security/recipes-security/security-manager/security-manager/security-manager-policy-reload-do-not-depend-on-GNU-.patch new file mode 100644 index 000000000..ac57964ca --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/security-manager-policy-reload-do-not-depend-on-GNU-.patch @@ -0,0 +1,35 @@ +From d2995014142306987bf86b4d508a84b9b4683c5c 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 2/2] 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.1.4 diff --git a/meta-security/recipes-security/security-manager/security-manager/socket-manager-removes-tizen-specific-call.patch b/meta-security/recipes-security/security-manager/security-manager/socket-manager-removes-tizen-specific-call.patch new file mode 100644 index 000000000..fa4c21c7f --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/socket-manager-removes-tizen-specific-call.patch @@ -0,0 +1,47 @@ +From 75c4852e47217ab85d6840b488ab4b3688091856 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 1/2] 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 0366186..c5cec18 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> +@@ -500,9 +501,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.1.4 + diff --git a/meta-security/recipes-security/security-manager/security-manager/systemd-stop-using-compat-libs.patch b/meta-security/recipes-security/security-manager/security-manager/systemd-stop-using-compat-libs.patch new file mode 100644 index 000000000..cd5c36a6a --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager/systemd-stop-using-compat-libs.patch @@ -0,0 +1,47 @@ +From 8ec024d2adecb53029c6f1af2b95c93dfd43a7cb 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] 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.1.4 diff --git a/meta-security/recipes-security/security-manager/security-manager_git.bb b/meta-security/recipes-security/security-manager/security-manager_git.bb new file mode 100644 index 000000000..65134d31a --- /dev/null +++ b/meta-security/recipes-security/security-manager/security-manager_git.bb @@ -0,0 +1,34 @@ +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://systemd-stop-using-compat-libs.patch \ +file://security-manager-policy-reload-do-not-depend-on-GNU-.patch \ +file://0001-Smack-rules-create-two-new-functions.patch \ +file://0002-app-install-implement-multiple-set-of-smack-rules.patch \ +file://c-11-replace-depracated-auto_ptr.patch \ +file://socket-manager-removes-tizen-specific-call.patch \ +file://Removing-tizen-platform-config.patch \ +file://removes-dependency-to-libslp-db-utils.patch \ +" + +########################################## +# This are patches for backward compatibility to the version dizzy of poky. +# The dizzy version of libcap isn't providing a packconfig file. +# This is solved by the patch libcap-without-pkgconfig.patch. +# But after solving that issue, it appears that linux/xattr.h should +# also be include add definitions of XATTR_NAME_SMACK... values. +# Unfortunately, there is no explanation why linux/xattr.h should +# also be included (patch include-linux-xattr.patch) +########################################## +do_patch[depends] = "libcap:do_populate_sysroot" +APPLY = "${@str('no' if os.path.exists('${STAGING_LIBDIR}/pkgconfig/libcap.pc') else 'yes')}" +SRC_URI += "\ + file://libcap-without-pkgconfig.patch;apply=${APPLY} \ + file://include-linux-xattr.patch;apply=${APPLY} \ +" + diff --git a/meta-security/recipes-security/smack/smack-userspace_git.bb b/meta-security/recipes-security/smack/smack-userspace_git.bb new file mode 100644 index 000000000..aa6d5fa6f --- /dev/null +++ b/meta-security/recipes-security/smack/smack-userspace_git.bb @@ -0,0 +1,27 @@ +DESCRIPTION = "Selection of tools for developers working with Smack" +HOMEPAGE = "https://github.com/smack-team/smack" +SECTION = "Security/Access Control" +LICENSE = "LGPL-2.1" + +# Alias needed to satisfy dependencies in other recipes. +# This recipe itself cannot be named "smack" because that +# would conflict with the "smack" override. +PROVIDES = "smack" +RPROVIDES_${PN} += "smack" + +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-2.0;md5=801f80980d171dd6425610833a22dbe6" +PV = "1.2.0+git${SRCPV}" +SRCREV = "d82bac7dac69823fd40015dffad1a128505a2258" +SRC_URI += "git://github.com/smack-team/smack.git;protocol=https;branch=v1.2.x" +S = "${WORKDIR}/git" + +inherit autotools + +BBCLASSEXTEND = "native" + +# Fix copied from meta-tizen. +do_configure_prepend() { + export ac_cv_prog_DOXYGEN="" + sed -i 's@systemd_new=no@systemd_new=yes@' ${S}/configure.ac + sed -i '/PKG_CHECK_MODULES(/,/)/{s/b/r/p;d}' ${S}/configure.ac +} diff --git a/meta-security/recipes-security/smacknet/files/smacknet b/meta-security/recipes-security/smacknet/files/smacknet new file mode 100644 index 000000000..3818d30ae --- /dev/null +++ b/meta-security/recipes-security/smacknet/files/smacknet @@ -0,0 +1,184 @@ +#!/usr/bin/python +# Copyright (c) 2012, 2013, Intel Corporation +# Copyright (c) 2009 David Wolinsky <davidiw@ufl.edu), University of Florida +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. The name of the author may not be used to endorse or promote products +# derived from this software without specific prior written permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +import socket,fcntl, struct, thread +import os.path +import sys + +SMACKFS_LOAD="/sys/fs/smackfs/load2" +SMACKFS_NETLABEL="/sys/fs/smackfs/netlabel" +SIOCGIFADDR = 0x8915 +SIOCGIFNETMASK = 0x891b + +def get_ip_address(ifname): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return fcntl.ioctl(s.fileno(), SIOCGIFADDR, + struct.pack('256s', ifname.encode("utf-8")))[20:24] + +def get_netmask(ifname): + s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) + return fcntl.ioctl(s.fileno(), SIOCGIFNETMASK, + struct.pack('256s', ifname.encode("utf-8")))[20:24] + +def applynetlabeltags(interface, addr): + if not interface.startswith("lo"): + bmask = get_netmask(interface.encode("utf-8")) + prefix = bin(struct.unpack(">L", bmask)[0]).count("1") + tags = [ + addr+"/"+str(prefix)+" Network::Local\n", + "0.0.0.0/0 Network::Cloud\n", + "127.0.0.1/8 -CIPSO\n"] + smackfs_netlabel(tags) + +def loadnetlabelrules(): + rulesSystem = [ + "System Network::Cloud w\n", + "System Network::Local w\n", + "Network::Cloud System w\n", + "Network::Local System w\n"] + smackfs_load2(rulesSystem) + +def smackfs_load2 (rules): + with open(SMACKFS_LOAD, "w") as load2: + for rule in rules: + load2.write(rule) + +def smackfs_netlabel (tags): + for tag in tags: + with open(SMACKFS_NETLABEL, "w") as netlabel: + netlabel.write(tag) + +""" + Source of: Class ip monitor, and other functions named bellow. + Original author: David Wolinsky <davidiw@ufl.edu + Copied from: https://github.com/davidiw/Grid-Appliance/blob/master/scripts/ip_monitor.py + +""" + +"""4 byte alignment""" + +def align(inc): + diff = inc % 4 + return inc + ((4 - diff) % 4) + +class ifaddr: + """Parse an ifaddr packet""" + LOCAL = 2 + LABEL = 3 + + def __init__(self, packet): + self.family, self.prefixlen, self.flags, self.scope, self.index = \ + struct.unpack("BBBBI", packet[:8]) + +class rtattr: + """Parse a rtattr packet""" + GRP_IPV4_IFADDR = 0x10 + + NEWADDR = 20 + DELADDR = 21 + GETADDR = 22 + + def __init__(self, packet): + self.len, self.type = struct.unpack("HH", packet[:4]) + if self.type == ifaddr.LOCAL: + addr = struct.unpack("BBBB", packet[4:self.len]) + self.payload = "%s.%s.%s.%s" % (addr[0], addr[1], addr[2], addr[3]) + elif self.type == ifaddr.LABEL: + self.payload = packet[4:self.len].strip("\0") + else: + self.payload = packet[4:self.len] + +class netlink: + """Parse a netlink packet""" + REQUEST = 1 + ROOT = 0x100 + MATCH = 0x200 + DONE = 3 + + def __init__(self, packet): + self.msglen, self.msgtype, self.flags, self.seq, self.pid = \ + struct.unpack("IHHII", packet[:16]) + self.ifa = None + try: + self.ifa = ifaddr(packet[16:24]) + except: + return + + self.rtas = {} + pos = 24 + while pos < self.msglen: + try: + rta = rtattr(packet[pos:]) + except: + break + pos += align(rta.len) + self.rtas[rta.type] = rta.payload + +class ip_monitor: + def __init__(self, callback = None): + if callback == None: + callback = self.print_cb + self._callback = callback + + def print_cb(self, label, addr): + print (label + " => " + addr) + + def request_addrs(self, sock): + sock.send(struct.pack("IHHIIBBBBI", 24, rtattr.GETADDR, \ + netlink.REQUEST | netlink.ROOT | netlink.MATCH, 0, sock.getsockname()[0], \ + socket.AF_INET, 0, 0, 0, 0)) + + def start_thread(self): + thread.start_new_thread(self.run, ()) + + def run(self): + sock = socket.socket(socket.AF_NETLINK, socket.SOCK_RAW, socket.NETLINK_ROUTE) + sock.bind((0, rtattr.GRP_IPV4_IFADDR)) + self.request_addrs(sock) + + while True: + data = sock.recv(4096) + pos = 0 + while pos < len(data): + nl = netlink(data[pos:]) + if nl.msgtype == netlink.DONE: + break + pos += align(nl.msglen) + if nl.msgtype != rtattr.NEWADDR: + continue + self._callback(nl.rtas[ifaddr.LABEL], nl.rtas[ifaddr.LOCAL]) + +def main(): + if not os.path.isfile(SMACKFS_LOAD): + print ("Smack not found.") + return -1 + loadnetlabelrules() + + ip_monitor(applynetlabeltags).run() + +if __name__ == "__main__": + main() diff --git a/meta-security/recipes-security/smacknet/files/smacknet.service b/meta-security/recipes-security/smacknet/files/smacknet.service new file mode 100644 index 000000000..218d8b896 --- /dev/null +++ b/meta-security/recipes-security/smacknet/files/smacknet.service @@ -0,0 +1,11 @@ +[Unit] +Description=netlabels configuration for SMACK +Wants=network.target network-online.target +After=network.target network-online.target + +[Service] +TimeoutStartSec=0 +ExecStart=@BINDIR@/smacknet + +[Install] +WantedBy=multi-user.target diff --git a/meta-security/recipes-security/smacknet/smacknet.bb b/meta-security/recipes-security/smacknet/smacknet.bb new file mode 100644 index 000000000..553456aee --- /dev/null +++ b/meta-security/recipes-security/smacknet/smacknet.bb @@ -0,0 +1,29 @@ +#SMACKNET Description +SUMMARY = "Smack network labels configuration" +DESCRIPTION = "Provide service that will be labeling the network rules" +LICENSE = "BSD-3-Clause" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/BSD-3-Clause;md5=550794465ba0ec5312d6919e203a55f9" +RDEPENDS_${PN} = "python" + +SRC_URI += "file://smacknet \ + file://smacknet.service \ + " +S = "${WORKDIR}" + +inherit systemd + +inherit distro_features_check +REQUIRED_DISTRO_FEATURES = "smack" + +#netlabel configuration service +SYSTEMD_SERVICE_${PN} = "smacknet.service" +SYSTEMD_AUTO_ENABLE = "enable" +do_install(){ + install -d ${D}${bindir} + install -m 0551 ${WORKDIR}/smacknet ${D}${bindir} + + install -d -m 755 ${D}${systemd_unitdir}/system + install -m 644 ${WORKDIR}/smacknet.service ${D}${systemd_unitdir}/system + sed -i -e 's,@BINDIR@,${bindir},g' ${D}${systemd_unitdir}/system/smacknet.service +} + diff --git a/meta-security/recipes-test/app-runas/app-runas.bb b/meta-security/recipes-test/app-runas/app-runas.bb new file mode 100644 index 000000000..95725c2e7 --- /dev/null +++ b/meta-security/recipes-test/app-runas/app-runas.bb @@ -0,0 +1,17 @@ +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://app-runas.cpp;beginline=3;endline=19;md5=1ca447189bb2c54039033d50d8982d92" +SRC_URI = "file://app-runas.cpp" +DEPENDS = "security-manager" +S = "${WORKDIR}" + +do_compile () { + ${CXX} ${CXXFLAGS} ${S}/app-runas.cpp `pkg-config --cflags --libs security-manager` -o app-runas +} + +do_install () { + install -D app-runas ${D}/${bindir}/app-runas + chmod u+s ${D}/${bindir}/app-runas +} + +inherit deploy-files +DEPLOY_FILES_FROM[target] = "app-runas" diff --git a/meta-security/recipes-test/app-runas/files/app-runas.cpp b/meta-security/recipes-test/app-runas/files/app-runas.cpp new file mode 100644 index 000000000..58fa15504 --- /dev/null +++ b/meta-security/recipes-test/app-runas/files/app-runas.cpp @@ -0,0 +1,221 @@ +// (C) Copyright 2015 Intel Corporation +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in +// all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +// THE SOFTWARE. + +#include <security-manager.h> + +#include <unistd.h> +#include <stdlib.h> +#include <stdio.h> +#include <errno.h> +#include <string.h> + +#include <sys/types.h> +#include <sys/wait.h> + +#include <string> +#include <vector> + +#define CHECK(x) { \ + int _ret = x; \ + if (_ret != SECURITY_MANAGER_SUCCESS) { \ + fprintf(stderr, "Failure in %s:%d: %s: %d = %s\n", __FILE__, __LINE__, #x, _ret, security_manager_strerror((lib_retcode)_ret)); \ + return EXIT_FAILURE; \ + } \ + } + +static int do_install(app_inst_req *preq) +{ + CHECK(security_manager_app_install(preq)); + return 0; +} + +static int do_uninstall(app_inst_req *preq) +{ + CHECK(security_manager_app_uninstall(preq)); + return 0; +} + +static int do_run(const char *appid, const char *uid, const char *file, char *const argv[]) +{ + if (!appid || !uid) { + fprintf(stderr, "Always need appid, uid for app startup.\n"); + return EXIT_FAILURE; + } + + pid_t child = fork(); + if (child == -1) { + perror("fork"); + return EXIT_FAILURE; + } else if (child) { + int status; + child = waitpid(child, &status, 0); + if (child == -1) { + perror("waitpid"); + return EXIT_FAILURE; + } + } else { + // We cannot change the UID before security_manager_prepare_app() + // (because then setup_smack() fails to change Smack labels of + // our fds) and we cannot change the UID after it (because then + // security_manager_drop_process_privileges() has already dropped + // the necessary CAP_SETUID. + // Instead, we need to do the steps from security_manager_prepare_app() + // ourselves. + CHECK(security_manager_set_process_label_from_appid(appid)); + CHECK(security_manager_set_process_groups_from_appid(appid)); + if (setuid(atoi(uid))) { + fprintf(stderr, "setuid(%s): %s\n", uid, strerror(errno)); + exit(EXIT_FAILURE); + } + CHECK(security_manager_drop_process_privileges()); + // CHECK(security_manager_prepare_app(appid)); + + execvp(file, argv); + fprintf(stderr, "execvp(%s): %s", argv[optind], strerror(errno)); + exit(EXIT_FAILURE); + } + return 0; +} + +int main(int argc, char **argv) +{ + int flags, opt; + int nsecs, tfnd; + const char *appid = NULL; + const char *pkgid = NULL; + const char *uid = NULL; + std::vector<const char *> privileges; + std::vector< std::pair<app_install_path_type, std::string> > paths; + int install = 0, uninstall = 0, run = 0; + + while ((opt = getopt(argc, argv, "a:p:u:r:t:ide")) != -1) { + switch (opt) { + case 'a': + appid = optarg; + break; + case 'p': + pkgid = optarg; + break; + case 'u': + uid = optarg; + break; + case 'r': + privileges.push_back(optarg); + break; + case 't': { + const char *colon = strchr(optarg, ':'); + if (!colon) { + fprintf(stderr, "-t parameter must be of the format <type>:<path>"); + return EXIT_FAILURE; + } + std::string typestr(optarg, colon - optarg); + std::string path(colon + 1); + app_install_path_type type; + if (typestr == "private") { + type = SECURITY_MANAGER_PATH_PRIVATE; + } else if (typestr == "public") { + type = SECURITY_MANAGER_PATH_PUBLIC; + } else if (typestr == "public-ro") { + type = SECURITY_MANAGER_PATH_PUBLIC_RO; + } else if (typestr == "rw") { + type = SECURITY_MANAGER_PATH_RW; + } else if (typestr == "ro") { + type = SECURITY_MANAGER_PATH_PRIVATE; + } else { + fprintf(stderr, "Invalid -t type: %s", typestr.c_str()); + return EXIT_FAILURE; + } + paths.push_back(std::make_pair(type, path)); + break; + } + case 'i': + install = 1; + break; + case 'd': + uninstall = 1; + break; + case 'e': + run = 1; + break; + default: /* '?' */ + fprintf(stderr, + "Usage: %s -i|-e|-d -a appid -u uid -p pkgid -r privilege1 ... -t private|public|public-ro|rw:<path> ... -- command args\n" + " -i = install, command ignored\n" + " -e = run command, privileges and pkgid ignored\n" + " -d = uninstall, command and privileges ignored\n" + " Install, run, and uninstall can be combined into a single invocation.\n", + argv[0]); + exit(EXIT_FAILURE); + break; + } + } + + if ((install || uninstall) && + (!appid || !pkgid || !uid)) { + fprintf(stderr, "Always need appid, pkgid, uid for app install or uninstall.\n"); + return EXIT_FAILURE; + } + if (run && optind >= argc) { + fprintf(stderr, "Expected command after options\n"); + return EXIT_FAILURE; + } + + app_inst_req *preq; + CHECK(security_manager_app_inst_req_new(&preq)); + if (appid) { + CHECK(security_manager_app_inst_req_set_app_id(preq, appid)); + } + if (pkgid) { + CHECK(security_manager_app_inst_req_set_pkg_id(preq, pkgid)); + } + if (uid) { + CHECK(security_manager_app_inst_req_set_uid(preq, atoi(uid))); + } + for (size_t i = 0; i < paths.size(); i++) { + security_manager_app_inst_req_add_path(preq, paths[i].second.c_str(), paths[i].first); + } + for (size_t i = 0; i < privileges.size(); i++) { + CHECK(security_manager_app_inst_req_add_privilege(preq, privileges[i])); + } + + int result = 0; + bool install_failed = false; + if (install) { + result = do_install(preq); + if (result) { + install_failed = true; + } + } + if (run && !install_failed) { + int run_result = do_run(appid, uid, argv[optind], argv + optind); + if (run_result) { + result = run_result; + } + } + if (uninstall && !install_failed) { + int uninstall_result = do_uninstall(preq); + if (uninstall_result) { + result = uninstall_result; + } + } + + security_manager_app_inst_req_free(preq); + return result; +} diff --git a/meta-security/recipes-test/mmap-smack-test/files/mmap.c b/meta-security/recipes-test/mmap-smack-test/files/mmap.c new file mode 100644 index 000000000..f358d27b5 --- /dev/null +++ b/meta-security/recipes-test/mmap-smack-test/files/mmap.c @@ -0,0 +1,7 @@ +#include <stdio.h> + +int main(int argc, char **argv) +{ + printf("Original test program removed while investigating its license.\n"); + return 1; +} diff --git a/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bb b/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bb new file mode 100644 index 000000000..9d11509d0 --- /dev/null +++ b/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bb @@ -0,0 +1,16 @@ +SUMMARY = "Mmap binary used to test smack mmap attribute" +DESCRIPTION = "Mmap binary used to test smack mmap attribute" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://mmap.c" + +S = "${WORKDIR}" +do_compile() { + ${CC} mmap.c ${LDFLAGS} -o mmap_test +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 mmap_test ${D}${bindir} +} diff --git a/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bbappend b/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bbappend new file mode 100644 index 000000000..e7d94f09f --- /dev/null +++ b/meta-security/recipes-test/mmap-smack-test/mmap-smack-test.bbappend @@ -0,0 +1,2 @@ +inherit deploy-files +DEPLOY_FILES_FROM[target] = "${WORKDIR}/mmap_test" diff --git a/meta-security/recipes-test/tcp-smack-test/files/tcp_client.c b/meta-security/recipes-test/tcp-smack-test/files/tcp_client.c new file mode 100644 index 000000000..185f97380 --- /dev/null +++ b/meta-security/recipes-test/tcp-smack-test/files/tcp_client.c @@ -0,0 +1,111 @@ +// (C) Copyright 2015 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <string.h>
+#include <sys/xattr.h>
+
+int main(int argc, char* argv[])
+{
+
+ int sock;
+ char message[255] = "hello";
+ struct sockaddr_in server_addr;
+ char* label_in;
+ char* label_out;
+ char* attr_out = "security.SMACK64IPOUT";
+ char* attr_in = "security.SMACK64IPIN";
+ char out[256];
+ int port;
+
+ struct timeval timeout;
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+
+ struct hostent* host = gethostbyname("localhost");
+
+ if (argc != 4)
+ {
+ perror("Client: Arguments missing, please provide socket labels");
+ return 2;
+ }
+
+ port = atoi(argv[1]);
+ label_in = argv[2];
+ label_out = argv[3];
+
+ if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ perror("Client: Socket failure");
+ return 2;
+ }
+
+
+ if(fsetxattr(sock, attr_out, label_out, strlen(label_out), 0) < 0)
+ {
+ perror("Client: Unable to set attribute SMACK64IPOUT");
+ return 2;
+ }
+
+ if(fsetxattr(sock, attr_in, label_in, strlen(label_in), 0) < 0)
+ {
+ perror("Client: Unable to set attribute SMACK64IPIN");
+ return 2;
+ }
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ bcopy((char*) host->h_addr, (char*) &server_addr.sin_addr.s_addr,host->h_length);
+ bzero(&(server_addr.sin_zero),8);
+
+ if(setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &timeout, sizeof(timeout)) < 0)
+ {
+ perror("Client: Set timeout failed\n");
+ return 2;
+ }
+
+ if (connect(sock, (struct sockaddr *)&server_addr,sizeof(struct sockaddr)) == -1)
+ {
+ perror("Client: Connection failure");
+ close(sock);
+ return 1;
+ }
+
+
+ if(write(sock, message, strlen(message)) < 0)
+ {
+ perror("Client: Error sending data\n");
+ close(sock);
+ return 1;
+ }
+ close(sock);
+ return 0;
+}
+
+
+
+
+
+
diff --git a/meta-security/recipes-test/tcp-smack-test/files/tcp_server.c b/meta-security/recipes-test/tcp-smack-test/files/tcp_server.c new file mode 100644 index 000000000..9285dc695 --- /dev/null +++ b/meta-security/recipes-test/tcp-smack-test/files/tcp_server.c @@ -0,0 +1,118 @@ +// (C) Copyright 2015 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#include <stdio.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <errno.h>
+#include <netinet/in.h>
+#include <unistd.h>
+#include <string.h>
+
+int main(int argc, char* argv[])
+{
+
+ int sock;
+ int clientsock;
+ char message[255];
+ socklen_t client_length;
+ struct sockaddr_in server_addr, client_addr;
+ char* label_in;
+ char* attr_in = "security.SMACK64IPIN";
+ int port;
+
+ struct timeval timeout;
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+
+ if (argc != 3)
+ {
+ perror("Server: Argument missing please provide port and label for SMACK64IPIN");
+ return 2;
+ }
+
+ port = atoi(argv[1]);
+ label_in = argv[2];
+ bzero(message,255);
+
+
+ if((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
+ {
+ perror("Server: Socket failure");
+ return 2;
+ }
+
+
+ if(fsetxattr(sock, attr_in, label_in, strlen(label_in),0) < 0)
+ {
+ perror("Server: Unable to set attribute ipin 2");
+ return 2;
+ }
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ bzero(&(server_addr.sin_zero),8);
+
+ if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
+ {
+ perror("Server: Set timeout failed\n");
+ return 2;
+ }
+
+ if(bind(sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
+ {
+ perror("Server: Bind failure ");
+ return 2;
+ }
+
+ listen(sock, 1);
+ client_length = sizeof(client_addr);
+
+ clientsock = accept(sock,(struct sockaddr*) &client_addr, &client_length);
+
+ if (clientsock < 0)
+ {
+ perror("Server: Connection failed");
+ close(sock);
+ return 1;
+ }
+
+
+ if(fsetxattr(clientsock, "security.SMACK64IPIN", label_in, strlen(label_in),0) < 0)
+ {
+ perror(" Server: Unable to set attribute ipin 2");
+ close(sock);
+ return 2;
+ }
+
+ if(read(clientsock, message, 254) < 0)
+ {
+ perror("Server: Error when reading from socket");
+ close(clientsock);
+ close(sock);
+ return 1;
+ }
+
+
+ close(clientsock);
+ close(sock);
+
+ return 0;
+}
diff --git a/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bb b/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bb new file mode 100644 index 000000000..57e7151a8 --- /dev/null +++ b/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bb @@ -0,0 +1,20 @@ +SUMMARY = "Binary used to test smack tcp sockets" +DESCRIPTION = "Server and client binaries used to test smack attributes on TCP sockets" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://tcp_server.c \ + file://tcp_client.c \ +" + +S = "${WORKDIR}" +do_compile() { + ${CC} tcp_client.c ${LDFLAGS} -o tcp_client + ${CC} tcp_server.c ${LDFLAGS} -o tcp_server +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 tcp_server ${D}${bindir} + install -m 0755 tcp_client ${D}${bindir} +} diff --git a/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bbappend b/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bbappend new file mode 100644 index 000000000..2755bf0e1 --- /dev/null +++ b/meta-security/recipes-test/tcp-smack-test/tcp-smack-test.bbappend @@ -0,0 +1,2 @@ +inherit deploy-files +DEPLOY_FILES_FROM[target] = "${WORKDIR}/tcp_client ${WORKDIR}/tcp_server" diff --git a/meta-security/recipes-test/udp-smack-test/files/udp_client.c b/meta-security/recipes-test/udp-smack-test/files/udp_client.c new file mode 100644 index 000000000..4d3afbe6c --- /dev/null +++ b/meta-security/recipes-test/udp-smack-test/files/udp_client.c @@ -0,0 +1,75 @@ +// (C) Copyright 2015 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#include <sys/socket.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+
+int main(int argc, char* argv[])
+{
+ char* message = "hello";
+ int sock, ret;
+ struct sockaddr_in server_addr;
+ struct hostent* host = gethostbyname("localhost");
+ char* label;
+ char* attr = "security.SMACK64IPOUT";
+ int port;
+ if (argc != 3)
+ {
+ perror("Client: Argument missing, please provide port and label for SMACK64IPOUT");
+ return 2;
+ }
+
+ port = atoi(argv[1]);
+ label = argv[2];
+ sock = socket(AF_INET, SOCK_DGRAM,0);
+ if(sock < 0)
+ {
+ perror("Client: Socket failure");
+ return 2;
+ }
+
+
+ if(fsetxattr(sock, attr, label, strlen(label),0) < 0)
+ {
+ perror("Client: Unable to set attribute ");
+ return 2;
+ }
+
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ bcopy((char*) host->h_addr, (char*) &server_addr.sin_addr.s_addr,host->h_length);
+ bzero(&(server_addr.sin_zero),8);
+
+ ret = sendto(sock, message, strlen(message),0,(const struct sockaddr*)&server_addr,
+ sizeof(struct sockaddr_in));
+
+ close(sock);
+ if(ret < 0)
+ {
+ perror("Client: Error sending message\n");
+ return 1;
+ }
+
+ return 0;
+}
+
diff --git a/meta-security/recipes-test/udp-smack-test/files/udp_server.c b/meta-security/recipes-test/udp-smack-test/files/udp_server.c new file mode 100644 index 000000000..cbab71e65 --- /dev/null +++ b/meta-security/recipes-test/udp-smack-test/files/udp_server.c @@ -0,0 +1,93 @@ +// (C) Copyright 2015 Intel Corporation
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in
+// all copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+// THE SOFTWARE.
+#include <sys/socket.h>
+#include <stdio.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#include <string.h>
+
+int main(int argc, char* argv[])
+{
+ int sock,ret;
+ struct sockaddr_in server_addr, client_addr;
+ socklen_t len;
+ char message[5];
+ char* label;
+ char* attr = "security.SMACK64IPIN";
+ int port;
+
+ if(argc != 3)
+ {
+ perror("Server: Argument missing, please provide port and label for SMACK64IPIN");
+ return 2;
+ }
+
+ port = atoi(argv[1]);
+ label = argv[2];
+
+ struct timeval timeout;
+ timeout.tv_sec = 15;
+ timeout.tv_usec = 0;
+
+ sock = socket(AF_INET,SOCK_DGRAM,0);
+ if(sock < 0)
+ {
+ perror("Server: Socket error");
+ return 2;
+ }
+
+
+ if(fsetxattr(sock, attr, label, strlen(label), 0) < 0)
+ {
+ perror("Server: Unable to set attribute ");
+ return 2;
+ }
+
+ server_addr.sin_family = AF_INET;
+ server_addr.sin_port = htons(port);
+ server_addr.sin_addr.s_addr = INADDR_ANY;
+ bzero(&(server_addr.sin_zero),8);
+
+
+ if(setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &timeout, sizeof(timeout)) < 0)
+ {
+ perror("Server: Set timeout failed\n");
+ return 2;
+ }
+
+ if(bind(sock, (struct sockaddr*) &server_addr, sizeof(server_addr)) < 0)
+ {
+ perror("Server: Bind failure");
+ return 2;
+ }
+
+ len = sizeof(client_addr);
+ ret = recvfrom(sock, message, sizeof(message), 0, (struct sockaddr*)&client_addr,
+ &len);
+ close(sock);
+ if(ret < 0)
+ {
+ perror("Server: Error receiving");
+ return 1;
+
+ }
+ return 0;
+}
+
diff --git a/meta-security/recipes-test/udp-smack-test/udp-smack-test.bb b/meta-security/recipes-test/udp-smack-test/udp-smack-test.bb new file mode 100644 index 000000000..478e3688d --- /dev/null +++ b/meta-security/recipes-test/udp-smack-test/udp-smack-test.bb @@ -0,0 +1,20 @@ +SUMMARY = "Binary used to test smack udp sockets" +DESCRIPTION = "Server and client binaries used to test smack attributes on UDP sockets" +LICENSE = "MIT" +LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/MIT;md5=0835ade698e0bcf8506ecda2f7b4f302" + +SRC_URI = "file://udp_server.c \ + file://udp_client.c \ +" + +S = "${WORKDIR}" +do_compile() { + ${CC} udp_client.c ${LDFLAGS} -o udp_client + ${CC} udp_server.c ${LDFLAGS} -o udp_server +} + +do_install() { + install -d ${D}${bindir} + install -m 0755 udp_server ${D}${bindir} + install -m 0755 udp_client ${D}${bindir} +} diff --git a/meta-security/recipes-test/udp-smack-test/udp-smack-test.bbappend b/meta-security/recipes-test/udp-smack-test/udp-smack-test.bbappend new file mode 100644 index 000000000..bf79ba4d4 --- /dev/null +++ b/meta-security/recipes-test/udp-smack-test/udp-smack-test.bbappend @@ -0,0 +1,2 @@ +inherit deploy-files +DEPLOY_FILES_FROM[target] = "${WORKDIR}/udp_client ${WORKDIR}/udp_server" |