Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Roberto Sassu and committed by
Mimi Zohar
8314b673 8c7a703e

+162
+4
Documentation/security/IMA-templates.rst
··· 78 78 - 'iuid': the inode UID; 79 79 - 'igid': the inode GID; 80 80 - '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; 81 85 82 86 83 87 Below, there is the list of defined template descriptors:
+10
include/linux/evm.h
··· 39 39 struct xattr *evm); 40 40 extern bool evm_revalidate_status(const char *xattr_name); 41 41 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); 42 45 #ifdef CONFIG_FS_POSIX_ACL 43 46 extern int posix_xattr_acl(const char *xattrname); 44 47 #else ··· 121 118 static inline int evm_protected_xattr_if_enabled(const char *req_xattr_name) 122 119 { 123 120 return false; 121 + } 122 + 123 + static inline int evm_read_protected_xattrs(struct dentry *dentry, u8 *buffer, 124 + int buffer_size, char type, 125 + bool canonical_fmt) 126 + { 127 + return -EOPNOTSUPP; 124 128 } 125 129 126 130 #endif /* CONFIG_EVM */
+69
security/integrity/evm/evm_main.c
··· 318 318 } 319 319 320 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 + 389 + /** 321 390 * evm_verifyxattr - verify the integrity of the requested xattr 322 391 * @dentry: object of the verify xattr 323 392 * @xattr_name: requested xattr
+9
security/integrity/ima/ima_template.c
··· 53 53 .field_show = ima_show_template_uint}, 54 54 {.field_id = "imode", .field_init = ima_eventinodemode_init, 55 55 .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}, 56 65 }; 57 66 58 67 /*
+64
security/integrity/ima/ima_template_lib.c
··· 11 11 12 12 #include "ima_template_lib.h" 13 13 #include <linux/xattr.h> 14 + #include <linux/evm.h> 14 15 15 16 static bool ima_template_hash_algo_allowed(u8 algo) 16 17 { ··· 618 617 619 618 return ima_write_template_field_data((char *)&mode, sizeof(mode), 620 619 DATA_FMT_UINT, field_data); 620 + } 621 + 622 + static int ima_eventinodexattrs_init_common(struct ima_event_data *event_data, 623 + struct ima_field_data *field_data, 624 + char type) 625 + { 626 + u8 *buffer = NULL; 627 + int rc; 628 + 629 + if (!event_data->file) 630 + return 0; 631 + 632 + rc = evm_read_protected_xattrs(file_dentry(event_data->file), NULL, 0, 633 + type, ima_canonical_fmt); 634 + if (rc < 0) 635 + return 0; 636 + 637 + buffer = kmalloc(rc, GFP_KERNEL); 638 + if (!buffer) 639 + return 0; 640 + 641 + rc = evm_read_protected_xattrs(file_dentry(event_data->file), buffer, 642 + rc, type, ima_canonical_fmt); 643 + if (rc < 0) { 644 + rc = 0; 645 + goto out; 646 + } 647 + 648 + rc = ima_write_template_field_data((char *)buffer, rc, DATA_FMT_HEX, 649 + field_data); 650 + out: 651 + kfree(buffer); 652 + return rc; 653 + } 654 + 655 + /* 656 + * ima_eventinodexattrnames_init - include a list of xattr names as part of the 657 + * template data 658 + */ 659 + int ima_eventinodexattrnames_init(struct ima_event_data *event_data, 660 + struct ima_field_data *field_data) 661 + { 662 + return ima_eventinodexattrs_init_common(event_data, field_data, 'n'); 663 + } 664 + 665 + /* 666 + * ima_eventinodexattrlengths_init - include a list of xattr lengths as part of 667 + * the template data 668 + */ 669 + int ima_eventinodexattrlengths_init(struct ima_event_data *event_data, 670 + struct ima_field_data *field_data) 671 + { 672 + return ima_eventinodexattrs_init_common(event_data, field_data, 'l'); 673 + } 674 + 675 + /* 676 + * ima_eventinodexattrvalues_init - include a list of xattr values as part of 677 + * the template data 678 + */ 679 + int ima_eventinodexattrvalues_init(struct ima_event_data *event_data, 680 + struct ima_field_data *field_data) 681 + { 682 + return ima_eventinodexattrs_init_common(event_data, field_data, 'v'); 621 683 }
+6
security/integrity/ima/ima_template_lib.h
··· 56 56 struct ima_field_data *field_data); 57 57 int ima_eventinodemode_init(struct ima_event_data *event_data, 58 58 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); 59 65 #endif /* __LINUX_IMA_TEMPLATE_LIB_H */