mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-29 22:02:02 +00:00
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: Roberto Sassu <roberto.sassu@huawei.com> Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
This commit is contained in:
parent
8c7a703ec9
commit
8314b6732a
6 changed files with 162 additions and 0 deletions
|
@ -78,6 +78,10 @@ descriptors by adding their identifier to the format string
|
||||||
- 'iuid': the inode UID;
|
- 'iuid': the inode UID;
|
||||||
- 'igid': the inode GID;
|
- 'igid': the inode GID;
|
||||||
- 'imode': the inode mode;
|
- '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:
|
Below, there is the list of defined template descriptors:
|
||||||
|
|
|
@ -39,6 +39,9 @@ extern int evm_inode_init_security(struct inode *inode,
|
||||||
struct xattr *evm);
|
struct xattr *evm);
|
||||||
extern bool evm_revalidate_status(const char *xattr_name);
|
extern bool evm_revalidate_status(const char *xattr_name);
|
||||||
extern int evm_protected_xattr_if_enabled(const char *req_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
|
#ifdef CONFIG_FS_POSIX_ACL
|
||||||
extern int posix_xattr_acl(const char *xattrname);
|
extern int posix_xattr_acl(const char *xattrname);
|
||||||
#else
|
#else
|
||||||
|
@ -120,5 +123,12 @@ static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name)
|
||||||
return false;
|
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 /* CONFIG_EVM */
|
||||||
#endif /* LINUX_EVM_H */
|
#endif /* LINUX_EVM_H */
|
||||||
|
|
|
@ -317,6 +317,75 @@ int evm_protected_xattr_if_enabled(const char *req_xattr_name)
|
||||||
return evm_protected_xattr_common(req_xattr_name, true);
|
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
|
* evm_verifyxattr - verify the integrity of the requested xattr
|
||||||
* @dentry: object of the verify xattr
|
* @dentry: object of the verify xattr
|
||||||
|
|
|
@ -53,6 +53,15 @@ static const struct ima_template_field supported_fields[] = {
|
||||||
.field_show = ima_show_template_uint},
|
.field_show = ima_show_template_uint},
|
||||||
{.field_id = "imode", .field_init = ima_eventinodemode_init,
|
{.field_id = "imode", .field_init = ima_eventinodemode_init,
|
||||||
.field_show = ima_show_template_uint},
|
.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},
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
|
|
||||||
#include "ima_template_lib.h"
|
#include "ima_template_lib.h"
|
||||||
#include <linux/xattr.h>
|
#include <linux/xattr.h>
|
||||||
|
#include <linux/evm.h>
|
||||||
|
|
||||||
static bool ima_template_hash_algo_allowed(u8 algo)
|
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),
|
return ima_write_template_field_data((char *)&mode, sizeof(mode),
|
||||||
DATA_FMT_UINT, field_data);
|
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');
|
||||||
|
}
|
||||||
|
|
|
@ -56,4 +56,10 @@ int ima_eventinodegid_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
int ima_eventinodemode_init(struct ima_event_data *event_data,
|
int ima_eventinodemode_init(struct ima_event_data *event_data,
|
||||||
struct ima_field_data *field_data);
|
struct ima_field_data *field_data);
|
||||||
|
int ima_eventinodexattrnames_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data);
|
||||||
|
int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data);
|
||||||
|
int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
|
||||||
|
struct ima_field_data *field_data);
|
||||||
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
|
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */
|
||||||
|
|
Loading…
Reference in a new issue