aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2017-11-02 10:43:40 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2017-11-02 10:43:40 -0400
commit6965f1aa7142a2989733c6ec53cc42ae97fd7f9d (patch)
treefbd13ab1bc848d3f44b821df307c8538ab965972
parente78c38f6bdd900b2ad9ac9df8eff58b745dc5b3c (diff)
parent2eb9eabf1e868fda15808954fb29b0f105ed65f1 (diff)
Merge branch 'fixes-v4.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security
Pull key handling fixes from James Morris: "Fixes for the Keys subsystem by Eric Biggers" * 'fixes-v4.14-rc7' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security: KEYS: fix out-of-bounds read during ASN.1 parsing KEYS: trusted: fix writing past end of buffer in trusted_read() KEYS: return full count in keyring_read() if buffer is too small
-rw-r--r--lib/asn1_decoder.c3
-rw-r--r--security/keys/keyring.c39
-rw-r--r--security/keys/trusted.c23
3 files changed, 34 insertions, 31 deletions
diff --git a/lib/asn1_decoder.c b/lib/asn1_decoder.c
index 0bd8a611eb83..fef5d2e114be 100644
--- a/lib/asn1_decoder.c
+++ b/lib/asn1_decoder.c
@@ -284,6 +284,9 @@ next_op:
284 if (unlikely(len > datalen - dp)) 284 if (unlikely(len > datalen - dp))
285 goto data_overrun_error; 285 goto data_overrun_error;
286 } 286 }
287 } else {
288 if (unlikely(len > datalen - dp))
289 goto data_overrun_error;
287 } 290 }
288 291
289 if (flags & FLAG_CONS) { 292 if (flags & FLAG_CONS) {
diff --git a/security/keys/keyring.c b/security/keys/keyring.c
index a7e51f793867..36f842ec87f0 100644
--- a/security/keys/keyring.c
+++ b/security/keys/keyring.c
@@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring,
459 char __user *buffer, size_t buflen) 459 char __user *buffer, size_t buflen)
460{ 460{
461 struct keyring_read_iterator_context ctx; 461 struct keyring_read_iterator_context ctx;
462 unsigned long nr_keys; 462 long ret;
463 int ret;
464 463
465 kenter("{%d},,%zu", key_serial(keyring), buflen); 464 kenter("{%d},,%zu", key_serial(keyring), buflen);
466 465
467 if (buflen & (sizeof(key_serial_t) - 1)) 466 if (buflen & (sizeof(key_serial_t) - 1))
468 return -EINVAL; 467 return -EINVAL;
469 468
470 nr_keys = keyring->keys.nr_leaves_on_tree; 469 /* Copy as many key IDs as fit into the buffer */
471 if (nr_keys == 0) 470 if (buffer && buflen) {
472 return 0; 471 ctx.buffer = (key_serial_t __user *)buffer;
473 472 ctx.buflen = buflen;
474 /* Calculate how much data we could return */ 473 ctx.count = 0;
475 if (!buffer || !buflen) 474 ret = assoc_array_iterate(&keyring->keys,
476 return nr_keys * sizeof(key_serial_t); 475 keyring_read_iterator, &ctx);
477 476 if (ret < 0) {
478 /* Copy the IDs of the subscribed keys into the buffer */ 477 kleave(" = %ld [iterate]", ret);
479 ctx.buffer = (key_serial_t __user *)buffer; 478 return ret;
480 ctx.buflen = buflen; 479 }
481 ctx.count = 0;
482 ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
483 if (ret < 0) {
484 kleave(" = %d [iterate]", ret);
485 return ret;
486 } 480 }
487 481
488 kleave(" = %zu [ok]", ctx.count); 482 /* Return the size of the buffer needed */
489 return ctx.count; 483 ret = keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t);
484 if (ret <= buflen)
485 kleave("= %ld [ok]", ret);
486 else
487 kleave("= %ld [buffer too small]", ret);
488 return ret;
490} 489}
491 490
492/* 491/*
diff --git a/security/keys/trusted.c b/security/keys/trusted.c
index bd85315cbfeb..98aa89ff7bfd 100644
--- a/security/keys/trusted.c
+++ b/security/keys/trusted.c
@@ -1147,20 +1147,21 @@ static long trusted_read(const struct key *key, char __user *buffer,
1147 p = dereference_key_locked(key); 1147 p = dereference_key_locked(key);
1148 if (!p) 1148 if (!p)
1149 return -EINVAL; 1149 return -EINVAL;
1150 if (!buffer || buflen <= 0)
1151 return 2 * p->blob_len;
1152 ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
1153 if (!ascii_buf)
1154 return -ENOMEM;
1155 1150
1156 bufp = ascii_buf; 1151 if (buffer && buflen >= 2 * p->blob_len) {
1157 for (i = 0; i < p->blob_len; i++) 1152 ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
1158 bufp = hex_byte_pack(bufp, p->blob[i]); 1153 if (!ascii_buf)
1159 if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { 1154 return -ENOMEM;
1155
1156 bufp = ascii_buf;
1157 for (i = 0; i < p->blob_len; i++)
1158 bufp = hex_byte_pack(bufp, p->blob[i]);
1159 if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
1160 kzfree(ascii_buf);
1161 return -EFAULT;
1162 }
1160 kzfree(ascii_buf); 1163 kzfree(ascii_buf);
1161 return -EFAULT;
1162 } 1164 }
1163 kzfree(ascii_buf);
1164 return 2 * p->blob_len; 1165 return 2 * p->blob_len;
1165} 1166}
1166 1167