lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <20210520085701.465369-7-roberto.sassu@huawei.com>
Date:   Thu, 20 May 2021 10:57:00 +0200
From:   Roberto Sassu <roberto.sassu@...wei.com>
To:     <zohar@...ux.ibm.com>, <mjg59@...f.ucam.org>
CC:     <linux-integrity@...r.kernel.org>,
        <linux-security-module@...r.kernel.org>,
        <linux-doc@...r.kernel.org>, <linux-kernel@...r.kernel.org>,
        Roberto Sassu <roberto.sassu@...wei.com>
Subject: [PATCH 6/7] ima: Introduce template field evmxattrs

This patch introduces the new template field evmxattrs, which contains the
number of EVM protected xattrs (u32 in little endian), the xattr names
separated by \0, the xattr lengths (u32 in little endian) and the xattr
values. Xattrs can be used to verify the EVM portable signature, if it was
included with the template fields sig or evmsig.

Signed-off-by: Roberto Sassu <roberto.sassu@...wei.com>
---
 Documentation/security/IMA-templates.rst  |   3 +
 security/integrity/ima/ima_template.c     |   2 +
 security/integrity/ima/ima_template_lib.c | 121 ++++++++++++++++++++++
 security/integrity/ima/ima_template_lib.h |   2 +
 4 files changed, 128 insertions(+)

diff --git a/Documentation/security/IMA-templates.rst b/Documentation/security/IMA-templates.rst
index 6e98bce20029..a9684fde3871 100644
--- a/Documentation/security/IMA-templates.rst
+++ b/Documentation/security/IMA-templates.rst
@@ -82,6 +82,9 @@ descriptors by adding their identifier to the format string
  - 'mntgidmap': the GID mappings of the idmapped mount (same format as
    'mntuidmap');
  - 'imode': the inode mode;
+ - 'evmxattrs': the EVM protected xattrs (num xattrs (u32 in canonical format),
+    xattr names separated by \0, xattr lengths (u32 in canonical format) and
+    xattr values);
 
 
 Below, there is the list of defined template descriptors:
diff --git a/security/integrity/ima/ima_template.c b/security/integrity/ima/ima_template.c
index 34674aef1cc5..b9dd900db0ff 100644
--- a/security/integrity/ima/ima_template.c
+++ b/security/integrity/ima/ima_template.c
@@ -59,6 +59,8 @@ static const struct ima_template_field supported_fields[] = {
 	 .field_show = ima_show_template_sig},
 	{.field_id = "imode", .field_init = ima_eventinodemode_init,
 	 .field_show = ima_show_template_uint},
+	{.field_id = "evmxattrs", .field_init = ima_eventinodeevmxattrs_init,
+	 .field_show = ima_show_template_sig},
 };
 
 /*
diff --git a/security/integrity/ima/ima_template_lib.c b/security/integrity/ima/ima_template_lib.c
index b82fb8f35e5d..71e642d90e63 100644
--- a/security/integrity/ima/ima_template_lib.c
+++ b/security/integrity/ima/ima_template_lib.c
@@ -11,6 +11,7 @@
 
 #include "ima_template_lib.h"
 #include <linux/xattr.h>
+#include <linux/evm.h>
 
 static bool ima_template_hash_algo_allowed(u8 algo)
 {
@@ -714,3 +715,123 @@ int ima_eventinodemode_init(struct ima_event_data *event_data,
 	return ima_write_template_field_data((char *)&mode, sizeof(mode),
 					     DATA_FMT_UINT, field_data);
 }
+
+/*
+ *  ima_eventinodeevmxattrs_init - include the number of EVM protected xattrs,
+ *  the xattr names, lengths and values as part of the template data
+ */
+int ima_eventinodeevmxattrs_init(struct ima_event_data *event_data,
+				 struct ima_field_data *field_data)
+
+{
+	struct inode *inode;
+	u8 *buffer = NULL;
+	char *xattr_names, *xattr_names_ptr, *xattr_name;
+	size_t names_size, total_size;
+	u32 num_xattrs = 0, xattr_value_len;
+	loff_t names_offset, lengths_offset, values_offset;
+	int rc, evm_present = 0;
+
+	if (!event_data->file)
+		return 0;
+
+	inode = file_inode(event_data->file);
+	if (!inode->i_op->listxattr || !(inode->i_opflags & IOP_XATTR))
+		return 0;
+
+	names_size = inode->i_op->listxattr(file_dentry(event_data->file),
+					    NULL, 0);
+	if (names_size <= 0)
+		return 0;
+
+	xattr_names = kmalloc(names_size, GFP_KERNEL);
+	if (!xattr_names)
+		return 0;
+
+	names_size = inode->i_op->listxattr(file_dentry(event_data->file),
+					    xattr_names, names_size);
+	if (names_size <= 0)
+		goto out;
+
+	xattr_names_ptr = xattr_names;
+	total_size = sizeof(num_xattrs);
+	lengths_offset = total_size;
+
+	while (xattr_names_ptr < xattr_names + names_size) {
+		xattr_name = xattr_names_ptr;
+		xattr_names_ptr += strlen(xattr_names_ptr) + 1;
+
+		if (!strcmp(xattr_name, XATTR_NAME_EVM)) {
+			evm_present = 1;
+			continue;
+		}
+
+		if (!evm_protected_xattr_if_enabled(xattr_name))
+			continue;
+
+		total_size += xattr_names_ptr - xattr_name;
+		lengths_offset += xattr_names_ptr - xattr_name;
+		total_size += sizeof(xattr_value_len);
+		rc = __vfs_getxattr(file_dentry(event_data->file),
+				    file_inode(event_data->file), xattr_name,
+				    NULL, 0);
+		xattr_value_len = (rc >= 0) ? rc : 0;
+		total_size += xattr_value_len;
+		num_xattrs++;
+	}
+
+	/*
+	 * Don't provide data if security.evm is not found or there are no
+	 * protected xattrs.
+	 */
+	if (!evm_present || !num_xattrs)
+		return 0;
+
+	buffer = kmalloc(total_size, GFP_KERNEL);
+	if (!buffer)
+		goto out;
+
+	*(u32 *)buffer = num_xattrs;
+	if (ima_canonical_fmt)
+		*(u32 *)buffer = cpu_to_le32(*(u32 *)buffer);
+
+	names_offset = sizeof(num_xattrs);
+	values_offset = lengths_offset + num_xattrs * sizeof(xattr_value_len);
+
+	xattr_names_ptr = xattr_names;
+
+	while (xattr_names_ptr < xattr_names + names_size) {
+		xattr_name = xattr_names_ptr;
+		xattr_names_ptr += strlen(xattr_names_ptr) + 1;
+
+		if (!strcmp(xattr_name, XATTR_NAME_EVM))
+			continue;
+
+		if (!evm_protected_xattr_if_enabled(xattr_name))
+			continue;
+
+		memcpy(buffer + names_offset, xattr_name,
+		       xattr_names_ptr - xattr_name);
+		names_offset += xattr_names_ptr - xattr_name;
+
+		rc = __vfs_getxattr(file_dentry(event_data->file),
+				    file_inode(event_data->file), xattr_name,
+				    buffer + values_offset,
+				    total_size - values_offset);
+		xattr_value_len = (rc >= 0) ? rc : 0;
+		*(u32 *)(buffer + lengths_offset) = xattr_value_len;
+		if (ima_canonical_fmt)
+			*(u32 *)(buffer + lengths_offset) =
+				cpu_to_le32(*(u32 *)(buffer + lengths_offset));
+
+		lengths_offset += sizeof(xattr_value_len);
+		values_offset += xattr_value_len;
+	}
+
+	rc = ima_write_template_field_data((char *)buffer, total_size,
+					   DATA_FMT_HEX, field_data);
+out:
+	kfree(xattr_names);
+	kfree(buffer);
+	return rc;
+}
diff --git a/security/integrity/ima/ima_template_lib.h b/security/integrity/ima/ima_template_lib.h
index dc3c16912f6d..ee8f53847305 100644
--- a/security/integrity/ima/ima_template_lib.h
+++ b/security/integrity/ima/ima_template_lib.h
@@ -60,4 +60,6 @@ int ima_eventmnt_userns_gid_map_init(struct ima_event_data *event_data,
 				     struct ima_field_data *field_data);
 int ima_eventinodemode_init(struct ima_event_data *event_data,
 			    struct ima_field_data *field_data);
+int ima_eventinodeevmxattrs_init(struct ima_event_data *event_data,
+				 struct ima_field_data *field_data);
 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */
-- 
2.25.1

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ