From: Roberto Sassu roberto.sassu@huawei.com
Similarly to evm_verify_hmac(), which allocates an evm_digest structure to satisfy the linear mapping requirement if CONFIG_VMAP_STACK is enabled, do the same in xattr_verify(). Allocate an ima_max_digest_data structure and use that instead of the in-stack counterpart.
Cc: stable@vger.kernel.org # 4.9.x Fixes: ba14a194a434 ("fork: Add generic vmalloced stack support") Signed-off-by: Roberto Sassu roberto.sassu@huawei.com --- security/integrity/ima/ima_appraise.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-)
diff --git a/security/integrity/ima/ima_appraise.c b/security/integrity/ima/ima_appraise.c index 3e0fbbd99534..ed8f05340fe8 100644 --- a/security/integrity/ima/ima_appraise.c +++ b/security/integrity/ima/ima_appraise.c @@ -278,6 +278,7 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, enum integrity_status *status, const char **cause) { struct ima_max_digest_data hash; + struct ima_max_digest_data *hash_ptr = &hash; struct signature_v2_hdr *sig; int rc = -EINVAL, hash_start = 0; int mask; @@ -376,8 +377,17 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, break; }
+ if (IS_ENABLED(CONFIG_VMAP_STACK)) { + hash_ptr = kmalloc(sizeof(*hash_ptr), GFP_KERNEL); + if (!hash_ptr) { + *cause = "out-of-memory"; + *status = INTEGRITY_FAIL; + break; + } + } + rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo, - iint->ima_hash->digest, &hash.hdr); + iint->ima_hash->digest, &hash_ptr->hdr); if (rc) { *cause = "sigv3-hashing-error"; *status = INTEGRITY_FAIL; @@ -386,8 +396,8 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint,
rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, (const char *)xattr_value, - xattr_len, hash.digest, - hash.hdr.length); + xattr_len, hash_ptr->digest, + hash_ptr->hdr.length); if (rc) { *cause = "invalid-verity-signature"; *status = INTEGRITY_FAIL; @@ -402,6 +412,9 @@ static int xattr_verify(enum ima_hooks func, struct integrity_iint_cache *iint, break; }
+ if (hash_ptr && hash_ptr != &hash) + kfree(hash_ptr); + return rc; }