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

Commit 5a147c9f authored by Linus Torvalds's avatar Linus Torvalds
Browse files
Pull key subsystem fixes from James Morris:
 "Fixes for the keys subsystem, one of which addresses a use-after-free
  bug"

* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux-security:
  PEFILE: Relax the check on the length of the PKCS#7 cert
  KEYS: Fix use-after-free in assoc_array_gc()
  KEYS: Fix public_key asymmetric key subtype name
  KEYS: Increase root_maxkeys and root_maxbytes sizes
parents 014018e0 0aa04094
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ static int public_key_verify_signature_2(const struct key *key,
struct asymmetric_key_subtype public_key_subtype = {
	.owner			= THIS_MODULE,
	.name			= "public_key",
	.name_len		= sizeof("public_key") - 1,
	.describe		= public_key_describe,
	.destroy		= public_key_destroy,
	.verify_signature	= public_key_verify_signature_2,
+33 −16
Original line number Diff line number Diff line
@@ -128,6 +128,7 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
{
	struct win_certificate wrapper;
	const u8 *pkcs7;
	unsigned len;

	if (ctx->sig_len < sizeof(wrapper)) {
		pr_debug("Signature wrapper too short\n");
@@ -154,33 +155,49 @@ static int pefile_strip_sig_wrapper(const void *pebuf,
		return -ENOTSUPP;
	}

	/* Looks like actual pkcs signature length is in wrapper->length.
	 * size obtained from data dir entries lists the total size of
	 * certificate table which is also aligned to octawrod boundary.
	 *
	 * So set signature length field appropriately.
	/* It looks like the pkcs signature length in wrapper->length and the
	 * size obtained from the data dir entries, which lists the total size
	 * of certificate table, are both aligned to an octaword boundary, so
	 * we may have to deal with some padding.
	 */
	ctx->sig_len = wrapper.length;
	ctx->sig_offset += sizeof(wrapper);
	ctx->sig_len -= sizeof(wrapper);
	if (ctx->sig_len == 0) {
	if (ctx->sig_len < 4) {
		pr_debug("Signature data missing\n");
		return -EKEYREJECTED;
	}

	/* What's left should a PKCS#7 cert */
	/* What's left should be a PKCS#7 cert */
	pkcs7 = pebuf + ctx->sig_offset;
	if (pkcs7[0] == (ASN1_CONS_BIT | ASN1_SEQ)) {
		if (pkcs7[1] == 0x82 &&
		    pkcs7[2] == (((ctx->sig_len - 4) >> 8) & 0xff) &&
		    pkcs7[3] ==  ((ctx->sig_len - 4)       & 0xff))
			return 0;
		if (pkcs7[1] == 0x80)
	if (pkcs7[0] != (ASN1_CONS_BIT | ASN1_SEQ))
		goto not_pkcs7;

	switch (pkcs7[1]) {
	case 0 ... 0x7f:
		len = pkcs7[1] + 2;
		goto check_len;
	case ASN1_INDEFINITE_LENGTH:
		return 0;
		if (pkcs7[1] > 0x82)
	case 0x81:
		len = pkcs7[2] + 3;
		goto check_len;
	case 0x82:
		len = ((pkcs7[2] << 8) | pkcs7[3]) + 4;
		goto check_len;
	case 0x83 ... 0xff:
		return -EMSGSIZE;
	default:
		goto not_pkcs7;
	}

check_len:
	if (len <= ctx->sig_len) {
		/* There may be padding */
		ctx->sig_len = len;
		return 0;
	}
not_pkcs7:
	pr_debug("Signature data not PKCS#7\n");
	return -ELIBBAD;
}
+1 −1
Original line number Diff line number Diff line
@@ -1735,7 +1735,7 @@ ascend_old_tree:
gc_complete:
	edit->set[0].to = new_root;
	assoc_array_apply_edit(edit);
	edit->array->nr_leaves_on_tree = nr_leaves_on_tree;
	array->nr_leaves_on_tree = nr_leaves_on_tree;
	return 0;

enomem:
+2 −2
Original line number Diff line number Diff line
@@ -27,8 +27,8 @@ DEFINE_SPINLOCK(key_serial_lock);
struct rb_root	key_user_tree; /* tree of quota records indexed by UID */
DEFINE_SPINLOCK(key_user_lock);

unsigned int key_quota_root_maxkeys = 200;	/* root's key count quota */
unsigned int key_quota_root_maxbytes = 20000;	/* root's key space quota */
unsigned int key_quota_root_maxkeys = 1000000;	/* root's key count quota */
unsigned int key_quota_root_maxbytes = 25000000; /* root's key space quota */
unsigned int key_quota_maxkeys = 200;		/* general key count quota */
unsigned int key_quota_maxbytes = 20000;	/* general key space quota */