2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-31 22:35:35 +00:00

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).

The @{profile_name} variable is expected to be most useful in the
context of signal and ptrace rules (e.g. for specifying that an app
can send itself signals).

Signed-off-by: Steve Beattie <steve@nxnw.org>
Acked-by: Seth Arnold <seth.arnold@canonical.com>
This commit is contained in:
Steve Beattie
2014-04-23 16:38:29 -07:00
parent e9019eb650
commit a67d9be5a2
11 changed files with 226 additions and 8 deletions

View File

@@ -290,6 +290,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;
@@ -412,6 +415,7 @@ extern int new_set_var(const char *var, const char *value);
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);

View File

@@ -330,6 +330,50 @@ char *get_next_set_value(struct set_value **list)
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");

View File

@@ -276,11 +276,22 @@ static int process_variables_in_rules(Profile &prof)
int process_profile_variables(Profile *prof)
{
int error = 0;
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;
}

View File

@@ -15,6 +15,8 @@
#define __AA_PROFILE_H
#include <set>
#include <string>
#include <iostream>
#include "parser.h"
#include "rule.h"
@@ -229,13 +231,25 @@ public:
hat_table.dump();
}
std::string* get_name(bool fqp)
{
std::string *buf;
if (fqp && parent) {
buf = parent->get_name(fqp);
buf->append("//");
buf->append(name);
} else {
return new std::string(name);
}
return buf;
}
void dump_name(bool fqp)
{
if (fqp && parent) {
parent->dump_name(fqp);
printf("//%s", name);
} else
printf("%s", name);
std::string *buf = get_name(fqp);;
cout << *buf;
delete buf;
}
};

View File

@@ -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,
}

View File

@@ -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,
}

View File

@@ -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,
}

View File

@@ -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,
}
}

View File

@@ -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,
}
}

View File

@@ -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,
}
}

View File

@@ -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,
}