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
This commit is contained in:
commit
6965f1aa71
|
@ -284,6 +284,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
|
|||
if (unlikely(len > datalen - dp))
|
||||
goto data_overrun_error;
|
||||
}
|
||||
} else {
|
||||
if (unlikely(len > datalen - dp))
|
||||
goto data_overrun_error;
|
||||
}
|
||||
|
||||
if (flags & FLAG_CONS) {
|
||||
|
|
|
@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring,
|
|||
char __user *buffer, size_t buflen)
|
||||
{
|
||||
struct keyring_read_iterator_context ctx;
|
||||
unsigned long nr_keys;
|
||||
int ret;
|
||||
long ret;
|
||||
|
||||
kenter("{%d},,%zu", key_serial(keyring), buflen);
|
||||
|
||||
if (buflen & (sizeof(key_serial_t) - 1))
|
||||
return -EINVAL;
|
||||
|
||||
nr_keys = keyring->keys.nr_leaves_on_tree;
|
||||
if (nr_keys == 0)
|
||||
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.buflen = buflen;
|
||||
ctx.count = 0;
|
||||
ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
|
||||
if (ret < 0) {
|
||||
kleave(" = %d [iterate]", ret);
|
||||
return ret;
|
||||
/* Copy as many key IDs as fit into the buffer */
|
||||
if (buffer && buflen) {
|
||||
ctx.buffer = (key_serial_t __user *)buffer;
|
||||
ctx.buflen = buflen;
|
||||
ctx.count = 0;
|
||||
ret = assoc_array_iterate(&keyring->keys,
|
||||
keyring_read_iterator, &ctx);
|
||||
if (ret < 0) {
|
||||
kleave(" = %ld [iterate]", ret);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
kleave(" = %zu [ok]", ctx.count);
|
||||
return ctx.count;
|
||||
/* Return the size of the buffer needed */
|
||||
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,20 +1147,21 @@ static long trusted_read(const struct key *key, char __user *buffer,
|
|||
p = dereference_key_locked(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;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue