diff options
Diffstat (limited to 'security/keys')
-rw-r--r-- | security/keys/gc.c | 4 | ||||
-rw-r--r-- | security/keys/key.c | 2 | ||||
-rw-r--r-- | security/keys/trusted-keys/trusted_dcp.c | 22 |
3 files changed, 23 insertions, 5 deletions
diff --git a/security/keys/gc.c b/security/keys/gc.c index 7d687b0962b1..f27223ea4578 100644 --- a/security/keys/gc.c +++ b/security/keys/gc.c @@ -218,8 +218,10 @@ continue_scanning: key = rb_entry(cursor, struct key, serial_node); cursor = rb_next(cursor); - if (refcount_read(&key->usage) == 0) + if (test_bit(KEY_FLAG_FINAL_PUT, &key->flags)) { + smp_mb(); /* Clobber key->user after FINAL_PUT seen. */ goto found_unreferenced_key; + } if (unlikely(gc_state & KEY_GC_REAPING_DEAD_1)) { if (key->type == key_gc_dead_keytype) { diff --git a/security/keys/key.c b/security/keys/key.c index 3d7d185019d3..7198cd2ac3a3 100644 --- a/security/keys/key.c +++ b/security/keys/key.c @@ -658,6 +658,8 @@ void key_put(struct key *key) key->user->qnbytes -= key->quotalen; spin_unlock_irqrestore(&key->user->lock, flags); } + smp_mb(); /* key->user before FINAL_PUT set. */ + set_bit(KEY_FLAG_FINAL_PUT, &key->flags); schedule_work(&key_gc_work); } } diff --git a/security/keys/trusted-keys/trusted_dcp.c b/security/keys/trusted-keys/trusted_dcp.c index e908c53a803c..7b6eb655df0c 100644 --- a/security/keys/trusted-keys/trusted_dcp.c +++ b/security/keys/trusted-keys/trusted_dcp.c @@ -201,12 +201,16 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) { struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; int blen, ret; - u8 plain_blob_key[AES_KEYSIZE_128]; + u8 *plain_blob_key; blen = calc_blob_len(p->key_len); if (blen > MAX_BLOB_SIZE) return -E2BIG; + plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL); + if (!plain_blob_key) + return -ENOMEM; + b->fmt_version = DCP_BLOB_VERSION; get_random_bytes(b->nonce, AES_KEYSIZE_128); get_random_bytes(plain_blob_key, AES_KEYSIZE_128); @@ -229,7 +233,8 @@ static int trusted_dcp_seal(struct trusted_key_payload *p, char *datablob) ret = 0; out: - memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); + memzero_explicit(plain_blob_key, AES_KEYSIZE_128); + kfree(plain_blob_key); return ret; } @@ -238,7 +243,7 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) { struct dcp_blob_fmt *b = (struct dcp_blob_fmt *)p->blob; int blen, ret; - u8 plain_blob_key[AES_KEYSIZE_128]; + u8 *plain_blob_key = NULL; if (b->fmt_version != DCP_BLOB_VERSION) { pr_err("DCP blob has bad version: %i, expected %i\n", @@ -256,6 +261,12 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) goto out; } + plain_blob_key = kmalloc(AES_KEYSIZE_128, GFP_KERNEL); + if (!plain_blob_key) { + ret = -ENOMEM; + goto out; + } + ret = decrypt_blob_key(b->blob_key, plain_blob_key); if (ret) { pr_err("Unable to decrypt blob key: %i\n", ret); @@ -271,7 +282,10 @@ static int trusted_dcp_unseal(struct trusted_key_payload *p, char *datablob) ret = 0; out: - memzero_explicit(plain_blob_key, sizeof(plain_blob_key)); + if (plain_blob_key) { + memzero_explicit(plain_blob_key, AES_KEYSIZE_128); + kfree(plain_blob_key); + } return ret; } |