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

Configure Feed

Select the types of activity you want to include in your feed.

certs: Allow root user to append signed hashes to the blacklist keyring

Add a kernel option SYSTEM_BLACKLIST_AUTH_UPDATE to enable the root user
to dynamically add new keys to the blacklist keyring. This enables to
invalidate new certificates, either from being loaded in a keyring, or
from being trusted in a PKCS#7 certificate chain. This also enables to
add new file hashes to be denied by the integrity infrastructure.

Being able to untrust a certificate which could have normaly been
trusted is a sensitive operation. This is why adding new hashes to the
blacklist keyring is only allowed when these hashes are signed and
vouched by the builtin trusted keyring. A blacklist hash is stored as a
key description. The PKCS#7 signature of this description must be
provided as the key payload.

Marking a certificate as untrusted should be enforced while the system
is running. It is then forbiden to remove such blacklist keys.

Update blacklist keyring, blacklist key and revoked certificate access
rights:
* allows the root user to search for a specific blacklisted hash, which
make sense because the descriptions are already viewable;
* forbids key update (blacklist and asymmetric ones);
* restricts kernel rights on the blacklist keyring to align with the
root user rights.

See help in tools/certs/print-cert-tbs-hash.sh .

Cc: David Howells <dhowells@redhat.com>
Cc: David Woodhouse <dwmw2@infradead.org>
Cc: Eric Snowberg <eric.snowberg@oracle.com>
Cc: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Mickaël Salaün <mic@linux.microsoft.com>
Link: https://lore.kernel.org/r/20210712170313.884724-6-mic@digikod.net
Reviewed-by: Jarkko Sakkinen <jarkko@kernel.org>
Tested-by: Jarkko Sakkinen <jarkko@kernel.org>
Signed-off-by: Jarkko Sakkinen <jarkko@kernel.org>

authored by

Mickaël Salaün and committed by
Jarkko Sakkinen
6364d106 addf4663

+85 -21
+10
certs/Kconfig
··· 127 127 containing X.509 certificates to be included in the default blacklist 128 128 keyring. 129 129 130 + config SYSTEM_BLACKLIST_AUTH_UPDATE 131 + bool "Allow root to add signed blacklist keys" 132 + depends on SYSTEM_BLACKLIST_KEYRING 133 + depends on SYSTEM_DATA_VERIFICATION 134 + help 135 + If set, provide the ability to load new blacklist keys at run time if 136 + they are signed and vouched by a certificate from the builtin trusted 137 + keyring. The PKCS#7 signature of the description is set in the key 138 + payload. Blacklist keys cannot be removed. 139 + 130 140 endmenu
+75 -21
certs/blacklist.c
··· 15 15 #include <linux/err.h> 16 16 #include <linux/seq_file.h> 17 17 #include <linux/uidgid.h> 18 + #include <linux/verification.h> 18 19 #include <keys/system_keyring.h> 19 20 #include "blacklist.h" 20 21 #include "common.h" ··· 26 25 * which translates into 128 hex characters. 27 26 */ 28 27 #define MAX_HASH_LEN 128 28 + 29 + #define BLACKLIST_KEY_PERM (KEY_POS_SEARCH | KEY_POS_VIEW | \ 30 + KEY_USR_SEARCH | KEY_USR_VIEW) 29 31 30 32 static const char tbs_prefix[] = "tbs"; 31 33 static const char bin_prefix[] = "bin"; ··· 84 80 return 0; 85 81 } 86 82 87 - /* 88 - * The hash to be blacklisted is expected to be in the description. There will 89 - * be no payload. 90 - */ 91 - static int blacklist_preparse(struct key_preparsed_payload *prep) 83 + static int blacklist_key_instantiate(struct key *key, 84 + struct key_preparsed_payload *prep) 92 85 { 93 - if (prep->datalen > 0) 94 - return -EINVAL; 95 - return 0; 86 + #ifdef CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE 87 + int err; 88 + #endif 89 + 90 + /* Sets safe default permissions for keys loaded by user space. */ 91 + key->perm = BLACKLIST_KEY_PERM; 92 + 93 + /* 94 + * Skips the authentication step for builtin hashes, they are not 95 + * signed but still trusted. 96 + */ 97 + if (key->flags & (1 << KEY_FLAG_BUILTIN)) 98 + goto out; 99 + 100 + #ifdef CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE 101 + /* 102 + * Verifies the description's PKCS#7 signature against the builtin 103 + * trusted keyring. 104 + */ 105 + err = verify_pkcs7_signature(key->description, 106 + strlen(key->description), prep->data, prep->datalen, 107 + NULL, VERIFYING_UNSPECIFIED_SIGNATURE, NULL, NULL); 108 + if (err) 109 + return err; 110 + #else 111 + /* 112 + * It should not be possible to come here because the keyring doesn't 113 + * have KEY_USR_WRITE and the only other way to call this function is 114 + * for builtin hashes. 115 + */ 116 + WARN_ON_ONCE(1); 117 + return -EPERM; 118 + #endif 119 + 120 + out: 121 + return generic_key_instantiate(key, prep); 96 122 } 97 123 98 - static void blacklist_free_preparse(struct key_preparsed_payload *prep) 124 + static int blacklist_key_update(struct key *key, 125 + struct key_preparsed_payload *prep) 99 126 { 127 + return -EPERM; 100 128 } 101 129 102 130 static void blacklist_describe(const struct key *key, struct seq_file *m) ··· 139 103 static struct key_type key_type_blacklist = { 140 104 .name = "blacklist", 141 105 .vet_description = blacklist_vet_description, 142 - .preparse = blacklist_preparse, 143 - .free_preparse = blacklist_free_preparse, 144 - .instantiate = generic_key_instantiate, 106 + .instantiate = blacklist_key_instantiate, 107 + .update = blacklist_key_update, 145 108 .describe = blacklist_describe, 146 109 }; 147 110 ··· 189 154 hash, 190 155 NULL, 191 156 0, 192 - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | 193 - KEY_USR_VIEW), 157 + BLACKLIST_KEY_PERM, 194 158 KEY_ALLOC_NOT_IN_QUOTA | 195 159 KEY_ALLOC_BUILT_IN); 196 160 if (IS_ERR(key)) { ··· 266 232 NULL, 267 233 data, 268 234 size, 269 - ((KEY_POS_ALL & ~KEY_POS_SETATTR) | KEY_USR_VIEW), 270 - KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN); 235 + KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH 236 + | KEY_USR_VIEW, 237 + KEY_ALLOC_NOT_IN_QUOTA | KEY_ALLOC_BUILT_IN 238 + | KEY_ALLOC_BYPASS_RESTRICTION); 271 239 272 240 if (IS_ERR(key)) { 273 241 pr_err("Problem with revocation key (%ld)\n", PTR_ERR(key)); ··· 296 260 } 297 261 #endif 298 262 263 + static int restrict_link_for_blacklist(struct key *dest_keyring, 264 + const struct key_type *type, const union key_payload *payload, 265 + struct key *restrict_key) 266 + { 267 + if (type == &key_type_blacklist) 268 + return 0; 269 + return -EOPNOTSUPP; 270 + } 271 + 299 272 /* 300 273 * Initialise the blacklist 301 274 */ 302 275 static int __init blacklist_init(void) 303 276 { 304 277 const char *const *bl; 278 + struct key_restriction *restriction; 305 279 306 280 if (register_key_type(&key_type_blacklist) < 0) 307 281 panic("Can't allocate system blacklist key type\n"); 308 282 283 + restriction = kzalloc(sizeof(*restriction), GFP_KERNEL); 284 + if (!restriction) 285 + panic("Can't allocate blacklist keyring restriction\n"); 286 + restriction->check = restrict_link_for_blacklist; 287 + 309 288 blacklist_keyring = 310 289 keyring_alloc(".blacklist", 311 290 GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, current_cred(), 312 - (KEY_POS_ALL & ~KEY_POS_SETATTR) | 313 - KEY_USR_VIEW | KEY_USR_READ | 314 - KEY_USR_SEARCH, 315 - KEY_ALLOC_NOT_IN_QUOTA | 291 + KEY_POS_VIEW | KEY_POS_READ | KEY_POS_SEARCH | 292 + KEY_POS_WRITE | 293 + KEY_USR_VIEW | KEY_USR_READ | KEY_USR_SEARCH 294 + #ifdef CONFIG_SYSTEM_BLACKLIST_AUTH_UPDATE 295 + | KEY_USR_WRITE 296 + #endif 297 + , KEY_ALLOC_NOT_IN_QUOTA | 316 298 KEY_ALLOC_SET_KEEP, 317 - NULL, NULL); 299 + restriction, NULL); 318 300 if (IS_ERR(blacklist_keyring)) 319 301 panic("Can't allocate system blacklist keyring\n"); 320 302