gplv2/integrity/centos/patches/0001-integrity-kcompat-supp...

1323 lines
44 KiB
Diff

From 7e956b974091563edc1b4f5a7646f4d8dff07ee5 Mon Sep 17 00:00:00 2001
From: Kam Nasim <kam.nasim@windriver.com>
Date: Fri, 8 Sep 2017 16:34:25 -0400
Subject: [PATCH] US101216: IMA out-of-tree modules for Titanium Kernel
Build a kcompat layer and the ability to build out the Integrity and IMA
Kernel modules against a 3.10 Linux Kernel (CentOS v7.3)
---
Makefile | 107 ++++++++++++++++-
common.mk | 330 ++++++++++++++++++++++++++++++++++++++++++++++++++++
digsig.c | 35 ++++--
digsig_asymmetric.c | 22 +++-
iint.c | 52 +++++++--
ima/Makefile | 8 +-
ima/ima.h | 9 +-
ima/ima_api.c | 14 +--
ima/ima_appraise.c | 42 ++++---
ima/ima_fs.c | 4 +
ima/ima_init.c | 4 +-
ima/ima_main.c | 40 +++++--
ima/ima_policy.c | 32 ++++-
integrity.h | 9 +-
integrity_audit.c | 17 ++-
kcompat.h | 34 ++++++
16 files changed, 677 insertions(+), 82 deletions(-)
create mode 100644 common.mk
create mode 100644 kcompat.h
diff --git a/Makefile b/Makefile
index 8d1f4bf..022a1b7 100644
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,7 @@
+
+ifneq ($(KERNELRELEASE),)
+# kbuild part of makefile
+
#
# Makefile for caching inode integrity data (iint)
#
@@ -11,5 +15,104 @@ integrity-$(CONFIG_INTEGRITY_ASYMMETRIC_KEYS) += digsig_asymmetric.o
subdir-$(CONFIG_IMA) += ima
obj-$(CONFIG_IMA) += ima/
-subdir-$(CONFIG_EVM) += evm
-obj-$(CONFIG_EVM) += evm/
+
+else # ifneq($(KERNELRELEASE),)
+# normal makefile
+
+# driver will be provided by the spec file
+DRIVER=
+
+ifeq (,$(wildcard common.mk))
+ $(error Cannot find common.mk build rules)
+else
+ include common.mk
+endif
+
+###############
+# Build rules #
+###############
+
+# Standard compilation, with regular output
+default:
+ @+$(call kernelbuild,modules)
+
+# Noisy output, for extra debugging
+noisy:
+ @+$(call kernelbuild,modules,V=1)
+
+# Silence any output generated
+silent:
+ @+$(call kernelbuild,modules,>/dev/null)
+
+# Enable higher warning level
+checkwarnings: clean
+ @+$(call kernelbuild,modules,W=1)
+
+# Run sparse static analyzer
+sparse: clean
+ @+$(call kernelbuild,modules,C=2 CF="-D__CHECK_ENDIAN__ -Wbitwise -Wcontext")
+
+# Run coccicheck static analyzer
+ccc: clean
+ @+$(call kernelbuild,modules,coccicheck MODE=report)
+
+# Install the modules
+install: default
+ @echo "Installing modules..."
+ @+$(call kernelbuild,modules_install)
+ @echo "Running depmod..."
+ @$(call cmd_depmod)
+ifeq (${cmd_initrd},)
+ @echo "Unable to update initrd. You may need to do this manually."
+else
+ @echo "Updating initrd..."
+ -@$(call cmd_initrd)
+endif
+
+# Target used by rpmbuild spec file
+rpm: default
+ @install -D -m 644 ${DRIVER}.ko ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko
+
+uninstall:
+ rm -f ${INSTALL_MOD_PATH}/lib/modules/${KVER}/${INSTALL_MOD_DIR}/${DRIVER}.ko;
+ $(call cmd_depmod)
+ifeq (${cmd_initrd},)
+ @echo "Unable to update initrd. You may need to do this manually."
+else
+ @echo "Updating initrd..."
+ -@$(call cmd_initrd)
+endif
+
+########
+# Help #
+########
+help:
+ @echo 'Cleaning targets:'
+ @echo ' clean - Clean files generated by kernel module build'
+ @echo 'Build targets:'
+ @echo ' default - Build module(s) with standard verbosity'
+ @echo ' noisy - Build module(s) with V=1 verbosity -- very noisy'
+ @echo ' silent - Build module(s), squelching all output'
+ @echo 'Static Analysis:'
+ @echo ' checkwarnings - Clean, then build module(s) with W=1 warnings enabled'
+ @echo ' sparse - Clean, then check module(s) using sparse'
+ @echo ' ccc - Clean, then check module(s) using coccicheck'
+ @echo 'Other targets:'
+ @echo ' install - Build then install the module(s)'
+ @echo ' uninstall - Uninstall the module(s)'
+ @echo ' help - Display this help message'
+ @echo 'Variables:'
+ @echo ' LINUX_VERSION - Debug tool to force kernel LINUX_VERSION_CODE. Use at your own risk.'
+ @echo ' W=N - Kernel variable for setting warning levels'
+ @echo ' V=N - Kernel variable for setting output verbosity'
+ @echo ' INSTALL_MOD_PATH - Add prefix for the module and manpage installation path'
+ @echo ' INSTALL_MOD_DIR - Use module directory other than updates/security/integrity/${DRIVER}'
+ @echo ' KSRC - Specifies the full path to the kernel tree to build against'
+ @echo ' Other variables may be available for tuning make process, see'
+ @echo ' Kernel Kbuild documentation for more information'
+
+.PHONY: default noisy clean silent sparse ccc install uninstall help
+
+endif # ifneq($(KERNELRELEASE),)
+
+
diff --git a/common.mk b/common.mk
new file mode 100644
index 0000000..3541284
--- /dev/null
+++ b/common.mk
@@ -0,0 +1,330 @@
+################################################################################
+#
+# Linux IMA subsystem
+# Copyright(c) 2013 - 2017 Intel Corporation.
+# Copyright (c) 2017 Wind River Systems, Inc.
+#
+# This program is free software; you can redistribute it and/or modify it
+# under the terms and conditions of the GNU General Public License,
+# version 2, as published by the Free Software Foundation.
+#
+# This program is distributed in the hope 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.
+#
+# The full GNU General Public License is included in this distribution in
+# the file called "COPYING".
+#
+# Contact Information:
+# e1000-devel Mailing List <e1000-devel@lists.sourceforge.net>
+# Intel Corporation, 5200 N.E. Elam Young Parkway, Hillsboro, OR 97124-6497
+################################################################################
+
+
+# common Makefile rules useful for out-of-tree Linux driver builds
+#
+# Usage: include common.mk
+#
+# After including, you probably want to add a minimum_kver_check call
+#
+# Required Variables:
+# DRIVER
+# -- Set to the lowercase driver name
+
+#####################
+# Helpful functions #
+#####################
+
+readlink = $(shell readlink -f ${1})
+
+# helper functions for converting kernel version to version codes
+get_kver = $(or $(word ${2},$(subst ., ,${1})),0)
+get_kvercode = $(shell [ "${1}" -ge 0 -a "${1}" -le 255 2>/dev/null ] && \
+ [ "${2}" -ge 0 -a "${2}" -le 255 2>/dev/null ] && \
+ [ "${3}" -ge 0 -a "${3}" -le 255 2>/dev/null ] && \
+ printf %d $$(( ( ${1} << 16 ) + ( ${2} << 8 ) + ( ${3} ) )) )
+
+################
+# depmod Macro #
+################
+
+cmd_depmod = /sbin/depmod $(if ${SYSTEM_MAP_FILE},-e -F ${SYSTEM_MAP_FILE}) \
+ $(if $(strip ${INSTALL_MOD_PATH}),-b ${INSTALL_MOD_PATH}) \
+ -a ${KVER}
+
+################
+# dracut Macro #
+################
+
+cmd_initrd := $(shell \
+ if which dracut > /dev/null 2>&1 ; then \
+ echo "dracut --force"; \
+ elif which update-initramfs > /dev/null 2>&1 ; then \
+ echo "update-initramfs -u"; \
+ fi )
+
+#####################
+# Environment tests #
+#####################
+
+DRIVER_UPPERCASE := $(shell echo ${DRIVER} | tr "[:lower:]" "[:upper:]" )
+
+ifeq (,${BUILD_KERNEL})
+BUILD_KERNEL=$(shell uname -r)
+endif
+
+# Kernel Search Path
+# All the places we look for kernel source
+KSP := /lib/modules/${BUILD_KERNEL}/source \
+ /lib/modules/${BUILD_KERNEL}/build \
+ /usr/src/linux-${BUILD_KERNEL} \
+ /usr/src/linux-$(${BUILD_KERNEL} | sed 's/-.*//') \
+ /usr/src/kernel-headers-${BUILD_KERNEL} \
+ /usr/src/kernel-source-${BUILD_KERNEL} \
+ /usr/src/linux-$(${BUILD_KERNEL} | sed 's/\([0-9]*\.[0-9]*\)\..*/\1/') \
+ /usr/src/linux \
+ /usr/src/kernels/${BUILD_KERNEL} \
+ /usr/src/kernels
+
+# prune the list down to only values that exist and have an include/linux
+# sub-directory. We can't use include/config because some older kernels don't
+# have this.
+test_dir = $(shell [ -e ${dir}/include/linux ] && echo ${dir})
+KSP := $(foreach dir, ${KSP}, ${test_dir})
+
+# we will use this first valid entry in the search path
+ifeq (,${KSRC})
+ KSRC := $(firstword ${KSP})
+endif
+
+ifeq (,${KSRC})
+ $(warning *** Kernel header files not in any of the expected locations.)
+ $(warning *** Install the appropriate kernel development package, e.g.)
+ $(error kernel-devel, for building kernel modules and try again)
+else
+ifeq (/lib/modules/${BUILD_KERNEL}/source, ${KSRC})
+ KOBJ := /lib/modules/${BUILD_KERNEL}/build
+else
+ KOBJ := ${KSRC}
+endif
+endif
+
+# Version file Search Path
+VSP := ${KOBJ}/include/generated/utsrelease.h \
+ ${KOBJ}/include/linux/utsrelease.h \
+ ${KOBJ}/include/linux/version.h \
+ ${KOBJ}/include/generated/uapi/linux/version.h \
+ /boot/vmlinuz.version.h
+
+# Config file Search Path
+CSP := ${KOBJ}/include/generated/autoconf.h \
+ ${KOBJ}/include/linux/autoconf.h \
+ /boot/vmlinuz.autoconf.h
+
+# System.map Search Path (for depmod)
+MSP := ${KSRC}/System.map \
+ /boot/System.map-${BUILD_KERNEL}
+
+# prune the lists down to only files that exist
+test_file = $(shell [ -f ${file} ] && echo ${file})
+VSP := $(foreach file, ${VSP}, ${test_file})
+CSP := $(foreach file, ${CSP}, ${test_file})
+MSP := $(foreach file, ${MSP}, ${test_file})
+
+
+# and use the first valid entry in the Search Paths
+ifeq (,${VERSION_FILE})
+ VERSION_FILE := $(firstword ${VSP})
+endif
+
+ifeq (,${CONFIG_FILE})
+ CONFIG_FILE := $(firstword ${CSP})
+endif
+
+ifeq (,${SYSTEM_MAP_FILE})
+ SYSTEM_MAP_FILE := $(firstword ${MSP})
+endif
+
+ifeq (,$(wildcard ${VERSION_FILE}))
+ $(error Linux kernel source not configured - missing version header file)
+endif
+
+ifeq (,$(wildcard ${CONFIG_FILE}))
+ $(error Linux kernel source not configured - missing autoconf.h)
+endif
+
+ifeq (,$(wildcard ${SYSTEM_MAP_FILE}))
+ $(warning Missing System.map file - depmod will not check for missing symbols)
+endif
+
+#######################
+# Linux Version Setup #
+#######################
+
+# The following command line parameter is intended for development of KCOMPAT
+# against upstream kernels such as net-next which have broken or non-updated
+# version codes in their Makefile. They are intended for debugging and
+# development purpose only so that we can easily test new KCOMPAT early. If you
+# don't know what this means, you do not need to set this flag. There is no
+# arcane magic here.
+
+# Convert LINUX_VERSION into LINUX_VERSION_CODE
+ifneq (${LINUX_VERSION},)
+ LINUX_VERSION_CODE=$(call get_kvercode,$(call get_kver,${LINUX_VERSION},1),$(call get_kver,${LINUX_VERSION},2),$(call get_kver,${LINUX_VERSION},3))
+endif
+
+# Honor LINUX_VERSION_CODE
+ifneq (${LINUX_VERSION_CODE},)
+ $(warning Forcing target kernel to build with LINUX_VERSION_CODE of ${LINUX_VERSION_CODE}$(if ${LINUX_VERSION}, from LINUX_VERSION=${LINUX_VERSION}). Do this at your own risk.)
+ KVER_CODE := ${LINUX_VERSION_CODE}
+ EXTRA_CFLAGS += -DLINUX_VERSION_CODE=${LINUX_VERSION_CODE}
+endif
+
+# Determine SLE_LOCALVERSION_CODE for SuSE SLE >= 11 (needed by kcompat)
+# This assumes SuSE will continue setting CONFIG_LOCALVERSION to the string
+# appended to the stable kernel version on which their kernel is based with
+# additional versioning information (up to 3 numbers), a possible abbreviated
+# git SHA1 commit id and a kernel type, e.g. CONFIG_LOCALVERSION=-1.2.3-default
+# or CONFIG_LOCALVERSION=-999.gdeadbee-default
+ifeq (1,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
+ grep -m 1 CONFIG_SUSE_KERNEL | awk '{ print $$3 }'))
+
+ifneq (10,$(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
+ grep -m 1 CONFIG_SLE_VERSION | awk '{ print $$3 }'))
+
+ LOCALVERSION := $(shell ${CC} -E -dM ${CONFIG_FILE} 2> /dev/null |\
+ grep -m 1 CONFIG_LOCALVERSION | awk '{ print $$3 }' |\
+ cut -d'-' -f2 | sed 's/\.g[[:xdigit:]]\{7\}//')
+ LOCALVER_A := $(shell echo ${LOCALVERSION} | cut -d'.' -f1)
+ LOCALVER_B := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f2)
+ LOCALVER_C := $(shell echo ${LOCALVERSION} | cut -s -d'.' -f3)
+ SLE_LOCALVERSION_CODE := $(shell expr ${LOCALVER_A} \* 65536 + \
+ 0${LOCALVER_B} \* 256 + 0${LOCALVER_C})
+ EXTRA_CFLAGS += -DSLE_LOCALVERSION_CODE=${SLE_LOCALVERSION_CODE}
+endif
+endif
+
+EXTRA_CFLAGS += ${CFLAGS_EXTRA}
+
+# get the kernel version - we use this to find the correct install path
+KVER := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VERSION_FILE} | grep UTS_RELEASE | \
+ awk '{ print $$3 }' | sed 's/\"//g')
+
+# assume source symlink is the same as build, otherwise adjust KOBJ
+ifneq (,$(wildcard /lib/modules/${KVER}/build))
+ ifneq (${KSRC},$(call readlink,/lib/modules/${KVER}/build))
+ KOBJ=/lib/modules/${KVER}/build
+ endif
+endif
+
+ifeq (${KVER_CODE},)
+ KVER_CODE := $(shell ${CC} ${EXTRA_CFLAGS} -E -dM ${VSP} 2> /dev/null |\
+ grep -m 1 LINUX_VERSION_CODE | awk '{ print $$3 }' | sed 's/\"//g')
+endif
+
+# minimum_kver_check
+#
+# helper function to provide uniform output for different drivers to abort the
+# build based on kernel version check. Usage: "$(call minimum_kver_check,2,6,XX)".
+define _minimum_kver_check
+ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,${1},${2},${3}) ]; echo "$$?"))
+ $$(warning *** Aborting the build.)
+ $$(error This driver is not supported on kernel versions older than ${1}.${2}.${3})
+endif
+endef
+minimum_kver_check = $(eval $(call _minimum_kver_check,${1},${2},${3}))
+
+################
+# Manual Pages #
+################
+
+MANSECTION = 7
+
+ifeq (,${MANDIR})
+ # find the best place to install the man page
+ MANPATH := $(shell (manpath 2>/dev/null || echo $MANPATH) | sed 's/:/ /g')
+ ifneq (,${MANPATH})
+ # test based on inclusion in MANPATH
+ test_dir = $(findstring ${dir}, ${MANPATH})
+ else
+ # no MANPATH, test based on directory existence
+ test_dir = $(shell [ -e ${dir} ] && echo ${dir})
+ endif
+ # our preferred install path
+ # should /usr/local/man be in here ?
+ MANDIR := /usr/share/man /usr/man
+ MANDIR := $(foreach dir, ${MANDIR}, ${test_dir})
+ MANDIR := $(firstword ${MANDIR})
+endif
+ifeq (,${MANDIR})
+ # fallback to /usr/man
+ MANDIR := /usr/man
+endif
+
+####################
+# CCFLAGS variable #
+####################
+
+# set correct CCFLAGS variable for kernels older than 2.6.24
+ifeq (0,$(shell [ ${KVER_CODE} -lt $(call get_kvercode,2,6,24) ]; echo $$?))
+CCFLAGS_VAR := EXTRA_CFLAGS
+else
+CCFLAGS_VAR := ccflags-y
+endif
+
+#################
+# KBUILD_OUTPUT #
+#################
+
+# Only set KBUILD_OUTPUT if KOBJ differs from KSRC
+ifneq (${KSRC},${KOBJ})
+export KBUILD_OUTPUT ?= ${KOBJ}
+endif
+
+############################
+# Module Install Directory #
+############################
+
+# Default to using updates/security/integrity/ path, since depmod since
+# v3.1 defaults to checking updates folder first, and only checking kernels/
+# and extra afterwards. We use updates instead of kernel/* due to desire to
+# prevent over-writing built-in modules files.
+export INSTALL_MOD_DIR ?= updates/security/integrity/
+
+
+######################
+# Kernel Build Macro #
+######################
+
+# kernel build function
+# ${1} is the kernel build target
+# ${2} may contain any extra rules to pass directly to the sub-make process
+#
+# This function is expected to be executed by
+# @+$(call kernelbuild,<target>,<extra parameters>)
+# from within a Makefile recipe.
+#
+# The following variables are expected to be defined for its use:
+# GCC_I_SYS -- if set it will enable use of gcc-i-sys.sh wrapper to use -isystem
+# CCFLAGS_VAR -- the CCFLAGS variable to set extra CFLAGS
+# EXTRA_CFLAGS -- a set of extra CFLAGS to pass into the ccflags-y variable
+# KSRC -- the location of the kernel source tree to build against
+# DRIVER_UPPERCASE -- the uppercase name of the kernel module, set from DRIVER
+#
+# N.B: We specify all of our hash, template and PCR choices
+# right when we build the option. This is because the kernel module
+# will be signed, and we will prevent users from modifying these
+# options at runtime and reloading the module
+kernelbuild = ${MAKE} $(if ${GCC_I_SYS},CC="${GCC_I_SYS}") \
+ ${CCFLAGS_VAR}="${EXTRA_CFLAGS}" \
+ -C "${KSRC}" \
+ CONFIG_INTEGRITY=m \
+ CONFIG_INTEGRITY_AUDIT=y \
+ CONFIG_INTEGRITY_SIGNATURE=y \
+ CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y \
+ CONFIG_IMA=m \
+ CONFIG_${DRIVER_UPPERCASE}=m \
+ modules \
+ M="${CURDIR}" \
+ ${2} ${1}
diff --git a/digsig.c b/digsig.c
index 106e855..f850ef7 100644
--- a/digsig.c
+++ b/digsig.c
@@ -37,9 +37,9 @@ static const char *keyring_name[INTEGRITY_KEYRING_MAX] = {
};
#ifdef CONFIG_INTEGRITY_TRUSTED_KEYRING
-static bool init_keyring __initdata = true;
+static bool init_keyring = true;
#else
-static bool init_keyring __initdata;
+static bool init_keyring;
#endif
#ifdef CONFIG_IMA_KEYRINGS_PERMIT_SIGNED_BY_BUILTIN_OR_SECONDARY
@@ -77,39 +77,43 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
return -EOPNOTSUPP;
}
+EXPORT_SYMBOL_GPL(integrity_digsig_verify);
-int __init integrity_init_keyring(const unsigned int id)
+int integrity_init_keyring(const unsigned int id)
{
const struct cred *cred = current_cred();
- struct key_restriction *restriction;
int err = 0;
- if (!init_keyring)
+ if (!init_keyring) {
+ /* WRS: This external keyring is created inside
+ * the Kernel as a trusted keyring for which
+ * a search reference is available
+ */
+ keyring[id] = ima_keyring;
return 0;
-
- restriction = kzalloc(sizeof(struct key_restriction), GFP_KERNEL);
- if (!restriction)
- return -ENOMEM;
-
- restriction->check = restrict_link_to_ima;
+ }
keyring[id] = keyring_alloc(keyring_name[id], KUIDT_INIT(0),
KGIDT_INIT(0), cred,
((KEY_POS_ALL & ~KEY_POS_SETATTR) |
KEY_USR_VIEW | KEY_USR_READ |
KEY_USR_WRITE | KEY_USR_SEARCH),
- KEY_ALLOC_NOT_IN_QUOTA,
- restriction, NULL);
- if (IS_ERR(keyring[id])) {
+ KEY_ALLOC_NOT_IN_QUOTA, NULL);
+
+ if (!IS_ERR(keyring[id])) {
+ set_bit(KEY_FLAG_TRUSTED_ONLY, &keyring[id]->flags);
+ } else {
err = PTR_ERR(keyring[id]);
pr_info("Can't allocate %s keyring (%d)\n",
keyring_name[id], err);
keyring[id] = NULL;
}
+ init_keyring = false;
return err;
}
+EXPORT_SYMBOL_GPL(integrity_init_keyring);
-int __init integrity_load_x509(const unsigned int id, const char *path)
+int integrity_load_x509(const unsigned int id, const char *path)
{
key_ref_t key;
char *data;
diff --git a/digsig_asymmetric.c b/digsig_asymmetric.c
index 80052ed..1753b60 100644
--- a/digsig_asymmetric.c
+++ b/digsig_asymmetric.c
@@ -34,6 +34,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
pr_debug("key search: \"%s\"\n", name);
+#ifdef CONFIG_IMA_MOK_KEYRING
key = get_ima_blacklist_keyring();
if (key) {
key_ref_t kref;
@@ -45,6 +46,7 @@ static struct key *request_asymmetric_key(struct key *keyring, uint32_t keyid)
return ERR_PTR(-EKEYREJECTED);
}
}
+#endif
if (keyring) {
/* search in specific keyring */
@@ -95,7 +97,11 @@ int asymmetric_verify(struct key *keyring, const char *sig,
if (siglen != __be16_to_cpu(hdr->sig_size))
return -EBADMSG;
+#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) )
+ if (hdr->hash_algo >= PKEY_HASH__LAST)
+#else
if (hdr->hash_algo >= HASH_ALGO__LAST)
+#endif
return -ENOPKG;
key = request_asymmetric_key(keyring, __be32_to_cpu(hdr->keyid));
@@ -103,14 +109,24 @@ int asymmetric_verify(struct key *keyring, const char *sig,
return PTR_ERR(key);
memset(&pks, 0, sizeof(pks));
-
- pks.pkey_algo = "rsa";
- pks.hash_algo = hash_algo_name[hdr->hash_algo];
+
pks.digest = (u8 *)data;
pks.digest_size = datalen;
+#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) )
+ pks.pkey_algo = PKEY_ALGO_RSA;
+ pks.pkey_hash_algo = hdr->hash_algo;
+ pks.nr_mpi =1;
+ pks.rsa.s = mpi_read_raw_data(hdr->sig, siglen);
+ if(pks.rsa.s)
+ ret = verify_signature(key, &pks);
+ mpi_free(pks.rsa.s);
+#else
+ pks.pkey_algo = "rsa";
+ pks.hash_algo = hash_algo_name[hdr->hash_algo];
pks.s = hdr->sig;
pks.s_size = siglen;
ret = verify_signature(key, &pks);
+#endif
key_put(key);
pr_debug("%s() = %d\n", __func__, ret);
return ret;
diff --git a/iint.c b/iint.c
index c710d22..83405a1 100644
--- a/iint.c
+++ b/iint.c
@@ -27,6 +27,9 @@ static struct rb_root integrity_iint_tree = RB_ROOT;
static DEFINE_RWLOCK(integrity_iint_lock);
static struct kmem_cache *iint_cache __read_mostly;
+static struct integrity_iint_cache * (*integrity_inode_get_kernel)(struct inode *);
+static void (*integrity_inode_free_kernel)(struct inode *);
+
/*
* __integrity_iint_find - return the iint associated with an inode
*/
@@ -67,6 +70,7 @@ struct integrity_iint_cache *integrity_iint_find(struct inode *inode)
return iint;
}
+EXPORT_SYMBOL_GPL(integrity_iint_find);
static void iint_free(struct integrity_iint_cache *iint)
{
@@ -90,7 +94,7 @@ static void iint_free(struct integrity_iint_cache *iint)
*
* Caller must lock i_mutex
*/
-struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
+static struct integrity_iint_cache *__integrity_inode_get(struct inode *inode)
{
struct rb_node **p;
struct rb_node *node, *parent = NULL;
@@ -100,7 +104,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
if (iint)
return iint;
- iint = kmem_cache_alloc(iint_cache, GFP_NOFS);
+ iint = kmem_cache_alloc(iint_cache, GFP_KERNEL);
if (!iint)
return NULL;
@@ -110,7 +114,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
while (*p) {
parent = *p;
test_iint = rb_entry(parent, struct integrity_iint_cache,
- rb_node);
+ rb_node);
if (inode < test_iint->inode)
p = &(*p)->rb_left;
else
@@ -133,7 +137,7 @@ struct integrity_iint_cache *integrity_inode_get(struct inode *inode)
*
* Free the integrity information(iint) associated with an inode.
*/
-void integrity_inode_free(struct inode *inode)
+static void __integrity_inode_free(struct inode *inode)
{
struct integrity_iint_cache *iint;
@@ -166,8 +170,21 @@ static void init_once(void *foo)
static int __init integrity_iintcache_init(void)
{
iint_cache =
- kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
- 0, SLAB_PANIC, init_once);
+ kmem_cache_create("iint_cache", sizeof(struct integrity_iint_cache),
+ 0, SLAB_PANIC, init_once);
+
+ /*
+ * stow away original Kernel references
+ * for these functions to assign back
+ * on deinit
+ */
+ integrity_inode_get_kernel = integrity_inode_get;
+ integrity_inode_free_kernel = integrity_inode_free;
+
+ integrity_inode_get = &__integrity_inode_get;
+ integrity_inode_free = &__integrity_inode_free;
+ pr_info("Initializing Integrity Base Module\n");
+
return 0;
}
security_initcall(integrity_iintcache_init);
@@ -186,18 +203,22 @@ int integrity_kernel_read(struct file *file, loff_t offset,
{
mm_segment_t old_fs;
char __user *buf = (char __user *)addr;
- ssize_t ret;
+ ssize_t ret = -EINVAL;
if (!(file->f_mode & FMODE_READ))
return -EBADF;
old_fs = get_fs();
set_fs(get_ds());
- ret = __vfs_read(file, buf, count, &offset);
+ if (file->f_op->read)
+ ret = file->f_op->read(file, buf, count, &offset);
+ else if (file->f_op->aio_read)
+ ret = do_sync_read(file, buf, count, &offset);
set_fs(old_fs);
return ret;
}
+EXPORT_SYMBOL_GPL(integrity_kernel_read);
/*
* integrity_read_file - read entire file content into the buffer
@@ -259,3 +280,18 @@ void __init integrity_load_keys(void)
ima_load_x509();
evm_load_x509();
}
+
+static void __exit cleanup_integrity(void)
+{
+ /*
+ * assign back to default kernel definations
+ * for these dynamic functions
+ */
+ integrity_inode_get = integrity_inode_get_kernel;
+ integrity_inode_free = integrity_inode_free_kernel;
+}
+
+module_exit(cleanup_integrity);
+MODULE_DESCRIPTION("Integrity Base Driver");
+MODULE_LICENSE("GPL");
+
diff --git a/ima/Makefile b/ima/Makefile
index 29f198b..cdf918c 100644
--- a/ima/Makefile
+++ b/ima/Makefile
@@ -6,7 +6,7 @@
obj-$(CONFIG_IMA) += ima.o
ima-y := ima_fs.o ima_queue.o ima_init.o ima_main.o ima_crypto.o ima_api.o \
- ima_policy.o ima_template.o ima_template_lib.o
-ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
-ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
-obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
+ ima_policy.o ima_template.o ima_template_lib.o ima_appraise.o
+#ima-$(CONFIG_IMA_APPRAISE) += ima_appraise.o
+#ima-$(CONFIG_HAVE_IMA_KEXEC) += ima_kexec.o
+#obj-$(CONFIG_IMA_BLACKLIST_KEYRING) += ima_mok.o
diff --git a/ima/ima.h b/ima/ima.h
index b563fbd..5492dda 100644
--- a/ima/ima.h
+++ b/ima/ima.h
@@ -17,6 +17,9 @@
#ifndef __LINUX_IMA_H
#define __LINUX_IMA_H
+// include kcompat layer
+#include "../kcompat.h"
+
#include <linux/types.h>
#include <linux/crypto.h>
#include <linux/fs.h>
@@ -155,6 +158,7 @@ unsigned long ima_get_binary_runtime_size(void);
int ima_init_template(void);
void ima_init_template_list(void);
+
/*
* used to protect h_table and sha_table
*/
@@ -242,7 +246,10 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value);
-
+void __ima_inode_post_setattr(struct dentry *dentry);
+int __ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
+ const void *xattr_value, size_t xattr_value_len);
+int __ima_inode_removexattr(struct dentry *dentry, const char *xattr_name);
#else
static inline int ima_appraise_measurement(enum ima_hooks func,
struct integrity_iint_cache *iint,
diff --git a/ima/ima_api.c b/ima/ima_api.c
index c2edba8..e14e9d0 100644
--- a/ima/ima_api.c
+++ b/ima/ima_api.c
@@ -307,11 +307,9 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
if (!ab)
return;
- audit_log_format(ab, "file=");
- audit_log_untrustedstring(ab, filename);
- audit_log_format(ab, " hash=");
+ audit_log_format(ab, "file=%s", filename);
snprintf(algo_hash, sizeof(algo_hash), "%s:%s", algo_name, hash);
- audit_log_untrustedstring(ab, algo_hash);
+ audit_log_format(ab, " hash=%s", algo_hash);
audit_log_task_info(ab, current);
audit_log_end(ab);
@@ -332,12 +330,12 @@ void ima_audit_measurement(struct integrity_iint_cache *iint,
const char *ima_d_path(const struct path *path, char **pathbuf, char *namebuf)
{
char *pathname = NULL;
-
- *pathbuf = __getname();
+ /* We will allow 11 spaces for ' (deleted)' to be appended */
+ *pathbuf = kmalloc(PATH_MAX + 11, GFP_KERNEL);
if (*pathbuf) {
- pathname = d_absolute_path(path, *pathbuf, PATH_MAX);
+ pathname = d_path(path, *pathbuf, PATH_MAX + 11);
if (IS_ERR(pathname)) {
- __putname(*pathbuf);
+ kfree(*pathbuf);
*pathbuf = NULL;
pathname = NULL;
}
diff --git a/ima/ima_appraise.c b/ima/ima_appraise.c
index 1fd9539..b0d4286 100644
--- a/ima/ima_appraise.c
+++ b/ima/ima_appraise.c
@@ -8,6 +8,9 @@
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, version 2 of the License.
*/
+
+#include "../kcompat.h"
+
#include <linux/module.h>
#include <linux/file.h>
#include <linux/fs.h>
@@ -58,10 +61,10 @@ static int ima_fix_xattr(struct dentry *dentry,
iint->ima_hash->xattr.ng.type = IMA_XATTR_DIGEST_NG;
iint->ima_hash->xattr.ng.algo = algo;
}
- rc = __vfs_setxattr_noperm(dentry, XATTR_NAME_IMA,
- &iint->ima_hash->xattr.data[offset],
- (sizeof(iint->ima_hash->xattr) - offset) +
- iint->ima_hash->length, 0);
+ rc = vfs_setxattr(dentry, XATTR_NAME_IMA,
+ &iint->ima_hash->xattr.data[offset],
+ (sizeof(iint->ima_hash->xattr) - offset) +
+ iint->ima_hash->length, 0);
return rc;
}
@@ -168,14 +171,14 @@ enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value)
{
- ssize_t ret;
+ struct inode *inode = d_backing_inode(dentry);
+ if (!inode->i_op->getxattr)
+ return 0;
- ret = vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
- 0, GFP_NOFS);
- if (ret == -EOPNOTSUPP)
- ret = 0;
- return ret;
+ return vfs_getxattr_alloc(dentry, XATTR_NAME_IMA, (char **)xattr_value,
+ 0, GFP_NOFS);
}
+EXPORT_SYMBOL_GPL(ima_read_xattr);
/*
* ima_appraise_measurement - appraise file measurement
@@ -198,7 +201,7 @@ int ima_appraise_measurement(enum ima_hooks func,
enum integrity_status status = INTEGRITY_UNKNOWN;
int rc = xattr_len, hash_start = 0;
- if (!(inode->i_opflags & IOP_XATTR))
+ if (!inode->i_op->getxattr)
return INTEGRITY_UNKNOWN;
if (rc <= 0) {
@@ -214,7 +217,11 @@ int ima_appraise_measurement(enum ima_hooks func,
goto out;
}
+#ifdef CONFIG_EVM
status = evm_verifyxattr(dentry, XATTR_NAME_IMA, xattr_value, rc, iint);
+#else
+ status = INTEGRITY_UNKNOWN; /* CONFIG_INTEGRITY */
+#endif
if ((status != INTEGRITY_PASS) && (status != INTEGRITY_UNKNOWN)) {
if ((status == INTEGRITY_NOLABEL)
|| (status == INTEGRITY_NOXATTRS))
@@ -321,14 +328,14 @@ void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file)
* This function is called from notify_change(), which expects the caller
* to lock the inode's i_mutex.
*/
-void ima_inode_post_setattr(struct dentry *dentry)
+void __ima_inode_post_setattr(struct dentry *dentry)
{
struct inode *inode = d_backing_inode(dentry);
struct integrity_iint_cache *iint;
- int must_appraise;
+ int must_appraise, rc;
if (!(ima_policy_flag & IMA_APPRAISE) || !S_ISREG(inode->i_mode)
- || !(inode->i_opflags & IOP_XATTR))
+ || !inode->i_op->removexattr)
return;
must_appraise = ima_must_appraise(inode, MAY_ACCESS, POST_SETATTR);
@@ -341,7 +348,8 @@ void ima_inode_post_setattr(struct dentry *dentry)
iint->flags |= IMA_APPRAISE;
}
if (!must_appraise)
- __vfs_removexattr(dentry, XATTR_NAME_IMA);
+ rc = inode->i_op->removexattr(dentry, XATTR_NAME_IMA);
+ return;
}
/*
@@ -378,7 +386,7 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
return;
}
-int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
+int __ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
const struct evm_ima_xattr_data *xvalue = xattr_value;
@@ -396,7 +404,7 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
return result;
}
-int ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
+int __ima_inode_removexattr(struct dentry *dentry, const char *xattr_name)
{
int result;
diff --git a/ima/ima_fs.c b/ima/ima_fs.c
index ca303e5..e871955 100644
--- a/ima/ima_fs.c
+++ b/ima/ima_fs.c
@@ -274,6 +274,9 @@ static const struct file_operations ima_ascii_measurements_ops = {
static ssize_t ima_read_policy(char *path)
{
+#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) )
+ return -EINVAL;
+#else
void *data;
char *datap;
loff_t size;
@@ -307,6 +310,7 @@ static ssize_t ima_read_policy(char *path)
return -EINVAL;
else
return pathlen;
+#endif
}
static ssize_t ima_write_policy(struct file *file, const char __user *buf,
diff --git a/ima/ima_init.c b/ima/ima_init.c
index 2967d49..0759c8c 100644
--- a/ima/ima_init.c
+++ b/ima/ima_init.c
@@ -117,7 +117,9 @@ int __init ima_init(void)
if (!ima_used_chip)
pr_info("No TPM chip found, activating TPM-bypass! (rc=%d)\n",
rc);
-
+ else
+ pr_info("TPM chip found, using TPM for aggregate measurements!\n");
+
rc = integrity_init_keyring(INTEGRITY_KEYRING_IMA);
if (rc)
return rc;
diff --git a/ima/ima_main.c b/ima/ima_main.c
index 2aebb79..5d6ba23 100644
--- a/ima/ima_main.c
+++ b/ima/ima_main.c
@@ -16,6 +16,10 @@
* implements the IMA hooks: ima_bprm_check, ima_file_mmap,
* and ima_file_check.
*/
+
+// include kcompat layer
+#include "../kcompat.h"
+
#include <linux/module.h>
#include <linux/file.h>
#include <linux/binfmts.h>
@@ -30,7 +34,10 @@
int ima_initialized;
#ifdef CONFIG_IMA_APPRAISE
-int ima_appraise = IMA_APPRAISE_ENFORCE;
+/*
+ * WRS: Set default appraise action as "log"
+ */
+int ima_appraise = IMA_APPRAISE_LOG;
#else
int ima_appraise;
#endif
@@ -140,7 +147,7 @@ static void ima_check_last_writer(struct integrity_iint_cache *iint,
*
* Flag files that changed, based on i_version
*/
-void ima_file_free(struct file *file)
+static void __ima_file_free(struct file *file)
{
struct inode *inode = file_inode(file);
struct integrity_iint_cache *iint;
@@ -259,8 +266,7 @@ out_digsig:
rc = -EACCES;
kfree(xattr_value);
out_free:
- if (pathbuf)
- __putname(pathbuf);
+ kfree(pathbuf);
out:
inode_unlock(inode);
if ((rc && must_appraise) && (ima_appraise & IMA_APPRAISE_ENFORCE))
@@ -279,7 +285,7 @@ out:
* On success return 0. On integrity appraisal error, assuming the file
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
-int ima_file_mmap(struct file *file, unsigned long prot)
+static int __ima_file_mmap(struct file *file, unsigned long prot)
{
if (file && (prot & PROT_EXEC))
return process_measurement(file, NULL, 0, MAY_EXEC,
@@ -300,7 +306,7 @@ int ima_file_mmap(struct file *file, unsigned long prot)
* On success return 0. On integrity appraisal error, assuming the file
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
-int ima_bprm_check(struct linux_binprm *bprm)
+static int __ima_bprm_check(struct linux_binprm *bprm)
{
return process_measurement(bprm->file, NULL, 0, MAY_EXEC,
BPRM_CHECK, 0);
@@ -316,13 +322,12 @@ int ima_bprm_check(struct linux_binprm *bprm)
* On success return 0. On integrity appraisal error, assuming the file
* is in policy and IMA-appraisal is in enforcing mode, return -EACCES.
*/
-int ima_file_check(struct file *file, int mask, int opened)
+static int __ima_file_check(struct file *file, int mask, int opened)
{
return process_measurement(file, NULL, 0,
mask & (MAY_READ | MAY_WRITE | MAY_EXEC |
MAY_APPEND), FILE_CHECK, opened);
}
-EXPORT_SYMBOL_GPL(ima_file_check);
/**
* ima_post_path_mknod - mark as a new inode
@@ -346,6 +351,7 @@ void ima_post_path_mknod(struct dentry *dentry)
iint->flags |= IMA_NEW_FILE;
}
+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) )
/**
* ima_read_file - pre-measure/appraise hook decision based on policy
* @file: pointer to the file to be measured/appraised/audit
@@ -415,10 +421,28 @@ int ima_post_read_file(struct file *file, void *buf, loff_t size,
func = read_idmap[read_id] ?: FILE_CHECK;
return process_measurement(file, buf, size, MAY_READ, func, 0);
}
+#endif
static int __init init_ima(void)
{
int error;
+
+ /*
+ * On loading the module, map the kernel inline
+ * function calls (used by the FS layer) to
+ * function definations within the module.
+ *
+ * N.B: No specific unmapping (to Kernel default)
+ * required as IMA module cannot be removed (even forcebly),
+ * once it binds to the Kernel VFS layer
+ */
+ ima_bprm_check = &__ima_bprm_check;
+ ima_file_check = &__ima_file_check;
+ ima_file_free = &__ima_file_free;
+ ima_file_mmap = &__ima_file_mmap;
+ ima_inode_post_setattr = &__ima_inode_post_setattr;
+ ima_inode_setxattr = &__ima_inode_setxattr;
+ ima_inode_removexattr = &__ima_inode_removexattr;
ima_init_template_list();
hash_setup(CONFIG_IMA_DEFAULT_HASH);
diff --git a/ima/ima_policy.c b/ima/ima_policy.c
index aed47b7..dd52d98 100644
--- a/ima/ima_policy.c
+++ b/ima/ima_policy.c
@@ -85,7 +85,7 @@ struct ima_rule_entry {
* normal users can easily run the machine out of memory simply building
* and running executables.
*/
-static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
+static struct ima_rule_entry dont_measure_rules[] = {
{.action = DONT_MEASURE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
@@ -96,10 +96,12 @@ static struct ima_rule_entry dont_measure_rules[] __ro_after_init = {
{.action = DONT_MEASURE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_MEASURE, .fsmagic = CGROUP_SUPER_MAGIC,
.flags = IMA_FSMAGIC},
+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) )
{.action = DONT_MEASURE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC}
+#endif
};
-static struct ima_rule_entry original_measurement_rules[] __ro_after_init = {
+static struct ima_rule_entry original_measurement_rules[] = {
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
@@ -111,7 +113,7 @@ static struct ima_rule_entry original_measurement_rules[] __ro_after_init = {
{.action = MEASURE, .func = FIRMWARE_CHECK, .flags = IMA_FUNC},
};
-static struct ima_rule_entry default_measurement_rules[] __ro_after_init = {
+static struct ima_rule_entry default_measurement_rules[] = {
{.action = MEASURE, .func = MMAP_CHECK, .mask = MAY_EXEC,
.flags = IMA_FUNC | IMA_MASK},
{.action = MEASURE, .func = BPRM_CHECK, .mask = MAY_EXEC,
@@ -127,7 +129,7 @@ static struct ima_rule_entry default_measurement_rules[] __ro_after_init = {
{.action = MEASURE, .func = POLICY_CHECK, .flags = IMA_FUNC},
};
-static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
+static struct ima_rule_entry default_appraise_rules[] = {
{.action = DONT_APPRAISE, .fsmagic = PROC_SUPER_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = SYSFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = DEBUGFS_MAGIC, .flags = IMA_FSMAGIC},
@@ -137,7 +139,9 @@ static struct ima_rule_entry default_appraise_rules[] __ro_after_init = {
{.action = DONT_APPRAISE, .fsmagic = BINFMTFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = SECURITYFS_MAGIC, .flags = IMA_FSMAGIC},
{.action = DONT_APPRAISE, .fsmagic = SELINUX_MAGIC, .flags = IMA_FSMAGIC},
+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) )
{.action = DONT_APPRAISE, .fsmagic = NSFS_MAGIC, .flags = IMA_FSMAGIC},
+#endif
{.action = DONT_APPRAISE, .fsmagic = CGROUP_SUPER_MAGIC, .flags = IMA_FSMAGIC},
#ifdef CONFIG_IMA_WRITE_POLICY
{.action = APPRAISE, .func = POLICY_CHECK,
@@ -249,7 +253,11 @@ static bool ima_match_rules(struct ima_rule_entry *rule, struct inode *inode,
if ((rule->flags & IMA_UID) && !rule->uid_op(cred->uid, rule->uid))
return false;
if (rule->flags & IMA_EUID) {
+#if ( LINUX_VERSION_CODE > KERNEL_VERSION(3,10,0) )
if (has_capability_noaudit(current, CAP_SETUID)) {
+#else
+ if (capable_wrt_inode_uidgid(inode, CAP_SETUID) || capable(CAP_SETUID)) {
+#endif
if (!rule->uid_op(cred->euid, rule->uid)
&& !rule->uid_op(cred->suid, rule->uid)
&& !rule->uid_op(cred->uid, rule->uid))
@@ -556,16 +564,34 @@ static int ima_lsm_rule_init(struct ima_rule_entry *entry,
return result;
}
+static int ima_string_contains_hex(const char *string, size_t len)
+{
+ const unsigned char *p;
+ for (p = string; p < (const unsigned char *)string + len; p++) {
+ if (*p == '"' || *p < 0x21 || *p > 0x7e)
+ return 1;
+ }
+ return 0;
+}
+
static void ima_log_string_op(struct audit_buffer *ab, char *key, char *value,
bool (*rule_operator)(kuid_t, kuid_t))
{
- if (rule_operator == &uid_gt)
- audit_log_format(ab, "%s>", key);
- else if (rule_operator == &uid_lt)
- audit_log_format(ab, "%s<", key);
- else
- audit_log_format(ab, "%s=", key);
- audit_log_untrustedstring(ab, value);
+ if (ima_string_contains_hex(value, strlen(value))) {
+ if (rule_operator == &uid_gt)
+ audit_log_format(ab, "%s>(contains hex)%s", key, value);
+ else if (rule_operator == &uid_lt)
+ audit_log_format(ab, "%s<(contains hex)%s", key, value);
+ else
+ audit_log_format(ab, "%s=(contains hex)%s", key, value);
+ } else {
+ if (rule_operator == &uid_gt)
+ audit_log_format(ab, "%s>", key);
+ else if (rule_operator == &uid_lt)
+ audit_log_format(ab, "%s<", key);
+ else
+ audit_log_format(ab, "%s=", key);
+ }
audit_log_format(ab, " ");
}
static void ima_log_string(struct audit_buffer *ab, char *key, char *value)
diff --git a/integrity.h b/integrity.h
index 24520b4..c13e61d 100644
--- a/integrity.h
+++ b/integrity.h
@@ -16,6 +16,8 @@
#include <crypto/sha.h>
#include <linux/key.h>
+#include "kcompat.h"
+
/* iint action cache flags */
#define IMA_MEASURE 0x00000001
#define IMA_MEASURED 0x00000002
@@ -91,7 +93,7 @@ struct ima_digest_data {
struct signature_v2_hdr {
uint8_t type; /* xattr type */
uint8_t version; /* signature format version */
- uint8_t hash_algo; /* Digest algorithm [enum hash_algo] */
+ uint8_t hash_algo; /* Digest algorithm [enum pkey_hash_algo] */
uint32_t keyid; /* IMA key identifier - not X509/PGP specific */
uint16_t sig_size; /* signature size */
uint8_t sig[0]; /* signature payload */
@@ -131,8 +133,8 @@ int __init integrity_read_file(const char *path, char **data);
int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
const char *digest, int digestlen);
-int __init integrity_init_keyring(const unsigned int id);
-int __init integrity_load_x509(const unsigned int id, const char *path);
+int integrity_init_keyring(const unsigned int id);
+int integrity_load_x509(const unsigned int id, const char *path);
#else
static inline int integrity_digsig_verify(const unsigned int id,
diff --git a/integrity_audit.c b/integrity_audit.c
index 90987d1..ba5e532 100644
--- a/integrity_audit.c
+++ b/integrity_audit.c
@@ -10,6 +10,7 @@
* Audit calls for the integrity subsystem
*/
+#include "kcompat.h"
#include <linux/fs.h>
#include <linux/gfp.h>
#include <linux/audit.h>
@@ -45,21 +46,17 @@ void integrity_audit_msg(int audit_msgno, struct inode *inode,
from_kuid(&init_user_ns, audit_get_loginuid(current)),
audit_get_sessionid(current));
audit_log_task_context(ab);
- audit_log_format(ab, " op=");
- audit_log_string(ab, op);
- audit_log_format(ab, " cause=");
- audit_log_string(ab, cause);
- audit_log_format(ab, " comm=");
- audit_log_untrustedstring(ab, get_task_comm(name, current));
+ audit_log_format(ab, " op=\"%s\"", op);
+ audit_log_format(ab, " cause=\"%s\"", cause);
+ audit_log_format(ab, " comm=%s", get_task_comm(name, current));
if (fname) {
- audit_log_format(ab, " name=");
- audit_log_untrustedstring(ab, fname);
+ audit_log_format(ab, " name=%s", fname);
}
if (inode) {
- audit_log_format(ab, " dev=");
- audit_log_untrustedstring(ab, inode->i_sb->s_id);
+ audit_log_format(ab, " dev=%s", inode->i_sb->s_id);
audit_log_format(ab, " ino=%lu", inode->i_ino);
}
audit_log_format(ab, " res=%d", !result);
audit_log_end(ab);
}
+EXPORT_SYMBOL_GPL(integrity_audit_msg);
diff --git a/kcompat.h b/kcompat.h
new file mode 100644
index 0000000..936b76c
--- /dev/null
+++ b/kcompat.h
@@ -0,0 +1,34 @@
+#ifndef _KCOMPAT_H_
+#define _KCOMPAT_H_
+
+#ifndef LINUX_VERSION_CODE
+#include <linux/version.h>
+#else
+#define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c))
+#endif
+
+#if ( LINUX_VERSION_CODE <= KERNEL_VERSION(3,10,0) )
+
+/* kcompat definitions */
+#define CONFIG_TCG_TPM_MODULE 1
+
+#define CONFIG_IMA 1
+#define CONFIG_IMA_APPRAISE_SIGNED_INIT 1
+#define CONFIG_IMA_APPRAISE 1
+#define CONFIG_IMA_DEFAULT_HASH "sha256"
+#define CONFIG_IMA_MEASURE_PCR_IDX 10
+#define CONFIG_IMA_DEFAULT_TEMPLATE "ima-sig"
+#define CONFIG_INTEGRITY 1
+#define CONFIG_INTEGRITY_AUDIT 1
+#define CONFIG_INTEGRITY_ASYMMETRIC_KEYS 1
+#define CONFIG_INTEGRITY_SIGNATURE 1
+#define CONFIG_CRYPTO_RSA 1
+
+#define __GFP_RECLAIM __GFP_WAIT
+
+#define inode_lock(_node) mutex_lock(&_node->i_mutex)
+#define inode_unlock(_node) mutex_unlock(&_node->i_mutex)
+
+
+#endif
+#endif
--
1.8.3.1