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

Attachment: signature.asc
Description: Digital signature

-- 
AppArmor mailing list
AppArmor@lists.ubuntu.com
Modify settings or unsubscribe at: 
https://lists.ubuntu.com/mailman/listinfo/apparmor

Reply via email to