[apparmor] [PATCH 2/4] parser: Add support for DBus rules

Tyler Hicks tyhicks at canonical.com
Tue Jul 30 17:22:50 UTC 2013


On 2013-07-30 00:14:28, John Johansen wrote:
> On 07/29/2013 03:40 PM, Seth Arnold wrote:
> > On Sat, Jul 27, 2013 at 02:45:16AM -0700, Tyler Hicks wrote:
> >> This patch implements the parsing of DBus rules.
> >>
> 
> << snip >>
> 
> >> +}
> >> +
> >> +static void copy_conditionals(struct dbus_entry *ent, struct cond_entry *conds)
> >> +{
> >> +	struct cond_entry *cond_ent;
> >> +
> >> +	list_for_each(conds, cond_ent) {
> >> +		char **ent_member = NULL;
> >> +
> >> +		/* for now disallow keyword 'in' (list) */
> >> +		if (!cond_ent->eq)
> >> +			yyerror("keyword \"in\" is not allowed in dbus rules\n");
> >> +		if (list_len(cond_ent->vals) > 1)
> >> +			yyerror("dbus conditional \"%s\" only supports a single value\n",
> >> +				cond_ent->name);
> >> +
> >> +		if (strcmp(cond_ent->name, "bus") == 0) {
> >> +			ent_member = &ent->bus;
> >> +		} else if (strcmp(cond_ent->name, "name") == 0) {
> >> +			ent_member = &ent->name;
> >> +		} else if (strcmp(cond_ent->name, "label") == 0) {
> >> +			ent_member = &ent->peer_label;
> >> +		} else if (strcmp(cond_ent->name, "path") == 0) {
> >> +			ent_member = &ent->path;
> >> +		} else if (strcmp(cond_ent->name, "interface") == 0) {
> >> +			ent_member = &ent->interface;
> >> +		} else if (strcmp(cond_ent->name, "member") == 0) {
> >> +			ent_member = &ent->member;
> >> +		} else {
> >> +			yyerror("invalid dbus conditional \"%s\"\n",
> >> +				cond_ent->name);
> >> +		}
> >> +
> >> +		if (ent_member) {
> >> +			if (*ent_member) {
> >> +				yyerror("dbus conditional \"%s\" can only be specified once\n",
> >> +					cond_ent->name);
> >> +			}
> >> +
> >> +			(*ent_member) = cond_ent->vals->value;
> >> +		}
> >> +
> >> +		cond_ent->vals->value = NULL;
> >> +	}
> >> +}
> > 
> > This is a bit intricate :) I've read through it a few times and I'm
> > not convinced I understand it. It seems a strange place to put the 'in'
> > check, and the pointer handling seems more complicated than ideal. I'm
> > sorry though, I don't have a concrete suggestion for improvement.
> > 
> 
> The 'in' check is handled here because the code is using a common parsing
> pattern routine, to pick up the entries.  So either this needs to be
> handled in the common parsing code by setting up/passing in context,
> or in post.
> 
> This is just handling the semantic check post rule match. And the check
> is here instead of have a large code block hanging off of the yacc rule.
> 
> As for pushing the semantics down into the generic pattern, this is
> difficult to do with yacc/bison. You can pass context, but we currently
> don't, and the context can only be updated once a certain match is
> achieved and reduced. So handling setting up meaningful context for
> this to be pushed into the generic pattern is probably more work than
> its worth.
> 
> There will be some patches to start push profile/block context down but
> this is will be less work and a lot more useful.

Thanks for replying, John.

I unfortunately didn't make it clear before, but John wrote a good
amount of this patch (and some of the others) and then I've
updated/refined/changed them over time. This 'in' check came from his
original patch, so I'm glad he jumped in. :)

> 
> As for the pointer handling sure its more complicated than you might
> like but isn't that always the case with pointers? I don't see a better
> way without standard templates to achieve the abstraction here

This goofy pointer handling was one of my changes. I wanted a way to do
a single check to see if we'd be clobbering an existing conditional
value (as with '/t { dbus bus=b1 bus=b2, }') and error out when that
happens.

Seth is right, it looks more complicated than it should. I've come up
with a better way of doing this. I'll reply with a v2 patch.

Tyler

> 
> 
> << snip >>
> 
> >> +dbus_perm: TOK_VALUE
> >> +	{
> >> +		if (strcmp($1, "bind") == 0)
> >> +			$$ = AA_DBUS_BIND;
> >> +		else if (strcmp($1, "send") == 0 || strcmp($1, "write") == 0)
> >> +			$$ = AA_DBUS_SEND;
> >> +		else if (strcmp($1, "receive") == 0 || strcmp($1, "read") == 0)
> >> +			$$ = AA_DBUS_RECEIVE;
> > 
> > Is this code still needed? You've got explicit tokens lower down...
> > 
> sadly yes, though perhaps we could abstract this more.
> 
> This is the difference between a bare keyword
> 
>   dbus send blah...,
> 
> and the keyword showing up in a permission list
> 
>   dbus (send receive) blah....
> 
> >> +		else if ($1) {
> >> +			parse_dbus_mode($1, &$$, 1);
> >> +		} else
> >> +			$$ = 0;
> >> +
> >> +		if ($1)
> >> +			free($1);
> >> +	}
> >> +	| TOK_BIND { $$ = AA_DBUS_BIND; }
> >> +	| TOK_SEND { $$ = AA_DBUS_SEND; }
> >> +	| TOK_RECEIVE { $$ = AA_DBUS_RECEIVE; }
> >> +	| TOK_READ { $$ = AA_DBUS_RECEIVE; }
> >> +	| TOK_WRITE { $$ = AA_DBUS_SEND; }
> >> +	| TOK_MODE
> >> +	{
> >> +		parse_dbus_mode($1, &$$, 1);
> >> +	}
> >> +
> >> +dbus_perms: { /* nothing */ $$ = 0; }
> >> +	| dbus_perms dbus_perm { $$ = $1 | $2; }
> >> +	| dbus_perms TOK_COMMA dbus_perm { $$ = $1 | $3; }
> >> +
> >> +opt_dbus_perm: { /* nothing */ $$ = 0; }
> >> +	| dbus_perm  { $$ = $1; }
> >> +	| TOK_OPENPAREN dbus_perms TOK_CLOSEPAREN { $$ = $2; }
> >> +
> >> +dbus_rule: TOK_DBUS opt_dbus_perm opt_conds opt_cond_list TOK_END_OF_RULE
> >> +	{
> >> +		struct dbus_entry *ent;
> >> +
> >> +		ent = new_dbus_entry($2, $3, $4);
> >> +		if (!ent) {
> >> +			yyerror(_("Memory allocation error."));
> >> +		}
> >> +		$$ = ent;
> >> +	}
> >> +
> >>  hat_start: TOK_CARET {}
> >>  	| TOK_HAT {}
> >>  
> > 
> > Thanks!
> > 
> > 
> > 
> 
> 
> -- 
> AppArmor mailing list
> AppArmor at lists.ubuntu.com
> Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 836 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20130730/67248150/attachment-0001.pgp>


More information about the AppArmor mailing list