From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:47:28
Hi James,
Here are a bunch of fixes for Linux keyrings, including:
(*) Fixing up the refcount handling now that key structs use the
refcount_t type and the refcount_t ops don't allow a 0->1 transition.
(*) Fix a potential NULL deref after error in x509_cert_parse().
(*) Don't put data for the crypto algorithms to use on the stack.
(*) Fix the handling of a null payload being passed to add_key().
(*) Fix incorrect cleanup an uninitialised key_preparsed_payload in
key_update().
(*) Explicit sanitisation of potentially secure data before freeing.
(*) Fixes for the Diffie-Helman code.
Note that I rebased the patches on top of -rc4 to avoid problems with a tty
locking bug encountered whilst trying to test it.
The patches can be found here also:
http://git.kernel.org/cgit/linux/kernel/git/dhowells/linux-fs.git/log/?h=keys-fixes
Tagged thusly:
git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs.git
keys-fixes-20170608
David
---
Bilal Amarni (1):
security/keys: add CONFIG_KEYS_COMPAT to Kconfig
Dan Carpenter (1):
X.509: Fix error code in x509_cert_parse()
Davidlohr Bueso (1):
security: use READ_ONCE instead of deprecated ACCESS_ONCE
Eric Biggers (16):
KEYS: put keyring if install_session_keyring_to_cred() fails
KEYS: encrypted: avoid encrypting/decrypting stack buffers
KEYS: encrypted: fix buffer overread in valid_master_desc()
KEYS: encrypted: fix race causing incorrect HMAC calculations
KEYS: encrypted: use constant-time HMAC comparison
KEYS: fix dereferencing NULL payload with nonzero length
KEYS: fix freeing uninitialized memory in key_update()
KEYS: sanitize add_key() and keyctl() key payloads
KEYS: user_defined: sanitize key payloads
KEYS: encrypted: sanitize all key material
KEYS: trusted: sanitize all key material
KEYS: sanitize key structs before freeing
KEYS: DH: forbid using digest_null as the KDF hash
KEYS: DH: don't feed uninitialized "otherinfo" into KDF
KEYS: DH: ensure the KDF counter is properly aligned
KEYS: DH: add __user annotations to keyctl_kdf_params
Loganaden Velvindron (1):
crypto : asymmetric_keys : verify_pefile:zero memory content before freeing
Mark Rutland (1):
KEYS: fix refcount_inc() on zero
Markus Elfring (1):
KEYS: Delete an error message for a failed memory allocation in get_derived_key()
Mat Martineau (1):
KEYS: Convert KEYCTL_DH_COMPUTE to use the crypto KPP API
arch/arm64/Kconfig | 4
arch/powerpc/Kconfig | 5
arch/s390/Kconfig | 3
arch/sparc/Kconfig | 3
arch/x86/Kconfig | 4
crypto/asymmetric_keys/verify_pefile.c | 4
crypto/asymmetric_keys/x509_cert_parser.c | 1
include/linux/key.h | 1
include/uapi/linux/keyctl.h | 4
security/keys/Kconfig | 6 -
security/keys/dh.c | 300 ++++++++++++++++++-----------
security/keys/encrypted-keys/encrypted.c | 204 +++++++-------------
security/keys/gc.c | 4
security/keys/key.c | 16 +-
security/keys/keyctl.c | 16 +-
security/keys/keyring.c | 12 +
security/keys/process_keys.c | 7 -
security/keys/trusted.c | 50 ++---
security/keys/user_defined.c | 16 +-
19 files changed, 330 insertions(+), 330 deletions(-)
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:47:37
From: Bilal Amarni <redacted>
CONFIG_KEYS_COMPAT is defined in arch-specific Kconfigs and is missing for
several 64-bit architectures : mips, parisc, tile.
At the moment and for those architectures, calling in 32-bit userspace the
keyctl syscall would return an ENOSYS error.
This patch moves the CONFIG_KEYS_COMPAT option to security/keys/Kconfig, to
make sure the compatibility wrapper is registered by default for any 64-bit
architecture as long as it is configured with CONFIG_COMPAT.
[DH: Modified to remove arm64 compat enablement also as requested by Eric
Biggers]
Signed-off-by: Bilal Amarni <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Reviewed-by: Arnd Bergmann <arnd@arndb.de>
cc: Eric Biggers <redacted>
---
arch/arm64/Kconfig | 4 ----
arch/powerpc/Kconfig | 5 -----
arch/s390/Kconfig | 3 ---
arch/sparc/Kconfig | 3 ---
arch/x86/Kconfig | 4 ----
security/keys/Kconfig | 4 ++++
6 files changed, 4 insertions(+), 19 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:47:47
From: Mark Rutland <mark.rutland@arm.com>
If a key's refcount is dropped to zero between key_lookup() peeking at
the refcount and subsequently attempting to increment it, refcount_inc()
will see a zero refcount. Here, refcount_inc() will WARN_ONCE(), and
will *not* increment the refcount, which will remain zero.
Once key_lookup() drops key_serial_lock, it is possible for the key to
be freed behind our back.
This patch uses refcount_inc_not_zero() to perform the peek and increment
atomically.
Fixes: fff292914d3a2f1e ("security, keys: convert key.usage from atomic_t to refcount_t")
Signed-off-by: Mark Rutland <mark.rutland@arm.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Cc: David Windsor <redacted>
Cc: Elena Reshetova <elena.reshetova@intel.com>
Cc: Hans Liljestrand <redacted>
Cc: James Morris <redacted>
Cc: Kees Cook <redacted>
Cc: Peter Zijlstra <peterz@infradead.org>
---
security/keys/key.c | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
@@ -660,14 +660,11 @@ struct key *key_lookup(key_serial_t id)gotoerror;found:-/* pretend it doesn't exist if it is awaiting deletion */-if(refcount_read(&key->usage)==0)-gotonot_found;--/* this races with key_put(), but that doesn't matter since key_put()-*doesn'tactuallychangethekey+/* A key is allowed to be looked up only if someone still owns a+*referencetoit-otherwiseit'sawaitingthegc.*/-__key_get(key);+if(!refcount_inc_not_zero(&key->usage))+gotonot_found;error:spin_unlock(&key_serial_lock);--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:01
From: Markus Elfring <redacted>
Omit an extra message for a memory allocation failure in this function.
This issue was detected by using the Coccinelle software.
Link: http://events.linuxfoundation.org/sites/events/files/slides/LCJ16-Refactor_Strings-WSang_0.pdf
Signed-off-by: Markus Elfring <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
@@ -385,10 +385,9 @@ static int get_derived_key(u8 *derived_key, enum derived_key_type key_type,derived_buf_len=HASH_SIZE;derived_buf=kzalloc(derived_buf_len,GFP_KERNEL);-if(!derived_buf){-pr_err("encrypted_key: out of memory\n");+if(!derived_buf)return-ENOMEM;-}+if(key_type)strcpy(derived_buf,"AUTH_KEY");else--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:05
From: Dan Carpenter <redacted>
We forgot to set the error code on this path so it could result in
returning NULL which leads to a NULL dereference.
Fixes: db6c43bd2132 ("crypto: KEYS: convert public key and digsig asym to the akcipher api")
Signed-off-by: Dan Carpenter <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
crypto/asymmetric_keys/x509_cert_parser.c | 1 +
1 file changed, 1 insertion(+)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:16
From: Eric Biggers <redacted>
In join_session_keyring(), if install_session_keyring_to_cred() were to
fail, we would leak the keyring reference, just like in the bug fixed by
commit 23567fd052a9 ("KEYS: Fix keyring ref leak in
join_session_keyring()"). Fortunately this cannot happen currently, but
we really should be more careful. Do this by adding and using a new
error label at which the keyring reference is dropped.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/process_keys.c | 7 ++++---
1 file changed, 4 insertions(+), 3 deletions(-)
@@ -809,15 +809,14 @@ long join_session_keyring(const char *name)ret=PTR_ERR(keyring);gotoerror2;}elseif(keyring==new->session_keyring){-key_put(keyring);ret=0;-gotoerror2;+gotoerror3;}/* we've got a keyring - now to install it */ret=install_session_keyring_to_cred(new,keyring);if(ret<0)-gotoerror2;+gotoerror3;commit_creds(new);mutex_unlock(&key_session_mutex);
@@ -827,6 +826,8 @@ long join_session_keyring(const char *name)okay:returnret;+error3:+key_put(keyring);error2:mutex_unlock(&key_session_mutex);error:--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info@ http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:25
From: Eric Biggers <redacted>
With the 'encrypted' key type it was possible for userspace to provide a
data blob ending with a master key description shorter than expected,
e.g. 'keyctl add encrypted desc "new x" @s'. When validating such a
master key description, validate_master_desc() could read beyond the end
of the buffer. Fix this by using strncmp() instead of memcmp(). [Also
clean up the code to deduplicate some logic.]
Cc: Mimi Zohar <redacted>
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++++---------------
1 file changed, 15 insertions(+), 16 deletions(-)
@@ -141,23 +141,22 @@ static int valid_ecryptfs_desc(const char *ecryptfs_desc)*/staticintvalid_master_desc(constchar*new_desc,constchar*orig_desc){-if(!memcmp(new_desc,KEY_TRUSTED_PREFIX,KEY_TRUSTED_PREFIX_LEN)){-if(strlen(new_desc)==KEY_TRUSTED_PREFIX_LEN)-gotoout;-if(orig_desc)-if(memcmp(new_desc,orig_desc,KEY_TRUSTED_PREFIX_LEN))-gotoout;-}elseif(!memcmp(new_desc,KEY_USER_PREFIX,KEY_USER_PREFIX_LEN)){-if(strlen(new_desc)==KEY_USER_PREFIX_LEN)-gotoout;-if(orig_desc)-if(memcmp(new_desc,orig_desc,KEY_USER_PREFIX_LEN))-gotoout;-}else-gotoout;+intprefix_len;++if(!strncmp(new_desc,KEY_TRUSTED_PREFIX,KEY_TRUSTED_PREFIX_LEN))+prefix_len=KEY_TRUSTED_PREFIX_LEN;+elseif(!strncmp(new_desc,KEY_USER_PREFIX,KEY_USER_PREFIX_LEN))+prefix_len=KEY_USER_PREFIX_LEN;+else+return-EINVAL;++if(!new_desc[prefix_len])+return-EINVAL;++if(orig_desc&&strncmp(new_desc,orig_desc,prefix_len))+return-EINVAL;+return0;-out:-return-EINVAL;}/*--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:31
From: Eric Biggers <redacted>
Since v4.9, the crypto API cannot (normally) be used to encrypt/decrypt
stack buffers because the stack may be virtually mapped. Fix this for
the padding buffers in encrypted-keys by using ZERO_PAGE for the
encryption padding and by allocating a temporary heap buffer for the
decryption padding.
Tested with CONFIG_DEBUG_SG=y:
keyctl new_session
keyctl add user master "abcdefghijklmnop" @s
keyid=$(keyctl add encrypted desc "new user:master 25" @s)
datablob="$(keyctl pipe $keyid)"
keyctl unlink $keyid
keyid=$(keyctl add encrypted desc "load $datablob" @s)
datablob2="$(keyctl pipe $keyid)"
[ "$datablob" = "$datablob2" ] && echo "Success!"
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Cc: Mimi Zohar <redacted>
Cc: stable at vger.kernel.org # 4.9+
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 17 +++++++++--------
1 file changed, 9 insertions(+), 8 deletions(-)
@@ -479,12 +479,9 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,structskcipher_request*req;unsignedintencrypted_datalen;u8iv[AES_BLOCK_SIZE];-unsignedintpadlen;-charpad[16];intret;encrypted_datalen=roundup(epayload->decrypted_datalen,blksize);-padlen=encrypted_datalen-epayload->decrypted_datalen;req=init_skcipher_req(derived_key,derived_keylen);ret=PTR_ERR(req);
@@ -492,11 +489,10 @@ static int derived_key_encrypt(struct encrypted_key_payload *epayload,gotoout;dump_decrypted_data(epayload);-memset(pad,0,sizeofpad);sg_init_table(sg_in,2);sg_set_buf(&sg_in[0],epayload->decrypted_data,epayload->decrypted_datalen);-sg_set_buf(&sg_in[1],pad,padlen);+sg_set_page(&sg_in[1],ZERO_PAGE(0),AES_BLOCK_SIZE,0);sg_init_table(sg_out,1);sg_set_buf(sg_out,epayload->encrypted_data,encrypted_datalen);
@@ -583,9 +579,14 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,structskcipher_request*req;unsignedintencrypted_datalen;u8iv[AES_BLOCK_SIZE];-charpad[16];+u8*pad;intret;+/* Throwaway buffer to hold the unused zero padding at the end */+pad=kmalloc(AES_BLOCK_SIZE,GFP_KERNEL);+if(!pad)+return-ENOMEM;+encrypted_datalen=roundup(epayload->decrypted_datalen,blksize);req=init_skcipher_req(derived_key,derived_keylen);ret=PTR_ERR(req);
@@ -593,13 +594,12 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,gotoout;dump_encrypted_data(epayload,encrypted_datalen);-memset(pad,0,sizeofpad);sg_init_table(sg_in,1);sg_init_table(sg_out,2);sg_set_buf(sg_in,epayload->encrypted_data,encrypted_datalen);sg_set_buf(&sg_out[0],epayload->decrypted_data,epayload->decrypted_datalen);-sg_set_buf(&sg_out[1],pad,sizeofpad);+sg_set_buf(&sg_out[1],pad,AES_BLOCK_SIZE);memcpy(iv,epayload->iv,sizeof(iv));skcipher_request_set_crypt(req,sg_in,sg_out,encrypted_datalen,iv);
@@ -611,6 +611,7 @@ static int derived_key_decrypt(struct encrypted_key_payload *epayload,gotoout;dump_decrypted_data(epayload);out:+kfree(pad);returnret;}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:48:45
From: Eric Biggers <redacted>
MACs should, in general, be compared using crypto_memneq() to prevent
timing attacks.
Cc: Mimi Zohar <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
@@ -534,8 +535,8 @@ static int datablob_hmac_verify(struct encrypted_key_payload *epayload,ret=calc_hmac(digest,derived_key,sizeofderived_key,p,len);if(ret<0)gotoout;-ret=memcmp(digest,epayload->format+epayload->datablob_len,-sizeofdigest);+ret=crypto_memneq(digest,epayload->format+epayload->datablob_len,+sizeof(digest));if(ret){ret=-EINVAL;dump_hmac("datablob",--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -963,12 +963,11 @@ int key_update(key_ref_t key_ref, const void *payload, size_t plen)/* the key must be writable */ret=key_permission(key_ref,KEY_NEED_WRITE);if(ret<0)-gotoerror;+returnret;/* attempt to update it if supported */-ret=-EOPNOTSUPP;if(!key->type->update)-gotoerror;+return-EOPNOTSUPP;memset(&prep,0,sizeof(prep));prep.data=payload;--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:49:17
From: Eric Biggers <redacted>
For keys of type "encrypted", consistently zero sensitive key material
before freeing it. This was already being done for the decrypted
payloads of encrypted keys, but not for the master key and the keys
derived from the master key.
Out of an abundance of caution and because it is trivial to do so, also
zero buffers containing the key payload in encrypted form, although
depending on how the encrypted-keys feature is used such information
does not necessarily need to be kept secret.
Cc: Mimi Zohar <redacted>
Cc: David Safford <redacted>
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 31 +++++++++++++-----------------
1 file changed, 13 insertions(+), 18 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:49:32
From: Eric Biggers <redacted>
While a 'struct key' itself normally does not contain sensitive
information, Documentation/security/keys.txt actually encourages this:
"Having a payload is not required; and the payload can, in fact,
just be a value stored in the struct key itself."
In case someone has taken this advice, or will take this advice in the
future, zero the key structure before freeing it. We might as well, and
as a bonus this could make it a bit more difficult for an adversary to
determine which keys have recently been in use.
This is safe because the key_jar cache does not use a constructor.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
include/linux/key.h | 1 -
security/keys/gc.c | 4 +---
2 files changed, 1 insertion(+), 4 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:49:45
From: Eric Biggers <redacted>
Requesting "digest_null" in the keyctl_kdf_params caused an infinite
loop in kdf_ctr() because the "null" hash has a digest size of 0. Fix
it by rejecting hash algorithms with a digest size of 0.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephan Mueller <redacted>
---
security/keys/dh.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:49:52
From: Eric Biggers <redacted>
If userspace called KEYCTL_DH_COMPUTE with kdf_params containing NULL
otherinfo but nonzero otherinfolen, the kernel would allocate a buffer
for the otherinfo, then feed it into the KDF without initializing it.
Fix this by always doing the copy from userspace (which will fail with
EFAULT in this scenario).
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephan Mueller <redacted>
---
security/keys/dh.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:49:54
From: Eric Biggers <redacted>
Accessing a 'u8[4]' through a '__be32 *' violates alignment rules. Just
make the counter a __be32 instead.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
Acked-by: Stephan Mueller <redacted>
---
security/keys/dh.c | 16 +++-------------
1 file changed, 3 insertions(+), 13 deletions(-)
@@ -130,14 +130,6 @@ static void kdf_dealloc(struct kdf_sdesc *sdesc)kzfree(sdesc);}-/* convert 32 bit integer into its string representation */-staticinlinevoidcrypto_kw_cpu_to_be32(u32val,u8*buf)-{-__be32*a=(__be32*)buf;--*a=cpu_to_be32(val);-}-/**ImplementationoftheKDFincountermodeaccordingtoSP800-108section5.1*aswellasSP800-56Asection5.8.1(Single-stepKDF).
@@ -154,16 +146,14 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,unsignedinth=crypto_shash_digestsize(desc->tfm);interr=0;u8*dst_orig=dst;-u32i=1;-u8iteration[sizeof(u32)];+__be32counter=cpu_to_be32(1);while(dlen){err=crypto_shash_init(desc);if(err)gotoerr;-crypto_kw_cpu_to_be32(i,iteration);-err=crypto_shash_update(desc,iteration,sizeof(u32));+err=crypto_shash_update(desc,(u8*)&counter,sizeof(__be32));if(err)gotoerr;
@@ -189,7 +179,7 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,dlen-=h;dst+=h;-i++;+counter=cpu_to_be32(be32_to_cpu(counter)+1);}}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
@@ -381,7 +381,7 @@ static int pefile_digest_pe(const void *pebuf, unsigned int pelen,}error:-kfree(desc);+kzfree(desc);error_no_desc:crypto_free_shash(tfm);kleave(" = %d",ret);
@@ -450,6 +450,6 @@ int verify_pefile_signature(const void *pebuf, unsigned pelen,ret=pefile_digest_pe(pebuf,pelen,&ctx);error:-kfree(ctx.digest);+kzfree(ctx.digest);returnret;}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:50:38
From: Mat Martineau <redacted>
The initial Diffie-Hellman computation made direct use of the MPI
library because the crypto module did not support DH at the time. Now
that KPP is implemented, KEYCTL_DH_COMPUTE should use it to get rid of
duplicate code and leverage possible hardware acceleration.
This fixes an issue whereby the input to the KDF computation would
include additional uninitialized memory when the result of the
Diffie-Hellman computation was shorter than the input prime number.
Signed-off-by: Mat Martineau <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/Kconfig | 2
security/keys/dh.c | 272 +++++++++++++++++++++++++++++++------------------
2 files changed, 171 insertions(+), 103 deletions(-)
@@ -157,6 +161,22 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,if(err)gotoerr;+if(zlen&&h){+u8tmpbuffer[h];+size_tchunk=min_t(size_t,zlen,h);+memset(tmpbuffer,0,chunk);++do{+err=crypto_shash_update(desc,tmpbuffer,+chunk);+if(err)+gotoerr;++zlen-=chunk;+chunk=min_t(size_t,zlen,h);+}while(zlen);+}+if(src&&slen){err=crypto_shash_update(desc,src,slen);if(err)
@@ -192,7 +212,7 @@ static int kdf_ctr(struct kdf_sdesc *sdesc, const u8 *src, unsigned int slen,staticintkeyctl_dh_compute_kdf(structkdf_sdesc*sdesc,char__user*buffer,size_tbuflen,-uint8_t*kbuf,size_tkbuflen)+uint8_t*kbuf,size_tkbuflen,size_tlzero){uint8_t*outbuf=NULL;intret;
@@ -203,7 +223,7 @@ static int keyctl_dh_compute_kdf(struct kdf_sdesc *sdesc,gotoerr;}-ret=kdf_ctr(sdesc,kbuf,kbuflen,outbuf,buflen);+ret=kdf_ctr(sdesc,kbuf,kbuflen,outbuf,buflen,lzero);if(ret)gotoerr;
@@ -221,21 +241,26 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,structkeyctl_kdf_params*kdfcopy){longret;-MPIbase,private,prime,result;-unsignednbytes;+ssize_tdlen;+intsecretlen;+intoutlen;structkeyctl_dh_paramspcopy;-uint8_t*kbuf;-ssize_tkeylen;-size_tresultlen;+structdhdh_inputs;+structscatterlistoutsg;+structdh_completioncompl;+structcrypto_kpp*tfm;+structkpp_request*req;+uint8_t*secret;+uint8_t*outbuf;structkdf_sdesc*sdesc=NULL;if(!params||(!buffer&&buflen)){ret=-EINVAL;-gotoout;+gotoout1;}if(copy_from_user(&pcopy,params,sizeof(pcopy))!=0){ret=-EFAULT;-gotoout;+gotoout1;}if(kdfcopy){
@@ -244,104 +269,147 @@ long __keyctl_dh_compute(struct keyctl_dh_params __user *params,if(buflen>KEYCTL_KDF_MAX_OUTPUT_LEN||kdfcopy->otherinfolen>KEYCTL_KDF_MAX_OI_LEN){ret=-EMSGSIZE;-gotoout;+gotoout1;}/* get KDF name string */hashname=strndup_user(kdfcopy->hashname,CRYPTO_MAX_ALG_NAME);if(IS_ERR(hashname)){ret=PTR_ERR(hashname);-gotoout;+gotoout1;}/* allocate KDF from the kernel crypto API */ret=kdf_alloc(&sdesc,hashname);kfree(hashname);if(ret)-gotoout;+gotoout1;}-/*-*IfthecallerrequestspostprocessingwithaKDF,allowan-*arbitraryoutputbuffersizesincetheKDFensurespropertruncation.-*/-keylen=mpi_from_key(pcopy.prime,kdfcopy?SIZE_MAX:buflen,&prime);-if(keylen<0||!prime){-/* buflen == 0 may be used to query the required buffer size,-*whichistheprimekeylength.-*/-ret=keylen;-gotoout;+memset(&dh_inputs,0,sizeof(dh_inputs));++dlen=dh_data_from_key(pcopy.prime,&dh_inputs.p);+if(dlen<0){+ret=dlen;+gotoout1;}+dh_inputs.p_size=dlen;-/* The result is never longer than the prime */-resultlen=keylen;+dlen=dh_data_from_key(pcopy.base,&dh_inputs.g);+if(dlen<0){+ret=dlen;+gotoout2;+}+dh_inputs.g_size=dlen;-keylen=mpi_from_key(pcopy.base,SIZE_MAX,&base);-if(keylen<0||!base){-ret=keylen;-gotoerror1;+dlen=dh_data_from_key(pcopy.private,&dh_inputs.key);+if(dlen<0){+ret=dlen;+gotoout2;}+dh_inputs.key_size=dlen;-keylen=mpi_from_key(pcopy.private,SIZE_MAX,&private);-if(keylen<0||!private){-ret=keylen;-gotoerror2;+secretlen=crypto_dh_key_len(&dh_inputs);+secret=kmalloc(secretlen,GFP_KERNEL);+if(!secret){+ret=-ENOMEM;+gotoout2;+}+ret=crypto_dh_encode_key(secret,secretlen,&dh_inputs);+if(ret)+gotoout3;++tfm=crypto_alloc_kpp("dh",CRYPTO_ALG_TYPE_KPP,0);+if(IS_ERR(tfm)){+ret=PTR_ERR(tfm);+gotoout3;+}++ret=crypto_kpp_set_secret(tfm,secret,secretlen);+if(ret)+gotoout4;++outlen=crypto_kpp_maxsize(tfm);++if(!kdfcopy){+/*+*WhennotusingaKDF,buflen0isusedtoreadthe+*requiredbufferlength+*/+if(buflen==0){+ret=outlen;+gotoout4;+}elseif(outlen>buflen){+ret=-EOVERFLOW;+gotoout4;+}}-result=mpi_alloc(0);-if(!result){+outbuf=kzalloc(kdfcopy?(outlen+kdfcopy->otherinfolen):outlen,+GFP_KERNEL);+if(!outbuf){ret=-ENOMEM;-gotoerror3;+gotoout4;}-/* allocate space for DH shared secret and SP800-56A otherinfo */-kbuf=kmalloc(kdfcopy?(resultlen+kdfcopy->otherinfolen):resultlen,-GFP_KERNEL);-if(!kbuf){+sg_init_one(&outsg,outbuf,outlen);++req=kpp_request_alloc(tfm,GFP_KERNEL);+if(!req){ret=-ENOMEM;-gotoerror4;+gotoout5;}+kpp_request_set_input(req,NULL,0);+kpp_request_set_output(req,&outsg,outlen);+init_completion(&compl.completion);+kpp_request_set_callback(req,CRYPTO_TFM_REQ_MAY_BACKLOG|+CRYPTO_TFM_REQ_MAY_SLEEP,+dh_crypto_done,&compl);+/*-*ConcatenateSP800-56AotherinfopastDHsharedsecret--the-*inputtotheKDFis(DHsharedsecret||otherinfo)+*ForDH,generate_public_keyandgenerate_shared_secretare+*thesamecalculation*/-if(kdfcopy&&-copy_from_user(kbuf+resultlen,kdfcopy->otherinfo,-kdfcopy->otherinfolen)!=0){-ret=-EFAULT;-gotoerror5;+ret=crypto_kpp_generate_public_key(req);+if(ret==-EINPROGRESS){+wait_for_completion(&compl.completion);+ret=compl.err;+if(ret)+gotoout6;}-ret=do_dh(result,base,private,prime);-if(ret)-gotoerror5;--ret=mpi_read_buffer(result,kbuf,resultlen,&nbytes,NULL);-if(ret!=0)-gotoerror5;-if(kdfcopy){-ret=keyctl_dh_compute_kdf(sdesc,buffer,buflen,kbuf,-resultlen+kdfcopy->otherinfolen);-}else{-ret=nbytes;-if(copy_to_user(buffer,kbuf,nbytes)!=0)+/*+*ConcatenateSP800-56AotherinfopastDHsharedsecret--the+*inputtotheKDFis(DHsharedsecret||otherinfo)+*/+if(copy_from_user(outbuf+req->dst_len,kdfcopy->otherinfo,+kdfcopy->otherinfolen)!=0){ret=-EFAULT;+gotoout6;+}++ret=keyctl_dh_compute_kdf(sdesc,buffer,buflen,outbuf,+req->dst_len+kdfcopy->otherinfolen,+outlen-req->dst_len);+}elseif(copy_to_user(buffer,outbuf,req->dst_len)==0){+ret=req->dst_len;+}else{+ret=-EFAULT;}-error5:-kzfree(kbuf);-error4:-mpi_free(result);-error3:-mpi_free(private);-error2:-mpi_free(base);-error1:-mpi_free(prime);-out:+out6:+kpp_request_free(req);+out5:+kzfree(outbuf);+out4:+crypto_free_kpp(tfm);+out3:+kzfree(secret);+out2:+dh_free_data(&dh_inputs);+out1:kdf_dealloc(sdesc);returnret;}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:52:09
From: Eric Biggers <redacted>
As the previous patch did for encrypted-keys, zero sensitive any
potentially sensitive data related to the "trusted" key type before it
is freed. Notably, we were not zeroing the tpm_buf structures in which
the actual key is stored for TPM seal and unseal, nor were we zeroing
the trusted_key_payload in certain error paths.
Cc: Mimi Zohar <redacted>
Cc: David Safford <redacted>
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/trusted.c | 50 +++++++++++++++++++++--------------------------
1 file changed, 22 insertions(+), 28 deletions(-)
@@ -703,7 +703,7 @@ static int key_unseal(struct trusted_key_payload *p,/* pull migratable flag out of sealed key */p->migratable=p->key[--p->key_len];-kfree(tb);+kzfree(tb);returnret;}
@@ -1037,12 +1037,12 @@ static int trusted_instantiate(struct key *key,if(!ret&&options->pcrlock)ret=pcrlock(options->pcrlock);out:-kfree(datablob);-kfree(options);+kzfree(datablob);+kzfree(options);if(!ret)rcu_assign_keypointer(key,payload);else-kfree(payload);+kzfree(payload);returnret;}
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:53:24
From: Eric Biggers <redacted>
Zero the payloads of user and logon keys before freeing them. This
prevents sensitive key material from being kept around in the slab
caches after a key is released.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/user_defined.c | 16 ++++++++++++----
1 file changed, 12 insertions(+), 4 deletions(-)
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:54:33
From: Eric Biggers <redacted>
Before returning from add_key() or one of the keyctl() commands that
takes in a key payload, zero the temporary buffer that was allocated to
hold the key payload copied from userspace. This may contain sensitive
key material that should not be kept around in the slab caches.
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/keyctl.c | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
@@ -347,7 +350,7 @@ long keyctl_update_key(key_serial_t id,key_ref_put(key_ref);error2:-kfree(payload);+kzfree(payload);error:returnret;}
@@ -1093,7 +1096,10 @@ long keyctl_instantiate_key_common(key_serial_t id,keyctl_change_reqkey_auth(NULL);error2:-kvfree(payload);+if(payload){+memzero_explicit(payload,plen);+kvfree(payload);+}error:returnret;}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:55:06
From: Eric Biggers <redacted>
sys_add_key() and the KEYCTL_UPDATE operation of sys_keyctl() allowed a
NULL payload with nonzero length to be passed to the key type's
->preparse(), ->instantiate(), and/or ->update() methods. Various key
types including asymmetric, cifs.idmap, cifs.spnego, and pkcs7_test did
not handle this case, allowing an unprivileged user to trivially cause a
NULL pointer dereference (kernel oops) if one of these key types was
present. Fix it by doing the copy_from_user() when 'plen' is nonzero
rather than when '_payload' is non-NULL, causing the syscall to fail
with EFAULT as expected when an invalid buffer is specified.
Cc: stable at vger.kernel.org # 2.6.10+
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/keyctl.c | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
@@ -99,7 +99,7 @@ SYSCALL_DEFINE5(add_key, const char __user *, _type,/* pull the payload in if one was supplied */payload=NULL;-if(_payload){+if(plen){ret=-ENOMEM;payload=kvmalloc(plen,GFP_KERNEL);if(!payload)
@@ -324,7 +324,7 @@ long keyctl_update_key(key_serial_t id,/* pull the payload in if one was supplied */payload=NULL;-if(_payload){+if(plen){ret=-ENOMEM;payload=kmalloc(plen,GFP_KERNEL);if(!payload)--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 13:55:28
From: Eric Biggers <redacted>
The encrypted-keys module was using a single global HMAC transform,
which could be rekeyed by multiple threads concurrently operating on
different keys, causing incorrect HMAC values to be calculated. Fix
this by allocating a new HMAC transform whenever we need to calculate a
HMAC. Also simplify things a bit by allocating the shash_desc's using
SHASH_DESC_ON_STACK() for both the HMAC and unkeyed hashes.
The following script reproduces the bug:
keyctl new_session
keyctl add user master "abcdefghijklmnop" @s
for i in $(seq 2); do
(
set -e
for j in $(seq 1000); do
keyid=$(keyctl add encrypted desc$i "new user:master 25" @s)
datablob="$(keyctl pipe $keyid)"
keyctl unlink $keyid > /dev/null
keyid=$(keyctl add encrypted desc$i "load $datablob" @s)
keyctl unlink $keyid > /dev/null
done
) &
done
Output with bug:
[ 439.691094] encrypted_key: bad hmac (-22)
add_key: Invalid argument
add_key: Invalid argument
Cc: Mimi Zohar <redacted>
Cc: Herbert Xu <herbert@gondor.apana.org.au>
Signed-off-by: Eric Biggers <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/encrypted-keys/encrypted.c | 115 ++++++++----------------------
1 file changed, 32 insertions(+), 83 deletions(-)
@@ -998,47 +977,17 @@ struct key_type key_type_encrypted = {};EXPORT_SYMBOL_GPL(key_type_encrypted);-staticvoidencrypted_shash_release(void)-{-if(hashalg)-crypto_free_shash(hashalg);-if(hmacalg)-crypto_free_shash(hmacalg);-}--staticint__initencrypted_shash_alloc(void)+staticint__initinit_encrypted(void){intret;-hmacalg=crypto_alloc_shash(hmac_alg,0,CRYPTO_ALG_ASYNC);-if(IS_ERR(hmacalg)){-pr_info("encrypted_key: could not allocate crypto %s\n",-hmac_alg);-returnPTR_ERR(hmacalg);+hash_tfm=crypto_alloc_shash(hash_alg,0,CRYPTO_ALG_ASYNC);+if(IS_ERR(hash_tfm)){+pr_err("encrypted_key: can't allocate %s transform: %ld\n",+hash_alg,PTR_ERR(hash_tfm));+returnPTR_ERR(hash_tfm);}-hashalg=crypto_alloc_shash(hash_alg,0,CRYPTO_ALG_ASYNC);-if(IS_ERR(hashalg)){-pr_info("encrypted_key: could not allocate crypto %s\n",-hash_alg);-ret=PTR_ERR(hashalg);-gotohashalg_fail;-}--return0;--hashalg_fail:-crypto_free_shash(hmacalg);-returnret;-}--staticint__initinit_encrypted(void)-{-intret;--ret=encrypted_shash_alloc();-if(ret<0)-returnret;ret=aes_get_sizes();if(ret<0)gotoout;
@@ -1047,14 +996,14 @@ static int __init init_encrypted(void)gotoout;return0;out:-encrypted_shash_release();+crypto_free_shash(hash_tfm);returnret;}staticvoid__exitcleanup_encrypted(void){-encrypted_shash_release();+crypto_free_shash(hash_tfm);unregister_key_type(&key_type_encrypted);}--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info@ http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 14:04:30
From: Davidlohr Bueso <dave@stgolabs.net>
With the new standardized functions, we can replace all ACCESS_ONCE()
calls across relevant security/keyrings/.
ACCESS_ONCE() does not work reliably on non-scalar types. For example
gcc 4.6 and 4.7 might remove the volatile tag for such accesses during
the SRA (scalar replacement of aggregates) step:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=58145
Update the new calls regardless of if it is a scalar type, this is
cleaner than having three alternatives.
Signed-off-by: Davidlohr Bueso <redacted>
Signed-off-by: David Howells <dhowells@redhat.com>
---
security/keys/keyring.c | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
@@ -752,7 +752,7 @@ static bool search_nested_keyrings(struct key *keyring,ascend_to_node:/* Go through the slots in a node */for(;slot<ASSOC_ARRAY_FAN_OUT;slot++){-ptr=ACCESS_ONCE(node->slots[slot]);+ptr=READ_ONCE(node->slots[slot]);if(assoc_array_ptr_is_meta(ptr)&&node->back_pointer)gotodescend_to_node;
@@ -790,13 +790,13 @@ static bool search_nested_keyrings(struct key *keyring,/* We've dealt with all the slots in the current node, so now we need*toascendtotheparentandcontinueprocessingthere.*/-ptr=ACCESS_ONCE(node->back_pointer);+ptr=READ_ONCE(node->back_pointer);slot=node->parent_slot;if(ptr&&assoc_array_ptr_is_shortcut(ptr)){shortcut=assoc_array_ptr_to_shortcut(ptr);smp_read_barrier_depends();-ptr=ACCESS_ONCE(shortcut->back_pointer);+ptr=READ_ONCE(shortcut->back_pointer);slot=shortcut->parent_slot;}if(!ptr)--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: James Morris <jmorris@namei.org> Date: 2017-06-08 14:34:03
On Thu, 8 Jun 2017, David Howells wrote:
Note that I rebased the patches on top of -rc4 to avoid problems with a tty
locking bug encountered whilst trying to test it.
This is for current Linus, correct?
--
James Morris
[off-list ref]
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
From: David Howells <dhowells@redhat.com> Date: 2017-06-08 14:49:26
James Morris [off-list ref] wrote:
quoted
Note that I rebased the patches on top of -rc4 to avoid problems with a tty
locking bug encountered whilst trying to test it.
This is for current Linus, correct?
Yes please.
David
--
To unsubscribe from this list: send the line "unsubscribe linux-security-module" in
the body of a message to majordomo at vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html