Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Merge tag 'integrity-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity

Pull IMA updates from Mimi Zohar:
"New is IMA 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, both based on policy.

In addition, are two bug fixes:

- avoid reading UEFI variables, which cause a page fault, on Apple
Macs with T2 chips.

- remove the original "ima" template Kconfig option to address a boot
command line ordering issue.

The rest is a mixture of code/documentation cleanup"

* tag 'integrity-v5.19' of git://git.kernel.org/pub/scm/linux/kernel/git/zohar/linux-integrity:
integrity: Fix sparse warnings in keyring_handler
evm: Clean up some variables
evm: Return INTEGRITY_PASS for enum integrity_status value '0'
efi: Do not import certificates from UEFI Secure Boot for T2 Macs
fsverity: update the documentation
ima: support fs-verity file digest based version 3 signatures
ima: permit fsverity's file digests in the IMA measurement list
ima: define a new template field named 'd-ngv2' and templates
fs-verity: define a function to return the integrity protected file digest
ima: use IMA default hash algorithm for integrity violations
ima: fix 'd-ng' comments and documentation
ima: remove the IMA_TEMPLATE Kconfig option
ima: remove redundant initialization of pointer 'file'.

+533 -81
+42 -3
Documentation/ABI/testing/ima_policy
··· 27 27 [fowner=] [fgroup=]] 28 28 lsm: [[subj_user=] [subj_role=] [subj_type=] 29 29 [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=] 32 33 base: 33 34 func:= [BPRM_CHECK][MMAP_CHECK][CREDS_CHECK][FILE_CHECK][MODULE_CHECK] 34 35 [FIRMWARE_CHECK] ··· 48 47 fgroup:= decimal value 49 48 lsm: are LSM specific 50 49 option: 51 - appraise_type:= [imasig] [imasig|modsig] 50 + appraise_type:= [imasig] | [imasig|modsig] | [sigv3] 51 + where 'imasig' is the original or the signature 52 + format v2. 53 + where 'modsig' is an appended signature, 54 + where 'sigv3' is the signature format v3. (Currently 55 + limited to fsverity digest based signatures 56 + stored in security.ima xattr. Requires 57 + specifying "digest_type=verity" first.) 58 + 52 59 appraise_flag:= [check_blacklist] 53 60 Currently, blacklist check is only for files signed with appended 54 61 signature. 62 + digest_type:= verity 63 + Require fs-verity's file digest instead of the 64 + regular IMA file hash. 55 65 keyrings:= list of keyrings 56 66 (eg, .builtin_trusted_keys|.ima). Only valid 57 67 when action is "measure" and func is KEY_CHECK. ··· 161 149 security.ima xattr of a file: 162 150 163 151 appraise func=SETXATTR_CHECK appraise_algos=sha256,sha384,sha512 152 + 153 + Example of a 'measure' rule requiring fs-verity's digests 154 + with indication of type of digest in the measurement list. 155 + 156 + measure func=FILE_CHECK digest_type=verity \ 157 + template=ima-ngv2 158 + 159 + Example of 'measure' and 'appraise' rules requiring fs-verity 160 + signatures (format version 3) stored in security.ima xattr. 161 + 162 + The 'measure' rule specifies the 'ima-sigv3' template option, 163 + which includes the indication of type of digest and the file 164 + signature in the measurement list. 165 + 166 + measure func=BPRM_CHECK digest_type=verity \ 167 + template=ima-sigv3 168 + 169 + 170 + The 'appraise' rule specifies the type and signature format 171 + version (sigv3) required. 172 + 173 + appraise func=BPRM_CHECK digest_type=verity \ 174 + appraise_type=sigv3 175 + 176 + All of these policy rules could, for example, be constrained 177 + either based on a filesystem's UUID (fsuuid) or based on LSM 178 + labels.
+2 -1
Documentation/admin-guide/kernel-parameters.txt
··· 1914 1914 1915 1915 ima_template= [IMA] 1916 1916 Select one of defined IMA measurements template formats. 1917 - Formats: { "ima" | "ima-ng" | "ima-sig" } 1917 + Formats: { "ima" | "ima-ng" | "ima-ngv2" | "ima-sig" | 1918 + "ima-sigv2" } 1918 1919 Default: "ima-ng" 1919 1920 1920 1921 ima_template_fmt=
+23 -12
Documentation/filesystems/fsverity.rst
··· 70 70 updated and potentially user-installed, so dm-verity cannot be used. 71 71 72 72 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 + 79 90 80 91 User API 81 92 ======== ··· 664 653 hashed and what to do with those hashes, such as log them, 665 654 authenticate them, or add them to a measurement list. 666 655 667 - IMA is planned to support the fs-verity hashing mechanism as an 668 - alternative to doing full file hashes, for people who want the 669 - performance and security benefits of the Merkle tree based hash. 670 - But it doesn't make sense to force all uses of fs-verity to be 671 - through IMA. As a standalone filesystem feature, fs-verity 672 - already meets many users' needs, and it's testable like other 656 + IMA supports the fs-verity hashing mechanism as an alternative 657 + to full file hashes, for those who want the performance and 658 + security benefits of the Merkle tree based hash. However, it 659 + doesn't make sense to force all uses of fs-verity to be through 660 + IMA. fs-verity already meets many users' needs even as a 661 + standalone filesystem feature, and it's testable like other 673 662 filesystem features e.g. with xfstests. 674 663 675 664 :Q: Isn't fs-verity useless because the attacker can just modify the
+7 -4
Documentation/security/IMA-templates.rst
··· 66 66 calculated with the SHA1 or MD5 hash algorithm; 67 67 - 'n': the name of the event (i.e. the file name), with size up to 255 bytes; 68 68 - '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); 71 72 - 'd-modsig': the digest of the event without the appended modsig; 72 73 - '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. 75 76 - 'modsig' the appended file signature; 76 77 - 'buf': the buffer data that was used to generate the hash without size limitations; 77 78 - 'evmsig': the EVM portable signature; ··· 89 88 90 89 - "ima": its format is ``d|n``; 91 90 - "ima-ng" (default): its format is ``d-ng|n-ng``; 91 + - "ima-ngv2": its format is ``d-ngv2|n-ng``; 92 92 - "ima-sig": its format is ``d-ng|n-ng|sig``; 93 + - "ima-sigv2": its format is ``d-ngv2|n-ng|sig``; 93 94 - "ima-buf": its format is ``d-ng|n-ng|buf``; 94 95 - "ima-modsig": its format is ``d-ng|n-ng|sig|d-modsig|modsig``; 95 96 - "evm-sig": its format is ``d-ng|n-ng|evmsig|xattrnames|xattrlengths|xattrvalues|iuid|igid|imode``;
+1
fs/verity/Kconfig
··· 3 3 config FS_VERITY 4 4 bool "FS Verity (read-only file-based authenticity protection)" 5 5 select CRYPTO 6 + select CRYPTO_HASH_INFO 6 7 # SHA-256 is implied as it's intended to be the default hash algorithm. 7 8 # To avoid bloat, other wanted algorithms must be selected explicitly. 8 9 # Note that CRYPTO_SHA256 denotes the generic C implementation, but
-7
fs/verity/fsverity_private.h
··· 14 14 15 15 #define pr_fmt(fmt) "fs-verity: " fmt 16 16 17 - #include <crypto/sha2.h> 18 17 #include <linux/fsverity.h> 19 18 #include <linux/mempool.h> 20 19 ··· 24 25 * it's enough for over U64_MAX bytes of data using SHA-256 and 4K blocks. 25 26 */ 26 27 #define FS_VERITY_MAX_LEVELS 8 27 - 28 - /* 29 - * Largest digest size among all hash algorithms supported by fs-verity. 30 - * Currently assumed to be <= size of fsverity_descriptor::root_hash. 31 - */ 32 - #define FS_VERITY_MAX_DIGEST_SIZE SHA512_DIGEST_SIZE 33 28 34 29 /* A hash algorithm supported by fs-verity */ 35 30 struct fsverity_hash_alg {
+43
fs/verity/measure.c
··· 57 57 return 0; 58 58 } 59 59 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 + }
+18
include/linux/fsverity.h
··· 12 12 #define _LINUX_FSVERITY_H 13 13 14 14 #include <linux/fs.h> 15 + #include <crypto/hash_info.h> 16 + #include <crypto/sha2.h> 15 17 #include <uapi/linux/fsverity.h> 18 + 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 16 24 17 25 /* Verity operations for filesystems */ 18 26 struct fsverity_operations { ··· 139 131 /* measure.c */ 140 132 141 133 int fsverity_ioctl_measure(struct file *filp, void __user *arg); 134 + int fsverity_get_digest(struct inode *inode, 135 + u8 digest[FS_VERITY_MAX_DIGEST_SIZE], 136 + enum hash_algo *alg); 142 137 143 138 /* open.c */ 144 139 ··· 177 166 /* measure.c */ 178 167 179 168 static inline int fsverity_ioctl_measure(struct file *filp, void __user *arg) 169 + { 170 + return -EOPNOTSUPP; 171 + } 172 + 173 + static inline int fsverity_get_digest(struct inode *inode, 174 + u8 digest[FS_VERITY_MAX_DIGEST_SIZE], 175 + enum hash_algo *alg) 180 176 { 181 177 return -EOPNOTSUPP; 182 178 }
+2 -1
security/integrity/digsig.c
··· 75 75 /* v1 API expect signature without xattr type */ 76 76 return digsig_verify(keyring, sig + 1, siglen - 1, digest, 77 77 digestlen); 78 - case 2: 78 + case 2: /* regular file data hash based signature */ 79 + case 3: /* struct ima_file_id data based signature */ 79 80 return asymmetric_verify(keyring, sig, siglen, digest, 80 81 digestlen); 81 82 }
-3
security/integrity/evm/evm.h
··· 38 38 39 39 extern int evm_hmac_attrs; 40 40 41 - extern struct crypto_shash *hmac_tfm; 42 - extern struct crypto_shash *hash_tfm; 43 - 44 41 /* List of EVM protected security xattrs */ 45 42 extern struct list_head evm_config_xattrnames; 46 43
+1 -1
security/integrity/evm/evm_crypto.c
··· 26 26 static unsigned char evmkey[MAX_KEY_SIZE]; 27 27 static const int evmkey_len = MAX_KEY_SIZE; 28 28 29 - struct crypto_shash *hmac_tfm; 29 + static struct crypto_shash *hmac_tfm; 30 30 static struct crypto_shash *evm_tfm[HASH_ALGO__LAST]; 31 31 32 32 static DEFINE_MUTEX(mutex);
+1 -1
security/integrity/evm/evm_main.c
··· 436 436 struct inode *inode = d_backing_inode(dentry); 437 437 438 438 if (!evm_key_loaded() || !S_ISREG(inode->i_mode) || evm_fixmode) 439 - return 0; 439 + return INTEGRITY_PASS; 440 440 return evm_verify_hmac(dentry, NULL, NULL, 0, NULL); 441 441 } 442 442
+6 -8
security/integrity/ima/Kconfig
··· 69 69 hash, defined as 20 bytes, and a null terminated pathname, 70 70 limited to 255 characters. The 'ima-ng' measurement list 71 71 template permits both larger hash digests and longer 72 - pathnames. 72 + pathnames. The configured default template can be replaced 73 + by specifying "ima_template=" on the boot command line. 73 74 74 - config IMA_TEMPLATE 75 - bool "ima" 76 75 config IMA_NG_TEMPLATE 77 76 bool "ima-ng (default)" 78 77 config IMA_SIG_TEMPLATE ··· 81 82 config IMA_DEFAULT_TEMPLATE 82 83 string 83 84 depends on IMA 84 - default "ima" if IMA_TEMPLATE 85 85 default "ima-ng" if IMA_NG_TEMPLATE 86 86 default "ima-sig" if IMA_SIG_TEMPLATE 87 87 ··· 100 102 101 103 config IMA_DEFAULT_HASH_SHA256 102 104 bool "SHA256" 103 - depends on CRYPTO_SHA256=y && !IMA_TEMPLATE 105 + depends on CRYPTO_SHA256=y 104 106 105 107 config IMA_DEFAULT_HASH_SHA512 106 108 bool "SHA512" 107 - depends on CRYPTO_SHA512=y && !IMA_TEMPLATE 109 + depends on CRYPTO_SHA512=y 108 110 109 111 config IMA_DEFAULT_HASH_WP512 110 112 bool "WP512" 111 - depends on CRYPTO_WP512=y && !IMA_TEMPLATE 113 + depends on CRYPTO_WP512=y 112 114 113 115 config IMA_DEFAULT_HASH_SM3 114 116 bool "SM3" 115 - depends on CRYPTO_SM3=y && !IMA_TEMPLATE 117 + depends on CRYPTO_SM3=y 116 118 endchoice 117 119 118 120 config IMA_DEFAULT_HASH
+44 -3
security/integrity/ima/ima_api.c
··· 14 14 #include <linux/xattr.h> 15 15 #include <linux/evm.h> 16 16 #include <linux/iversion.h> 17 + #include <linux/fsverity.h> 17 18 18 19 #include "ima.h" 19 20 ··· 201 200 allowed_algos); 202 201 } 203 202 203 + static int ima_get_verity_digest(struct integrity_iint_cache *iint, 204 + struct ima_max_digest_data *hash) 205 + { 206 + enum hash_algo verity_alg; 207 + int ret; 208 + 209 + /* 210 + * On failure, 'measure' policy rules will result in a file data 211 + * hash containing 0's. 212 + */ 213 + ret = fsverity_get_digest(iint->inode, hash->digest, &verity_alg); 214 + if (ret) 215 + return ret; 216 + 217 + /* 218 + * Unlike in the case of actually calculating the file hash, in 219 + * the fsverity case regardless of the hash algorithm, return 220 + * the verity digest to be included in the measurement list. A 221 + * mismatch between the verity algorithm and the xattr signature 222 + * algorithm, if one exists, will be detected later. 223 + */ 224 + hash->hdr.algo = verity_alg; 225 + hash->hdr.length = hash_digest_size[verity_alg]; 226 + return 0; 227 + } 228 + 204 229 /* 205 230 * ima_collect_measurement - collect file measurement 206 231 * ··· 269 242 */ 270 243 i_version = inode_query_iversion(inode); 271 244 hash.hdr.algo = algo; 245 + hash.hdr.length = hash_digest_size[algo]; 272 246 273 247 /* Initialize hash digest to 0's in case of failure */ 274 248 memset(&hash.digest, 0, sizeof(hash.digest)); 275 249 276 - if (buf) 250 + if (iint->flags & IMA_VERITY_REQUIRED) { 251 + result = ima_get_verity_digest(iint, &hash); 252 + switch (result) { 253 + case 0: 254 + break; 255 + case -ENODATA: 256 + audit_cause = "no-verity-digest"; 257 + break; 258 + default: 259 + audit_cause = "invalid-verity-digest"; 260 + break; 261 + } 262 + } else if (buf) { 277 263 result = ima_calc_buffer_hash(buf, size, &hash.hdr); 278 - else 264 + } else { 279 265 result = ima_calc_file_hash(file, &hash.hdr); 266 + } 280 267 281 - if (result && result != -EBADF && result != -EINVAL) 268 + if (result == -ENOMEM) 282 269 goto out; 283 270 284 271 length = sizeof(hash.hdr) + hash.hdr.length;
+110 -4
security/integrity/ima/ima_appraise.c
··· 13 13 #include <linux/magic.h> 14 14 #include <linux/ima.h> 15 15 #include <linux/evm.h> 16 + #include <linux/fsverity.h> 16 17 #include <keys/system_keyring.h> 18 + #include <uapi/linux/fsverity.h> 17 19 18 20 #include "ima.h" 19 21 ··· 185 183 return ima_hash_algo; 186 184 187 185 switch (xattr_value->type) { 186 + case IMA_VERITY_DIGSIG: 187 + sig = (typeof(sig))xattr_value; 188 + if (sig->version != 3 || xattr_len <= sizeof(*sig) || 189 + sig->hash_algo >= HASH_ALGO__LAST) 190 + return ima_hash_algo; 191 + return sig->hash_algo; 188 192 case EVM_IMA_XATTR_DIGSIG: 189 193 sig = (typeof(sig))xattr_value; 190 194 if (sig->version != 2 || xattr_len <= sizeof(*sig) 191 195 || sig->hash_algo >= HASH_ALGO__LAST) 192 196 return ima_hash_algo; 193 197 return sig->hash_algo; 194 - break; 195 198 case IMA_XATTR_DIGEST_NG: 196 199 /* first byte contains algorithm id */ 197 200 ret = xattr_value->data[0]; ··· 233 226 } 234 227 235 228 /* 229 + * calc_file_id_hash - calculate the hash of the ima_file_id struct data 230 + * @type: xattr type [enum evm_ima_xattr_type] 231 + * @algo: hash algorithm [enum hash_algo] 232 + * @digest: pointer to the digest to be hashed 233 + * @hash: (out) pointer to the hash 234 + * 235 + * IMA signature version 3 disambiguates the data that is signed by 236 + * indirectly signing the hash of the ima_file_id structure data. 237 + * 238 + * Signing the ima_file_id struct is currently only supported for 239 + * IMA_VERITY_DIGSIG type xattrs. 240 + * 241 + * Return 0 on success, error code otherwise. 242 + */ 243 + static int calc_file_id_hash(enum evm_ima_xattr_type type, 244 + enum hash_algo algo, const u8 *digest, 245 + struct ima_digest_data *hash) 246 + { 247 + struct ima_file_id file_id = { 248 + .hash_type = IMA_VERITY_DIGSIG, .hash_algorithm = algo}; 249 + unsigned int unused = HASH_MAX_DIGESTSIZE - hash_digest_size[algo]; 250 + 251 + if (type != IMA_VERITY_DIGSIG) 252 + return -EINVAL; 253 + 254 + memcpy(file_id.hash, digest, hash_digest_size[algo]); 255 + 256 + hash->algo = algo; 257 + hash->length = hash_digest_size[algo]; 258 + 259 + return ima_calc_buffer_hash(&file_id, sizeof(file_id) - unused, hash); 260 + } 261 + 262 + /* 236 263 * xattr_verify - verify xattr digest or signature 237 264 * 238 265 * Verify whether the hash or signature matches the file contents. ··· 277 236 struct evm_ima_xattr_data *xattr_value, int xattr_len, 278 237 enum integrity_status *status, const char **cause) 279 238 { 239 + struct ima_max_digest_data hash; 240 + struct signature_v2_hdr *sig; 280 241 int rc = -EINVAL, hash_start = 0; 242 + int mask; 281 243 282 244 switch (xattr_value->type) { 283 245 case IMA_XATTR_DIGEST_NG: ··· 290 246 case IMA_XATTR_DIGEST: 291 247 if (*status != INTEGRITY_PASS_IMMUTABLE) { 292 248 if (iint->flags & IMA_DIGSIG_REQUIRED) { 293 - *cause = "IMA-signature-required"; 249 + if (iint->flags & IMA_VERITY_REQUIRED) 250 + *cause = "verity-signature-required"; 251 + else 252 + *cause = "IMA-signature-required"; 294 253 *status = INTEGRITY_FAIL; 295 254 break; 296 255 } ··· 321 274 break; 322 275 case EVM_IMA_XATTR_DIGSIG: 323 276 set_bit(IMA_DIGSIG, &iint->atomic_flags); 277 + 278 + mask = IMA_DIGSIG_REQUIRED | IMA_VERITY_REQUIRED; 279 + if ((iint->flags & mask) == mask) { 280 + *cause = "verity-signature-required"; 281 + *status = INTEGRITY_FAIL; 282 + break; 283 + } 284 + 285 + sig = (typeof(sig))xattr_value; 286 + if (sig->version >= 3) { 287 + *cause = "invalid-signature-version"; 288 + *status = INTEGRITY_FAIL; 289 + break; 290 + } 324 291 rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 325 292 (const char *)xattr_value, 326 293 xattr_len, ··· 357 296 } else { 358 297 *status = INTEGRITY_PASS; 359 298 } 299 + break; 300 + case IMA_VERITY_DIGSIG: 301 + set_bit(IMA_DIGSIG, &iint->atomic_flags); 302 + 303 + if (iint->flags & IMA_DIGSIG_REQUIRED) { 304 + if (!(iint->flags & IMA_VERITY_REQUIRED)) { 305 + *cause = "IMA-signature-required"; 306 + *status = INTEGRITY_FAIL; 307 + break; 308 + } 309 + } 310 + 311 + sig = (typeof(sig))xattr_value; 312 + if (sig->version != 3) { 313 + *cause = "invalid-signature-version"; 314 + *status = INTEGRITY_FAIL; 315 + break; 316 + } 317 + 318 + rc = calc_file_id_hash(IMA_VERITY_DIGSIG, iint->ima_hash->algo, 319 + iint->ima_hash->digest, &hash.hdr); 320 + if (rc) { 321 + *cause = "sigv3-hashing-error"; 322 + *status = INTEGRITY_FAIL; 323 + break; 324 + } 325 + 326 + rc = integrity_digsig_verify(INTEGRITY_KEYRING_IMA, 327 + (const char *)xattr_value, 328 + xattr_len, hash.digest, 329 + hash.hdr.length); 330 + if (rc) { 331 + *cause = "invalid-verity-signature"; 332 + *status = INTEGRITY_FAIL; 333 + } else { 334 + *status = INTEGRITY_PASS; 335 + } 336 + 360 337 break; 361 338 default: 362 339 *status = INTEGRITY_UNKNOWN; ··· 495 396 if (rc && rc != -ENODATA) 496 397 goto out; 497 398 498 - cause = iint->flags & IMA_DIGSIG_REQUIRED ? 499 - "IMA-signature-required" : "missing-hash"; 399 + if (iint->flags & IMA_DIGSIG_REQUIRED) { 400 + if (iint->flags & IMA_VERITY_REQUIRED) 401 + cause = "verity-signature-required"; 402 + else 403 + cause = "IMA-signature-required"; 404 + } else { 405 + cause = "missing-hash"; 406 + } 407 + 500 408 status = INTEGRITY_NOLABEL; 501 409 if (file->f_mode & FMODE_CREATED) 502 410 iint->flags |= IMA_NEW_FILE;
+2 -2
security/integrity/ima/ima_main.c
··· 335 335 hash_algo = ima_get_hash_algo(xattr_value, xattr_len); 336 336 337 337 rc = ima_collect_measurement(iint, file, buf, size, hash_algo, modsig); 338 - if (rc != 0 && rc != -EBADF && rc != -EINVAL) 338 + if (rc == -ENOMEM) 339 339 goto out_locked; 340 340 341 341 if (!pathbuf) /* ima_rdwr_violation possibly pre-fetched */ ··· 432 432 int ima_file_mprotect(struct vm_area_struct *vma, unsigned long prot) 433 433 { 434 434 struct ima_template_desc *template = NULL; 435 - struct file *file = vma->vm_file; 435 + struct file *file; 436 436 char filename[NAME_MAX]; 437 437 char *pathbuf = NULL; 438 438 const char *pathname = NULL;
+76 -10
security/integrity/ima/ima_policy.c
··· 1023 1023 Opt_fowner_gt, Opt_fgroup_gt, 1024 1024 Opt_uid_lt, Opt_euid_lt, Opt_gid_lt, Opt_egid_lt, 1025 1025 Opt_fowner_lt, Opt_fgroup_lt, 1026 + Opt_digest_type, 1026 1027 Opt_appraise_type, Opt_appraise_flag, Opt_appraise_algos, 1027 1028 Opt_permit_directio, Opt_pcr, Opt_template, Opt_keyrings, 1028 1029 Opt_label, Opt_err ··· 1066 1065 {Opt_egid_lt, "egid<%s"}, 1067 1066 {Opt_fowner_lt, "fowner<%s"}, 1068 1067 {Opt_fgroup_lt, "fgroup<%s"}, 1068 + {Opt_digest_type, "digest_type=%s"}, 1069 1069 {Opt_appraise_type, "appraise_type=%s"}, 1070 1070 {Opt_appraise_flag, "appraise_flag=%s"}, 1071 1071 {Opt_appraise_algos, "appraise_algos=%s"}, ··· 1174 1172 #undef MSG 1175 1173 } 1176 1174 1175 + /* 1176 + * Warn if the template does not contain the given field. 1177 + */ 1178 + static void check_template_field(const struct ima_template_desc *template, 1179 + const char *field, const char *msg) 1180 + { 1181 + int i; 1182 + 1183 + for (i = 0; i < template->num_fields; i++) 1184 + if (!strcmp(template->fields[i]->field_id, field)) 1185 + return; 1186 + 1187 + pr_notice_once("%s", msg); 1188 + } 1189 + 1177 1190 static bool ima_validate_rule(struct ima_rule_entry *entry) 1178 1191 { 1179 1192 /* Ensure that the action is set and is compatible with the flags */ ··· 1231 1214 IMA_INMASK | IMA_EUID | IMA_PCR | 1232 1215 IMA_FSNAME | IMA_GID | IMA_EGID | 1233 1216 IMA_FGROUP | IMA_DIGSIG_REQUIRED | 1234 - IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS)) 1217 + IMA_PERMIT_DIRECTIO | IMA_VALIDATE_ALGOS | 1218 + IMA_VERITY_REQUIRED)) 1235 1219 return false; 1236 1220 1237 1221 break; ··· 1308 1290 /* Ensure that combinations of flags are compatible with each other */ 1309 1291 if (entry->flags & IMA_CHECK_BLACKLIST && 1310 1292 !(entry->flags & IMA_MODSIG_ALLOWED)) 1293 + return false; 1294 + 1295 + /* 1296 + * Unlike for regular IMA 'appraise' policy rules where security.ima 1297 + * xattr may contain either a file hash or signature, the security.ima 1298 + * xattr for fsverity must contain a file signature (sigv3). Ensure 1299 + * that 'appraise' rules for fsverity require file signatures by 1300 + * checking the IMA_DIGSIG_REQUIRED flag is set. 1301 + */ 1302 + if (entry->action == APPRAISE && 1303 + (entry->flags & IMA_VERITY_REQUIRED) && 1304 + !(entry->flags & IMA_DIGSIG_REQUIRED)) 1311 1305 return false; 1312 1306 1313 1307 return true; ··· 1737 1707 LSM_SUBJ_TYPE, 1738 1708 AUDIT_SUBJ_TYPE); 1739 1709 break; 1740 - case Opt_appraise_type: 1741 - ima_log_string(ab, "appraise_type", args[0].from); 1742 - if ((strcmp(args[0].from, "imasig")) == 0) 1743 - entry->flags |= IMA_DIGSIG_REQUIRED; 1744 - else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) && 1745 - strcmp(args[0].from, "imasig|modsig") == 0) 1746 - entry->flags |= IMA_DIGSIG_REQUIRED | 1747 - IMA_MODSIG_ALLOWED; 1710 + case Opt_digest_type: 1711 + ima_log_string(ab, "digest_type", args[0].from); 1712 + if (entry->flags & IMA_DIGSIG_REQUIRED) 1713 + result = -EINVAL; 1714 + else if ((strcmp(args[0].from, "verity")) == 0) 1715 + entry->flags |= IMA_VERITY_REQUIRED; 1748 1716 else 1749 1717 result = -EINVAL; 1718 + break; 1719 + case Opt_appraise_type: 1720 + ima_log_string(ab, "appraise_type", args[0].from); 1721 + 1722 + if ((strcmp(args[0].from, "imasig")) == 0) { 1723 + if (entry->flags & IMA_VERITY_REQUIRED) 1724 + result = -EINVAL; 1725 + else 1726 + entry->flags |= IMA_DIGSIG_REQUIRED; 1727 + } else if (strcmp(args[0].from, "sigv3") == 0) { 1728 + /* Only fsverity supports sigv3 for now */ 1729 + if (entry->flags & IMA_VERITY_REQUIRED) 1730 + entry->flags |= IMA_DIGSIG_REQUIRED; 1731 + else 1732 + result = -EINVAL; 1733 + } else if (IS_ENABLED(CONFIG_IMA_APPRAISE_MODSIG) && 1734 + strcmp(args[0].from, "imasig|modsig") == 0) { 1735 + if (entry->flags & IMA_VERITY_REQUIRED) 1736 + result = -EINVAL; 1737 + else 1738 + entry->flags |= IMA_DIGSIG_REQUIRED | 1739 + IMA_MODSIG_ALLOWED; 1740 + } else { 1741 + result = -EINVAL; 1742 + } 1750 1743 break; 1751 1744 case Opt_appraise_flag: 1752 1745 ima_log_string(ab, "appraise_flag", args[0].from); ··· 1848 1795 template_desc = entry->template ? entry->template : 1849 1796 ima_template_desc_current(); 1850 1797 check_template_modsig(template_desc); 1798 + } 1799 + 1800 + /* d-ngv2 template field recommended for unsigned fs-verity digests */ 1801 + if (!result && entry->action == MEASURE && 1802 + entry->flags & IMA_VERITY_REQUIRED) { 1803 + template_desc = entry->template ? entry->template : 1804 + ima_template_desc_current(); 1805 + check_template_field(template_desc, "d-ngv2", 1806 + "verity rules should include d-ngv2"); 1851 1807 } 1852 1808 1853 1809 audit_log_format(ab, "res=%d", !result); ··· 2211 2149 if (entry->template) 2212 2150 seq_printf(m, "template=%s ", entry->template->name); 2213 2151 if (entry->flags & IMA_DIGSIG_REQUIRED) { 2214 - if (entry->flags & IMA_MODSIG_ALLOWED) 2152 + if (entry->flags & IMA_VERITY_REQUIRED) 2153 + seq_puts(m, "appraise_type=sigv3 "); 2154 + else if (entry->flags & IMA_MODSIG_ALLOWED) 2215 2155 seq_puts(m, "appraise_type=imasig|modsig "); 2216 2156 else 2217 2157 seq_puts(m, "appraise_type=imasig "); 2218 2158 } 2159 + if (entry->flags & IMA_VERITY_REQUIRED) 2160 + seq_puts(m, "digest_type=verity "); 2219 2161 if (entry->flags & IMA_CHECK_BLACKLIST) 2220 2162 seq_puts(m, "appraise_flag=check_blacklist "); 2221 2163 if (entry->flags & IMA_PERMIT_DIRECTIO)
+4
security/integrity/ima/ima_template.c
··· 20 20 {.name = IMA_TEMPLATE_IMA_NAME, .fmt = IMA_TEMPLATE_IMA_FMT}, 21 21 {.name = "ima-ng", .fmt = "d-ng|n-ng"}, 22 22 {.name = "ima-sig", .fmt = "d-ng|n-ng|sig"}, 23 + {.name = "ima-ngv2", .fmt = "d-ngv2|n-ng"}, 24 + {.name = "ima-sigv2", .fmt = "d-ngv2|n-ng|sig"}, 23 25 {.name = "ima-buf", .fmt = "d-ng|n-ng|buf"}, 24 26 {.name = "ima-modsig", .fmt = "d-ng|n-ng|sig|d-modsig|modsig"}, 25 27 {.name = "evm-sig", ··· 40 38 .field_show = ima_show_template_string}, 41 39 {.field_id = "d-ng", .field_init = ima_eventdigest_ng_init, 42 40 .field_show = ima_show_template_digest_ng}, 41 + {.field_id = "d-ngv2", .field_init = ima_eventdigest_ngv2_init, 42 + .field_show = ima_show_template_digest_ngv2}, 43 43 {.field_id = "n-ng", .field_init = ima_eventname_ng_init, 44 44 .field_show = ima_show_template_string}, 45 45 {.field_id = "sig", .field_init = ima_eventsig_init,
+78 -16
security/integrity/ima/ima_template_lib.c
··· 24 24 enum data_formats { 25 25 DATA_FMT_DIGEST = 0, 26 26 DATA_FMT_DIGEST_WITH_ALGO, 27 + DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO, 27 28 DATA_FMT_STRING, 28 29 DATA_FMT_HEX, 29 30 DATA_FMT_UINT 31 + }; 32 + 33 + enum digest_type { 34 + DIGEST_TYPE_IMA, 35 + DIGEST_TYPE_VERITY, 36 + DIGEST_TYPE__LAST 37 + }; 38 + 39 + #define DIGEST_TYPE_NAME_LEN_MAX 7 /* including NUL */ 40 + static const char * const digest_type_name[DIGEST_TYPE__LAST] = { 41 + [DIGEST_TYPE_IMA] = "ima", 42 + [DIGEST_TYPE_VERITY] = "verity" 30 43 }; 31 44 32 45 static int ima_write_template_field_data(const void *data, const u32 datalen, ··· 85 72 u32 buflen = field_data->len; 86 73 87 74 switch (datafmt) { 75 + case DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO: 88 76 case DATA_FMT_DIGEST_WITH_ALGO: 89 - buf_ptr = strnchr(field_data->data, buflen, ':'); 77 + buf_ptr = strrchr(field_data->data, ':'); 90 78 if (buf_ptr != field_data->data) 91 79 seq_printf(m, "%s", field_data->data); 92 80 ··· 192 178 field_data); 193 179 } 194 180 181 + void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show, 182 + struct ima_field_data *field_data) 183 + { 184 + ima_show_template_field_data(m, show, 185 + DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO, 186 + field_data); 187 + } 188 + 195 189 void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 196 190 struct ima_field_data *field_data) 197 191 { ··· 287 265 } 288 266 289 267 static int ima_eventdigest_init_common(const u8 *digest, u32 digestsize, 290 - u8 hash_algo, 268 + u8 digest_type, u8 hash_algo, 291 269 struct ima_field_data *field_data) 292 270 { 293 271 /* 294 272 * digest formats: 295 273 * - DATA_FMT_DIGEST: digest 296 - * - DATA_FMT_DIGEST_WITH_ALGO: [<hash algo>] + ':' + '\0' + digest, 297 - * where <hash algo> is provided if the hash algorithm is not 298 - * SHA1 or MD5 274 + * - DATA_FMT_DIGEST_WITH_ALGO: <hash algo> + ':' + '\0' + digest, 275 + * - DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO: 276 + * <digest type> + ':' + <hash algo> + ':' + '\0' + digest, 277 + * 278 + * where 'DATA_FMT_DIGEST' is the original digest format ('d') 279 + * with a hash size limitation of 20 bytes, 280 + * where <digest type> is either "ima" or "verity", 281 + * where <hash algo> is the hash_algo_name[] string. 299 282 */ 300 - u8 buffer[CRYPTO_MAX_ALG_NAME + 2 + IMA_MAX_DIGEST_SIZE] = { 0 }; 283 + u8 buffer[DIGEST_TYPE_NAME_LEN_MAX + CRYPTO_MAX_ALG_NAME + 2 + 284 + IMA_MAX_DIGEST_SIZE] = { 0 }; 301 285 enum data_formats fmt = DATA_FMT_DIGEST; 302 286 u32 offset = 0; 303 287 304 - if (hash_algo < HASH_ALGO__LAST) { 288 + if (digest_type < DIGEST_TYPE__LAST && hash_algo < HASH_ALGO__LAST) { 289 + fmt = DATA_FMT_DIGEST_WITH_TYPE_AND_ALGO; 290 + offset += 1 + sprintf(buffer, "%s:%s:", 291 + digest_type_name[digest_type], 292 + hash_algo_name[hash_algo]); 293 + } else if (hash_algo < HASH_ALGO__LAST) { 305 294 fmt = DATA_FMT_DIGEST_WITH_ALGO; 306 - offset += snprintf(buffer, CRYPTO_MAX_ALG_NAME + 1, "%s", 307 - hash_algo_name[hash_algo]); 308 - buffer[offset] = ':'; 309 - offset += 2; 295 + offset += 1 + sprintf(buffer, "%s:", 296 + hash_algo_name[hash_algo]); 310 297 } 311 298 312 299 if (digest) ··· 390 359 cur_digestsize = hash.hdr.length; 391 360 out: 392 361 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 393 - HASH_ALGO__LAST, field_data); 362 + DIGEST_TYPE__LAST, HASH_ALGO__LAST, 363 + field_data); 394 364 } 395 365 396 366 /* ··· 400 368 int ima_eventdigest_ng_init(struct ima_event_data *event_data, 401 369 struct ima_field_data *field_data) 402 370 { 403 - u8 *cur_digest = NULL, hash_algo = HASH_ALGO_SHA1; 371 + u8 *cur_digest = NULL, hash_algo = ima_hash_algo; 404 372 u32 cur_digestsize = 0; 405 373 406 374 if (event_data->violation) /* recording a violation. */ ··· 412 380 hash_algo = event_data->iint->ima_hash->algo; 413 381 out: 414 382 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 415 - hash_algo, field_data); 383 + DIGEST_TYPE__LAST, hash_algo, 384 + field_data); 385 + } 386 + 387 + /* 388 + * This function writes the digest of an event (without size limit), 389 + * prefixed with both the digest type and hash algorithm. 390 + */ 391 + int ima_eventdigest_ngv2_init(struct ima_event_data *event_data, 392 + struct ima_field_data *field_data) 393 + { 394 + u8 *cur_digest = NULL, hash_algo = ima_hash_algo; 395 + u32 cur_digestsize = 0; 396 + u8 digest_type = DIGEST_TYPE_IMA; 397 + 398 + if (event_data->violation) /* recording a violation. */ 399 + goto out; 400 + 401 + cur_digest = event_data->iint->ima_hash->digest; 402 + cur_digestsize = event_data->iint->ima_hash->length; 403 + 404 + hash_algo = event_data->iint->ima_hash->algo; 405 + if (event_data->iint->flags & IMA_VERITY_REQUIRED) 406 + digest_type = DIGEST_TYPE_VERITY; 407 + out: 408 + return ima_eventdigest_init_common(cur_digest, cur_digestsize, 409 + digest_type, hash_algo, 410 + field_data); 416 411 } 417 412 418 413 /* ··· 474 415 } 475 416 476 417 return ima_eventdigest_init_common(cur_digest, cur_digestsize, 477 - hash_algo, field_data); 418 + DIGEST_TYPE__LAST, hash_algo, 419 + field_data); 478 420 } 479 421 480 422 static int ima_eventname_init_common(struct ima_event_data *event_data, ··· 535 475 { 536 476 struct evm_ima_xattr_data *xattr_value = event_data->xattr_value; 537 477 538 - if ((!xattr_value) || (xattr_value->type != EVM_IMA_XATTR_DIGSIG)) 478 + if (!xattr_value || 479 + (xattr_value->type != EVM_IMA_XATTR_DIGSIG && 480 + xattr_value->type != IMA_VERITY_DIGSIG)) 539 481 return ima_eventevmsig_init(event_data, field_data); 540 482 541 483 return ima_write_template_field_data(xattr_value, event_data->xattr_len,
+4
security/integrity/ima/ima_template_lib.h
··· 21 21 struct ima_field_data *field_data); 22 22 void ima_show_template_digest_ng(struct seq_file *m, enum ima_show_type show, 23 23 struct ima_field_data *field_data); 24 + void ima_show_template_digest_ngv2(struct seq_file *m, enum ima_show_type show, 25 + struct ima_field_data *field_data); 24 26 void ima_show_template_string(struct seq_file *m, enum ima_show_type show, 25 27 struct ima_field_data *field_data); 26 28 void ima_show_template_sig(struct seq_file *m, enum ima_show_type show, ··· 40 38 struct ima_field_data *field_data); 41 39 int ima_eventdigest_ng_init(struct ima_event_data *event_data, 42 40 struct ima_field_data *field_data); 41 + int ima_eventdigest_ngv2_init(struct ima_event_data *event_data, 42 + struct ima_field_data *field_data); 43 43 int ima_eventdigest_modsig_init(struct ima_event_data *event_data, 44 44 struct ima_field_data *field_data); 45 45 int ima_eventname_ng_init(struct ima_event_data *event_data,
+25 -2
security/integrity/integrity.h
··· 40 40 #define IMA_FAIL_UNVERIFIABLE_SIGS 0x10000000 41 41 #define IMA_MODSIG_ALLOWED 0x20000000 42 42 #define IMA_CHECK_BLACKLIST 0x40000000 43 + #define IMA_VERITY_REQUIRED 0x80000000 43 44 44 45 #define IMA_DO_MASK (IMA_MEASURE | IMA_APPRAISE | IMA_AUDIT | \ 45 46 IMA_HASH | IMA_APPRAISE_SUBMASK) ··· 79 78 EVM_IMA_XATTR_DIGSIG, 80 79 IMA_XATTR_DIGEST_NG, 81 80 EVM_XATTR_PORTABLE_DIGSIG, 81 + IMA_VERITY_DIGSIG, 82 82 IMA_XATTR_LAST 83 83 }; 84 84 ··· 94 92 u8 digest[SHA1_DIGEST_SIZE]; 95 93 } __packed; 96 94 97 - #define IMA_MAX_DIGEST_SIZE 64 95 + #define IMA_MAX_DIGEST_SIZE HASH_MAX_DIGESTSIZE 98 96 99 97 struct ima_digest_data { 100 98 u8 algo; ··· 123 121 } __packed; 124 122 125 123 /* 126 - * signature format v2 - for using with asymmetric keys 124 + * signature header format v2 - for using with asymmetric keys 125 + * 126 + * The signature_v2_hdr struct includes a signature format version 127 + * to simplify defining new signature formats. 128 + * 129 + * signature format: 130 + * version 2: regular file data hash based signature 131 + * version 3: struct ima_file_id data based signature 127 132 */ 128 133 struct signature_v2_hdr { 129 134 uint8_t type; /* xattr type */ ··· 139 130 __be32 keyid; /* IMA key identifier - not X509/PGP specific */ 140 131 __be16 sig_size; /* signature size */ 141 132 uint8_t sig[]; /* signature payload */ 133 + } __packed; 134 + 135 + /* 136 + * IMA signature version 3 disambiguates the data that is signed, by 137 + * indirectly signing the hash of the ima_file_id structure data, 138 + * containing either the fsverity_descriptor struct digest or, in the 139 + * future, the regular IMA file hash. 140 + * 141 + * (The hash of the ima_file_id structure is only of the portion used.) 142 + */ 143 + struct ima_file_id { 144 + __u8 hash_type; /* xattr type [enum evm_ima_xattr_type] */ 145 + __u8 hash_algorithm; /* Digest algorithm [enum hash_algo] */ 146 + __u8 hash[HASH_MAX_DIGESTSIZE]; 142 147 } __packed; 143 148 144 149 /* integrity data associated with an inode */
+3 -3
security/integrity/platform_certs/keyring_handler.c
··· 51 51 { 52 52 if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) 53 53 return add_to_platform_keyring; 54 - return 0; 54 + return NULL; 55 55 } 56 56 57 57 /* ··· 66 66 else 67 67 return add_to_platform_keyring; 68 68 } 69 - return 0; 69 + return NULL; 70 70 } 71 71 72 72 /* ··· 81 81 return uefi_blacklist_binary; 82 82 if (efi_guidcmp(*sig_type, efi_cert_x509_guid) == 0) 83 83 return uefi_revocation_list_x509; 84 - return 0; 84 + return NULL; 85 85 }
+8
security/integrity/platform_certs/keyring_handler.h
··· 35 35 efi_element_handler_t get_handler_for_dbx(const efi_guid_t *sig_type); 36 36 37 37 #endif 38 + 39 + #ifndef UEFI_QUIRK_SKIP_CERT 40 + #define UEFI_QUIRK_SKIP_CERT(vendor, product) \ 41 + .matches = { \ 42 + DMI_MATCH(DMI_BOARD_VENDOR, vendor), \ 43 + DMI_MATCH(DMI_PRODUCT_NAME, product), \ 44 + }, 45 + #endif
+33
security/integrity/platform_certs/load_uefi.c
··· 3 3 #include <linux/kernel.h> 4 4 #include <linux/sched.h> 5 5 #include <linux/cred.h> 6 + #include <linux/dmi.h> 6 7 #include <linux/err.h> 7 8 #include <linux/efi.h> 8 9 #include <linux/slab.h> ··· 12 11 #include <keys/system_keyring.h> 13 12 #include "../integrity.h" 14 13 #include "keyring_handler.h" 14 + 15 + /* 16 + * On T2 Macs reading the db and dbx efi variables to load UEFI Secure Boot 17 + * certificates causes occurrence of a page fault in Apple's firmware and 18 + * a crash disabling EFI runtime services. The following quirk skips reading 19 + * these variables. 20 + */ 21 + static const struct dmi_system_id uefi_skip_cert[] = { 22 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,1") }, 23 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,2") }, 24 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,3") }, 25 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro15,4") }, 26 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,1") }, 27 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,2") }, 28 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,3") }, 29 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookPro16,4") }, 30 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,1") }, 31 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir8,2") }, 32 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacBookAir9,1") }, 33 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacMini8,1") }, 34 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "MacPro7,1") }, 35 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,1") }, 36 + { UEFI_QUIRK_SKIP_CERT("Apple Inc.", "iMac20,2") }, 37 + { } 38 + }; 15 39 16 40 /* 17 41 * Look to see if a UEFI variable called MokIgnoreDB exists and return true if ··· 164 138 unsigned long dbsize = 0, dbxsize = 0, mokxsize = 0; 165 139 efi_status_t status; 166 140 int rc = 0; 141 + const struct dmi_system_id *dmi_id; 142 + 143 + dmi_id = dmi_first_match(uefi_skip_cert); 144 + if (dmi_id) { 145 + pr_err("Reading UEFI Secure Boot Certs is not supported on T2 Macs.\n"); 146 + return false; 147 + } 167 148 168 149 if (!efi_rt_services_supported(EFI_RT_SUPPORTED_GET_VARIABLE)) 169 150 return false;