>From 9f6cf77a341939a012fb2c114c6cf23821ffaedc Mon Sep 17 00:00:00 2001 From: Lev Olshvang <levonshe@xxxxxxxxx> Date: Mon, 30 Mar 2020 16:00:27 +0300 Subject: [PATCH] integrity - add more inode metadata to signature Add another 2 inode fields to inode hash: size and flags. File flags may have immutable flag set which I consider important security indicator. File systems may use other flags which attacker may tweak to change behavior. Having original file size may improve IMA performance (although some code redesign is required). If we are evident to file size change, we can spare IMA from other read operations and checks. Signed-off-by: Lev Olshvang <levonshe@xxxxxxxxx> --- security/integrity/evm/evm_crypto.c | 30 +++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/security/integrity/evm/evm_crypto.c b/security/integrity/evm/evm_crypto.c index d485f6fc908e..76703413952d 100644 --- a/security/integrity/evm/evm_crypto.c +++ b/security/integrity/evm/evm_crypto.c @@ -139,15 +139,18 @@ static struct shash_desc *init_desc(char type, uint8_t hash_algo) * (Additional directory/file metadata needs to be added for more complete * protection.) */ -static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, +static int hmac_add_misc(struct shash_desc *desc, struct inode *inode, char type, char *digest) { + int rc = 0; struct h_misc { unsigned long ino; __u32 generation; uid_t uid; gid_t gid; umode_t mode; + __u32 filesize; + __u32 flags; } hmac_misc; memset(&hmac_misc, 0, sizeof(hmac_misc)); @@ -169,11 +172,24 @@ static void hmac_add_misc(struct shash_desc *desc, struct inode *inode, hmac_misc.uid = from_kuid(&init_user_ns, inode->i_uid); hmac_misc.gid = from_kgid(&init_user_ns, inode->i_gid); hmac_misc.mode = inode->i_mode; - crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc)); + hmac_misc.flags = inode->i_flags; + /* hardly imagine calculating hash for file > 4G */ + if (likely(inode->i_size < 0xFFFFFFFF)) + hmac_misc.filesize = (__u32) inode->i_size; + else + return -E2BIG; + + rc = crypto_shash_update(desc, (const u8 *)&hmac_misc, sizeof(hmac_misc)); + if (unlikely(!rc)) + return rc - __LINE__; if ((evm_hmac_attrs & EVM_ATTR_FSUUID) && - type != EVM_XATTR_PORTABLE_DIGSIG) - crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE); - crypto_shash_final(desc, digest); + type != EVM_XATTR_PORTABLE_DIGSIG) { + rc = crypto_shash_update(desc, (u8 *)&inode->i_sb->s_uuid, UUID_SIZE); + if (unlikely(!rc)) + return rc - __LINE__; + } + rc = crypto_shash_final(desc, digest); + return rc; } /* @@ -239,7 +255,9 @@ static int evm_calc_hmac_or_hash(struct dentry *dentry, if (is_ima) ima_present = true; } - hmac_add_misc(desc, inode, type, data->digest); + error = hmac_add_misc(desc, inode, type, data->digest); + if (error < 0) + return error; /* Portable EVM signatures must include an IMA hash */ if (type == EVM_XATTR_PORTABLE_DIGSIG && !ima_present) -- 2.17.1