Skip to content

Commit 6965f1a

Browse files
committed
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
2 parents e78c38f + 2eb9eab commit 6965f1a

File tree

3 files changed

+34
-31
lines changed

3 files changed

+34
-31
lines changed

lib/asn1_decoder.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -284,6 +284,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
284284
if (unlikely(len > datalen - dp))
285285
goto data_overrun_error;
286286
}
287+
} else {
288+
if (unlikely(len > datalen - dp))
289+
goto data_overrun_error;
287290
}
288291

289292
if (flags & FLAG_CONS) {

security/keys/keyring.c

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring,
459459
char __user *buffer, size_t buflen)
460460
{
461461
struct keyring_read_iterator_context ctx;
462-
unsigned long nr_keys;
463-
int ret;
462+
long ret;
464463

465464
kenter("{%d},,%zu", key_serial(keyring), buflen);
466465

467466
if (buflen & (sizeof(key_serial_t) - 1))
468467
return -EINVAL;
469468

470-
nr_keys = keyring->keys.nr_leaves_on_tree;
471-
if (nr_keys == 0)
472-
return 0;
473-
474-
/* Calculate how much data we could return */
475-
if (!buffer || !buflen)
476-
return nr_keys * sizeof(key_serial_t);
477-
478-
/* Copy the IDs of the subscribed keys into the buffer */
479-
ctx.buffer = (key_serial_t __user *)buffer;
480-
ctx.buflen = buflen;
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;
469+
/* Copy as many key IDs as fit into the buffer */
470+
if (buffer && buflen) {
471+
ctx.buffer = (key_serial_t __user *)buffer;
472+
ctx.buflen = buflen;
473+
ctx.count = 0;
474+
ret = assoc_array_iterate(&keyring->keys,
475+
keyring_read_iterator, &ctx);
476+
if (ret < 0) {
477+
kleave(" = %ld [iterate]", ret);
478+
return ret;
479+
}
486480
}
487481

488-
kleave(" = %zu [ok]", ctx.count);
489-
return ctx.count;
482+
/* Return the size of the buffer needed */
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;
490489
}
491490

492491
/*

security/keys/trusted.c

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1147,20 +1147,21 @@ static long trusted_read(const struct key *key, char __user *buffer,
11471147
p = dereference_key_locked(key);
11481148
if (!p)
11491149
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;
11551150

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) {
1151+
if (buffer && buflen >= 2 * p->blob_len) {
1152+
ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
1153+
if (!ascii_buf)
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+
}
11601163
kzfree(ascii_buf);
1161-
return -EFAULT;
11621164
}
1163-
kzfree(ascii_buf);
11641165
return 2 * p->blob_len;
11651166
}
11661167

0 commit comments

Comments
 (0)