Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit c46d541

Browse files
committed
Merge branch 'next-integrity.fsverity-v9' into next-integrity
Support for including fs-verity file digests and signatures in the IMA measurement list as well as verifying the fs-verity file digest based signatures. Signed-off-by: Mimi Zohar <[email protected]>
2 parents 891163a + 02ee231 commit c46d541

File tree

17 files changed

+478
-62
lines changed

17 files changed

+478
-62
lines changed

Documentation/ABI/testing/ima_policy

Lines changed: 42 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,9 @@ Description:
2727
[fowner=] [fgroup=]]
2828
lsm: [[subj_user=] [subj_role=] [subj_type=]
2929
[obj_user=] [obj_role=] [obj_type=]]
30-
option: [[appraise_type=]] [template=] [permit_directio]
31-
[appraise_flag=] [appraise_algos=] [keyrings=]
30+
option: [digest_type=] [template=] [permit_directio]
31+
[appraise_type=] [appraise_flag=]
32+
[appraise_algos=] [keyrings=]
3233
base:
3334
func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK]
3435
[FIRMWARE_CHECK]
@@ -47,10 +48,21 @@ Description:
4748
fgroup:= decimal value
4849
lsm: are LSM specific
4950
option:
50-
appraise_type:= [imasig] [imasig|modsig]
51+
appraise_type:= [imasig] | [imasig|modsig] | [sigv3]
52+
where 'imasig' is the original or the signature
53+
format v2.
54+
where 'modsig' is an appended signature,
55+
where 'sigv3' is the signature format v3. (Currently
56+
limited to fsverity digest based signatures
57+
stored in security.ima xattr. Requires
58+
specifying "digest_type=verity" first.)
59+
5160
appraise_flag:= [check_blacklist]
5261
Currently, blacklist check is only for files signed with appended
5362
signature.
63+
digest_type:= verity
64+
Require fs-verity's file digest instead of the
65+
regular IMA file hash.
5466
keyrings:= list of keyrings
5567
(eg, .builtin_trusted_keys|.ima). Only valid
5668
when action is "measure" and func is KEY_CHECK.
@@ -149,3 +161,30 @@ Description:
149161
security.ima xattr of a file:
150162

151163
appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512
164+
165+
Example of a 'measure' rule requiring fs-verity's digests
166+
with indication of type of digest in the measurement list.
167+
168+
measure func=FILE_CHECK digest_type=verity \
169+
template=ima-ngv2
170+
171+
Example of 'measure' and 'appraise' rules requiring fs-verity
172+
signatures (format version 3) stored in security.ima xattr.
173+
174+
The 'measure' rule specifies the 'ima-sigv3' template option,
175+
which includes the indication of type of digest and the file
176+
signature in the measurement list.
177+
178+
measure func=BPRM_CHECK digest_type=verity \
179+
template=ima-sigv3
180+
181+
182+
The 'appraise' rule specifies the type and signature format
183+
version (sigv3) required.
184+
185+
appraise func=BPRM_CHECK digest_type=verity \
186+
appraise_type=sigv3
187+
188+
All of these policy rules could, for example, be constrained
189+
either based on a filesystem's UUID (fsuuid) or based on LSM
190+
labels.

Documentation/admin-guide/kernel-parameters.txt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1903,7 +1903,8 @@
19031903

19041904
ima_template= [IMA]
19051905
Select one of defined IMA measurements template formats.
1906-
Formats: { "ima" | "ima-ng" | "ima-sig" }
1906+
Formats: { "ima" | "ima-ng" | "ima-ngv2" | "ima-sig" |
1907+
"ima-sigv2" }
19071908
Default: "ima-ng"
19081909

19091910
ima_template_fmt=

Documentation/filesystems/fsverity.rst

Lines changed: 23 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -70,12 +70,23 @@ must live on a read-write filesystem because they are independently
7070
updated and potentially user-installed, so dm-verity cannot be used.
7171

7272
The base fs-verity feature is a hashing mechanism only; actually
73-
authenticating the files is up to userspace. However, to meet some
74-
users' needs, fs-verity optionally supports a simple signature
75-
verification mechanism where users can configure the kernel to require
76-
that all fs-verity files be signed by a key loaded into a keyring; see
77-
`Built-in signature verification`_. Support for fs-verity file hashes
78-
in IMA (Integrity Measurement Architecture) policies is also planned.
73+
authenticating the files may be done by:
74+
75+
* Userspace-only
76+
77+
* Builtin signature verification + userspace policy
78+
79+
fs-verity optionally supports a simple signature verification
80+
mechanism where users can configure the kernel to require that
81+
all fs-verity files be signed by a key loaded into a keyring;
82+
see `Built-in signature verification`_.
83+
84+
* Integrity Measurement Architecture (IMA)
85+
86+
IMA supports including fs-verity file digests and signatures in the
87+
IMA measurement list and verifying fs-verity based file signatures
88+
stored as security.ima xattrs, based on policy.
89+
7990

8091
User API
8192
========
@@ -653,12 +664,12 @@ weren't already directly answered in other parts of this document.
653664
hashed and what to do with those hashes, such as log them,
654665
authenticate them, or add them to a measurement list.
655666

656-
IMA is planned to support the fs-verity hashing mechanism as an
657-
alternative to doing full file hashes, for people who want the
658-
performance and security benefits of the Merkle tree based hash.
659-
But it doesn't make sense to force all uses of fs-verity to be
660-
through IMA. As a standalone filesystem feature, fs-verity
661-
already meets many users' needs, and it's testable like other
667+
IMA supports the fs-verity hashing mechanism as an alternative
668+
to full file hashes, for those who want the performance and
669+
security benefits of the Merkle tree based hash. However, it
670+
doesn't make sense to force all uses of fs-verity to be through
671+
IMA. fs-verity already meets many users' needs even as a
672+
standalone filesystem feature, and it's testable like other
662673
filesystem features e.g. with xfstests.
663674

664675
:Q: Isn't fs-verity useless because the attacker can just modify the

Documentation/security/IMA-templates.rst

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -66,12 +66,13 @@ descriptors by adding their identifier to the format string
6666
calculated with the SHA1 or MD5 hash algorithm;
6767
- 'n': the name of the event (i.e. the file name), with size up to 255 bytes;
6868
- 'd-ng': the digest of the event, calculated with an arbitrary hash
69-
algorithm (field format: [<hash algo>:]digest, where the digest
70-
prefix is shown only if the hash algorithm is not SHA1 or MD5);
69+
algorithm (field format: <hash algo>:digest);
70+
- 'd-ngv2': same as d-ng, but prefixed with the "ima" or "verity" digest type
71+
(field format: <digest type>:<hash algo>:digest);
7172
- 'd-modsig': the digest of the event without the appended modsig;
7273
- 'n-ng': the name of the event, without size limitations;
73-
- 'sig': the file signature, or the EVM portable signature if the file
74-
signature is not found;
74+
- 'sig': the file signature, based on either the file's/fsverity's digest[1],
75+
or the EVM portable signature, if 'security.ima' contains a file hash.
7576
- 'modsig' the appended file signature;
7677
- 'buf': the buffer data that was used to generate the hash without size limitations;
7778
- 'evmsig': the EVM portable signature;
@@ -88,7 +89,9 @@ Below, there is the list of defined template descriptors:
8889

8990
- "ima": its format is ``d|n``;
9091
- "ima-ng" (default): its format is ``d-ng|n-ng``;
92+
- "ima-ngv2": its format is ``d-ngv2|n-ng``;
9193
- "ima-sig": its format is ``d-ng|n-ng|sig``;
94+
- "ima-sigv2": its format is ``d-ngv2|n-ng|sig``;
9295
- "ima-buf": its format is ``d-ng|n-ng|buf``;
9396
- "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``;
9497
- "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;

fs/verity/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
config FS_VERITY
44
bool "FS Verity (read-only file-based authenticity protection)"
55
select CRYPTO
6+
select CRYPTO_HASH_INFO
67
# SHA-256 is implied as it's intended to be the default hash algorithm.
78
# To avoid bloat, other wanted algorithms must be selected explicitly.
89
# Note that CRYPTO_SHA256 denotes the generic C implementation, but

fs/verity/fsverity_private.h

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414

1515
#define pr_fmt(fmt) "fs-verity: " fmt
1616

17-
#include <crypto/sha2.h>
1817
#include <linux/fsverity.h>
1918
#include <linux/mempool.h>
2019

@@ -26,12 +25,6 @@ struct ahash_request;
2625
*/
2726
#define FS_VERITY_MAX_LEVELS 8
2827

29-
/*
30-
* Largest digest size among all hash algorithms supported by fs-verity.
31-
* Currently assumed to be <= size of fsverity_descriptor::root_hash.
32-
*/
33-
#define FS_VERITY_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
34-
3528
/* A hash algorithm supported by fs-verity */
3629
struct fsverity_hash_alg {
3730
struct crypto_ahash *tfm; /* hash tfm, allocated on demand */

fs/verity/measure.c

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,3 +57,46 @@ int fsverity_ioctl_measure(struct file *filp, void __user *_uarg)
5757
return 0;
5858
}
5959
EXPORT_SYMBOL_GPL(fsverity_ioctl_measure);
60+
61+
/**
62+
* fsverity_get_digest() - get a verity file's digest
63+
* @inode: inode to get digest of
64+
* @digest: (out) pointer to the digest
65+
* @alg: (out) pointer to the hash algorithm enumeration
66+
*
67+
* Return the file hash algorithm and digest of an fsverity protected file.
68+
* Assumption: before calling fsverity_get_digest(), the file must have been
69+
* opened.
70+
*
71+
* Return: 0 on success, -errno on failure
72+
*/
73+
int fsverity_get_digest(struct inode *inode,
74+
u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
75+
enum hash_algo *alg)
76+
{
77+
const struct fsverity_info *vi;
78+
const struct fsverity_hash_alg *hash_alg;
79+
int i;
80+
81+
vi = fsverity_get_info(inode);
82+
if (!vi)
83+
return -ENODATA; /* not a verity file */
84+
85+
hash_alg = vi->tree_params.hash_alg;
86+
memset(digest, 0, FS_VERITY_MAX_DIGEST_SIZE);
87+
88+
/* convert the verity hash algorithm name to a hash_algo_name enum */
89+
i = match_string(hash_algo_name, HASH_ALGO__LAST, hash_alg->name);
90+
if (i < 0)
91+
return -EINVAL;
92+
*alg = i;
93+
94+
if (WARN_ON_ONCE(hash_alg->digest_size != hash_digest_size[*alg]))
95+
return -EINVAL;
96+
memcpy(digest, vi->file_digest, hash_alg->digest_size);
97+
98+
pr_debug("file digest %s:%*phN\n", hash_algo_name[*alg],
99+
hash_digest_size[*alg], digest);
100+
101+
return 0;
102+
}

include/linux/fsverity.h

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,16 @@
1212
#define _LINUX_FSVERITY_H
1313

1414
#include <linux/fs.h>
15+
#include <crypto/hash_info.h>
16+
#include <crypto/sha2.h>
1517
#include <uapi/linux/fsverity.h>
1618

19+
/*
20+
* Largest digest size among all hash algorithms supported by fs-verity.
21+
* Currently assumed to be <= size of fsverity_descriptor::root_hash.
22+
*/
23+
#define FS_VERITY_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE
24+
1725
/* Verity operations for filesystems */
1826
struct fsverity_operations {
1927

@@ -131,6 +139,9 @@ int fsverity_ioctl_enable(struct file *filp, const void __user *arg);
131139
/* measure.c */
132140

133141
int fsverity_ioctl_measure(struct file *filp, void __user *arg);
142+
int fsverity_get_digest(struct inode *inode,
143+
u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
144+
enum hash_algo *alg);
134145

135146
/* open.c */
136147

@@ -170,6 +181,13 @@ static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg)
170181
return -EOPNOTSUPP;
171182
}
172183

184+
static inline int fsverity_get_digest(struct inode *inode,
185+
u8 digest[FS_VERITY_MAX_DIGEST_SIZE],
186+
enum hash_algo *alg)
187+
{
188+
return -EOPNOTSUPP;
189+
}
190+
173191
/* open.c */
174192

175193
static inline int fsverity_file_open(struct inode *inode, struct file *filp)

security/integrity/digsig.c

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -75,7 +75,8 @@ int integrity_digsig_verify(const unsigned int id, const char *sig, int siglen,
7575
/* v1 API expect signature without xattr type */
7676
return digsig_verify(keyring, sig + 1, siglen - 1, digest,
7777
digestlen);
78-
case 2:
78+
case 2: /* regular file data hash based signature */
79+
case 3: /* struct ima_file_id data based signature */
7980
return asymmetric_verify(keyring, sig, siglen, digest,
8081
digestlen);
8182
}

security/integrity/ima/ima_api.c

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#include <linux/xattr.h>
1515
#include <linux/evm.h>
1616
#include <linux/iversion.h>
17+
#include <linux/fsverity.h>
1718

1819
#include "ima.h"
1920

@@ -200,6 +201,32 @@ int ima_get_action(struct user_namespace *mnt_userns, struct inode *inode,
200201
allowed_algos);
201202
}
202203

204+
static int ima_get_verity_digest(struct integrity_iint_cache *iint,
205+
struct ima_max_digest_data *hash)
206+
{
207+
enum hash_algo verity_alg;
208+
int ret;
209+
210+
/*
211+
* On failure, 'measure' policy rules will result in a file data
212+
* hash containing 0's.
213+
*/
214+
ret = fsverity_get_digest(iint->inode, hash->digest, &verity_alg);
215+
if (ret)
216+
return ret;
217+
218+
/*
219+
* Unlike in the case of actually calculating the file hash, in
220+
* the fsverity case regardless of the hash algorithm, return
221+
* the verity digest to be included in the measurement list. A
222+
* mismatch between the verity algorithm and the xattr signature
223+
* algorithm, if one exists, will be detected later.
224+
*/
225+
hash->hdr.algo = verity_alg;
226+
hash->hdr.length = hash_digest_size[verity_alg];
227+
return 0;
228+
}
229+
203230
/*
204231
* ima_collect_measurement - collect file measurement
205232
*
@@ -242,16 +269,30 @@ int ima_collect_measurement(struct integrity_iint_cache *iint,
242269
*/
243270
i_version = inode_query_iversion(inode);
244271
hash.hdr.algo = algo;
272+
hash.hdr.length = hash_digest_size[algo];
245273

246274
/* Initialize hash digest to 0's in case of failure */
247275
memset(&hash.digest, 0, sizeof(hash.digest));
248276

249-
if (buf)
277+
if (iint->flags & IMA_VERITY_REQUIRED) {
278+
result = ima_get_verity_digest(iint, &hash);
279+
switch (result) {
280+
case 0:
281+
break;
282+
case -ENODATA:
283+
audit_cause = "no-verity-digest";
284+
break;
285+
default:
286+
audit_cause = "invalid-verity-digest";
287+
break;
288+
}
289+
} else if (buf) {
250290
result = ima_calc_buffer_hash(buf, size, &hash.hdr);
251-
else
291+
} else {
252292
result = ima_calc_file_hash(file, &hash.hdr);
293+
}
253294

254-
if (result && result != -EBADF && result != -EINVAL)
295+
if (result == -ENOMEM)
255296
goto out;
256297

257298
length = sizeof(hash.hdr) + hash.hdr.length;

0 commit comments

Comments
 (0)