mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 10:07:12 +00:00
parser: make auto vars @{exec_path} and @{attach_path} local vars
Make it so the @{exec_path} and @{attach_path} variables behavior completely as local variables, overriding global variables of the same name, instead of conflicting with them. The exec var is only validate for the profile block after the attachment is defined so the pattern @{exec_path}=/path profile test @{exec_path} { @{exec_path} rw, } is valid with the global var defining the attachent which then sets the local auto @{exec_path} and @{attach_path} variables. Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
ee3b5d746f
commit
f3178d79b8
@ -464,12 +464,27 @@ struct set_value {
|
|||||||
char *val;
|
char *val;
|
||||||
struct set_value *next;
|
struct set_value *next;
|
||||||
};
|
};
|
||||||
|
enum var_type {
|
||||||
|
sd_boolean,
|
||||||
|
sd_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct symtab {
|
||||||
|
char *var_name;
|
||||||
|
enum var_type type;
|
||||||
|
int boolean;
|
||||||
|
struct set_value *values;
|
||||||
|
struct set_value *expanded;
|
||||||
|
};
|
||||||
|
|
||||||
extern int add_boolean_var(const char *var, int boolean);
|
extern int add_boolean_var(const char *var, int boolean);
|
||||||
extern int get_boolean_var(const char *var);
|
extern int get_boolean_var(const char *var);
|
||||||
extern int new_set_var(const char *var, const char *value);
|
extern int new_set_var(const char *var, const char *value);
|
||||||
extern int add_set_value(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 struct set_value *get_set_var(const char *var);
|
||||||
extern char *get_next_set_value(struct set_value **context);
|
extern char *get_next_set_value(struct set_value **context);
|
||||||
|
extern int insert_set_var(struct symtab *var);
|
||||||
|
extern struct symtab *remove_set_var(const char *var_name);
|
||||||
extern int delete_set_var(const char *var_name);
|
extern int delete_set_var(const char *var_name);
|
||||||
extern void dump_symtab(void);
|
extern void dump_symtab(void);
|
||||||
extern void dump_expanded_symtab(void);
|
extern void dump_expanded_symtab(void);
|
||||||
|
@ -28,18 +28,6 @@
|
|||||||
typedef int (*comparison_fn_t)(const void *, const void *);
|
typedef int (*comparison_fn_t)(const void *, const void *);
|
||||||
typedef void (*__free_fn_t)(void *);
|
typedef void (*__free_fn_t)(void *);
|
||||||
|
|
||||||
enum var_type {
|
|
||||||
sd_boolean,
|
|
||||||
sd_set,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct symtab {
|
|
||||||
char *var_name;
|
|
||||||
enum var_type type;
|
|
||||||
int boolean;
|
|
||||||
struct set_value *values;
|
|
||||||
struct set_value *expanded;
|
|
||||||
};
|
|
||||||
|
|
||||||
static void *my_symtab = NULL;
|
static void *my_symtab = NULL;
|
||||||
|
|
||||||
@ -209,12 +197,32 @@ out:
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int insert_set_var(struct symtab *var)
|
||||||
|
{
|
||||||
|
struct symtab **result;
|
||||||
|
|
||||||
|
result = (struct symtab **) tsearch(var, &my_symtab, (comparison_fn_t) &compare_symtabs);
|
||||||
|
if (!result) {
|
||||||
|
PERROR("Failed to allocate memory: %s\n", strerror(errno));
|
||||||
|
return errno;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*result != var) {
|
||||||
|
/* already existing variable */
|
||||||
|
PERROR("'%s' is already defined\n", var->var_name);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* new_set_var
|
/* new_set_var
|
||||||
* creates copies of arguments, so caller can free them after use
|
* creates copies of arguments, so caller can free them after use
|
||||||
*/
|
*/
|
||||||
int new_set_var(const char *var, const char *value)
|
int new_set_var(const char *var, const char *value)
|
||||||
{
|
{
|
||||||
struct symtab *n, **result;
|
struct symtab *n;
|
||||||
int rc = 0;
|
int rc = 0;
|
||||||
|
|
||||||
n = new_symtab_entry(var);
|
n = new_symtab_entry(var);
|
||||||
@ -226,20 +234,8 @@ int new_set_var(const char *var, const char *value)
|
|||||||
n->type = sd_set;
|
n->type = sd_set;
|
||||||
add_to_set(&(n->values), value);
|
add_to_set(&(n->values), value);
|
||||||
|
|
||||||
result = (struct symtab **) tsearch(n, &my_symtab, (comparison_fn_t) &compare_symtabs);
|
rc = insert_set_var(n);
|
||||||
if (!result) {
|
if (! rc)
|
||||||
PERROR("Failed to allocate memory: %s\n", strerror(errno));
|
|
||||||
rc = errno;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*result != n) {
|
|
||||||
/* already existing variable */
|
|
||||||
PERROR("'%s' is already defined\n", var);
|
|
||||||
rc = 1;
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
@ -331,25 +327,21 @@ char *get_next_set_value(struct set_value **list)
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* delete_symbol
|
|
||||||
* removes an individual variable from the symbol table. We don't
|
struct symtab *remove_set_var(const char *var_name)
|
||||||
* 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 = NULL;
|
||||||
struct symtab **result, *n, *var;
|
|
||||||
|
|
||||||
n = new_symtab_entry(var_name);
|
n = new_symtab_entry(var_name);
|
||||||
if (!n) {
|
if (!n) {
|
||||||
rc = ENOMEM;
|
//rc = ENOMEM;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
result = (struct symtab **) tfind(n, &my_symtab, (comparison_fn_t) &compare_symtabs);
|
result = (struct symtab **) tfind(n, &my_symtab, (comparison_fn_t) &compare_symtabs);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
/* XXX Warning? */
|
/* XXX Warning? */
|
||||||
|
//rc = ENOENT;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -368,11 +360,27 @@ int delete_set_var(const char *var_name)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
free_symtab(var);
|
|
||||||
|
|
||||||
out:
|
out:
|
||||||
free_symtab(n);
|
free_symtab(n);
|
||||||
return rc;
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* 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)
|
||||||
|
{
|
||||||
|
struct symtab *var;
|
||||||
|
|
||||||
|
var = remove_set_var(var_name);
|
||||||
|
if (var) {
|
||||||
|
free_symtab(var);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ENOENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void *seenlist = NULL;
|
static void *seenlist = NULL;
|
||||||
|
@ -339,6 +339,8 @@ static std::string escape_re(std::string str)
|
|||||||
int process_profile_variables(Profile *prof)
|
int process_profile_variables(Profile *prof)
|
||||||
{
|
{
|
||||||
int error = 0, rc;
|
int error = 0, rc;
|
||||||
|
struct symtab *saved_exec_path = NULL;
|
||||||
|
struct symtab *saved_attach_path = NULL;
|
||||||
|
|
||||||
/* needs to be before PROFILE_NAME_VARIABLE so that variable will
|
/* needs to be before PROFILE_NAME_VARIABLE so that variable will
|
||||||
* have the correct name
|
* have the correct name
|
||||||
@ -362,10 +364,12 @@ int process_profile_variables(Profile *prof)
|
|||||||
* the attachment.
|
* the attachment.
|
||||||
*/
|
*/
|
||||||
/* need to take into account alias, but not yet */
|
/* need to take into account alias, but not yet */
|
||||||
|
saved_attach_path = remove_set_var(PROFILE_ATTACH_VAR);
|
||||||
error = new_set_var(PROFILE_ATTACH_VAR, prof->attachment);
|
error = new_set_var(PROFILE_ATTACH_VAR, prof->attachment);
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup_name;
|
goto cleanup_name;
|
||||||
/* update to use kernel vars if available */
|
/* update to use kernel vars if available */
|
||||||
|
saved_exec_path = remove_set_var(PROFILE_EXEC_VAR);
|
||||||
error = new_set_var(PROFILE_EXEC_VAR, prof->attachment);
|
error = new_set_var(PROFILE_EXEC_VAR, prof->attachment);
|
||||||
if (error)
|
if (error)
|
||||||
goto cleanup_attach;
|
goto cleanup_attach;
|
||||||
@ -385,12 +389,16 @@ cleanup:
|
|||||||
rc = delete_set_var(PROFILE_EXEC_VAR);
|
rc = delete_set_var(PROFILE_EXEC_VAR);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = rc;
|
error = rc;
|
||||||
|
if (saved_exec_path)
|
||||||
|
insert_set_var(saved_exec_path);
|
||||||
}
|
}
|
||||||
cleanup_attach:
|
cleanup_attach:
|
||||||
if (prof->attachment) {
|
if (prof->attachment) {
|
||||||
rc = delete_set_var(PROFILE_ATTACH_VAR);
|
rc = delete_set_var(PROFILE_ATTACH_VAR);
|
||||||
if (!error)
|
if (!error)
|
||||||
error = rc;
|
error = rc;
|
||||||
|
if (saved_attach_path)
|
||||||
|
insert_set_var(saved_attach_path);
|
||||||
}
|
}
|
||||||
cleanup_name:
|
cleanup_name:
|
||||||
rc = delete_set_var(PROFILE_NAME_VARIABLE);
|
rc = delete_set_var(PROFILE_NAME_VARIABLE);
|
||||||
|
10
parser/tst/simple_tests/vars/vars_auto_attach_path_09.sd
Normal file
10
parser/tst/simple_tests/vars/vars_auto_attach_path_09.sd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION reference auto attach_path variable overrides with user defined
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{attach_path}=/path
|
||||||
|
profile /a/test/profile {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{attach_path} rwk,
|
||||||
|
|
||||||
|
}
|
16
parser/tst/simple_tests/vars/vars_auto_attach_path_10.sd
Normal file
16
parser/tst/simple_tests/vars/vars_auto_attach_path_10.sd
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#=DESCRIPTION user @{attach_path} available after override
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{attach_path}=/path
|
||||||
|
profile /a/test/profile {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{attach_path} rwk,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
profile extra {
|
||||||
|
|
||||||
|
@{attach_path} rw,
|
||||||
|
|
||||||
|
}
|
10
parser/tst/simple_tests/vars/vars_auto_attach_path_11.sd
Normal file
10
parser/tst/simple_tests/vars/vars_auto_attach_path_11.sd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION user @{attach_path} can set attachment and then auto var used
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{attach_path}=/path
|
||||||
|
profile @{attach_path} {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{attach_path} rwk,
|
||||||
|
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
#=DESCRIPTION reference auto attach_path variable collides with user defined
|
|
||||||
#=EXRESULT FAIL
|
|
||||||
|
|
||||||
@{attach_path}=/BAD
|
|
||||||
profile /a/test/profile {
|
|
||||||
/a/test/profile rix,
|
|
||||||
|
|
||||||
@{attach_path} rwk,
|
|
||||||
|
|
||||||
}
|
|
10
parser/tst/simple_tests/vars/vars_auto_exec_path_09.sd
Normal file
10
parser/tst/simple_tests/vars/vars_auto_exec_path_09.sd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION reference auto exec_path variable overrides with user defined
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{exec_path}=/path
|
||||||
|
profile /a/test/profile {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{exec_path} rwk,
|
||||||
|
|
||||||
|
}
|
16
parser/tst/simple_tests/vars/vars_auto_exec_path_10.sd
Normal file
16
parser/tst/simple_tests/vars/vars_auto_exec_path_10.sd
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
#=DESCRIPTION user @{exec_path} available after override
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{exec_path}=/path
|
||||||
|
profile /a/test/profile {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{exec_path} rwk,
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
profile extra {
|
||||||
|
|
||||||
|
@{exec_path} rw,
|
||||||
|
|
||||||
|
}
|
10
parser/tst/simple_tests/vars/vars_auto_exec_path_11.sd
Normal file
10
parser/tst/simple_tests/vars/vars_auto_exec_path_11.sd
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#=DESCRIPTION user @{exec_path} can set attachment and then auto var used
|
||||||
|
#=EXRESULT PASS
|
||||||
|
|
||||||
|
@{exec_path}=/path
|
||||||
|
profile @{exec_path} {
|
||||||
|
/a/test/profile rix,
|
||||||
|
|
||||||
|
@{exec_path} rwk,
|
||||||
|
|
||||||
|
}
|
@ -1,10 +0,0 @@
|
|||||||
#=DESCRIPTION reference auto exec_path variable collides with user defined
|
|
||||||
#=EXRESULT FAIL
|
|
||||||
|
|
||||||
@{exec_path}=/BAD
|
|
||||||
profile /a/test/profile {
|
|
||||||
/a/test/profile rix,
|
|
||||||
|
|
||||||
@{exec_path} rwk,
|
|
||||||
|
|
||||||
}
|
|
@ -43,10 +43,6 @@ skip_startswith = (
|
|||||||
'vars/vars_auto_attach_path_bad_3.sd',
|
'vars/vars_auto_attach_path_bad_3.sd',
|
||||||
'vars/vars_auto_exec_path_bad_5.sd',
|
'vars/vars_auto_exec_path_bad_5.sd',
|
||||||
'vars/vars_auto_attach_path_bad_5.sd',
|
'vars/vars_auto_attach_path_bad_5.sd',
|
||||||
|
|
||||||
# profiles that define an autovar that then gets defined causing a conflict
|
|
||||||
'vars/vars_auto_exec_path_bad_4.sd',
|
|
||||||
'vars/vars_auto_attach_path_bad_4.sd',
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# testcases that should raise an exception, but don't
|
# testcases that should raise an exception, but don't
|
||||||
|
Loading…
x
Reference in New Issue
Block a user