From 7e956b974091563edc1b4f5a7646f4d8dff07ee5 Mon Sep 17 00:00:00 2001 From: Kam Nasim 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 +# 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,,) +# 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 #include #include @@ -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 #include #include @@ -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 #include #include @@ -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 #include +#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 #include #include @@ -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 +#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