[apparmor] [patch 2/2] parser: add implicit set variable @{profile_name} to profile symbol table
Seth Arnold
seth.arnold at canonical.com
Wed Apr 23 22:51:54 UTC 2014
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 <steve at nxnw.org>
Acked-by: Seth Arnold <seth.arnold at 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
> <sbeattie at ubuntu.com>
> http://NxNW.org/~steve/
> --
> 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: 473 bytes
Desc: Digital signature
URL: <https://lists.ubuntu.com/archives/apparmor/attachments/20140423/79b7cd89/attachment-0001.pgp>
More information about the AppArmor
mailing list