diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 09:07:09 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2023-08-30 09:07:09 -0700 |
commit | 1086eeac9c333b6db6c98594f02996c8261c60c5 (patch) | |
tree | 23b89550b3681c6c329fc7e8dfb7eadc39512d35 /security/integrity | |
parent | 1dbae189873066e817fe94b4e4ac7c8c42b51d77 (diff) | |
parent | 8e4672d6f902d5c4db1e87e8aa9f530149d85bc6 (diff) |
Merge tag 'lsm-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm
Pull LSM updates from Paul Moore:
- Add proper multi-LSM support for xattrs in the
security_inode_init_security() hook
Historically the LSM layer has only allowed a single LSM to add an
xattr to an inode, with IMA/EVM measuring that and adding its own as
well. As we work towards promoting IMA/EVM to a "proper LSM" instead
of the special case that it is now, we need to better support the
case of multiple LSMs each adding xattrs to an inode and after
several attempts we now appear to have something that is working
well. It is worth noting that in the process of making this change we
uncovered a problem with Smack's SMACK64TRANSMUTE xattr which is also
fixed in this pull request.
- Additional LSM hook constification
Two patches to constify parameters to security_capget() and
security_binder_transfer_file(). While I generally don't make a
special note of who submitted these patches, these were the work of
an Outreachy intern, Khadija Kamran, and that makes me happy;
hopefully it does the same for all of you reading this.
- LSM hook comment header fixes
One patch to add a missing hook comment header, one to fix a minor
typo.
- Remove an old, unused credential function declaration
It wasn't clear to me who should pick this up, but it was trivial,
obviously correct, and arguably the LSM layer has a vested interest
in credentials so I merged it. Sadly I'm now noticing that despite my
subject line cleanup I didn't cleanup the "unsued" misspelling, sigh
* tag 'lsm-pr-20230829' of git://git.kernel.org/pub/scm/linux/kernel/git/pcmoore/lsm:
lsm: constify the 'file' parameter in security_binder_transfer_file()
lsm: constify the 'target' parameter in security_capget()
lsm: add comment block for security_sk_classify_flow LSM hook
security: Fix ret values doc for security_inode_init_security()
cred: remove unsued extern declaration change_create_files_as()
evm: Support multiple LSMs providing an xattr
evm: Align evm_inode_init_security() definition with LSM infrastructure
smack: Set the SMACK64TRANSMUTE xattr in smack_inode_init_security()
security: Allow all LSMs to provide xattrs for inode_init_security hook
lsm: fix typo in security_file_lock() comment header
Diffstat (limited to 'security/integrity')
-rw-r--r-- | security/integrity/evm/evm.h | 4 | ||||
-rw-r--r-- | security/integrity/evm/evm_crypto.c | 11 | ||||
-rw-r--r-- | security/integrity/evm/evm_main.c | 39 |
3 files changed, 44 insertions, 10 deletions
diff --git a/security/integrity/evm/evm.h b/security/integrity/evm/evm.h index f8b8c5004fc7..53bd7fec93fa 100644 --- a/security/integrity/evm/evm.h +++ b/security/integrity/evm/evm.h @@ -46,6 +46,8 @@ struct evm_digest { char digest[IMA_MAX_DIGEST_SIZE]; } __packed; +int evm_protected_xattr(const char *req_xattr_name); + int evm_init_key(void); int evm_update_evmxattr(struct dentry *dentry, const char *req_xattr_name, @@ -58,7 +60,7 @@ int evm_calc_hash(struct dentry *dentry, const char *req_xattr_name, const char *req_xattr_value, size_t req_xattr_value_len, char type, struct evm_digest *data); -int evm_init_hmac(struct inode *inode, const struct xattr *xattr, +int evm_init_hmac(struct inode *inode, const struct xattr *xattrs, char *hmac_val); int evm_init_secfs(void); diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index 0dae649f3740..b1ffd4cc0b44 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -385,10 +385,11 @@ int evm_update_evmxattr(struct dentry *dentry, const char *xattr_name, return rc; } -int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, +int evm_init_hmac(struct inode *inode, const struct xattr *xattrs, char *hmac_val) { struct shash_desc *desc; + const struct xattr *xattr; desc = init_desc(EVM_XATTR_HMAC, HASH_ALGO_SHA1); if (IS_ERR(desc)) { @@ -396,7 +397,13 @@ int evm_init_hmac(struct inode *inode, const struct xattr *lsm_xattr, return PTR_ERR(desc); } - crypto_shash_update(desc, lsm_xattr->value, lsm_xattr->value_len); + for (xattr = xattrs; xattr->name; xattr++) { + if (!evm_protected_xattr(xattr->name)) + continue; + + crypto_shash_update(desc, xattr->value, xattr->value_len); + } + hmac_add_misc(desc, inode, EVM_XATTR_HMAC, hmac_val); kfree(desc); return 0; diff --git a/security/integrity/evm/evm_main.c b/security/integrity/evm/evm_main.c index c9b6e2a43478..ff9a939dad8e 100644 --- a/security/integrity/evm/evm_main.c +++ b/security/integrity/evm/evm_main.c @@ -21,6 +21,7 @@ #include <linux/evm.h> #include <linux/magic.h> #include <linux/posix_acl_xattr.h> +#include <linux/lsm_hooks.h> #include <crypto/hash.h> #include <crypto/hash_info.h> @@ -305,7 +306,7 @@ static int evm_protected_xattr_common(const char *req_xattr_name, return found; } -static int evm_protected_xattr(const char *req_xattr_name) +int evm_protected_xattr(const char *req_xattr_name) { return evm_protected_xattr_common(req_xattr_name, false); } @@ -866,23 +867,47 @@ void evm_inode_post_setattr(struct dentry *dentry, int ia_valid) /* * evm_inode_init_security - initializes security.evm HMAC value */ -int evm_inode_init_security(struct inode *inode, - const struct xattr *lsm_xattr, - struct xattr *evm_xattr) +int evm_inode_init_security(struct inode *inode, struct inode *dir, + const struct qstr *qstr, struct xattr *xattrs, + int *xattr_count) { struct evm_xattr *xattr_data; + struct xattr *xattr, *evm_xattr; + bool evm_protected_xattrs = false; int rc; - if (!(evm_initialized & EVM_INIT_HMAC) || - !evm_protected_xattr(lsm_xattr->name)) + if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs) return 0; + /* + * security_inode_init_security() makes sure that the xattrs array is + * contiguous, there is enough space for security.evm, and that there is + * a terminator at the end of the array. + */ + for (xattr = xattrs; xattr->name; xattr++) { + if (evm_protected_xattr(xattr->name)) + evm_protected_xattrs = true; + } + + /* EVM xattr not needed. */ + if (!evm_protected_xattrs) + return 0; + + evm_xattr = lsm_get_xattr_slot(xattrs, xattr_count); + /* + * Array terminator (xattr name = NULL) must be the first non-filled + * xattr slot. + */ + WARN_ONCE(evm_xattr != xattr, + "%s: xattrs terminator is not the first non-filled slot\n", + __func__); + xattr_data = kzalloc(sizeof(*xattr_data), GFP_NOFS); if (!xattr_data) return -ENOMEM; xattr_data->data.type = EVM_XATTR_HMAC; - rc = evm_init_hmac(inode, lsm_xattr, xattr_data->digest); + rc = evm_init_hmac(inode, xattrs, xattr_data->digest); if (rc < 0) goto out; |