Pull key handling fixes from James Morris: "This includes a fix for the capabilities code from Colin King, and a set of further fixes for the keys subsystem. From David: - Fix a bunch of places where kernel drivers may access revoked user-type keys and don't do it correctly. - Fix some ecryptfs bits. - Fix big_key to require CONFIG_CRYPTO. - Fix a couple of bugs in the asymmetric key type. - Fix a race between updating and finding negative keys. - Prevent add_key() from updating uninstantiated keys. - Make loading of key flags and expiry time atomic when not holding locks" * 'fixes-v4.14-rc5' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: commoncap: move assignment of fs_ns to avoid null pointer dereference pkcs7: Prevent NULL pointer dereference, since sinfo is not always set. KEYS: load key flags and expiry time atomically in proc_keys_show() KEYS: Load key expiry time atomically in keyring_search_iterator() KEYS: load key flags and expiry time atomically in key_validate() KEYS: don't let add_key() update an uninstantiated key KEYS: Fix race between updating and finding a negative key KEYS: checking the input id parameters before finding asymmetric key KEYS: Fix the wrong index when checking the existence of second id security/keys: BIG_KEY requires CONFIG_CRYPTO ecryptfs: fix dereference of NULL user_key_payload fscrypt: fix dereference of NULL user_key_payload lib/digsig: fix dereference of NULL user_key_payload FS-Cache: fix dereference of NULL user_key_payload KEYS: encrypted: fix dereference of NULL user_key_payload
Unified · Split
| @@ -57,6 +57,8 @@ struct key *find_asymmetric_key(struct key *keyring, · 56 unmodified lines | |||
| 57 | char *req, *p; | 57 | char *req, *p; |
| 58 | int len; | 58 | int len; |
| 59 | 59 | ||
| 60 | BUG_ON(!id_0 && !id_1); | ||
| 61 | |||
| 60 | if (id_0) { | 62 | if (id_0) { |
| 61 | lookup = id_0->data; | 63 | lookup = id_0->data; |
| 62 | len = id_0->len; | 64 | len = id_0->len; |
| @@ -105,7 +107,7 @@ struct key *find_asymmetric_key(struct key *keyring, · 42 unmodified lines | |||
| 105 | if (id_0 && id_1) { | 107 | if (id_0 && id_1) { |
| 106 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); | 108 | const struct asymmetric_key_ids *kids = asymmetric_key_ids(key); |
| 107 | 109 | ||
| 108 | if (!kids->id[0]) { | 110 | if (!kids->id[1]) { |
| 109 | pr_debug("First ID matches, but second is missing\n"); | 111 | pr_debug("First ID matches, but second is missing\n"); |
| 110 | goto reject; | 112 | goto reject; |
| 111 | } | 113 | } |
| @@ -88,6 +88,9 @@ static int pkcs7_check_authattrs(struct pkcs7_message *msg) · 87 unmodified lines | |||
| 88 | bool want = false; | 88 | bool want = false; |
| 89 | 89 | ||
| 90 | sinfo = msg->signed_infos; | 90 | sinfo = msg->signed_infos; |
| 91 | if (!sinfo) | ||
| 92 | goto inconsistent; | ||
| 93 | |||
| 91 | if (sinfo->authattrs) { | 94 | if (sinfo->authattrs) { |
| 92 | want = true; | 95 | want = true; |
| 93 | msg->have_authattrs = true; | 96 | msg->have_authattrs = true; |
| @@ -109,6 +109,11 @@ static int validate_user_key(struct fscrypt_info *crypt_info, · 108 unmodified lines | |||
| 109 | goto out; | 109 | goto out; |
| 110 | } | 110 | } |
| 111 | ukp = user_key_payload_locked(keyring_key); | 111 | ukp = user_key_payload_locked(keyring_key); |
| 112 | if (!ukp) { | ||
| 113 | /* key was revoked before we acquired its semaphore */ | ||
| 114 | res = -EKEYREVOKED; | ||
| 115 | goto out; | ||
| 116 | } | ||
| 112 | if (ukp->datalen != sizeof(struct fscrypt_key)) { | 117 | if (ukp->datalen != sizeof(struct fscrypt_key)) { |
| 113 | res = -EINVAL; | 118 | res = -EINVAL; |
| 114 | goto out; | 119 | goto out; |
| @@ -84,11 +84,16 @@ struct ecryptfs_page_crypt_context { · 83 unmodified lines | |||
| 84 | static inline struct ecryptfs_auth_tok * | 84 | static inline struct ecryptfs_auth_tok * |
| 85 | ecryptfs_get_encrypted_key_payload_data(struct key *key) | 85 | ecryptfs_get_encrypted_key_payload_data(struct key *key) |
| 86 | { | 86 | { |
| 87 | if (key->type == &key_type_encrypted) | 87 | struct encrypted_key_payload *payload; |
| 88 | return (struct ecryptfs_auth_tok *) | 88 | |
| 89 | (&((struct encrypted_key_payload *)key->payload.data[0])->payload_data); | 89 | if (key->type != &key_type_encrypted) |
| 90 | else | ||
| 91 | return NULL; | 90 | return NULL; |
| 91 | |||
| 92 | payload = key->payload.data[0]; | ||
| 93 | if (!payload) | ||
| 94 | return ERR_PTR(-EKEYREVOKED); | ||
| 95 | |||
| 96 | return (struct ecryptfs_auth_tok *)payload->payload_data; | ||
| 92 | } | 97 | } |
| 93 | 98 | ||
| 94 | static inline struct key *ecryptfs_get_encrypted_key(char *sig) | 99 | static inline struct key *ecryptfs_get_encrypted_key(char *sig) |
| @@ -114,12 +119,17 @@ static inline struct ecryptfs_auth_tok * · 19 unmodified lines | |||
| 114 | ecryptfs_get_key_payload_data(struct key *key) | 119 | ecryptfs_get_key_payload_data(struct key *key) |
| 115 | { | 120 | { |
| 116 | struct ecryptfs_auth_tok *auth_tok; | 121 | struct ecryptfs_auth_tok *auth_tok; |
| 122 | struct user_key_payload *ukp; | ||
| 117 | 123 | ||
| 118 | auth_tok = ecryptfs_get_encrypted_key_payload_data(key); | 124 | auth_tok = ecryptfs_get_encrypted_key_payload_data(key); |
| 119 | if (!auth_tok) | 125 | if (auth_tok) |
| 120 | return (struct ecryptfs_auth_tok *)user_key_payload_locked(key)->data; | ||
| 121 | else | ||
| 122 | return auth_tok; | 126 | return auth_tok; |
| 127 | |||
| 128 | ukp = user_key_payload_locked(key); | ||
| 129 | if (!ukp) | ||
| 130 | return ERR_PTR(-EKEYREVOKED); | ||
| 131 | |||
| 132 | return (struct ecryptfs_auth_tok *)ukp->data; | ||
| 123 | } | 133 | } |
| 124 | 134 | ||
| 125 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 | 135 | #define ECRYPTFS_MAX_KEYSET_SIZE 1024 |
| @@ -459,7 +459,8 @@ out: · 458 unmodified lines | |||
| 459 | * @auth_tok_key: key containing the authentication token | 459 | * @auth_tok_key: key containing the authentication token |
| 460 | * @auth_tok: authentication token | 460 | * @auth_tok: authentication token |
| 461 | * | 461 | * |
| 462 | * Returns zero on valid auth tok; -EINVAL otherwise | 462 | * Returns zero on valid auth tok; -EINVAL if the payload is invalid; or |
| 463 | * -EKEYREVOKED if the key was revoked before we acquired its semaphore. | ||
| 463 | */ | 464 | */ |
| 464 | static int | 465 | static int |
| 465 | ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, | 466 | ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, |
| @@ -468,6 +469,12 @@ ecryptfs_verify_auth_tok_from_key(struct key *auth_tok_key, · 2 unmodified lines | |||
| 468 | int rc = 0; | 469 | int rc = 0; |
| 469 | 470 | ||
| 470 | (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); | 471 | (*auth_tok) = ecryptfs_get_key_payload_data(auth_tok_key); |
| 472 | if (IS_ERR(*auth_tok)) { | ||
| 473 | rc = PTR_ERR(*auth_tok); | ||
| 474 | *auth_tok = NULL; | ||
| 475 | goto out; | ||
| 476 | } | ||
| 477 | |||
| 471 | if (ecryptfs_verify_version((*auth_tok)->version)) { | 478 | if (ecryptfs_verify_version((*auth_tok)->version)) { |
| 472 | printk(KERN_ERR "Data structure version mismatch. Userspace " | 479 | printk(KERN_ERR "Data structure version mismatch. Userspace " |
| 473 | "tools must match eCryptfs kernel module with major " | 480 | "tools must match eCryptfs kernel module with major " |
| @@ -331,6 +331,13 @@ static void fscache_objlist_config(struct fscache_objlist_data *data) · 330 unmodified lines | |||
| 331 | rcu_read_lock(); | 331 | rcu_read_lock(); |
| 332 | 332 | ||
| 333 | confkey = user_key_payload_rcu(key); | 333 | confkey = user_key_payload_rcu(key); |
| 334 | if (!confkey) { | ||
| 335 | /* key was revoked */ | ||
| 336 | rcu_read_unlock(); | ||
| 337 | key_put(key); | ||
| 338 | goto no_config; | ||
| 339 | } | ||
| 340 | |||
| 334 | buf = confkey->data; | 341 | buf = confkey->data; |
| 335 | 342 | ||
| 336 | for (len = confkey->datalen - 1; len >= 0; len--) { | 343 | for (len = confkey->datalen - 1; len >= 0; len--) { |
| @@ -138,6 +138,11 @@ struct key_restriction { · 137 unmodified lines | |||
| 138 | struct key_type *keytype; | 138 | struct key_type *keytype; |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
| 141 | enum key_state { | ||
| 142 | KEY_IS_UNINSTANTIATED, | ||
| 143 | KEY_IS_POSITIVE, /* Positively instantiated */ | ||
| 144 | }; | ||
| 145 | |||
| 141 | /*****************************************************************************/ | 146 | /*****************************************************************************/ |
| 142 | /* | 147 | /* |
| 143 | * authentication token / access credential / keyring | 148 | * authentication token / access credential / keyring |
| @@ -169,6 +174,7 @@ struct key { · 25 unmodified lines | |||
| 169 | * - may not match RCU dereferenced payload | 174 | * - may not match RCU dereferenced payload |
| 170 | * - payload should contain own length | 175 | * - payload should contain own length |
| 171 | */ | 176 | */ |
| 177 | short state; /* Key state (+) or rejection error (-) */ | ||
| 172 | 178 | ||
| 173 | #ifdef KEY_DEBUGGING | 179 | #ifdef KEY_DEBUGGING |
| 174 | unsigned magic; | 180 | unsigned magic; |
| @@ -176,18 +182,16 @@ struct key { · 1 unmodified line | |||
| 176 | #endif | 182 | #endif |
| 177 | 183 | ||
| 178 | unsigned long flags; /* status flags (change with bitops) */ | 184 | unsigned long flags; /* status flags (change with bitops) */ |
| 179 | #define KEY_FLAG_INSTANTIATED 0 /* set if key has been instantiated */ | 185 | #define KEY_FLAG_DEAD 0 /* set if key type has been deleted */ |
| 180 | #define KEY_FLAG_DEAD 1 /* set if key type has been deleted */ | 186 | #define KEY_FLAG_REVOKED 1 /* set if key had been revoked */ |
| 181 | #define KEY_FLAG_REVOKED 2 /* set if key had been revoked */ | 187 | #define KEY_FLAG_IN_QUOTA 2 /* set if key consumes quota */ |
| 182 | #define KEY_FLAG_IN_QUOTA 3 /* set if key consumes quota */ | 188 | #define KEY_FLAG_USER_CONSTRUCT 3 /* set if key is being constructed in userspace */ |
| 183 | #define KEY_FLAG_USER_CONSTRUCT 4 /* set if key is being constructed in userspace */ | 189 | #define KEY_FLAG_ROOT_CAN_CLEAR 4 /* set if key can be cleared by root without permission */ |
| 184 | #define KEY_FLAG_NEGATIVE 5 /* set if key is negative */ | 190 | #define KEY_FLAG_INVALIDATED 5 /* set if key has been invalidated */ |
| 185 | #define KEY_FLAG_ROOT_CAN_CLEAR 6 /* set if key can be cleared by root without permission */ | 191 | #define KEY_FLAG_BUILTIN 6 /* set if key is built in to the kernel */ |
| 186 | #define KEY_FLAG_INVALIDATED 7 /* set if key has been invalidated */ | 192 | #define KEY_FLAG_ROOT_CAN_INVAL 7 /* set if key can be invalidated by root without permission */ |
| 187 | #define KEY_FLAG_BUILTIN 8 /* set if key is built in to the kernel */ | 193 | #define KEY_FLAG_KEEP 8 /* set if key should not be removed */ |
| 188 | #define KEY_FLAG_ROOT_CAN_INVAL 9 /* set if key can be invalidated by root without permission */ | 194 | #define KEY_FLAG_UID_KEYRING 9 /* set if key is a user or user session keyring */ |
| 189 | #define KEY_FLAG_KEEP 10 /* set if key should not be removed */ | ||
| 190 | #define KEY_FLAG_UID_KEYRING 11 /* set if key is a user or user session keyring */ | ||
| 191 | 195 | ||
| 192 | /* the key type and key description string | 196 | /* the key type and key description string |
| 193 | * - the desc is used to match a key against search criteria | 197 | * - the desc is used to match a key against search criteria |
| @@ -213,7 +217,6 @@ struct key { · 19 unmodified lines | |||
| 213 | struct list_head name_link; | 217 | struct list_head name_link; |
| 214 | struct assoc_array keys; | 218 | struct assoc_array keys; |
| 215 | }; | 219 | }; |
| 216 | int reject_error; | ||
| 217 | }; | 220 | }; |
| 218 | 221 | ||
| 219 | /* This is set on a keyring to restrict the addition of a link to a key | 222 | /* This is set on a keyring to restrict the addition of a link to a key |
| @@ -353,17 +356,27 @@ extern void key_set_timeout(struct key *, unsigned); · 133 unmodified lines | |||
| 353 | #define KEY_NEED_SETATTR 0x20 /* Require permission to change attributes */ | 356 | #define KEY_NEED_SETATTR 0x20 /* Require permission to change attributes */ |
| 354 | #define KEY_NEED_ALL 0x3f /* All the above permissions */ | 357 | #define KEY_NEED_ALL 0x3f /* All the above permissions */ |
| 355 | 358 | ||
| 359 | static inline short key_read_state(const struct key *key) | ||
| 360 | { | ||
| 361 | /* Barrier versus mark_key_instantiated(). */ | ||
| 362 | return smp_load_acquire(&key->state); | ||
| 363 | } | ||
| 364 | |||
| 356 | /** | 365 | /** |
| 357 | * key_is_instantiated - Determine if a key has been positively instantiated | 366 | * key_is_positive - Determine if a key has been positively instantiated |
| 358 | * @key: The key to check. | 367 | * @key: The key to check. |
| 359 | * | 368 | * |
| 360 | * Return true if the specified key has been positively instantiated, false | 369 | * Return true if the specified key has been positively instantiated, false |
| 361 | * otherwise. | 370 | * otherwise. |
| 362 | */ | 371 | */ |
| 363 | static inline bool key_is_instantiated(const struct key *key) | 372 | static inline bool key_is_positive(const struct key *key) |
| 373 | { | ||
| 374 | return key_read_state(key) == KEY_IS_POSITIVE; | ||
| 375 | } | ||
| 376 | |||
| 377 | static inline bool key_is_negative(const struct key *key) | ||
| 364 | { | 378 | { |
| 365 | return test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && | 379 | return key_read_state(key) < 0; |
| 366 | !test_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
| 367 | } | 380 | } |
| 368 | 381 | ||
| 369 | #define dereference_key_rcu(KEY) \ | 382 | #define dereference_key_rcu(KEY) \ |
| @@ -87,6 +87,12 @@ static int digsig_verify_rsa(struct key *key, · 86 unmodified lines | |||
| 87 | down_read(&key->sem); | 87 | down_read(&key->sem); |
| 88 | ukp = user_key_payload_locked(key); | 88 | ukp = user_key_payload_locked(key); |
| 89 | 89 | ||
| 90 | if (!ukp) { | ||
| 91 | /* key was revoked before we acquired its semaphore */ | ||
| 92 | err = -EKEYREVOKED; | ||
| 93 | goto err1; | ||
| 94 | } | ||
| 95 | |||
| 90 | if (ukp->datalen < sizeof(*pkh)) | 96 | if (ukp->datalen < sizeof(*pkh)) |
| 91 | goto err1; | 97 | goto err1; |
| 92 | 98 | ||
| @@ -224,7 +224,7 @@ static int dns_resolver_match_preparse(struct key_match_data *match_data) · 223 unmodified lines | |||
| 224 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) | 224 | static void dns_resolver_describe(const struct key *key, struct seq_file *m) |
| 225 | { | 225 | { |
| 226 | seq_puts(m, key->description); | 226 | seq_puts(m, key->description); |
| 227 | if (key_is_instantiated(key)) { | 227 | if (key_is_positive(key)) { |
| 228 | int err = PTR_ERR(key->payload.data[dns_key_error]); | 228 | int err = PTR_ERR(key->payload.data[dns_key_error]); |
| 229 | 229 | ||
| 230 | if (err) | 230 | if (err) |
| @@ -585,13 +585,14 @@ int get_vfs_caps_from_disk(const struct dentry *dentry, struct cpu_vfs_cap_data · 584 unmodified lines | |||
| 585 | struct vfs_ns_cap_data data, *nscaps = &data; | 585 | struct vfs_ns_cap_data data, *nscaps = &data; |
| 586 | struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; | 586 | struct vfs_cap_data *caps = (struct vfs_cap_data *) &data; |
| 587 | kuid_t rootkuid; | 587 | kuid_t rootkuid; |
| 588 | struct user_namespace *fs_ns = inode->i_sb->s_user_ns; | 588 | struct user_namespace *fs_ns; |
| 589 | 589 | ||
| 590 | memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); | 590 | memset(cpu_caps, 0, sizeof(struct cpu_vfs_cap_data)); |
| 591 | 591 | ||
| 592 | if (!inode) | 592 | if (!inode) |
| 593 | return -ENODATA; | 593 | return -ENODATA; |
| 594 | 594 | ||
| 595 | fs_ns = inode->i_sb->s_user_ns; | ||
| 595 | size = __vfs_getxattr((struct dentry *)dentry, inode, | 596 | size = __vfs_getxattr((struct dentry *)dentry, inode, |
| 596 | XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ); | 597 | XATTR_NAME_CAPS, &data, XATTR_CAPS_SZ); |
| 597 | if (size == -ENODATA || size == -EOPNOTSUPP) | 598 | if (size == -ENODATA || size == -EOPNOTSUPP) |
| @@ -45,6 +45,7 @@ config BIG_KEYS · 44 unmodified lines | |||
| 45 | bool "Large payload keys" | 45 | bool "Large payload keys" |
| 46 | depends on KEYS | 46 | depends on KEYS |
| 47 | depends on TMPFS | 47 | depends on TMPFS |
| 48 | select CRYPTO | ||
| 48 | select CRYPTO_AES | 49 | select CRYPTO_AES |
| 49 | select CRYPTO_GCM | 50 | select CRYPTO_GCM |
| 50 | help | 51 | help |
| @@ -247,7 +247,7 @@ void big_key_revoke(struct key *key) · 246 unmodified lines | |||
| 247 | 247 | ||
| 248 | /* clear the quota */ | 248 | /* clear the quota */ |
| 249 | key_payload_reserve(key, 0); | 249 | key_payload_reserve(key, 0); |
| 250 | if (key_is_instantiated(key) && | 250 | if (key_is_positive(key) && |
| 251 | (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD) | 251 | (size_t)key->payload.data[big_key_len] > BIG_KEY_FILE_THRESHOLD) |
| 252 | vfs_truncate(path, 0); | 252 | vfs_truncate(path, 0); |
| 253 | } | 253 | } |
| @@ -279,7 +279,7 @@ void big_key_describe(const struct key *key, struct seq_file *m) · 25 unmodified lines | |||
| 279 | 279 | ||
| 280 | seq_puts(m, key->description); | 280 | seq_puts(m, key->description); |
| 281 | 281 | ||
| 282 | if (key_is_instantiated(key)) | 282 | if (key_is_positive(key)) |
| 283 | seq_printf(m, ": %zu [%s]", | 283 | seq_printf(m, ": %zu [%s]", |
| 284 | datalen, | 284 | datalen, |
| 285 | datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); | 285 | datalen > BIG_KEY_FILE_THRESHOLD ? "file" : "buff"); |
| @@ -309,6 +309,13 @@ static struct key *request_user_key(const char *master_desc, const u8 **master_k · 308 unmodified lines | |||
| 309 | 309 | ||
| 310 | down_read(&ukey->sem); | 310 | down_read(&ukey->sem); |
| 311 | upayload = user_key_payload_locked(ukey); | 311 | upayload = user_key_payload_locked(ukey); |
| 312 | if (!upayload) { | ||
| 313 | /* key was revoked before we acquired its semaphore */ | ||
| 314 | up_read(&ukey->sem); | ||
| 315 | key_put(ukey); | ||
| 316 | ukey = ERR_PTR(-EKEYREVOKED); | ||
| 317 | goto error; | ||
| 318 | } | ||
| 312 | *master_key = upayload->data; | 319 | *master_key = upayload->data; |
| 313 | *master_keylen = upayload->datalen; | 320 | *master_keylen = upayload->datalen; |
| 314 | error: | 321 | error: |
| @@ -847,7 +854,7 @@ static int encrypted_update(struct key *key, struct key_preparsed_payload *prep) · 532 unmodified lines | |||
| 847 | size_t datalen = prep->datalen; | 854 | size_t datalen = prep->datalen; |
| 848 | int ret = 0; | 855 | int ret = 0; |
| 849 | 856 | ||
| 850 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | 857 | if (key_is_negative(key)) |
| 851 | return -ENOKEY; | 858 | return -ENOKEY; |
| 852 | if (datalen <= 0 || datalen > 32767 || !prep->data) | 859 | if (datalen <= 0 || datalen > 32767 || !prep->data) |
| 853 | return -EINVAL; | 860 | return -EINVAL; |
| @@ -129,15 +129,15 @@ static noinline void key_gc_unused_keys(struct list_head *keys) · 128 unmodified lines | |||
| 129 | while (!list_empty(keys)) { | 129 | while (!list_empty(keys)) { |
| 130 | struct key *key = | 130 | struct key *key = |
| 131 | list_entry(keys->next, struct key, graveyard_link); | 131 | list_entry(keys->next, struct key, graveyard_link); |
| 132 | short state = key->state; | ||
| 133 | |||
| 132 | list_del(&key->graveyard_link); | 134 | list_del(&key->graveyard_link); |
| 133 | 135 | ||
| 134 | kdebug("- %u", key->serial); | 136 | kdebug("- %u", key->serial); |
| 135 | key_check(key); | 137 | key_check(key); |
| 136 | 138 | ||
| 137 | /* Throw away the key data if the key is instantiated */ | 139 | /* Throw away the key data if the key is instantiated */ |
| 138 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags) && | 140 | if (state == KEY_IS_POSITIVE && key->type->destroy) |
| 139 | !test_bit(KEY_FLAG_NEGATIVE, &key->flags) && | ||
| 140 | key->type->destroy) | ||
| 141 | key->type->destroy(key); | 141 | key->type->destroy(key); |
| 142 | 142 | ||
| 143 | security_key_free(key); | 143 | security_key_free(key); |
| @@ -151,7 +151,7 @@ static noinline void key_gc_unused_keys(struct list_head *keys) · 7 unmodified lines | |||
| 151 | } | 151 | } |
| 152 | 152 | ||
| 153 | atomic_dec(&key->user->nkeys); | 153 | atomic_dec(&key->user->nkeys); |
| 154 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 154 | if (state != KEY_IS_UNINSTANTIATED) |
| 155 | atomic_dec(&key->user->nikeys); | 155 | atomic_dec(&key->user->nikeys); |
| 156 | 156 | ||
| 157 | key_user_put(key->user); | 157 | key_user_put(key->user); |
| @@ -401,6 +401,18 @@ int key_payload_reserve(struct key *key, size_t datalen) · 400 unmodified lines | |||
| 401 | } | 401 | } |
| 402 | EXPORT_SYMBOL(key_payload_reserve); | 402 | EXPORT_SYMBOL(key_payload_reserve); |
| 403 | 403 | ||
| 404 | /* | ||
| 405 | * Change the key state to being instantiated. | ||
| 406 | */ | ||
| 407 | static void mark_key_instantiated(struct key *key, int reject_error) | ||
| 408 | { | ||
| 409 | /* Commit the payload before setting the state; barrier versus | ||
| 410 | * key_read_state(). | ||
| 411 | */ | ||
| 412 | smp_store_release(&key->state, | ||
| 413 | (reject_error < 0) ? reject_error : KEY_IS_POSITIVE); | ||
| 414 | } | ||
| 415 | |||
| 404 | /* | 416 | /* |
| 405 | * Instantiate a key and link it into the target keyring atomically. Must be | 417 | * Instantiate a key and link it into the target keyring atomically. Must be |
| 406 | * called with the target keyring's semaphore writelocked. The target key's | 418 | * called with the target keyring's semaphore writelocked. The target key's |
| @@ -424,14 +436,14 @@ static int __key_instantiate_and_link(struct key *key, · 17 unmodified lines | |||
| 424 | mutex_lock(&key_construction_mutex); | 436 | mutex_lock(&key_construction_mutex); |
| 425 | 437 | ||
| 426 | /* can't instantiate twice */ | 438 | /* can't instantiate twice */ |
| 427 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 439 | if (key->state == KEY_IS_UNINSTANTIATED) { |
| 428 | /* instantiate the key */ | 440 | /* instantiate the key */ |
| 429 | ret = key->type->instantiate(key, prep); | 441 | ret = key->type->instantiate(key, prep); |
| 430 | 442 | ||
| 431 | if (ret == 0) { | 443 | if (ret == 0) { |
| 432 | /* mark the key as being instantiated */ | 444 | /* mark the key as being instantiated */ |
| 433 | atomic_inc(&key->user->nikeys); | 445 | atomic_inc(&key->user->nikeys); |
| 434 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | 446 | mark_key_instantiated(key, 0); |
| 435 | 447 | ||
| 436 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) | 448 | if (test_and_clear_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) |
| 437 | awaken = 1; | 449 | awaken = 1; |
| @@ -577,13 +589,10 @@ int key_reject_and_link(struct key *key, · 139 unmodified lines | |||
| 577 | mutex_lock(&key_construction_mutex); | 589 | mutex_lock(&key_construction_mutex); |
| 578 | 590 | ||
| 579 | /* can't instantiate twice */ | 591 | /* can't instantiate twice */ |
| 580 | if (!test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 592 | if (key->state == KEY_IS_UNINSTANTIATED) { |
| 581 | /* mark the key as being negatively instantiated */ | 593 | /* mark the key as being negatively instantiated */ |
| 582 | atomic_inc(&key->user->nikeys); | 594 | atomic_inc(&key->user->nikeys); |
| 583 | key->reject_error = -error; | 595 | mark_key_instantiated(key, -error); |
| 584 | smp_wmb(); | ||
| 585 | set_bit(KEY_FLAG_NEGATIVE, &key->flags); | ||
| 586 | set_bit(KEY_FLAG_INSTANTIATED, &key->flags); | ||
| 587 | now = current_kernel_time(); | 596 | now = current_kernel_time(); |
| 588 | key->expiry = now.tv_sec + timeout; | 597 | key->expiry = now.tv_sec + timeout; |
| 589 | key_schedule_gc(key->expiry + key_gc_delay); | 598 | key_schedule_gc(key->expiry + key_gc_delay); |
| @@ -752,8 +761,8 @@ static inline key_ref_t __key_update(key_ref_t key_ref, · 162 unmodified lines | |||
| 752 | 761 | ||
| 753 | ret = key->type->update(key, prep); | 762 | ret = key->type->update(key, prep); |
| 754 | if (ret == 0) | 763 | if (ret == 0) |
| 755 | /* updating a negative key instantiates it */ | 764 | /* Updating a negative key positively instantiates it */ |
| 756 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 765 | mark_key_instantiated(key, 0); |
| 757 | 766 | ||
| 758 | up_write(&key->sem); | 767 | up_write(&key->sem); |
| 759 | 768 | ||
| @@ -936,6 +945,16 @@ error: · 176 unmodified lines | |||
| 936 | */ | 945 | */ |
| 937 | __key_link_end(keyring, &index_key, edit); | 946 | __key_link_end(keyring, &index_key, edit); |
| 938 | 947 | ||
| 948 | key = key_ref_to_ptr(key_ref); | ||
| 949 | if (test_bit(KEY_FLAG_USER_CONSTRUCT, &key->flags)) { | ||
| 950 | ret = wait_for_key_construction(key, true); | ||
| 951 | if (ret < 0) { | ||
| 952 | key_ref_put(key_ref); | ||
| 953 | key_ref = ERR_PTR(ret); | ||
| 954 | goto error_free_prep; | ||
| 955 | } | ||
| 956 | } | ||
| 957 | |||
| 939 | key_ref = __key_update(key_ref, &prep); | 958 | key_ref = __key_update(key_ref, &prep); |
| 940 | goto error_free_prep; | 959 | goto error_free_prep; |
| 941 | } | 960 | } |
| @@ -986,8 +1005,8 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen) · 44 unmodified lines | |||
| 986 | 1005 | ||
| 987 | ret = key->type->update(key, &prep); | 1006 | ret = key->type->update(key, &prep); |
| 988 | if (ret == 0) | 1007 | if (ret == 0) |
| 989 | /* updating a negative key instantiates it */ | 1008 | /* Updating a negative key positively instantiates it */ |
| 990 | clear_bit(KEY_FLAG_NEGATIVE, &key->flags); | 1009 | mark_key_instantiated(key, 0); |
| 991 | 1010 | ||
| 992 | up_write(&key->sem); | 1011 | up_write(&key->sem); |
| 993 | 1012 | ||
| @@ -766,10 +766,9 @@ long keyctl_read_key(key_serial_t keyid, char __user *buffer, size_t buflen) · 765 unmodified lines | |||
| 766 | 766 | ||
| 767 | key = key_ref_to_ptr(key_ref); | 767 | key = key_ref_to_ptr(key_ref); |
| 768 | 768 | ||
| 769 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | 769 | ret = key_read_state(key); |
| 770 | ret = -ENOKEY; | 770 | if (ret < 0) |
| 771 | goto error2; | 771 | goto error2; /* Negatively instantiated */ |
| 772 | } | ||
| 773 | 772 | ||
| 774 | /* see if we can read it directly */ | 773 | /* see if we can read it directly */ |
| 775 | ret = key_permission(key_ref, KEY_NEED_READ); | 774 | ret = key_permission(key_ref, KEY_NEED_READ); |
| @@ -901,7 +900,7 @@ long keyctl_chown_key(key_serial_t id, uid_t user, gid_t group) · 125 unmodified lines | |||
| 901 | atomic_dec(&key->user->nkeys); | 900 | atomic_dec(&key->user->nkeys); |
| 902 | atomic_inc(&newowner->nkeys); | 901 | atomic_inc(&newowner->nkeys); |
| 903 | 902 | ||
| 904 | if (test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) { | 903 | if (key->state != KEY_IS_UNINSTANTIATED) { |
| 905 | atomic_dec(&key->user->nikeys); | 904 | atomic_dec(&key->user->nikeys); |
| 906 | atomic_inc(&newowner->nikeys); | 905 | atomic_inc(&newowner->nikeys); |
| 907 | } | 906 | } |
| @@ -414,7 +414,7 @@ static void keyring_describe(const struct key *keyring, struct seq_file *m) · 413 unmodified lines | |||
| 414 | else | 414 | else |
| 415 | seq_puts(m, "[anon]"); | 415 | seq_puts(m, "[anon]"); |
| 416 | 416 | ||
| 417 | if (key_is_instantiated(keyring)) { | 417 | if (key_is_positive(keyring)) { |
| 418 | if (keyring->keys.nr_leaves_on_tree != 0) | 418 | if (keyring->keys.nr_leaves_on_tree != 0) |
| 419 | seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree); | 419 | seq_printf(m, ": %lu", keyring->keys.nr_leaves_on_tree); |
| 420 | else | 420 | else |
| @@ -553,7 +553,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data) · 132 unmodified lines | |||
| 553 | { | 553 | { |
| 554 | struct keyring_search_context *ctx = iterator_data; | 554 | struct keyring_search_context *ctx = iterator_data; |
| 555 | const struct key *key = keyring_ptr_to_key(object); | 555 | const struct key *key = keyring_ptr_to_key(object); |
| 556 | unsigned long kflags = key->flags; | 556 | unsigned long kflags = READ_ONCE(key->flags); |
| 557 | short state = READ_ONCE(key->state); | ||
| 557 | 558 | ||
| 558 | kenter("{%d}", key->serial); | 559 | kenter("{%d}", key->serial); |
| 559 | 560 | ||
| @@ -565,6 +566,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data) · 5 unmodified lines | |||
| 565 | 566 | ||
| 566 | /* skip invalidated, revoked and expired keys */ | 567 | /* skip invalidated, revoked and expired keys */ |
| 567 | if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { | 568 | if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { |
| 569 | time_t expiry = READ_ONCE(key->expiry); | ||
| 570 | |||
| 568 | if (kflags & ((1 << KEY_FLAG_INVALIDATED) | | 571 | if (kflags & ((1 << KEY_FLAG_INVALIDATED) | |
| 569 | (1 << KEY_FLAG_REVOKED))) { | 572 | (1 << KEY_FLAG_REVOKED))) { |
| 570 | ctx->result = ERR_PTR(-EKEYREVOKED); | 573 | ctx->result = ERR_PTR(-EKEYREVOKED); |
| @@ -572,7 +575,7 @@ static int keyring_search_iterator(const void *object, void *iterator_data) · 1 unmodified line | |||
| 572 | goto skipped; | 575 | goto skipped; |
| 573 | } | 576 | } |
| 574 | 577 | ||
| 575 | if (key->expiry && ctx->now.tv_sec >= key->expiry) { | 578 | if (expiry && ctx->now.tv_sec >= expiry) { |
| 576 | if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) | 579 | if (!(ctx->flags & KEYRING_SEARCH_SKIP_EXPIRED)) |
| 577 | ctx->result = ERR_PTR(-EKEYEXPIRED); | 580 | ctx->result = ERR_PTR(-EKEYEXPIRED); |
| 578 | kleave(" = %d [expire]", ctx->skipped_ret); | 581 | kleave(" = %d [expire]", ctx->skipped_ret); |
| @@ -597,9 +600,8 @@ static int keyring_search_iterator(const void *object, void *iterator_data) · 18 unmodified lines | |||
| 597 | 600 | ||
| 598 | if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { | 601 | if (ctx->flags & KEYRING_SEARCH_DO_STATE_CHECK) { |
| 599 | /* we set a different error code if we pass a negative key */ | 602 | /* we set a different error code if we pass a negative key */ |
| 600 | if (kflags & (1 << KEY_FLAG_NEGATIVE)) { | 603 | if (state < 0) { |
| 601 | smp_rmb(); | 604 | ctx->result = ERR_PTR(state); |
| 602 | ctx->result = ERR_PTR(key->reject_error); | ||
| 603 | kleave(" = %d [neg]", ctx->skipped_ret); | 605 | kleave(" = %d [neg]", ctx->skipped_ret); |
| 604 | goto skipped; | 606 | goto skipped; |
| 605 | } | 607 | } |
| @@ -88,7 +88,8 @@ EXPORT_SYMBOL(key_task_permission); · 87 unmodified lines | |||
| 88 | */ | 88 | */ |
| 89 | int key_validate(const struct key *key) | 89 | int key_validate(const struct key *key) |
| 90 | { | 90 | { |
| 91 | unsigned long flags = key->flags; | 91 | unsigned long flags = READ_ONCE(key->flags); |
| 92 | time_t expiry = READ_ONCE(key->expiry); | ||
| 92 | 93 | ||
| 93 | if (flags & (1 << KEY_FLAG_INVALIDATED)) | 94 | if (flags & (1 << KEY_FLAG_INVALIDATED)) |
| 94 | return -ENOKEY; | 95 | return -ENOKEY; |
| @@ -99,9 +100,9 @@ int key_validate(const struct key *key) · 4 unmodified lines | |||
| 99 | return -EKEYREVOKED; | 100 | return -EKEYREVOKED; |
| 100 | 101 | ||
| 101 | /* check it hasn't expired */ | 102 | /* check it hasn't expired */ |
| 102 | if (key->expiry) { | 103 | if (expiry) { |
| 103 | struct timespec now = current_kernel_time(); | 104 | struct timespec now = current_kernel_time(); |
| 104 | if (now.tv_sec >= key->expiry) | 105 | if (now.tv_sec >= expiry) |
| 105 | return -EKEYEXPIRED; | 106 | return -EKEYEXPIRED; |
| 106 | } | 107 | } |
| 107 | 108 | ||
| @@ -179,9 +179,12 @@ static int proc_keys_show(struct seq_file *m, void *v) · 178 unmodified lines | |||
| 179 | struct rb_node *_p = v; | 179 | struct rb_node *_p = v; |
| 180 | struct key *key = rb_entry(_p, struct key, serial_node); | 180 | struct key *key = rb_entry(_p, struct key, serial_node); |
| 181 | struct timespec now; | 181 | struct timespec now; |
| 182 | time_t expiry; | ||
| 182 | unsigned long timo; | 183 | unsigned long timo; |
| 184 | unsigned long flags; | ||
| 183 | key_ref_t key_ref, skey_ref; | 185 | key_ref_t key_ref, skey_ref; |
| 184 | char xbuf[16]; | 186 | char xbuf[16]; |
| 187 | short state; | ||
| 185 | int rc; | 188 | int rc; |
| 186 | 189 | ||
| 187 | struct keyring_search_context ctx = { | 190 | struct keyring_search_context ctx = { |
| @@ -217,12 +220,13 @@ static int proc_keys_show(struct seq_file *m, void *v) · 29 unmodified lines | |||
| 217 | rcu_read_lock(); | 220 | rcu_read_lock(); |
| 218 | 221 | ||
| 219 | /* come up with a suitable timeout value */ | 222 | /* come up with a suitable timeout value */ |
| 220 | if (key->expiry == 0) { | 223 | expiry = READ_ONCE(key->expiry); |
| 224 | if (expiry == 0) { | ||
| 221 | memcpy(xbuf, "perm", 5); | 225 | memcpy(xbuf, "perm", 5); |
| 222 | } else if (now.tv_sec >= key->expiry) { | 226 | } else if (now.tv_sec >= expiry) { |
| 223 | memcpy(xbuf, "expd", 5); | 227 | memcpy(xbuf, "expd", 5); |
| 224 | } else { | 228 | } else { |
| 225 | timo = key->expiry - now.tv_sec; | 229 | timo = expiry - now.tv_sec; |
| 226 | 230 | ||
| 227 | if (timo < 60) | 231 | if (timo < 60) |
| 228 | sprintf(xbuf, "%lus", timo); | 232 | sprintf(xbuf, "%lus", timo); |
| @@ -236,18 +240,21 @@ static int proc_keys_show(struct seq_file *m, void *v) · 7 unmodified lines | |||
| 236 | sprintf(xbuf, "%luw", timo / (60*60*24*7)); | 240 | sprintf(xbuf, "%luw", timo / (60*60*24*7)); |
| 237 | } | 241 | } |
| 238 | 242 | ||
| 239 | #define showflag(KEY, LETTER, FLAG) \ | 243 | state = key_read_state(key); |
| 240 | (test_bit(FLAG, &(KEY)->flags) ? LETTER : '-') | ||
| 241 | 244 | ||
| 245 | #define showflag(FLAGS, LETTER, FLAG) \ | ||
| 246 | ((FLAGS & (1 << FLAG)) ? LETTER : '-') | ||
| 247 | |||
| 248 | flags = READ_ONCE(key->flags); | ||
| 242 | seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", | 249 | seq_printf(m, "%08x %c%c%c%c%c%c%c %5d %4s %08x %5d %5d %-9.9s ", |
| 243 | key->serial, | 250 | key->serial, |
| 244 | showflag(key, 'I', KEY_FLAG_INSTANTIATED), | 251 | state != KEY_IS_UNINSTANTIATED ? 'I' : '-', |
| 245 | showflag(key, 'R', KEY_FLAG_REVOKED), | 252 | showflag(flags, 'R', KEY_FLAG_REVOKED), |
| 246 | showflag(key, 'D', KEY_FLAG_DEAD), | 253 | showflag(flags, 'D', KEY_FLAG_DEAD), |
| 247 | showflag(key, 'Q', KEY_FLAG_IN_QUOTA), | 254 | showflag(flags, 'Q', KEY_FLAG_IN_QUOTA), |
| 248 | showflag(key, 'U', KEY_FLAG_USER_CONSTRUCT), | 255 | showflag(flags, 'U', KEY_FLAG_USER_CONSTRUCT), |
| 249 | showflag(key, 'N', KEY_FLAG_NEGATIVE), | 256 | state < 0 ? 'N' : '-', |
| 250 | showflag(key, 'i', KEY_FLAG_INVALIDATED), | 257 | showflag(flags, 'i', KEY_FLAG_INVALIDATED), |
| 251 | refcount_read(&key->usage), | 258 | refcount_read(&key->usage), |
| 252 | xbuf, | 259 | xbuf, |
| 253 | key->perm, | 260 | key->perm, |
| @@ -730,7 +730,7 @@ try_again: · 729 unmodified lines | |||
| 730 | 730 | ||
| 731 | ret = -EIO; | 731 | ret = -EIO; |
| 732 | if (!(lflags & KEY_LOOKUP_PARTIAL) && | 732 | if (!(lflags & KEY_LOOKUP_PARTIAL) && |
| 733 | !test_bit(KEY_FLAG_INSTANTIATED, &key->flags)) | 733 | key_read_state(key) == KEY_IS_UNINSTANTIATED) |
| 734 | goto invalid_key; | 734 | goto invalid_key; |
| 735 | 735 | ||
| 736 | /* check the permissions */ | 736 | /* check the permissions */ |
| @@ -595,10 +595,9 @@ int wait_for_key_construction(struct key *key, bool intr) · 594 unmodified lines | |||
| 595 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); | 595 | intr ? TASK_INTERRUPTIBLE : TASK_UNINTERRUPTIBLE); |
| 596 | if (ret) | 596 | if (ret) |
| 597 | return -ERESTARTSYS; | 597 | return -ERESTARTSYS; |
| 598 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) { | 598 | ret = key_read_state(key); |
| 599 | smp_rmb(); | 599 | if (ret < 0) |
| 600 | return key->reject_error; | 600 | return ret; |
| 601 | } | ||
| 602 | return key_validate(key); | 601 | return key_validate(key); |
| 603 | } | 602 | } |
| 604 | EXPORT_SYMBOL(wait_for_key_construction); | 603 | EXPORT_SYMBOL(wait_for_key_construction); |
| @@ -73,7 +73,7 @@ static void request_key_auth_describe(const struct key *key, · 72 unmodified lines | |||
| 73 | 73 | ||
| 74 | seq_puts(m, "key:"); | 74 | seq_puts(m, "key:"); |
| 75 | seq_puts(m, key->description); | 75 | seq_puts(m, key->description); |
| 76 | if (key_is_instantiated(key)) | 76 | if (key_is_positive(key)) |
| 77 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); | 77 | seq_printf(m, " pid:%d ci:%zu", rka->pid, rka->callout_len); |
| 78 | } | 78 | } |
| 79 | 79 | ||
| @@ -1066,7 +1066,7 @@ static int trusted_update(struct key *key, struct key_preparsed_payload *prep) · 1065 unmodified lines | |||
| 1066 | char *datablob; | 1066 | char *datablob; |
| 1067 | int ret = 0; | 1067 | int ret = 0; |
| 1068 | 1068 | ||
| 1069 | if (test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | 1069 | if (key_is_negative(key)) |
| 1070 | return -ENOKEY; | 1070 | return -ENOKEY; |
| 1071 | p = key->payload.data[0]; | 1071 | p = key->payload.data[0]; |
| 1072 | if (!p->migratable) | 1072 | if (!p->migratable) |
| @@ -114,7 +114,7 @@ int user_update(struct key *key, struct key_preparsed_payload *prep) · 113 unmodified lines | |||
| 114 | 114 | ||
| 115 | /* attach the new data, displacing the old */ | 115 | /* attach the new data, displacing the old */ |
| 116 | key->expiry = prep->expiry; | 116 | key->expiry = prep->expiry; |
| 117 | if (!test_bit(KEY_FLAG_NEGATIVE, &key->flags)) | 117 | if (key_is_positive(key)) |
| 118 | zap = dereference_key_locked(key); | 118 | zap = dereference_key_locked(key); |
| 119 | rcu_assign_keypointer(key, prep->payload.data[0]); | 119 | rcu_assign_keypointer(key, prep->payload.data[0]); |
| 120 | prep->payload.data[0] = NULL; | 120 | prep->payload.data[0] = NULL; |
| @@ -162,7 +162,7 @@ EXPORT_SYMBOL_GPL(user_destroy); · 41 unmodified lines | |||
| 162 | void user_describe(const struct key *key, struct seq_file *m) | 162 | void user_describe(const struct key *key, struct seq_file *m) |
| 163 | { | 163 | { |
| 164 | seq_puts(m, key->description); | 164 | seq_puts(m, key->description); |
| 165 | if (key_is_instantiated(key)) | 165 | if (key_is_positive(key)) |
| 166 | seq_printf(m, ": %u", key->datalen); | 166 | seq_printf(m, ": %u", key->datalen); |
| 167 | } | 167 | } |
| 168 | 168 | ||