On Fri, Mar 28, 2014 at 11:15:51AM -0700, Steve Beattie wrote: > parser: add implicit set variable @{profile_name} to profile symbol table > > This patch adds the creation of an implicit set variable > @{profile_name} for use within policy. It expands to: > > - a given profile name if specified; e.g. for > 'profile flappy_bird /some/pattern/match* { [...] }' > @{profile_name} would expand to 'flappy_bird' > - if no given name, the match pattern; e.g. for > '/usr/bin/doge_bird { [...] }' > @{profile_name} would expand to '/usr/bin/doge_bird' > - hats and child profiles will include the fully qualified name; e.g. > the 'doge' hat in the /usr/bin/flappy_bird profile would cause > @{profile_name} to expand to '/usr/bin/flappy_bird//doge' within the > 'doge' hat, and '/usr/bin/flappy_bird' outside of it in the profile. > > There are some parsing tests added, but more tests are needed to verify > that expansion occurs properly (I've verified manually using parser > dumps of the added tests, but automated checks are needed). > > [A side question is whether a @{profile_hatname} or > @{profile_childname} implicit variable that doesn't include the > fully qualified path would be useful for writing template profiles > for multiple nearly identical hats.]
Might be useful, but we can await the day when we have a use for it :) > Signed-off-by: Steve Beattie <st...@nxnw.org> Acked-by: Seth Arnold <seth.arn...@canonical.com> Thanks! > --- > parser/parser.h | 4 > parser/parser_symtab.c | 63 > ++++++++++++++ > parser/parser_variable.c | 17 +++ > parser/profile.h | 24 ++++- > parser/tst/simple_tests/vars/vars_auto_profile_name_01.sd | 9 ++ > parser/tst/simple_tests/vars/vars_auto_profile_name_02.sd | 9 ++ > parser/tst/simple_tests/vars/vars_auto_profile_name_03.sd | 9 ++ > parser/tst/simple_tests/vars/vars_auto_profile_name_04.sd | 18 ++++ > parser/tst/simple_tests/vars/vars_auto_profile_name_05.sd | 40 ++++++++ > parser/tst/simple_tests/vars/vars_auto_profile_name_06.sd | 19 ++++ > parser/tst/simple_tests/vars/vars_auto_profile_name_07.sd | 22 ++++ > 11 files changed, 226 insertions(+), 8 deletions(-) > > Index: b/parser/parser_symtab.c > =================================================================== > --- a/parser/parser_symtab.c > +++ b/parser/parser_symtab.c > @@ -330,6 +330,50 @@ char *get_next_set_value(struct set_valu > return ret; > } > > +/* delete_symbol > + * removes an individual variable from the symbol table. We don't > + * support this in the language, but for special variables that change > + * between profiles, we need this. > + */ > +int delete_set_var(const char *var_name) > +{ > + int rc = 0; > + struct symtab **result, *n, *var; > + > + n = new_symtab_entry(var_name); > + if (!n) { > + rc = ENOMEM; > + goto out; > + } > + > + result = (struct symtab **) tfind(n, &my_symtab, (comparison_fn_t) > &compare_symtabs); > + if (!result) { > + /* XXX Warning? */ > + goto out; > + } > + > + var = (*result); > + > + result = (struct symtab **) tdelete(n, &my_symtab, (comparison_fn_t) > &compare_symtabs); > + if (!result) { > + PERROR("ASSERT: delete_set_var: tfind found var %s but tdelete > failed to delete it\n", > + var_name); > + exit(1); > + } > + > + if (var->type != sd_set) { > + PERROR("ASSERT: delete_set_var: deleting %s but is a boolean > variable\n", > + var_name); > + exit(1); > + } > + > + free_symtab(var); > + > +out: > + free_symtab(n); > + return rc; > +} > + > static void *seenlist = NULL; > > static int is_seen(const char *var) > @@ -708,6 +752,21 @@ int test_expand_set_var_during_dump(void > return rc; > } > > +int test_delete_set_var(void) > +{ > + int rc = 0; > + int retval; > + > + retval = new_set_var("deleteme", "delete this variable"); > + MY_TEST(retval == 0, "new delete set variable"); > + retval = delete_set_var("deleteme"); > + MY_TEST(retval == 0, "delete set variable"); > + > + free_symtabs(); > + > + return rc; > +} > + > int main(void) > { > int rc = 0; > @@ -740,6 +799,10 @@ int main(void) > if (rc == 0) > rc = retval; > > + retval = test_delete_set_var(); > + if (rc == 0) > + rc = retval; > + > retval = new_set_var("test", "test value"); > MY_TEST(retval == 0, "new set variable 1"); > > Index: b/parser/parser.h > =================================================================== > --- a/parser/parser.h > +++ b/parser/parser.h > @@ -284,6 +284,9 @@ do { > \ > version; \ > }) > > +/* The parser fills this variable in automatically */ > +#define PROFILE_NAME_VARIABLE "profile_name" > + > /* from parser_common.c */ > extern uint32_t policy_version; > extern uint32_t parser_abi_version; > @@ -404,6 +407,7 @@ extern int new_set_var(const char *var, > extern int add_set_value(const char *var, const char *value); > extern struct set_value *get_set_var(const char *var); > extern char *get_next_set_value(struct set_value **context); > +extern int delete_set_var(const char *var_name); > extern void dump_symtab(void); > extern void dump_expanded_symtab(void); > void free_symtabs(void); > Index: b/parser/parser_variable.c > =================================================================== > --- a/parser/parser_variable.c > +++ b/parser/parser_variable.c > @@ -276,11 +276,22 @@ static int process_variables_in_rules(Pr > > int process_profile_variables(Profile *prof) > { > - int error = 0; > - error = process_variables_in_entries(prof->entries); > - if (!error) > + int error = 0, rc; > + std::string *buf = prof->get_name(true); > + > + error = new_set_var(PROFILE_NAME_VARIABLE, buf->c_str()); > + delete buf; > + > + if (!error) > + error = process_variables_in_entries(prof->entries); > + > + if (!error) > error = process_variables_in_rules(*prof); > > + rc = delete_set_var(PROFILE_NAME_VARIABLE); > + if (!error) > + error = rc; > + > return error; > } > > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_01.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_01.sd > @@ -0,0 +1,9 @@ > +#=DESCRIPTION reference auto profile_name variable in rules > +#=EXRESULT PASS > + > +/a/test/profile { > + /a/test/profile rix, > + > + /var/run/@{profile_name} rwk, > + > +} > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_02.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_02.sd > @@ -0,0 +1,9 @@ > +#=DESCRIPTION reference auto profile_name variable in rules > +#=EXRESULT PASS > + > +profile /a/test/profile { > + /a/test/profile rix, > + > + /var/@{profile_name}/tmp rwk, > + > +} > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_03.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_03.sd > @@ -0,0 +1,9 @@ > +#=DESCRIPTION reference auto profile_name variable in rules > +#=EXRESULT PASS > + > +profile this_is_a_test /a/test/profile { > + /a/test/profile rix, > + > + /run/@{profile_name}/tmp rwk, > + > +} > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_04.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_04.sd > @@ -0,0 +1,18 @@ > +#=DESCRIPTION reference auto profile_name variable in rules w/hats > +#=EXRESULT PASS > + > +/test/profile { > + /test/profile rix, > + > + /run/@{profile_name}/tmp rwk, > + > + ^spork { > + owner /tmp/* r, > + /spork/@{profile_name}/** rw, > + } > + > + ^spelunkk { > + owner /tmp/* r, > + /spelunk/@{profile_name}/** rw, > + } > +} > Index: b/parser/profile.h > =================================================================== > --- a/parser/profile.h > +++ b/parser/profile.h > @@ -15,6 +15,8 @@ > #define __AA_PROFILE_H > > #include <set> > +#include <string> > +#include <iostream> > > #include "parser.h" > #include "rule.h" > @@ -225,13 +227,25 @@ public: > hat_table.dump(); > } > > - void dump_name(bool fqp) > + std::string* get_name(bool fqp) > { > + std::string *buf; > if (fqp && parent) { > - parent->dump_name(fqp); > - printf("//%s", name); > - } else > - printf("%s", name); > + buf = parent->get_name(fqp); > + buf->append("//"); > + buf->append(name); > + } else { > + return new std::string(name); > + } > + > + return buf; > + } > + > + void dump_name(bool fqp) > + { > + std::string *buf = get_name(fqp);; > + cout << *buf; > + delete buf; > } > }; > > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_05.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_05.sd > @@ -0,0 +1,40 @@ > +#=DESCRIPTION reference auto profile_name variable in rules w/hats > +#=EXRESULT PASS > + > +profile idf3s2A6GX8vrk /simple/profile { > + /test/profile rix, > + > + /run/@{profile_name}/tmp rwk, > + > + ^spork { > + owner /tmp/* r, > + /spork/@{profile_name}/** rw, > + } > + > + ^spelunkk { > + owner /tmp/* r, > + /spelunk/@{profile_name}/** rw, > + } > +} > + > +profile LzdZb9bKTMN6y /not/simple/profile { > + /test/profile rix, > + > + /run/@{profile_name}/tmp rwk, > + > + ^spork { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > + ^spelunkk { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > + ^spry { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > +} > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_06.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_06.sd > @@ -0,0 +1,19 @@ > +#=DESCRIPTION reference auto profile_name variable in rules w/Cx profiles > +#=EXRESULT PASS > + > +profile top_profile /test/profile { > + /test/profile rix, > + > + /run/@{profile_name}/tmp rwk, > + /bin/spork Cx -> spork, > + > + profile spork { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > + profile spelunkk { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > +} > Index: b/parser/tst/simple_tests/vars/vars_auto_profile_name_07.sd > =================================================================== > --- /dev/null > +++ b/parser/tst/simple_tests/vars/vars_auto_profile_name_07.sd > @@ -0,0 +1,22 @@ > +#=DESCRIPTION ensure profile_name expansion after subprofiles works > +#=EXRESULT PASS > + > +profile top_profile /test/profile { > + /test/profile rix, > + > + /first/path/@{profile_name}/tmp rwk, > + /bin/spork Cx -> spork, > + > + profile spork { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > + hat spelunkk { > + owner /tmp/* r, > + /run/@{profile_name}/** rw, > + } > + > + # Does this expand properly? > + /second/path/@{profile_name}/tmp rk, > +} > > -- > Steve Beattie > <sbeat...@ubuntu.com> > http://NxNW.org/~steve/ > -- > AppArmor mailing list > AppArmor@lists.ubuntu.com > Modify settings or unsubscribe at: > https://lists.ubuntu.com/mailman/listinfo/apparmor
signature.asc
Description: Digital signature
-- AppArmor mailing list AppArmor@lists.ubuntu.com Modify settings or unsubscribe at: https://lists.ubuntu.com/mailman/listinfo/apparmor