meta-integrity: port over from meta-intel-iot-security

Signed-off-by: Armin Kuster <akuster808@gmail.com>
This commit is contained in:
Armin Kuster
2019-05-16 15:41:49 -07:00
parent 479d9cc23a
commit 6680225c05
30 changed files with 1402 additions and 0 deletions

View File

@@ -0,0 +1,116 @@
IMA_ENABLED_HERE := "${@'yes' if bb.data.inherits_class('kernel', d) and 'ima' in d.getVar('DISTRO_FEATURES', True).split() else 'no'}"
IMA_FILESEXTRAPATHS_yes := "${THISDIR}/linux:"
IMA_FILESEXTRAPATHS_no := ""
FILESEXTRAPATHS_prepend := "${IMA_FILESEXTRAPATHS_${IMA_ENABLED_HERE}}"
# These two patches are necessary to unpack archives with security.ima xattr
# such that security.ima is taken from the archive. If the policy
# allows hashing, unpatched kernels (at least up to 4.3) will replace
# a signed hash in security.ima with a locally computed hash.
#
# Note that only bsdtar/libarchive are known to work; GNU tar sets
# the security.ima on an empty file and the tries re-opening it for
# writing its content, which then fails due to the IMA hash mismatch.
#
# Kernels >= 4.7 have the patches, while older kernels are likely to
# need the patches. So apply them by default. To avoid that,
# set IMA_EVM_SETATTR_PATCH_x.y.z (where x.y.z == linux kernel version)
# to an empty string (to avoid patching) or some other patch files
# suitable for that kernel.
def ima_evm_setattr_patch(d):
result = []
linux_version = d.getVar('LINUX_VERSION', True) or ''
# These two patches are known to be included upstream.
if bb.utils.vercmp_string_op(linux_version, '4.7', '<'):
patches = d.getVar('IMA_EVM_SETATTR_PATCH_' + linux_version, True)
if patches != None:
# Patches explicitly chosen, may be empty.
result.append(patches)
else:
# Enabled by default.
result.append('file://0001-ima-fix-ima_inode_post_setattr.patch file://0002-ima-add-support-for-creating-files-using-the-mknodat.patch')
# This one addresses a problem added in 4.2. The upstream revert will land
# in some future kernel. We need to extend version check once we know
# which kernels have the patch.
if bb.utils.vercmp_string_op(linux_version, '4.2', '>='):
patches = d.getVar('IMA_EVM_SETATTR_REVERT_PATCH_' + linux_version, True)
if patches != None:
# Patches explicitly chosen, may be empty.
result.append(patches)
else:
# Enabled by default.
result.append('file://Revert-ima-limit-file-hash-setting-by-user-to-fix-an.patch')
return ' '.join(result)
# Edison kernel too old, patch not applicable -> swupd is broken in Ostro OS for Edison.
IMA_EVM_SETATTR_PATCH_3.10.98 = ""
# Kernel config fragment enabling IMA/EVM and (where necessary and possible)
# also patching the kernel.
IMA_EVM_CFG_yes = " file://ima.cfg \
${@ ima_evm_setattr_patch(d)} \
"
IMA_EVM_CFG_no = ""
SRC_URI_append = "${IMA_EVM_CFG_${IMA_ENABLED_HERE}}"
# IMA_EVM_ROOT_CA, if set, is the absolute path to a der-encoded
# x509 CA certificate which will get compiled into the kernel.
# The kernel will then use it to validate additional certificates,
# like the one loaded dynamically for IMA.
#
# Depending on the kernel version, there are two ways to add the
# CA certificate:
# - For Linux < 4.3, we put the x509 file into the source directory
# where the kernel compilation will find it automatically
# (http://lxr.free-electrons.com/source/kernel/Makefile?v=4.2#L115).
# - For Linux >= 4.3, we set SYSTEM_TRUSTED_KEYS
# (http://lxr.free-electrons.com/source/certs/Kconfig?v=4.3#L29).
# The ima_evm_root_ca.cfg only contains a blank file name.
# The actual file name gets patched in after the file was used
# to configure the kernel (see do_kernel_configme_append).
# This has to point to a single file, i.e. using it for IMA has to
# be coordinated with other usages.
#
# The IMA_EVM_ROOT_CA default is set globally in ima-evm-rootfs.bbclass.
# Need weaker default here in case that ima-evm-rootfs.bbclass is not
# inherited.
IMA_EVM_ROOT_CA ??= ""
# Add CONFIG_SYSTEM_TRUSTED_KEYS (for recent kernels) and
# copy the root certificate into the build directory. By using
# the normal fetcher mechanism for the certificate we ensure that
# a rebuild is triggered when the file name or content change.
#
# Recompiling on name change is a bit too aggressive and causes
# unnecessary rebuilds when only the location of the file, but not its
# content change. This may need further work, should it become a problem
# in practice. For example, IMA_EVM_ROOT_CA could be redefined as
# an URL that then gets found via the normal file lookup.
#
# The fetcher does not expand SRC_URI. We have to enforce that here.
IMA_EVM_ROOT_CA_CFG_yes = "${@ \
((' file://ima_evm_root_ca.cfg' if bb.utils.vercmp_string_op('${LINUX_VERSION}', '4.3', '>=') else '') + \
' file://${IMA_EVM_ROOT_CA}') \
if '${IMA_EVM_ROOT_CA}' else ''}"
IMA_EVM_ROOT_CA_CFG_no = ""
SRC_URI_append = "${IMA_EVM_ROOT_CA_CFG_${IMA_ENABLED_HERE}}"
do_kernel_configme_append () {
if [ '${IMA_EVM_ROOT_CA}' ] && grep -q '^CONFIG_SYSTEM_TRUSTED_KEYS=' ${B}/.config; then
# We can replace a blank value from ima_evm_root_ca.cfg,
# but when we find some other value, then we have to abort
# because we can't set more than one value.
eval `grep '^CONFIG_SYSTEM_TRUSTED_KEYS='`
if [ "$CONFIG_SYSTEM_TRUSTED_KEYS" ] && [ "$CONFIG_SYSTEM_TRUSTED_KEYS" != "${IMA_EVM_ROOT_CA}" ]; then
bbfatal "CONFIG_SYSTEM_TRUSTED_KEYS already set to $CONFIG_SYSTEM_TRUSTED_KEYS, cannot replace with IMA_EVM_ROOT_CA = ${IMA_EVM_ROOT_CA}"
exit 1
fi
pemcert=${B}/`basename ${IMA_EVM_ROOT_CA}`.pem
openssl x509 -inform der -in ${IMA_EVM_ROOT_CA} -out $pemcert
sed -i -e "s;^CONFIG_SYSTEM_TRUSTED_KEYS=.*;CONFIG_SYSTEM_TRUSTED_KEYS=\"$pemcert\";" ${B}/.config
fi
}
do_kernel_configme[depends] += "${@ 'openssl-native:do_populate_sysroot' if '${IMA_ENABLED_HERE}' == 'yes' and '${IMA_EVM_ROOT_CA}' else '' }"

View File

@@ -0,0 +1,51 @@
From 45ea681ebc0dd44aaec5d3cc4143b9722070d3ac Mon Sep 17 00:00:00 2001
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Tue, 8 Mar 2016 16:43:55 -0500
Subject: [PATCH] ima: fix ima_inode_post_setattr
Changing file metadata (eg. uid, guid) could result in having to
re-appraise a file's integrity, but does not change the "new file"
status nor the security.ima xattr. The IMA_PERMIT_DIRECTIO and
IMA_DIGSIG_REQUIRED flags are policy rule specific. This patch
only resets these flags, not the IMA_NEW_FILE or IMA_DIGSIG flags.
With this patch, changing the file timestamp will not remove the
file signature on new files.
Upstream-Status: Accepted [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/integrity/ima/ima_appraise.c?id=42a4c603198f0d45b7aa936d3ac6ba1b8bd14a1b]
Reported-by: Dmitry Rozhkov <dmitry.rozhkov@linux.intel.com>
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
security/integrity/ima/ima_appraise.c | 2 +-
security/integrity/integrity.h | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4df493e..a384ba1 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -327,7 +327,7 @@ void ima_inode_post_setattr(struct dentry *dentry)
if (iint) {
iint->flags &= ~(IMA_APPRAISE | IMA_APPRAISED |
IMA_APPRAISE_SUBMASK | IMA_APPRAISED_SUBMASK |
- IMA_ACTION_FLAGS);
+ IMA_ACTION_RULE_FLAGS);
if (must_appraise)
iint->flags |= IMA_APPRAISE;
}
diff --git a/security/integrity/integrity.h b/security/integrity/integrity.h
index 0fc9519..f9decae 100644
--- a/security/integrity/integrity.h
+++ b/security/integrity/integrity.h
@@ -28,6 +28,7 @@
/* iint cache flags */
#define IMA_ACTION_FLAGS 0xff000000
+#define IMA_ACTION_RULE_FLAGS 0x06000000
#define IMA_DIGSIG 0x01000000
#define IMA_DIGSIG_REQUIRED 0x02000000
#define IMA_PERMIT_DIRECTIO 0x04000000
--
2.5.0

View File

@@ -0,0 +1,138 @@
From baaec960e9e7be0b526eaf831b079ddfe5c15124 Mon Sep 17 00:00:00 2001
From: Mimi Zohar <zohar@linux.vnet.ibm.com>
Date: Thu, 10 Mar 2016 18:19:20 +0200
Subject: [PATCH] ima: add support for creating files using the mknodat
syscall
Commit 3034a14 "ima: pass 'opened' flag to identify newly created files"
stopped identifying empty files as new files. However new empty files
can be created using the mknodat syscall. On systems with IMA-appraisal
enabled, these empty files are not labeled with security.ima extended
attributes properly, preventing them from subsequently being opened in
order to write the file data contents. This patch marks these empty
files, created using mknodat, as new in order to allow the file data
contents to be written.
Files with security.ima xattrs containing a file signature are considered
"immutable" and can not be modified. The file contents need to be
written, before signing the file. This patch relaxes this requirement
for new files, allowing the file signature to be written before the file
contents.
Upstream-Status: Accepted [https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/commit/security/integrity/ima/ima_appraise.c?id=05d1a717ec0430c916a749b94eb90ab74bbfa356]
Signed-off-by: Mimi Zohar <zohar@linux.vnet.ibm.com>
---
fs/namei.c | 2 ++
include/linux/ima.h | 7 ++++++-
security/integrity/ima/ima_appraise.c | 3 +++
security/integrity/ima/ima_main.c | 32 +++++++++++++++++++++++++++++++-
4 files changed, 42 insertions(+), 2 deletions(-)
diff --git a/fs/namei.c b/fs/namei.c
index ccd7f98..19502da 100644
--- a/fs/namei.c
+++ b/fs/namei.c
@@ -3526,6 +3526,8 @@ retry:
switch (mode & S_IFMT) {
case 0: case S_IFREG:
error = vfs_create(path.dentry->d_inode,dentry,mode,true);
+ if (!error)
+ ima_post_path_mknod(dentry);
break;
case S_IFCHR: case S_IFBLK:
error = vfs_mknod(path.dentry->d_inode,dentry,mode,
diff --git a/include/linux/ima.h b/include/linux/ima.h
index 120ccc5..7f51971 100644
--- a/include/linux/ima.h
+++ b/include/linux/ima.h
@@ -20,7 +20,7 @@ extern void ima_file_free(struct file *file);
extern int ima_file_mmap(struct file *file, unsigned long prot);
extern int ima_module_check(struct file *file);
extern int ima_fw_from_file(struct file *file, char *buf, size_t size);
-
+extern void ima_post_path_mknod(struct dentry *dentry);
#else
static inline int ima_bprm_check(struct linux_binprm *bprm)
{
@@ -52,6 +52,11 @@ static inline int ima_fw_from_file(struct file *file, char *buf, size_t size)
return 0;
}
+static inline void ima_post_path_mknod(struct dentry *dentry)
+{
+ return;
+}
+
#endif /* CONFIG_IMA */
#ifdef CONFIG_IMA_APPRAISE
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4df493e..20806ea 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -274,6 +274,11 @@ out:
xattr_value->type != EVM_IMA_XATTR_DIGSIG)) {
if (!ima_fix_xattr(dentry, iint))
status = INTEGRITY_PASS;
+ } else if ((inode->i_size == 0) &&
+ (iint->flags & IMA_NEW_FILE) &&
+ (xattr_value &&
+ xattr_value->type == EVM_IMA_XATTR_DIGSIG)) {
+ status = INTEGRITY_PASS;
}
integrity_audit_msg(AUDIT_INTEGRITY_DATA, inode, filename,
op, cause, rc, 0);
diff --git a/security/integrity/ima/ima_main.c b/security/integrity/ima/ima_main.c
index eeee00dc..705bf78 100644
--- a/security/integrity/ima/ima_main.c
+++ b/security/integrity/ima/ima_main.c
@@ -242,7 +242,8 @@ static int process_measurement(struct file *file, int mask, int function,
ima_audit_measurement(iint, pathname);
out_digsig:
- if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG))
+ if ((mask & MAY_WRITE) && (iint->flags & IMA_DIGSIG) &&
+ !(iint->flags & IMA_NEW_FILE))
rc = -EACCES;
kfree(xattr_value);
out_free:
@@ -310,6 +311,35 @@ int ima_file_check(struct file *file, int mask, int opened)
EXPORT_SYMBOL_GPL(ima_file_check);
/**
+ * ima_post_path_mknod - mark as a new inode
+ * @dentry: newly created dentry
+ *
+ * Mark files created via the mknodat syscall as new, so that the
+ * file data can be written later.
+ */
+void ima_post_path_mknod(struct dentry *dentry)
+{
+ struct integrity_iint_cache *iint;
+ struct inode *inode;
+ int must_appraise;
+
+ if (!dentry || !dentry->d_inode)
+ return;
+
+ inode = dentry->d_inode;
+ if (inode->i_size != 0)
+ return;
+
+ must_appraise = ima_must_appraise(inode, MAY_ACCESS, FILE_CHECK);
+ if (!must_appraise)
+ return;
+
+ iint = integrity_inode_get(inode);
+ if (iint)
+ iint->flags |= IMA_NEW_FILE;
+}
+
+/**
* ima_module_check - based on policy, collect/store/appraise measurement.
* @file: pointer to the file to be measured/appraised
*
--
2.5.0

View File

@@ -0,0 +1,60 @@
From a34d61850b680c152e1dcc958ee83c3ab3261c3d Mon Sep 17 00:00:00 2001
From: Patrick Ohly <patrick.ohly@intel.com>
Date: Tue, 15 Nov 2016 10:10:23 +0100
Subject: [PATCH] Revert "ima: limit file hash setting by user to fix and log
modes"
This reverts commit c68ed80c97d9720f51ef31fe91560fdd1e121533.
The original motivation was security hardening ("File hashes are
automatically set and updated and should not be manually set.")
However, that hardening ignores and breaks some valid use cases:
- File hashes might not be set because the file is currently
outside of the policy and therefore have to be set by the
creator. Examples:
- Booting into an initramfs with an IMA-enabled kernel but
without setting an IMA policy, then installing
the OS onto the target partition by unpacking a rootfs archive
which has the file hashes pre-computed.
- Unpacking a file into a staging area with meta data (like owner)
that leaves the file outside of the current policy, then changing
the meta data such that it becomes part of the current policy.
- "should not be set manually" implies that the creator is aware
of IMA semantic, the current system's configuration, and then
skips setting file hashes in security.ima if (and only if) the
kernel would prevent it. That's not the case for standard, unmodified
tools. Example: unpacking an archive with security.ima xattrs with
bsdtar or GNU tar.
Upstream-Status: Submitted [https://sourceforge.net/p/linux-ima/mailman/message/35492824/]
Signed-off-by: Patrick Ohly <patrick.ohly@intel.com>
---
security/integrity/ima/ima_appraise.c | 8 ++------
1 file changed, 2 insertions(+), 6 deletions(-)
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c
index 4b9b4a4..b8b2dd9 100644
--- a/security/integrity/ima/ima_appraise.c
+++ b/security/integrity/ima/ima_appraise.c
@@ -385,14 +385,10 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
result = ima_protect_xattr(dentry, xattr_name, xattr_value,
xattr_value_len);
if (result == 1) {
- bool digsig;
-
if (!xattr_value_len || (xvalue->type >= IMA_XATTR_LAST))
return -EINVAL;
- digsig = (xvalue->type == EVM_IMA_XATTR_DIGSIG);
- if (!digsig && (ima_appraise & IMA_APPRAISE_ENFORCE))
- return -EPERM;
- ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
+ ima_reset_appraise_flags(d_backing_inode(dentry),
+ (xvalue->type == EVM_IMA_XATTR_DIGSIG) ? 1 : 0);
result = 0;
}
return result;
--
2.1.4

View File

@@ -0,0 +1,16 @@
# Enable bare minimum IMA measurement and appraisal as needed by this layer.
CONFIG_SECURITY=y
CONFIG_INTEGRITY=y
# measurement
CONFIG_IMA=y
# appraisal
CONFIG_IMA_APPRAISE=y
CONFIG_INTEGRITY_SIGNATURE=y
CONFIG_INTEGRITY_ASYMMETRIC_KEYS=y
# Kernel will get built with embedded X.509 root CA key and all keys
# need to be signed with that.
CONFIG_IMA_TRUSTED_KEYRING=y

View File

@@ -0,0 +1,3 @@
CONFIG_KEYS=y
CONFIG_SYSTEM_TRUSTED_KEYRING=y
CONFIG_SYSTEM_TRUSTED_KEYS=""