Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

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
Loading
Loading
Loading
Loading
+3 −0
Original line number Diff line number Diff line
@@ -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) {
+19 −20
Original line number Diff line number Diff line
@@ -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 */
	/* 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);
		ret = assoc_array_iterate(&keyring->keys,
					  keyring_read_iterator, &ctx);
		if (ret < 0) {
		kleave(" = %d [iterate]", ret);
			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;
}

/*
+12 −11
Original line number Diff line number Diff line
@@ -1147,8 +1147,8 @@ 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;

	if (buffer && buflen >= 2 * p->blob_len) {
		ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
		if (!ascii_buf)
			return -ENOMEM;
@@ -1156,11 +1156,12 @@ static long trusted_read(const struct key *key, char __user *buffer,
		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 (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
			kzfree(ascii_buf);
			return -EFAULT;
		}
		kzfree(ascii_buf);
	}
	return 2 * p->blob_len;
}