Skip to content

Commit 8314b67

Browse files
robertosassumimizohar
authored andcommitted
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>
1 parent 8c7a703 commit 8314b67

6 files changed

Lines changed: 162 additions & 0 deletions

File tree

Documentation/security/IMA-templates.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,10 @@ descriptors by adding their identifier to the format string
7878
- 'iuid': the inode UID;
7979
- 'igid': the inode GID;
8080
- 'imode': the inode mode;
81+
- 'xattrnames': a list of xattr names (separated by |), only if the xattr is
82+
present;
83+
- 'xattrlengths': a list of xattr lengths (u32), only if the xattr is present;
84+
- 'xattrvalues': a list of xattr values;
8185
8286

8387
Below, there is the list of defined template descriptors:

include/linux/evm.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ extern int evm_inode_init_security(struct inode *inode,
3939
struct xattr *evm);
4040
extern bool evm_revalidate_status(const char *xattr_name);
4141
extern int evm_protected_xattr_if_enabled(const char *req_xattr_name);
42+
extern int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
43+
int buffer_size, char type,
44+
bool canonical_fmt);
4245
#ifdef CONFIG_FS_POSIX_ACL
4346
extern int posix_xattr_acl(const char *xattrname);
4447
#else
@@ -120,5 +123,12 @@ static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name)
120123
return false;
121124
}
122125

126+
static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
127+
int buffer_size, char type,
128+
bool canonical_fmt)
129+
{
130+
return -EOPNOTSUPP;
131+
}
132+
123133
#endif /* CONFIG_EVM */
124134
#endif /* LINUX_EVM_H */

security/integrity/evm/evm_main.c

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -317,6 +317,75 @@ int evm_protected_xattr_if_enabled(const char *req_xattr_name)
317317
return evm_protected_xattr_common(req_xattr_name, true);
318318
}
319319

320+
/**
321+
* evm_read_protected_xattrs - read EVM protected xattr names, lengths, values
322+
* @dentry: dentry of the read xattrs
323+
* @inode: inode of the read xattrs
324+
* @buffer: buffer xattr names, lengths or values are copied to
325+
* @buffer_size: size of buffer
326+
* @type: n: names, l: lengths, v: values
327+
* @canonical_fmt: data format (true: little endian, false: native format)
328+
*
329+
* Read protected xattr names (separated by |), lengths (u32) or values for a
330+
* given dentry and return the total size of copied data. If buffer is NULL,
331+
* just return the total size.
332+
*
333+
* Returns the total size on success, a negative value on error.
334+
*/
335+
int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer,
336+
int buffer_size, char type, bool canonical_fmt)
337+
{
338+
struct xattr_list *xattr;
339+
int rc, size, total_size = 0;
340+
341+
list_for_each_entry_lockless(xattr, &evm_config_xattrnames, list) {
342+
rc = __vfs_getxattr(dentry, d_backing_inode(dentry),
343+
xattr->name, NULL, 0);
344+
if (rc < 0 && rc == -ENODATA)
345+
continue;
346+
else if (rc < 0)
347+
return rc;
348+
349+
switch (type) {
350+
case 'n':
351+
size = strlen(xattr->name) + 1;
352+
if (buffer) {
353+
if (total_size)
354+
*(buffer + total_size - 1) = '|';
355+
356+
memcpy(buffer + total_size, xattr->name, size);
357+
}
358+
break;
359+
case 'l':
360+
size = sizeof(u32);
361+
if (buffer) {
362+
if (canonical_fmt)
363+
rc = cpu_to_le32(rc);
364+
365+
*(u32 *)(buffer + total_size) = rc;
366+
}
367+
break;
368+
case 'v':
369+
size = rc;
370+
if (buffer) {
371+
rc = __vfs_getxattr(dentry,
372+
d_backing_inode(dentry), xattr->name,
373+
buffer + total_size,
374+
buffer_size - total_size);
375+
if (rc < 0)
376+
return rc;
377+
}
378+
break;
379+
default:
380+
return -EINVAL;
381+
}
382+
383+
total_size += size;
384+
}
385+
386+
return total_size;
387+
}
388+
320389
/**
321390
* evm_verifyxattr - verify the integrity of the requested xattr
322391
* @dentry: object of the verify xattr

security/integrity/ima/ima_template.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,15 @@ static const struct ima_template_field supported_fields[] = {
5353
.field_show = ima_show_template_uint},
5454
{.field_id = "imode", .field_init = ima_eventinodemode_init,
5555
.field_show = ima_show_template_uint},
56+
{.field_id = "xattrnames",
57+
.field_init = ima_eventinodexattrnames_init,
58+
.field_show = ima_show_template_string},
59+
{.field_id = "xattrlengths",
60+
.field_init = ima_eventinodexattrlengths_init,
61+
.field_show = ima_show_template_sig},
62+
{.field_id = "xattrvalues",
63+
.field_init = ima_eventinodexattrvalues_init,
64+
.field_show = ima_show_template_sig},
5665
};
5766

5867
/*

security/integrity/ima/ima_template_lib.c

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "ima_template_lib.h"
1313
#include <linux/xattr.h>
14+
#include <linux/evm.h>
1415

1516
static bool ima_template_hash_algo_allowed(u8 algo)
1617
{
@@ -618,3 +619,66 @@ int ima_eventinodemode_init(struct ima_event_data *event_data,
618619
return ima_write_template_field_data((char *)&mode, sizeof(mode),
619620
DATA_FMT_UINT, field_data);
620621
}
622+
623+
static int ima_eventinodexattrs_init_common(struct ima_event_data *event_data,
624+
struct ima_field_data *field_data,
625+
char type)
626+
{
627+
u8 *buffer = NULL;
628+
int rc;
629+
630+
if (!event_data->file)
631+
return 0;
632+
633+
rc = evm_read_protected_xattrs(file_dentry(event_data->file), NULL, 0,
634+
type, ima_canonical_fmt);
635+
if (rc < 0)
636+
return 0;
637+
638+
buffer = kmalloc(rc, GFP_KERNEL);
639+
if (!buffer)
640+
return 0;
641+
642+
rc = evm_read_protected_xattrs(file_dentry(event_data->file), buffer,
643+
rc, type, ima_canonical_fmt);
644+
if (rc < 0) {
645+
rc = 0;
646+
goto out;
647+
}
648+
649+
rc = ima_write_template_field_data((char *)buffer, rc, DATA_FMT_HEX,
650+
field_data);
651+
out:
652+
kfree(buffer);
653+
return rc;
654+
}
655+
656+
/*
657+
* ima_eventinodexattrnames_init - include a list of xattr names as part of the
658+
* template data
659+
*/
660+
int ima_eventinodexattrnames_init(struct ima_event_data *event_data,
661+
struct ima_field_data *field_data)
662+
{
663+
return ima_eventinodexattrs_init_common(event_data, field_data, 'n');
664+
}
665+
666+
/*
667+
* ima_eventinodexattrlengths_init - include a list of xattr lengths as part of
668+
* the template data
669+
*/
670+
int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
671+
struct ima_field_data *field_data)
672+
{
673+
return ima_eventinodexattrs_init_common(event_data, field_data, 'l');
674+
}
675+
676+
/*
677+
* ima_eventinodexattrvalues_init - include a list of xattr values as part of
678+
* the template data
679+
*/
680+
int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
681+
struct ima_field_data *field_data)
682+
{
683+
return ima_eventinodexattrs_init_common(event_data, field_data, 'v');
684+
}

security/integrity/ima/ima_template_lib.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,4 +56,10 @@ int ima_eventinodegid_init(struct ima_event_data *event_data,
5656
struct ima_field_data *field_data);
5757
int ima_eventinodemode_init(struct ima_event_data *event_data,
5858
struct ima_field_data *field_data);
59+
int ima_eventinodexattrnames_init(struct ima_event_data *event_data,
60+
struct ima_field_data *field_data);
61+
int ima_eventinodexattrlengths_init(struct ima_event_data *event_data,
62+
struct ima_field_data *field_data);
63+
int ima_eventinodexattrvalues_init(struct ima_event_data *event_data,
64+
struct ima_field_data *field_data);
5965
#endif /* __LINUX_IMA_TEMPLATE_LIB_H */

0 commit comments

Comments
 (0)