fsverity: rework fsverity_get_digest() again

Address several issues with the calling convention and documentation of
fsverity_get_digest():

- Make it provide the hash algorithm as either a FS_VERITY_HASH_ALG_*
  value or HASH_ALGO_* value, at the caller's choice, rather than only a
  HASH_ALGO_* value as it did before.  This allows callers to work with
  the fsverity native algorithm numbers if they want to.  HASH_ALGO_* is
  what IMA uses, but other users (e.g. overlayfs) should use
  FS_VERITY_HASH_ALG_* to match fsverity-utils and the fsverity UAPI.

- Make it return the digest size so that it doesn't need to be looked up
  separately.  Use the return value for this, since 0 works nicely for
  the "file doesn't have fsverity enabled" case.  This also makes it
  clear that no other errors are possible.

- Rename the 'digest' parameter to 'raw_digest' and clearly document
  that it is only useful in combination with the algorithm ID.  This
  hopefully clears up a point of confusion.

- Export it to modules, since overlayfs will need it for checking the
  fsverity digests of lowerdata files
  (https://lore.kernel.org/r/dd294a44e8f401e6b5140029d8355f88748cd8fd.1686565330.git.alexl@redhat.com).

Acked-by: Mimi Zohar <zohar@linux.ibm.com> # for the IMA piece
Link: https://lore.kernel.org/r/20230612190047.59755-1-ebiggers@kernel.org
Signed-off-by: Eric Biggers <ebiggers@google.com>
This commit is contained in:
Eric Biggers
2023-06-12 12:00:47 -07:00
parent 13e2408d02
commit 74836ecbc5
3 changed files with 47 additions and 35 deletions

View File

@@ -202,19 +202,19 @@ int ima_get_action(struct mnt_idmap *idmap, struct inode *inode,
allowed_algos);
}
static int ima_get_verity_digest(struct integrity_iint_cache *iint,
struct ima_max_digest_data *hash)
static bool ima_get_verity_digest(struct integrity_iint_cache *iint,
struct ima_max_digest_data *hash)
{
enum hash_algo verity_alg;
int ret;
enum hash_algo alg;
int digest_len;
/*
* On failure, 'measure' policy rules will result in a file data
* hash containing 0's.
*/
ret = fsverity_get_digest(iint->inode, hash->digest, &verity_alg);
if (ret)
return ret;
digest_len = fsverity_get_digest(iint->inode, hash->digest, NULL, &alg);
if (digest_len == 0)
return false;
/*
* Unlike in the case of actually calculating the file hash, in
@@ -223,9 +223,9 @@ static int ima_get_verity_digest(struct integrity_iint_cache *iint,
* mismatch between the verity algorithm and the xattr signature
* algorithm, if one exists, will be detected later.
*/
hash->hdr.algo = verity_alg;
hash->hdr.length = hash_digest_size[verity_alg];
return 0;
hash->hdr.algo = alg;
hash->hdr.length = digest_len;
return true;
}
/*
@@ -276,16 +276,9 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
memset(&hash.digest, 0, sizeof(hash.digest));
if (iint->flags & IMA_VERITY_REQUIRED) {
result = ima_get_verity_digest(iint, &hash);
switch (result) {
case 0:
break;
case -ENODATA:
if (!ima_get_verity_digest(iint, &hash)) {
audit_cause = "no-verity-digest";
break;
default:
audit_cause = "invalid-verity-digest";
break;
result = -ENODATA;
}
} else if (buf) {
result = ima_calc_buffer_hash(buf, size, &hash.hdr);