Commit 6965f1aa authored by Linus Torvalds's avatar Linus Torvalds

Merge branch 'fixes-v4.14-rc7' of...

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
parents e78c38f6 2eb9eabf
...@@ -284,6 +284,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder, ...@@ -284,6 +284,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
if (unlikely(len > datalen - dp)) if (unlikely(len > datalen - dp))
goto data_overrun_error; goto data_overrun_error;
} }
} else {
if (unlikely(len > datalen - dp))
goto data_overrun_error;
} }
if (flags & FLAG_CONS) { if (flags & FLAG_CONS) {
......
...@@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring, ...@@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring,
char __user *buffer, size_t buflen) char __user *buffer, size_t buflen)
{ {
struct keyring_read_iterator_context ctx; struct keyring_read_iterator_context ctx;
unsigned long nr_keys; long ret;
int ret;
kenter("{%d},,%zu", key_serial(keyring), buflen); kenter("{%d},,%zu", key_serial(keyring), buflen);
if (buflen & (sizeof(key_serial_t) - 1)) if (buflen & (sizeof(key_serial_t) - 1))
return -EINVAL; return -EINVAL;
nr_keys = keyring->keys.nr_leaves_on_tree; /* Copy as many key IDs as fit into the buffer */
if (nr_keys == 0) if (buffer && buflen) {
return 0;
/* Calculate how much data we could return */
if (!buffer || !buflen)
return nr_keys * sizeof(key_serial_t);
/* Copy the IDs of the subscribed keys into the buffer */
ctx.buffer = (key_serial_t __user *)buffer; ctx.buffer = (key_serial_t __user *)buffer;
ctx.buflen = buflen; ctx.buflen = buflen;
ctx.count = 0; ctx.count = 0;
ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx); ret = assoc_array_iterate(&keyring->keys,
keyring_read_iterator, &ctx);
if (ret < 0) { if (ret < 0) {
kleave(" = %d [iterate]", ret); kleave(" = %ld [iterate]", ret);
return ret; return ret;
} }
}
kleave(" = %zu [ok]", ctx.count); /* Return the size of the buffer needed */
return ctx.count; ret = keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t);
if (ret <= buflen)
kleave("= %ld [ok]", ret);
else
kleave("= %ld [buffer too small]", ret);
return ret;
} }
/* /*
......
...@@ -1147,8 +1147,8 @@ static long trusted_read(const struct key *key, char __user *buffer, ...@@ -1147,8 +1147,8 @@ static long trusted_read(const struct key *key, char __user *buffer,
p = dereference_key_locked(key); p = dereference_key_locked(key);
if (!p) if (!p)
return -EINVAL; return -EINVAL;
if (!buffer || buflen <= 0)
return 2 * p->blob_len; if (buffer && buflen >= 2 * p->blob_len) {
ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL); ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
if (!ascii_buf) if (!ascii_buf)
return -ENOMEM; return -ENOMEM;
...@@ -1156,11 +1156,12 @@ static long trusted_read(const struct key *key, char __user *buffer, ...@@ -1156,11 +1156,12 @@ static long trusted_read(const struct key *key, char __user *buffer,
bufp = ascii_buf; bufp = ascii_buf;
for (i = 0; i < p->blob_len; i++) for (i = 0; i < p->blob_len; i++)
bufp = hex_byte_pack(bufp, p->blob[i]); bufp = hex_byte_pack(bufp, p->blob[i]);
if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) { if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
kzfree(ascii_buf); kzfree(ascii_buf);
return -EFAULT; return -EFAULT;
} }
kzfree(ascii_buf); kzfree(ascii_buf);
}
return 2 * p->blob_len; return 2 * p->blob_len;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment