Skip to content

Commit

Permalink
IMA: block writes of the security.ima xattr with unsupported algorithms
Browse files Browse the repository at this point in the history
By default, writes to the extended attributes security.ima will be
allowed even if the hash algorithm used for the xattr is not compiled
in the kernel (which does not make sense because the kernel would not
be able to appraise that file as it lacks support for validating the
hash).

Prevent and audit writes to the security.ima xattr if the hash algorithm
used in the new value is not available in the current kernel.

Signed-off-by: THOBY Simon <Simon.THOBY@viveris.fr>
Reviewed-by: Lakshmi Ramasubramanian <nramas@linux.microsoft.com>
Signed-off-by: Mimi Zohar <zohar@linux.ibm.com>
  • Loading branch information
THOBY Simon authored and Mimi Zohar committed Aug 16, 2021
1 parent 8510505 commit 50f742d
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 4 deletions.
2 changes: 1 addition & 1 deletion security/integrity/ima/ima.h
Original file line number Diff line number Diff line change
Expand Up @@ -319,7 +319,7 @@ int ima_must_appraise(struct user_namespace *mnt_userns, struct inode *inode,
void ima_update_xattr(struct integrity_iint_cache *iint, struct file *file);
enum integrity_status ima_get_cache_status(struct integrity_iint_cache *iint,
enum ima_hooks func);
enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len);
int ima_read_xattr(struct dentry *dentry,
struct evm_ima_xattr_data **xattr_value);
Expand Down
49 changes: 46 additions & 3 deletions security/integrity/ima/ima_appraise.c
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ static void ima_cache_flags(struct integrity_iint_cache *iint,
}
}

enum hash_algo ima_get_hash_algo(struct evm_ima_xattr_data *xattr_value,
enum hash_algo ima_get_hash_algo(const struct evm_ima_xattr_data *xattr_value,
int xattr_len)
{
struct signature_v2_hdr *sig;
Expand Down Expand Up @@ -575,6 +575,47 @@ static void ima_reset_appraise_flags(struct inode *inode, int digsig)
clear_bit(IMA_DIGSIG, &iint->atomic_flags);
}

/**
* validate_hash_algo() - Block setxattr with unsupported hash algorithms
* @dentry: object of the setxattr()
* @xattr_value: userland supplied xattr value
* @xattr_value_len: length of xattr_value
*
* The xattr value is mapped to its hash algorithm, and this algorithm
* must be built in the kernel for the setxattr to be allowed.
*
* Emit an audit message when the algorithm is invalid.
*
* Return: 0 on success, else an error.
*/
static int validate_hash_algo(struct dentry *dentry,
const struct evm_ima_xattr_data *xattr_value,
size_t xattr_value_len)
{
char *path = NULL, *pathbuf = NULL;
enum hash_algo xattr_hash_algo;

xattr_hash_algo = ima_get_hash_algo(xattr_value, xattr_value_len);

if (likely(xattr_hash_algo == ima_hash_algo ||
crypto_has_alg(hash_algo_name[xattr_hash_algo], 0, 0)))
return 0;

pathbuf = kmalloc(PATH_MAX, GFP_KERNEL);
if (!pathbuf)
return -EACCES;

path = dentry_path(dentry, pathbuf, PATH_MAX);

integrity_audit_msg(AUDIT_INTEGRITY_DATA, d_inode(dentry), path,
"set_data", "unavailable-hash-algorithm",
-EACCES, 0);

kfree(pathbuf);

return -EACCES;
}

int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
const void *xattr_value, size_t xattr_value_len)
{
Expand All @@ -592,9 +633,11 @@ int ima_inode_setxattr(struct dentry *dentry, const char *xattr_name,
digsig = (xvalue->type == EVM_XATTR_PORTABLE_DIGSIG);
}
if (result == 1 || evm_revalidate_status(xattr_name)) {
result = validate_hash_algo(dentry, xvalue, xattr_value_len);
if (result)
return result;

ima_reset_appraise_flags(d_backing_inode(dentry), digsig);
if (result == 1)
result = 0;
}
return result;
}
Expand Down

0 comments on commit 50f742d

Please sign in to comment.