mirror of
https://git.yoctoproject.org/meta-security
synced 2026-04-20 23:40:05 +00:00
meta-integrity: port over from meta-intel-iot-security
Signed-off-by: Armin Kuster <akuster808@gmail.com>
This commit is contained in:
116
meta-integrity/recipes-kernel/linux/linux-%.bbappend
Normal file
116
meta-integrity/recipes-kernel/linux/linux-%.bbappend
Normal 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 '' }"
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
16
meta-integrity/recipes-kernel/linux/linux/ima.cfg
Normal file
16
meta-integrity/recipes-kernel/linux/linux/ima.cfg
Normal 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
|
||||
@@ -0,0 +1,3 @@
|
||||
CONFIG_KEYS=y
|
||||
CONFIG_SYSTEM_TRUSTED_KEYRING=y
|
||||
CONFIG_SYSTEM_TRUSTED_KEYS=""
|
||||
Reference in New Issue
Block a user