Commit 8314b673 authored by Roberto Sassu's avatar Roberto Sassu Committed by Mimi Zohar
Browse files

ima: Define new template fields xattrnames, xattrlengths and xattrvalues



This patch defines the new template fields xattrnames, xattrlengths and
xattrvalues, which contain respectively a list of xattr names (strings,
separated by |), lengths (u32, hex) and values (hex). If an xattr is not
present, the name and length are not displayed in the measurement list.

Reported-by: kernel test robot <lkp@intel.com> (Missing prototype def)
Signed-off-by: default avatarRoberto Sassu <roberto.sassu@huawei.com>
Signed-off-by: default avatarMimi Zohar <zohar@linux.ibm.com>
parent 8c7a703e
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -78,6 +78,10 @@ descriptors by adding their identifier to the format string
 - '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:
+10 −0
Original line number Diff line number Diff line
@@ -39,6 +39,9 @@ extern int evm_inode_init_security(struct inode *inode,
				   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
@@ -120,5 +123,12 @@ 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 */
+69 −0
Original line number Diff line number Diff line
@@ -317,6 +317,75 @@ 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
+9 −0
Original line number Diff line number Diff line
@@ -53,6 +53,15 @@ static const struct ima_template_field supported_fields[] = {
	 .field_show = ima_show_template_uint},
	{.field_id = "imode", .field_init = ima_eventinodemode_init,
	 .field_show = ima_show_template_uint},
	{.field_id = "xattrnames",
	 .field_init = ima_eventinodexattrnames_init,
	 .field_show = ima_show_template_string},
	{.field_id = "xattrlengths",
	 .field_init = ima_eventinodexattrlengths_init,
	 .field_show = ima_show_template_sig},
	{.field_id = "xattrvalues",
	 .field_init = ima_eventinodexattrvalues_init,
	 .field_show = ima_show_template_sig},
};

/*
+64 −0
Original line number Diff line number Diff line
@@ -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)
{
@@ -618,3 +619,66 @@ 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);
}

static int ima_eventinodexattrs_init_common(struct ima_event_data *event_data,
					    struct ima_field_data *field_data,
					    char type)
{
	u8 *buffer = NULL;
	int rc;

	if (!event_data->file)
		return 0;

	rc = evm_read_protected_xattrs(file_dentry(event_data->file), NULL, 0,
				       type, ima_canonical_fmt);
	if (rc < 0)
		return 0;

	buffer = kmalloc(rc, GFP_KERNEL);
	if (!buffer)
		return 0;

	rc = evm_read_protected_xattrs(file_dentry(event_data->file), buffer,
				       rc, type, ima_canonical_fmt);
	if (rc < 0) {
		rc = 0;
		goto out;
	}

	rc = ima_write_template_field_data((char *)buffer, rc, DATA_FMT_HEX,
					   field_data);
out:
	kfree(buffer);
	return rc;
}

/*
 *  ima_eventinodexattrnames_init - include a list of xattr names as part of the
 *  template data
 */
int ima_eventinodexattrnames_init(struct ima_event_data *event_data,
				  struct ima_field_data *field_data)
{
	return ima_eventinodexattrs_init_common(event_data, field_data, 'n');
}

/*
 *  ima_eventinodexattrlengths_init - include a list of xattr lengths as part of
 *  the template data
 */
int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
				    struct ima_field_data *field_data)
{
	return ima_eventinodexattrs_init_common(event_data, field_data, 'l');
}

/*
 *  ima_eventinodexattrvalues_init - include a list of xattr values as part of
 *  the template data
 */
int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
				   struct ima_field_data *field_data)
{
	return ima_eventinodexattrs_init_common(event_data, field_data, 'v');
}
Loading