@@ -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);
@@ -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;
@@ -306,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);
}
@@ -870,14 +870,35 @@ int evm_inode_init_security(struct inode *inode, struct inode *dir,
int *xattr_count)
{
struct evm_xattr *xattr_data;
- struct xattr *evm_xattr;
+ struct xattr *xattr, *evm_xattr;
+ bool evm_protected_xattrs = false;
int rc;
- if (!(evm_initialized & EVM_INIT_HMAC) || !xattrs ||
- !evm_protected_xattr(xattrs->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)