Commit dc0983f2 authored by Mimi Zohar's avatar Mimi Zohar
Browse files

Merge branch 'verify-evm-portable-sig-v2' into next-integrity

From the cover letter:

The recent patch set 'evm: Improve usability of portable signatures' added
the possibility to include EVM portable signatures in the IMA measurement
list.

However, the information necessary to verify the signature were not
included in the IMA measurement list. This patch set introduces new
template fields to accomplish this goal:

- 'iuid': the inode UID;
- 'igid': the inode GID;
- 'imode': the inode mode;
- 'xattrnames': a list of xattr names (separated by |), only if the xattr is
  present;
- 'xattrlengths': a list of xattr lengths (u32), only if the xattr is present;
- 'xattrvalues': a list of xattr values;

Patch 1 adds an helper function to show integers in the measurement list.
Patches 2, 3 and 5 introduce new template fields. Patch 4 make it possible
to verify EVM portable signatures which protect xattrs belonging to LSMs
not enabled in the target platform. Patch 6 introduces the new IMA template
evm-sig. Patch 7 fixes a small issue in evm_write_xattrs() when audit is
not enabled.

Link: https://lore.kernel.org/linux-integrity/20210528073812.407936-1-roberto.sassu@huawei.com/
parents 5a25d8ce d721c15f
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -75,6 +75,13 @@ descriptors by adding their identifier to the format string
 - 'modsig' the appended file signature;
 - 'buf': the buffer data that was used to generate the hash without size limitations;
 - 'evmsig': the EVM portable signature;
 - 'iuid': the inode UID;
 - 'igid': the inode GID;
 - 'imode': the inode mode;
 - 'xattrnames': a list of xattr names (separated by |), only if the xattr is
    present;
 - 'xattrlengths': a list of xattr lengths (u32), only if the xattr is present;
 - 'xattrvalues': a list of xattr values;


Below, there is the list of defined template descriptors:
@@ -84,6 +91,7 @@ Below, there is the list of defined template descriptors:
 - "ima-sig": its format is ``d-ng|n-ng|sig``;
 - "ima-buf": its format is ``d-ng|n-ng|buf``;
 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
 - "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;


Use
+16 −0
Original line number Diff line number Diff line
@@ -38,6 +38,10 @@ extern int evm_inode_init_security(struct inode *inode,
				   const struct xattr *xattr_array,
				   struct xattr *evm);
extern bool evm_revalidate_status(const char *xattr_name);
extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
				     int buffer_size, char type,
				     bool canonical_fmt);
#ifdef CONFIG_FS_POSIX_ACL
extern int posix_xattr_acl(const char *xattrname);
#else
@@ -114,5 +118,17 @@ static inline bool evm_revalidate_status(const char *xattr_name)
	return false;
}

static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name)
{
	return false;
}

static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
					    int buffer_size, char type,
					    bool canonical_fmt)
{
	return -EOPNOTSUPP;
}

#endif /* CONFIG_EVM */
#endif /* LINUX_EVM_H */
+1 −0
Original line number Diff line number Diff line
@@ -29,6 +29,7 @@
struct xattr_list {
	struct list_head list;
	char *name;
	bool enabled;
};

extern int evm_initialized;
+7 −0
Original line number Diff line number Diff line
@@ -216,6 +216,13 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry,
		if (strcmp(xattr->name, XATTR_NAME_IMA) == 0)
			is_ima = true;

		/*
		 * Skip non-enabled xattrs for locally calculated
		 * signatures/HMACs.
		 */
		if (type != EVM_XATTR_PORTABLE_DIGSIG && !xattr->enabled)
			continue;

		if ((req_xattr_name && req_xattr_value)
		    && !strcmp(xattr->name, req_xattr_name)) {
			error = 0;
+115 −10
Original line number Diff line number Diff line
@@ -34,24 +34,44 @@ static const char * const integrity_status_msg[] = {
int evm_hmac_attrs;

static struct xattr_list evm_config_default_xattrnames[] = {
	{.name = XATTR_NAME_SELINUX,
#ifdef CONFIG_SECURITY_SELINUX
	{.name = XATTR_NAME_SELINUX},
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_SMACK,
#ifdef CONFIG_SECURITY_SMACK
	{.name = XATTR_NAME_SMACK},
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_SMACKEXEC,
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_SMACKTRANSMUTE,
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
	{.name = XATTR_NAME_SMACKEXEC},
	{.name = XATTR_NAME_SMACKTRANSMUTE},
	{.name = XATTR_NAME_SMACKMMAP},
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_SMACKMMAP,
#ifdef CONFIG_EVM_EXTRA_SMACK_XATTRS
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_APPARMOR,
#ifdef CONFIG_SECURITY_APPARMOR
	{.name = XATTR_NAME_APPARMOR},
	 .enabled = true
#endif
	},
	{.name = XATTR_NAME_IMA,
#ifdef CONFIG_IMA_APPRAISE
	{.name = XATTR_NAME_IMA},
	 .enabled = true
#endif
	{.name = XATTR_NAME_CAPS},
	},
	{.name = XATTR_NAME_CAPS,
	 .enabled = true
	},
};

LIST_HEAD(evm_config_xattrnames);
@@ -76,7 +96,9 @@ static void __init evm_init_config(void)

	pr_info("Initialising EVM extended attributes:\n");
	for (i = 0; i < xattrs; i++) {
		pr_info("%s\n", evm_config_default_xattrnames[i].name);
		pr_info("%s%s\n", evm_config_default_xattrnames[i].name,
			!evm_config_default_xattrnames[i].enabled ?
			" (disabled)" : "");
		list_add_tail(&evm_config_default_xattrnames[i].list,
			      &evm_config_xattrnames);
	}
@@ -257,7 +279,8 @@ static enum integrity_status evm_verify_hmac(struct dentry *dentry,
	return evm_status;
}

static int evm_protected_xattr(const char *req_xattr_name)
static int evm_protected_xattr_common(const char *req_xattr_name,
				      bool all_xattrs)
{
	int namelen;
	int found = 0;
@@ -265,6 +288,9 @@ static int evm_protected_xattr(const char *req_xattr_name)

	namelen = strlen(req_xattr_name);
	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
		if (!all_xattrs && !xattr->enabled)
			continue;

		if ((strlen(xattr->name) == namelen)
		    && (strncmp(req_xattr_name, xattr->name, namelen) == 0)) {
			found = 1;
@@ -281,6 +307,85 @@ static int evm_protected_xattr(const char *req_xattr_name)
	return found;
}

static int evm_protected_xattr(const char *req_xattr_name)
{
	return evm_protected_xattr_common(req_xattr_name, false);
}

int evm_protected_xattr_if_enabled(const char *req_xattr_name)
{
	return evm_protected_xattr_common(req_xattr_name, true);
}

/**
 * evm_read_protected_xattrs - read EVM protected xattr names, lengths, values
 * @dentry: dentry of the read xattrs
 * @inode: inode of the read xattrs
 * @buffer: buffer xattr names, lengths or values are copied to
 * @buffer_size: size of buffer
 * @type: n: names, l: lengths, v: values
 * @canonical_fmt: data format (true: little endian, false: native format)
 *
 * Read protected xattr names (separated by |), lengths (u32) or values for a
 * given dentry and return the total size of copied data. If buffer is NULL,
 * just return the total size.
 *
 * Returns the total size on success, a negative value on error.
 */
int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
			      int buffer_size, char type, bool canonical_fmt)
{
	struct xattr_list *xattr;
	int rc, size, total_size = 0;

	list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
		rc = __vfs_getxattr(dentry, d_backing_inode(dentry),
				    xattr->name, NULL, 0);
		if (rc < 0 && rc == -ENODATA)
			continue;
		else if (rc < 0)
			return rc;

		switch (type) {
		case 'n':
			size = strlen(xattr->name) + 1;
			if (buffer) {
				if (total_size)
					*(buffer + total_size - 1) = '|';

				memcpy(buffer + total_size, xattr->name, size);
			}
			break;
		case 'l':
			size = sizeof(u32);
			if (buffer) {
				if (canonical_fmt)
					rc = cpu_to_le32(rc);

				*(u32 *)(buffer + total_size) = rc;
			}
			break;
		case 'v':
			size = rc;
			if (buffer) {
				rc = __vfs_getxattr(dentry,
					d_backing_inode(dentry), xattr->name,
					buffer + total_size,
					buffer_size - total_size);
				if (rc < 0)
					return rc;
			}
			break;
		default:
			return -EINVAL;
		}

		total_size += size;
	}

	return total_size;
}

/**
 * evm_verifyxattr - verify the integrity of the requested xattr
 * @dentry: object of the verify xattr
Loading