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

Commit 459c15e5 authored by James Morris's avatar James Morris
Browse files

Merge tag 'asn1-fixes-20150805' of...

Merge tag 'asn1-fixes-20150805' of git://git.kernel.org/pub/scm/linux/kernel/git/dhowells/linux-fs into next
parents 730daa16 233ce79d
Loading
Loading
Loading
Loading
+11 −5
Original line number Diff line number Diff line
@@ -45,23 +45,27 @@ enum asn1_opcode {
	ASN1_OP_MATCH_JUMP		= 0x04,
	ASN1_OP_MATCH_JUMP_OR_SKIP	= 0x05,
	ASN1_OP_MATCH_ANY		= 0x08,
	ASN1_OP_MATCH_ANY_OR_SKIP	= 0x09,
	ASN1_OP_MATCH_ANY_ACT		= 0x0a,
	ASN1_OP_MATCH_ANY_ACT_OR_SKIP	= 0x0b,
	/* Everything before here matches unconditionally */

	ASN1_OP_COND_MATCH_OR_SKIP	= 0x11,
	ASN1_OP_COND_MATCH_ACT_OR_SKIP	= 0x13,
	ASN1_OP_COND_MATCH_JUMP_OR_SKIP	= 0x15,
	ASN1_OP_COND_MATCH_ANY		= 0x18,
	ASN1_OP_COND_MATCH_ANY_OR_SKIP	= 0x19,
	ASN1_OP_COND_MATCH_ANY_ACT	= 0x1a,
	ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP = 0x1b,

	/* Everything before here will want a tag from the data */
#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT
#define ASN1_OP__MATCHES_TAG ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP

	/* These are here to help fill up space */
	ASN1_OP_COND_FAIL		= 0x1b,
	ASN1_OP_COMPLETE		= 0x1c,
	ASN1_OP_ACT			= 0x1d,
	ASN1_OP_RETURN			= 0x1e,
	ASN1_OP_COND_FAIL		= 0x1c,
	ASN1_OP_COMPLETE		= 0x1d,
	ASN1_OP_ACT			= 0x1e,
	ASN1_OP_MAYBE_ACT		= 0x1f,

	/* The following eight have bit 0 -> SET, 1 -> OF, 2 -> ACT */
	ASN1_OP_END_SEQ			= 0x20,
@@ -76,6 +80,8 @@ enum asn1_opcode {
#define ASN1_OP_END__OF			  0x02
#define ASN1_OP_END__ACT		  0x04

	ASN1_OP_RETURN			= 0x28,

	ASN1_OP__NR
};

+23 −4
Original line number Diff line number Diff line
@@ -24,15 +24,20 @@ static const unsigned char asn1_op_lengths[ASN1_OP__NR] = {
	[ASN1_OP_MATCH_JUMP]			= 1 + 1 + 1,
	[ASN1_OP_MATCH_JUMP_OR_SKIP]		= 1 + 1 + 1,
	[ASN1_OP_MATCH_ANY]			= 1,
	[ASN1_OP_MATCH_ANY_OR_SKIP]		= 1,
	[ASN1_OP_MATCH_ANY_ACT]			= 1         + 1,
	[ASN1_OP_MATCH_ANY_ACT_OR_SKIP]		= 1         + 1,
	[ASN1_OP_COND_MATCH_OR_SKIP]		= 1 + 1,
	[ASN1_OP_COND_MATCH_ACT_OR_SKIP]	= 1 + 1     + 1,
	[ASN1_OP_COND_MATCH_JUMP_OR_SKIP]	= 1 + 1 + 1,
	[ASN1_OP_COND_MATCH_ANY]		= 1,
	[ASN1_OP_COND_MATCH_ANY_OR_SKIP]	= 1,
	[ASN1_OP_COND_MATCH_ANY_ACT]		= 1         + 1,
	[ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP]	= 1         + 1,
	[ASN1_OP_COND_FAIL]			= 1,
	[ASN1_OP_COMPLETE]			= 1,
	[ASN1_OP_ACT]				= 1         + 1,
	[ASN1_OP_MAYBE_ACT]			= 1         + 1,
	[ASN1_OP_RETURN]			= 1,
	[ASN1_OP_END_SEQ]			= 1,
	[ASN1_OP_END_SEQ_OF]			= 1     + 1,
@@ -177,6 +182,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
	unsigned char flags = 0;
#define FLAG_INDEFINITE_LENGTH	0x01
#define FLAG_MATCHED		0x02
#define FLAG_LAST_MATCHED	0x04 /* Last tag matched */
#define FLAG_CONS		0x20 /* Corresponds to CONS bit in the opcode tag
				      * - ie. whether or not we are going to parse
				      *   a compound type.
@@ -208,9 +214,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
		unsigned char tmp;

		/* Skip conditional matches if possible */
		if ((op & ASN1_OP_MATCH__COND &&
		     flags & FLAG_MATCHED) ||
		    dp == datalen) {
		if ((op & ASN1_OP_MATCH__COND && flags & FLAG_MATCHED) ||
		    (op & ASN1_OP_MATCH__SKIP && dp == datalen)) {
			flags &= ~FLAG_LAST_MATCHED;
			pc += asn1_op_lengths[op];
			goto next_op;
		}
@@ -302,7 +308,9 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
	/* Decide how to handle the operation */
	switch (op) {
	case ASN1_OP_MATCH_ANY_ACT:
	case ASN1_OP_MATCH_ANY_ACT_OR_SKIP:
	case ASN1_OP_COND_MATCH_ANY_ACT:
	case ASN1_OP_COND_MATCH_ANY_ACT_OR_SKIP:
		ret = actions[machine[pc + 1]](context, hdr, tag, data + dp, len);
		if (ret < 0)
			return ret;
@@ -319,8 +327,10 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
	case ASN1_OP_MATCH:
	case ASN1_OP_MATCH_OR_SKIP:
	case ASN1_OP_MATCH_ANY:
	case ASN1_OP_MATCH_ANY_OR_SKIP:
	case ASN1_OP_COND_MATCH_OR_SKIP:
	case ASN1_OP_COND_MATCH_ANY:
	case ASN1_OP_COND_MATCH_ANY_OR_SKIP:
	skip_data:
		if (!(flags & FLAG_CONS)) {
			if (flags & FLAG_INDEFINITE_LENGTH) {
@@ -422,8 +432,15 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
		pc += asn1_op_lengths[op];
		goto next_op;

	case ASN1_OP_MAYBE_ACT:
		if (!(flags & FLAG_LAST_MATCHED)) {
			pc += asn1_op_lengths[op];
			goto next_op;
		}
	case ASN1_OP_ACT:
		ret = actions[machine[pc + 1]](context, hdr, tag, data + tdp, len);
		if (ret < 0)
			return ret;
		pc += asn1_op_lengths[op];
		goto next_op;

@@ -431,6 +448,7 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
		if (unlikely(jsp <= 0))
			goto jump_stack_underflow;
		pc = jump_stack[--jsp];
		flags |= FLAG_MATCHED | FLAG_LAST_MATCHED;
		goto next_op;

	default:
@@ -438,7 +456,8 @@ int asn1_ber_decoder(const struct asn1_decoder *decoder,
	}

	/* Shouldn't reach here */
	pr_err("ASN.1 decoder error: Found reserved opcode (%u)\n", op);
	pr_err("ASN.1 decoder error: Found reserved opcode (%u) pc=%zu\n",
	       op, pc);
	return -EBADMSG;

data_overrun_error:
+14 −9
Original line number Diff line number Diff line
@@ -666,7 +666,7 @@ struct element {
	unsigned	flags;
#define ELEMENT_IMPLICIT	0x0001
#define ELEMENT_EXPLICIT	0x0002
#define ELEMENT_MARKED		0x0004
#define ELEMENT_TAG_SPECIFIED	0x0004
#define ELEMENT_RENDERED	0x0008
#define ELEMENT_SKIPPABLE	0x0010
#define ELEMENT_CONDITIONAL	0x0020
@@ -879,6 +879,7 @@ static struct element *parse_type(struct token **_cursor, struct token *end,

		element->tag &= ~0x1f;
		element->tag |= strtoul(cursor->value, &p, 10);
		element->flags |= ELEMENT_TAG_SPECIFIED;
		if (p - cursor->value != cursor->size)
			abort();
		cursor++;
@@ -1376,7 +1377,7 @@ static void render_out_of_line_list(FILE *out)
 */
static void render_element(FILE *out, struct element *e, struct element *tag)
{
	struct element *ec;
	struct element *ec, *x;
	const char *cond, *act;
	int entry, skippable = 0, outofline = 0;

@@ -1400,7 +1401,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
	act = e->action ? "_ACT" : "";
	switch (e->compound) {
	case ANY:
		render_opcode(out, "ASN1_OP_%sMATCH_ANY%s,", cond, act);
		render_opcode(out, "ASN1_OP_%sMATCH_ANY%s%s,",
			      cond, act, skippable ? "_OR_SKIP" : "");
		if (e->name)
			render_more(out, "\t\t// %*.*s",
				    (int)e->name->size, (int)e->name->size,
@@ -1435,15 +1437,17 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
		break;
	}

	if (e->name)
	x = tag ?: e;
	if (x->name)
		render_more(out, "\t\t// %*.*s",
			    (int)e->name->size, (int)e->name->size,
			    e->name->value);
			    (int)x->name->size, (int)x->name->size,
			    x->name->value);
	render_more(out, "\n");

	/* Render the tag */
	if (!tag)
	if (!tag || !(tag->flags & ELEMENT_TAG_SPECIFIED))
		tag = e;

	if (tag->class == ASN1_UNIV &&
	    tag->tag != 14 &&
	    tag->tag != 15 &&
@@ -1465,7 +1469,8 @@ static void render_element(FILE *out, struct element *e, struct element *tag)
	case TYPE_REF:
		render_element(out, e->type->type->element, tag);
		if (e->action)
			render_opcode(out, "ASN1_OP_ACT,\n");
			render_opcode(out, "ASN1_OP_%sACT,\n",
				      skippable ? "MAYBE_" : "");
		break;

	case SEQUENCE:
@@ -1539,7 +1544,7 @@ static void render_element(FILE *out, struct element *e, struct element *tag)

	case CHOICE:
		for (ec = e->children; ec; ec = ec->next)
			render_element(out, ec, NULL);
			render_element(out, ec, ec);
		if (!skippable)
			render_opcode(out, "ASN1_OP_COND_FAIL,\n");
		if (e->action)