mirror of
https://gitlab.com/apparmor/apparmor
synced 2025-08-22 18:17:09 +00:00
parser: Stop splitting the namespace from the named transition targets
The parser was splitting up the namespace and profile name from named transition targets only to rejoin it later when creating the binary policy. This complicated the changes needed to support the stacking identifier '&' in named transition targets. To keep the stacking support simple, this patch keeps the entire named transition target string intact from initial profile parsing to writing out the binary. All of these changes are straightforward except the hunk that removes the namespace string addition to the vector in the process_dfa_entry() function. After speaking with John, kernels with stacking have support for consuming the namespace with the profile name. Signed-off-by: Tyler Hicks <tyhicks@canonical.com> Acked-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
a49c988c03
commit
a83d03a6a7
@ -66,13 +66,6 @@ struct prefixes {
|
|||||||
int owner;
|
int owner;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
struct named_transition {
|
|
||||||
int present;
|
|
||||||
char *ns;
|
|
||||||
char *name;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct cod_pattern {
|
struct cod_pattern {
|
||||||
char *regex; // posix regex
|
char *regex; // posix regex
|
||||||
};
|
};
|
||||||
@ -98,7 +91,6 @@ struct cond_entry_list {
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct cod_entry {
|
struct cod_entry {
|
||||||
char *ns;
|
|
||||||
char *name;
|
char *name;
|
||||||
union {
|
union {
|
||||||
char *link_name;
|
char *link_name;
|
||||||
@ -393,10 +385,9 @@ extern int get_rlimit(const char *name);
|
|||||||
extern char *process_var(const char *var);
|
extern char *process_var(const char *var);
|
||||||
extern int parse_mode(const char *mode);
|
extern int parse_mode(const char *mode);
|
||||||
extern int parse_X_mode(const char *X, int valid, const char *str_mode, int *mode, int fail);
|
extern int parse_X_mode(const char *X, int valid, const char *str_mode, int *mode, int fail);
|
||||||
|
bool label_contains_ns(const char *label);
|
||||||
void parse_label(char **ns, char **name, const char *label);
|
void parse_label(char **ns, char **name, const char *label);
|
||||||
void parse_named_transition_target(struct named_transition *nt,
|
extern struct cod_entry *new_entry(char *id, int mode, char *link_id);
|
||||||
const char *target);
|
|
||||||
extern struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id);
|
|
||||||
|
|
||||||
/* returns -1 if value != true or false, otherwise 0 == false, 1 == true */
|
/* returns -1 if value != true or false, otherwise 0 == false, 1 == true */
|
||||||
extern int str_to_boolean(const char* str);
|
extern int str_to_boolean(const char* str);
|
||||||
|
@ -32,18 +32,6 @@ static int file_comp(const void *c1, const void *c2)
|
|||||||
e2 = (struct cod_entry **)c2;
|
e2 = (struct cod_entry **)c2;
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
//PERROR("strcmp %s %s\n", (*e1)->name, (*e2)->name);
|
|
||||||
if ((*e1)->ns) {
|
|
||||||
if ((*e2)->ns)
|
|
||||||
res = strcmp((*e1)->ns, (*e2)->ns);
|
|
||||||
else
|
|
||||||
return 1;
|
|
||||||
} else if ((*e2)->ns) {
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
if (res)
|
|
||||||
return res;
|
|
||||||
|
|
||||||
if ((*e1)->link_name) {
|
if ((*e1)->link_name) {
|
||||||
if ((*e2)->link_name)
|
if ((*e2)->link_name)
|
||||||
res = strcmp((*e1)->link_name, (*e2)->link_name);
|
res = strcmp((*e1)->link_name, (*e2)->link_name);
|
||||||
|
@ -637,6 +637,16 @@ static int _parse_label(char **ns, size_t *ns_len,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool label_contains_ns(const char *label)
|
||||||
|
{
|
||||||
|
char *ns = NULL;
|
||||||
|
char *name = NULL;
|
||||||
|
size_t ns_len = 0;
|
||||||
|
size_t name_len = 0;
|
||||||
|
|
||||||
|
return _parse_label(&ns, &ns_len, &name, &name_len, label) == 0 && ns;
|
||||||
|
}
|
||||||
|
|
||||||
void parse_label(char **_ns, char **_name, const char *label)
|
void parse_label(char **_ns, char **_name, const char *label)
|
||||||
{
|
{
|
||||||
char *ns = NULL;
|
char *ns = NULL;
|
||||||
@ -671,20 +681,7 @@ void parse_label(char **_ns, char **_name, const char *label)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void parse_named_transition_target(struct named_transition *nt,
|
struct cod_entry *new_entry(char *id, int mode, char *link_id)
|
||||||
const char *target)
|
|
||||||
{
|
|
||||||
memset(nt, 0, sizeof(*nt));
|
|
||||||
if (!target) {
|
|
||||||
/* Return with nt->present set to 0 (thanks to the memset) */
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
parse_label(&nt->ns, &nt->name, target);
|
|
||||||
nt->present = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id)
|
|
||||||
{
|
{
|
||||||
struct cod_entry *entry = NULL;
|
struct cod_entry *entry = NULL;
|
||||||
|
|
||||||
@ -692,7 +689,6 @@ struct cod_entry *new_entry(char *ns, char *id, int mode, char *link_id)
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
entry->ns = ns;
|
|
||||||
entry->name = id;
|
entry->name = id;
|
||||||
entry->link_name = link_id;
|
entry->link_name = link_id;
|
||||||
entry->mode = mode;
|
entry->mode = mode;
|
||||||
@ -716,7 +712,6 @@ struct cod_entry *copy_cod_entry(struct cod_entry *orig)
|
|||||||
if (!entry)
|
if (!entry)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
DUP_STRING(orig, entry, ns, err);
|
|
||||||
DUP_STRING(orig, entry, name, err);
|
DUP_STRING(orig, entry, name, err);
|
||||||
DUP_STRING(orig, entry, link_name, err);
|
DUP_STRING(orig, entry, link_name, err);
|
||||||
DUP_STRING(orig, entry, nt_name, err);
|
DUP_STRING(orig, entry, nt_name, err);
|
||||||
@ -743,8 +738,6 @@ void free_cod_entries(struct cod_entry *list)
|
|||||||
return;
|
return;
|
||||||
if (list->next)
|
if (list->next)
|
||||||
free_cod_entries(list->next);
|
free_cod_entries(list->next);
|
||||||
if (list->ns)
|
|
||||||
free(list->ns);
|
|
||||||
if (list->name)
|
if (list->name)
|
||||||
free(list->name);
|
free(list->name);
|
||||||
if (list->link_name)
|
if (list->link_name)
|
||||||
@ -797,9 +790,6 @@ void debug_cod_entries(struct cod_entry *list)
|
|||||||
else
|
else
|
||||||
printf("\tName:\tNULL\n");
|
printf("\tName:\tNULL\n");
|
||||||
|
|
||||||
if (item->ns)
|
|
||||||
printf("\tNs:\t(%s)\n", item->ns);
|
|
||||||
|
|
||||||
if (AA_LINK_BITS & item->mode)
|
if (AA_LINK_BITS & item->mode)
|
||||||
printf("\tlink:\t(%s)\n", item->link_name ? item->link_name : "/**");
|
printf("\tlink:\t(%s)\n", item->link_name ? item->link_name : "/**");
|
||||||
|
|
||||||
|
@ -91,7 +91,7 @@ static int add_named_transition(Profile *prof, struct cod_entry *entry)
|
|||||||
char *name = NULL;
|
char *name = NULL;
|
||||||
|
|
||||||
/* check to see if it is a local transition */
|
/* check to see if it is a local transition */
|
||||||
if (!entry->ns) {
|
if (!label_contains_ns(entry->nt_name)) {
|
||||||
char *sub = strstr(entry->nt_name, "//");
|
char *sub = strstr(entry->nt_name, "//");
|
||||||
/* does the subprofile name match the rule */
|
/* does the subprofile name match the rule */
|
||||||
|
|
||||||
@ -128,15 +128,11 @@ static int add_named_transition(Profile *prof, struct cod_entry *entry)
|
|||||||
entry->nt_name = NULL;
|
entry->nt_name = NULL;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
name = (char *) malloc(strlen(entry->ns) + strlen(entry->nt_name) + 3);
|
/**
|
||||||
if (!name) {
|
* pass control of the memory pointed to by nt_name
|
||||||
PERROR("Memory allocation error\n");
|
* from entry to add_entry_to_x_table()
|
||||||
exit(1);
|
*/
|
||||||
}
|
name = entry->nt_name;
|
||||||
sprintf(name, ":%s:%s", entry->ns, entry->nt_name);
|
|
||||||
free(entry->ns);
|
|
||||||
free(entry->nt_name);
|
|
||||||
entry->ns = NULL;
|
|
||||||
entry->nt_name = NULL;
|
entry->nt_name = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -184,7 +180,7 @@ void post_process_file_entries(Profile *prof)
|
|||||||
PERROR("Memory allocation error\n");
|
PERROR("Memory allocation error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
new_ent = new_entry(NULL, buffer, AA_MAY_WRITE, NULL);
|
new_ent = new_entry(buffer, AA_MAY_WRITE, NULL);
|
||||||
if (!new_ent) {
|
if (!new_ent) {
|
||||||
PERROR("Memory allocation error\n");
|
PERROR("Memory allocation error\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
@ -214,7 +210,7 @@ static int profile_add_hat_rules(Profile *prof)
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* add entry to hat */
|
/* add entry to hat */
|
||||||
entry = new_entry(NULL, strdup(CHANGEHAT_PATH), AA_MAY_WRITE, NULL);
|
entry = new_entry(strdup(CHANGEHAT_PATH), AA_MAY_WRITE, NULL);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
return ENOMEM;
|
return ENOMEM;
|
||||||
|
|
||||||
|
@ -585,11 +585,6 @@ static int process_dfa_entry(aare_rules *dfarules, struct cod_entry *entry)
|
|||||||
/* allow change_profile for all execs */
|
/* allow change_profile for all execs */
|
||||||
vec[0] = "/[^/\\x00][^\\x00]*";
|
vec[0] = "/[^/\\x00][^\\x00]*";
|
||||||
|
|
||||||
if (entry->ns) {
|
|
||||||
int pos;
|
|
||||||
ptype = convert_aaregex_to_pcre(entry->ns, 0, glob_default, lbuf, &pos);
|
|
||||||
vec[index++] = lbuf.c_str();
|
|
||||||
}
|
|
||||||
vec[index++] = tbuf.c_str();
|
vec[index++] = tbuf.c_str();
|
||||||
|
|
||||||
/* regular change_profile rule */
|
/* regular change_profile rule */
|
||||||
|
@ -71,8 +71,7 @@
|
|||||||
|
|
||||||
int parser_token = 0;
|
int parser_token = 0;
|
||||||
|
|
||||||
struct cod_entry *do_file_rule(char *ns, char *id, int mode,
|
struct cod_entry *do_file_rule(char *id, int mode, char *link_id, char *nt);
|
||||||
char *link_id, char *nt);
|
|
||||||
mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
|
mnt_rule *do_mnt_rule(struct cond_entry *src_conds, char *src,
|
||||||
struct cond_entry *dst_conds, char *dst,
|
struct cond_entry *dst_conds, char *dst,
|
||||||
int mode);
|
int mode);
|
||||||
@ -212,7 +211,6 @@ void add_local_entry(Profile *prof);
|
|||||||
struct cond_entry *cond_entry;
|
struct cond_entry *cond_entry;
|
||||||
struct cond_entry_list cond_entry_list;
|
struct cond_entry_list cond_entry_list;
|
||||||
int boolean;
|
int boolean;
|
||||||
struct named_transition transition;
|
|
||||||
struct prefixes prefix;
|
struct prefixes prefix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -277,7 +275,7 @@ void add_local_entry(Profile *prof);
|
|||||||
%type <fmode> opt_net_perm
|
%type <fmode> opt_net_perm
|
||||||
%type <unix_entry> unix_rule
|
%type <unix_entry> unix_rule
|
||||||
%type <id> opt_target
|
%type <id> opt_target
|
||||||
%type <transition> opt_named_transition
|
%type <id> opt_named_transition
|
||||||
%type <boolean> opt_unsafe
|
%type <boolean> opt_unsafe
|
||||||
%type <boolean> opt_file
|
%type <boolean> opt_file
|
||||||
%%
|
%%
|
||||||
@ -1048,14 +1046,10 @@ id_or_var: TOK_SET_VAR { $$ = $1; };
|
|||||||
opt_target: /* nothing */ { $$ = NULL; }
|
opt_target: /* nothing */ { $$ = NULL; }
|
||||||
opt_target: TOK_ARROW id_or_var { $$ = $2; };
|
opt_target: TOK_ARROW id_or_var { $$ = $2; };
|
||||||
|
|
||||||
opt_named_transition:
|
opt_named_transition: { /* nothing */ $$ = NULL; }
|
||||||
{ /* nothing */
|
|
||||||
parse_named_transition_target(&$$, NULL);
|
|
||||||
}
|
|
||||||
| TOK_ARROW id_or_var
|
| TOK_ARROW id_or_var
|
||||||
{
|
{
|
||||||
parse_named_transition_target(&$$, $2);
|
$$ = $2;
|
||||||
free($2);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
rule: file_rule { $$ = $1; }
|
rule: file_rule { $$ = $1; }
|
||||||
@ -1070,23 +1064,24 @@ opt_file: { /* nothing */ $$ = 0; }
|
|||||||
|
|
||||||
frule: id_or_var file_mode opt_named_transition TOK_END_OF_RULE
|
frule: id_or_var file_mode opt_named_transition TOK_END_OF_RULE
|
||||||
{
|
{
|
||||||
$$ = do_file_rule($3.ns, $1, $2, NULL, $3.name);
|
$$ = do_file_rule($1, $2, NULL, $3);
|
||||||
};
|
};
|
||||||
|
|
||||||
frule: file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
|
frule: file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
|
||||||
{
|
{
|
||||||
if ($2 && ($1 & ~AA_LINK_BITS))
|
if ($2 && ($1 & ~AA_LINK_BITS))
|
||||||
yyerror(_("subset can only be used with link rules."));
|
yyerror(_("subset can only be used with link rules."));
|
||||||
if ($4.present && ($1 & AA_LINK_BITS) && ($1 & AA_EXEC_BITS))
|
if ($4 && ($1 & AA_LINK_BITS) && ($1 & AA_EXEC_BITS))
|
||||||
yyerror(_("link and exec perms conflict on a file rule using ->"));
|
yyerror(_("link and exec perms conflict on a file rule using ->"));
|
||||||
if ($4.present && $4.ns && ($1 & AA_LINK_BITS))
|
if ($4 && label_contains_ns($4) && ($1 & AA_LINK_BITS))
|
||||||
yyerror(_("link perms are not allowed on a named profile transition.\n"));
|
yyerror(_("link perms are not allowed on a named profile transition.\n"));
|
||||||
|
|
||||||
if (($1 & AA_LINK_BITS)) {
|
if (($1 & AA_LINK_BITS)) {
|
||||||
$$ = do_file_rule(NULL, $3, $1, $4.name, NULL);
|
$$ = do_file_rule($3, $1, $4, NULL);
|
||||||
$$->subset = $2;
|
$$->subset = $2;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$$ = do_file_rule($4.ns, $3, $1, NULL, $4.name);
|
$$ = do_file_rule($3, $1, NULL, $4);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -1099,7 +1094,7 @@ file_rule: TOK_FILE TOK_END_OF_RULE
|
|||||||
perms |= perms << AA_OTHER_SHIFT;
|
perms |= perms << AA_OTHER_SHIFT;
|
||||||
if (!path)
|
if (!path)
|
||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
$$ = do_file_rule(NULL, path, perms, NULL, NULL);
|
$$ = do_file_rule(path, perms, NULL, NULL);
|
||||||
}
|
}
|
||||||
| opt_file file_rule_tail { $$ = $2; }
|
| opt_file file_rule_tail { $$ = $2; }
|
||||||
|
|
||||||
@ -1132,7 +1127,7 @@ link_rule: TOK_LINK opt_subset_flag id_or_var TOK_ARROW id_or_var TOK_END_OF_RUL
|
|||||||
{
|
{
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
|
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
|
||||||
entry = new_entry(NULL, $3, AA_LINK_BITS, $5);
|
entry = new_entry($3, AA_LINK_BITS, $5);
|
||||||
entry->subset = $2;
|
entry->subset = $2;
|
||||||
PDEBUG("rule.entry: link (%s)\n", entry->name);
|
PDEBUG("rule.entry: link (%s)\n", entry->name);
|
||||||
$$ = entry;
|
$$ = entry;
|
||||||
@ -1486,17 +1481,16 @@ change_profile: change_profile_head opt_named_transition TOK_END_OF_RULE
|
|||||||
{
|
{
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
|
|
||||||
if ($2.present) {
|
if ($2) {
|
||||||
PDEBUG("Matched change_profile: tok_id (:%s://%s)\n",
|
PDEBUG("Matched change_profile: tok_id (%s)\n", $2);
|
||||||
$2.ns ? $2.ns : "", $2.name);
|
entry = new_entry($2, AA_CHANGE_PROFILE, $1);
|
||||||
entry = new_entry($2.ns, $2.name, AA_CHANGE_PROFILE, $1);
|
|
||||||
} else {
|
} else {
|
||||||
char *rule = strdup("**");
|
char *rule = strdup("**");
|
||||||
if (!rule)
|
if (!rule)
|
||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
|
|
||||||
PDEBUG("Matched change_profile,\n");
|
PDEBUG("Matched change_profile,\n");
|
||||||
entry = new_entry(NULL, rule, AA_CHANGE_PROFILE, $1);
|
entry = new_entry(rule, AA_CHANGE_PROFILE, $1);
|
||||||
}
|
}
|
||||||
if (!entry)
|
if (!entry)
|
||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
@ -1567,12 +1561,11 @@ void yyerror(const char *msg, ...)
|
|||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct cod_entry *do_file_rule(char *ns, char *id, int mode,
|
struct cod_entry *do_file_rule(char *id, int mode, char *link_id, char *nt)
|
||||||
char *link_id, char *nt)
|
|
||||||
{
|
{
|
||||||
struct cod_entry *entry;
|
struct cod_entry *entry;
|
||||||
PDEBUG("Matched: tok_id (%s) tok_mode (0x%x)\n", id, mode);
|
PDEBUG("Matched: tok_id (%s) tok_mode (0x%x)\n", id, mode);
|
||||||
entry = new_entry(ns, id, mode, link_id);
|
entry = new_entry(id, mode, link_id);
|
||||||
if (!entry)
|
if (!entry)
|
||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
entry->nt_name = nt;
|
entry->nt_name = nt;
|
||||||
@ -1595,7 +1588,7 @@ void add_local_entry(Profile *prof)
|
|||||||
yyerror(_("Memory allocation error."));
|
yyerror(_("Memory allocation error."));
|
||||||
sprintf(name, "%s//%s", prof->parent->name, prof->name);
|
sprintf(name, "%s//%s", prof->parent->name, prof->name);
|
||||||
|
|
||||||
entry = new_entry(NULL, name, prof->local_mode, NULL);
|
entry = new_entry(name, prof->local_mode, NULL);
|
||||||
entry->audit = prof->local_audit;
|
entry->audit = prof->local_audit;
|
||||||
entry->nt_name = trans;
|
entry->nt_name = trans;
|
||||||
if (!entry)
|
if (!entry)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user