]>
Commit | Line | Data |
---|---|---|
1218db86 GKH |
1 | From a3c812f7cfd80cf51e8f5b7034f7418f6beb56c1 Mon Sep 17 00:00:00 2001 |
2 | From: Eric Biggers <ebiggers@google.com> | |
3 | Date: Thu, 2 Nov 2017 00:47:12 +0000 | |
4 | Subject: KEYS: trusted: fix writing past end of buffer in trusted_read() | |
5 | ||
6 | From: Eric Biggers <ebiggers@google.com> | |
7 | ||
8 | commit a3c812f7cfd80cf51e8f5b7034f7418f6beb56c1 upstream. | |
9 | ||
10 | When calling keyctl_read() on a key of type "trusted", if the | |
11 | user-supplied buffer was too small, the kernel ignored the buffer length | |
12 | and just wrote past the end of the buffer, potentially corrupting | |
13 | userspace memory. Fix it by instead returning the size required, as per | |
14 | the documentation for keyctl_read(). | |
15 | ||
16 | We also don't even fill the buffer at all in this case, as this is | |
17 | slightly easier to implement than doing a short read, and either | |
18 | behavior appears to be permitted. It also makes it match the behavior | |
19 | of the "encrypted" key type. | |
20 | ||
21 | Fixes: d00a1c72f7f4 ("keys: add new trusted key-type") | |
22 | Reported-by: Ben Hutchings <ben@decadent.org.uk> | |
23 | Cc: <stable@vger.kernel.org> # v2.6.38+ | |
24 | Signed-off-by: Eric Biggers <ebiggers@google.com> | |
25 | Signed-off-by: David Howells <dhowells@redhat.com> | |
26 | Reviewed-by: Mimi Zohar <zohar@linux.vnet.ibm.com> | |
27 | Reviewed-by: James Morris <james.l.morris@oracle.com> | |
28 | Signed-off-by: James Morris <james.l.morris@oracle.com> | |
29 | Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> | |
30 | ||
31 | --- | |
32 | security/keys/trusted.c | 23 ++++++++++++----------- | |
33 | 1 file changed, 12 insertions(+), 11 deletions(-) | |
34 | ||
35 | --- a/security/keys/trusted.c | |
36 | +++ b/security/keys/trusted.c | |
37 | @@ -1065,20 +1065,21 @@ static long trusted_read(const struct ke | |
38 | p = rcu_dereference_key(key); | |
39 | if (!p) | |
40 | return -EINVAL; | |
41 | - if (!buffer || buflen <= 0) | |
42 | - return 2 * p->blob_len; | |
43 | - ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); | |
44 | - if (!ascii_buf) | |
45 | - return -ENOMEM; | |
46 | ||
47 | - bufp = ascii_buf; | |
48 | - for (i = 0; i < p->blob_len; i++) | |
49 | - bufp = hex_byte_pack(bufp, p->blob[i]); | |
50 | - if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { | |
51 | + if (buffer && buflen >= 2 * p->blob_len) { | |
52 | + ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); | |
53 | + if (!ascii_buf) | |
54 | + return -ENOMEM; | |
55 | + | |
56 | + bufp = ascii_buf; | |
57 | + for (i = 0; i < p->blob_len; i++) | |
58 | + bufp = hex_byte_pack(bufp, p->blob[i]); | |
59 | + if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) { | |
60 | + kzfree(ascii_buf); | |
61 | + return -EFAULT; | |
62 | + } | |
63 | kzfree(ascii_buf); | |
64 | - return -EFAULT; | |
65 | } | |
66 | - kzfree(ascii_buf); | |
67 | return 2 * p->blob_len; | |
68 | } | |
69 |