From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-it0-f68.google.com ([209.85.214.68]:35306 "EHLO mail-it0-f68.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753765AbdKJTaY (ORCPT ); Fri, 10 Nov 2017 14:30:24 -0500 Received: by mail-it0-f68.google.com with SMTP id u132so2913036ita.0 for ; Fri, 10 Nov 2017 11:30:24 -0800 (PST) From: Eric Biggers To: stable@vger.kernel.org Cc: ben@decadent.org.uk, dhowells@redhat.com, james.l.morris@oracle.com, zohar@linux.vnet.ibm.com, Eric Biggers Subject: [PATCH 2/2] KEYS: trusted: fix writing past end of buffer in trusted_read() Date: Fri, 10 Nov 2017 11:28:51 -0800 Message-Id: <20171110192851.136444-2-ebiggers@google.com> In-Reply-To: <20171110192851.136444-1-ebiggers@google.com> References: <20171110192851.136444-1-ebiggers@google.com> Sender: stable-owner@vger.kernel.org List-ID: commit a3c812f7cfd80cf51e8f5b7034f7418f6beb56c1 upstream. [Please apply to 3.18-stable.] When calling keyctl_read() on a key of type "trusted", if the user-supplied buffer was too small, the kernel ignored the buffer length and just wrote past the end of the buffer, potentially corrupting userspace memory. Fix it by instead returning the size required, as per the documentation for keyctl_read(). We also don't even fill the buffer at all in this case, as this is slightly easier to implement than doing a short read, and either behavior appears to be permitted. It also makes it match the behavior of the "encrypted" key type. Fixes: d00a1c72f7f4 ("keys: add new trusted key-type") Reported-by: Ben Hutchings Cc: # v2.6.38+ Signed-off-by: Eric Biggers Signed-off-by: David Howells Reviewed-by: Mimi Zohar Reviewed-by: James Morris Signed-off-by: James Morris --- security/keys/trusted.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/security/keys/trusted.c b/security/keys/trusted.c index 917453895cbc..1273e22aaa28 100644 --- a/security/keys/trusted.c +++ b/security/keys/trusted.c @@ -1065,20 +1065,21 @@ static long trusted_read(const struct key *key, char __user *buffer, p = rcu_dereference_key(key); if (!p) return -EINVAL; - if (!buffer || buflen <= 0) - return 2 * p->blob_len; - ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); - if (!ascii_buf) - return -ENOMEM; - bufp = ascii_buf; - for (i = 0; i < p->blob_len; i++) - bufp = hex_byte_pack(bufp, p->blob[i]); - if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { + if (buffer && buflen >= 2 * p->blob_len) { + ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); + if (!ascii_buf) + return -ENOMEM; + + bufp = ascii_buf; + for (i = 0; i < p->blob_len; i++) + bufp = hex_byte_pack(bufp, p->blob[i]); + if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { + kzfree(ascii_buf); + return -EFAULT; + } kzfree(ascii_buf); - return -EFAULT; } - kzfree(ascii_buf); return 2 * p->blob_len; } -- 2.15.0.448.gf294e3d99a-goog