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:
@@ -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);
|
||||
|
@@ -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");
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
@@ -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;
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -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,
|
||||
|
||||
}
|
@@ -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,
|
||||
|
||||
}
|
@@ -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,
|
||||
|
||||
}
|
18
parser/tst/simple_tests/vars/vars_auto_profile_name_04.sd
Normal file
18
parser/tst/simple_tests/vars/vars_auto_profile_name_04.sd
Normal 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,
|
||||
}
|
||||
}
|
40
parser/tst/simple_tests/vars/vars_auto_profile_name_05.sd
Normal file
40
parser/tst/simple_tests/vars/vars_auto_profile_name_05.sd
Normal 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,
|
||||
}
|
||||
|
||||
}
|
19
parser/tst/simple_tests/vars/vars_auto_profile_name_06.sd
Normal file
19
parser/tst/simple_tests/vars/vars_auto_profile_name_06.sd
Normal 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,
|
||||
}
|
||||
}
|
22
parser/tst/simple_tests/vars/vars_auto_profile_name_07.sd
Normal file
22
parser/tst/simple_tests/vars/vars_auto_profile_name_07.sd
Normal 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,
|
||||
}
|
Reference in New Issue
Block a user