2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 01:57:43 +00:00

Named transition - but disabled due to a bug

This commit is contained in:
John Johansen 2008-04-16 04:45:02 +00:00
parent db34aac811
commit 015df061e3
7 changed files with 286 additions and 38 deletions

View File

@ -31,6 +31,12 @@ struct flagval {
int audit;
};
struct named_transition {
int present;
char *namespace;
char *name;
};
struct cod_pattern {
char *regex; // posix regex
pcre *compiled; // compiled regex, size is compiled->size
@ -40,6 +46,7 @@ struct cod_entry {
char *namespace;
char *name;
char *link_name;
char *nt_name;
struct codomain *codomain; /* Special codomain defined
* just for this executable */
int mode; /* mode is 'or' of AA_* bits */
@ -73,6 +80,9 @@ struct codomain {
char *name; /* codomain name */
char *sub_name; /* subdomain name or NULL */
int default_deny; /* TRUE or FALSE */
int local;
int local_mode; /* true if local, not hat */
int local_audit;
struct codomain *parent;
@ -92,6 +102,7 @@ struct codomain {
struct aa_rlimits rlimits;
char *exec_table[AA_EXEC_COUNT];
struct cod_entry *entries;
void *hat_table;
//struct codomain *next;

View File

@ -377,13 +377,11 @@ inline int sd_write_aligned_blob(sd_serialize *p, void *b, int buf_size,
return 1;
}
inline int sd_write_string(sd_serialize *p, char *b, char *name)
static int sd_write_strn(sd_serialize *p, char *b, int size, char *name)
{
u16 tmp;
int size;
if (!sd_write_name(p, name))
return 0;
size = strlen(b) + 1;
if (!sd_prepare_write(p, SD_STRING, SD_STR_LEN + size))
return 0;
tmp = cpu_to_le16(size);
@ -394,6 +392,11 @@ inline int sd_write_string(sd_serialize *p, char *b, char *name)
return 1;
}
inline int sd_write_string(sd_serialize *p, char *b, char *name)
{
return sd_write_strn(p, b, strlen(b) + 1, name);
}
inline int sd_write_struct(sd_serialize *p, char *name)
{
if (!sd_write_name(p, name))
@ -527,6 +530,41 @@ int sd_serialize_rlimits(sd_serialize *p, struct aa_rlimits *limits)
return 1;
}
int sd_serialize_xtable(sd_serialize *p, char **table)
{
int count, i;
if (!table[4])
return 1;
if (!sd_write_struct(p, "xtable"))
return 0;
count = 0;
for (i = 4; i < AA_EXEC_COUNT; i++) {
if (table[i])
count++;
}
if (!sd_write_array(p, NULL, count))
return 0;
for (i = 4; i < count + 4; i++) {
int len = strlen(table[i]) + 1;
/* if its a namespace make sure the second : is overwritten
* with 0, so that the namespace and name are \0 seperated
*/
if (*table[i] == ':') {
char *tmp = table[i] + 1;
strsep(&tmp, ":");
}
if (!sd_write_strn(p, table[i], len, NULL));
return 0;
}
if (!sd_write_arrayend(p))
return 0;
if (!sd_write_structend(p))
return 0;
return 1;
}
int count_file_ents(struct cod_entry *list)
{
struct cod_entry *entry;
@ -634,6 +672,9 @@ int sd_serialize_profile(sd_serialize *p, struct codomain *profile,
if (regex_type == AARE_DFA) {
if (!sd_serialize_dfa(p, profile->dfa, profile->dfa_size))
return 0;
if (!sd_serialize_xtable(p, profile->exec_table))
return 0;
} else {
/* pcre globbing entries */
if (count_pcre_ents(profile->entries)) {

View File

@ -93,8 +93,62 @@ void add_hat_to_policy(struct codomain *cod, struct codomain *hat)
}
}
static int add_named_transition(struct codomain *cod, char *namespace, char *trans)
{
char *name = NULL;
int i;
/* check to see if it is a local transition */
if (!namespace) {
if (strstr(name, "//")) {
free(trans);
return AA_EXEC_LOCAL;
}
}
if (namespace) {
name = malloc(strlen(namespace) + strlen(trans) + 3);
if (!name) {
PERROR("Memory allocation error\n");
exit(1);
}
sprintf(name, ":%s:%s", namespace, trans);
free(namespace);
free(trans);
} else {
name = trans;
}
for (i = (AA_EXEC_LOCAL + 1) >> 10; i < AA_EXEC_COUNT; i++) {
if (!cod->exec_table[i]) {
cod->exec_table[i] = name;
return i;
} else if (strcmp(cod->exec_table[i], name) == 0) {
/* name already in table */
free(name);
return i;
}
}
free(name);
return 0;
}
void add_entry_to_policy(struct codomain *cod, struct cod_entry *entry)
{
if (entry->nt_name) {
int mode = 0;
int n = add_named_transition(cod, entry->namespace, entry->nt_name);
if (!n)
PERROR("Profile %s has to many specified profile transitions.\n", cod->name);
exit(1);
if (entry->mode & AA_USER_EXEC)
mode |= SHIFT_MODE(n << 10, AA_USER_SHIFT);
if (entry->mode & AA_OTHER_EXEC)
mode |= SHIFT_MODE(n << 10, AA_OTHER_SHIFT);
entry->mode = ((entry->mode & ~AA_ALL_EXEC_MODIFIERS) |
(mode & AA_ALL_EXEC_MODIFIERS));
entry->namespace = NULL;
entry->nt_name = NULL;
}
entry->next = cod->entries;
cod->entries = entry;
}
@ -272,6 +326,10 @@ static void __add_hat_rules_parent(const void *nodep, const VISIT value,
if (!(*t)->hat_table && !(*t)->parent)
return;
/* don't add hat rules for local_profiles */
if ((*t)->local)
return;
/* add rule to grant permission to change_hat - AA 2.3 requirement,
* rules are added to the parent of the hat
*/
@ -319,6 +377,10 @@ static void __add_hat_rules_hats(const void *nodep, const VISIT value,
if (!(*t)->hat_table && !(*t)->parent)
return;
/* don't add hat rules for local_profiles */
if ((*t)->local)
return;
/* hat */
if ((*t)->parent) {
struct cod_entry *entry, *new_ent;

View File

@ -68,7 +68,11 @@ struct value_list {
void free_value_list(struct value_list *list);
struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
char *link_id);
char *link_id, char *nt);
void add_local_entry(struct codomain *cod);
struct codomain *do_local_profile(struct codomain *cod, char *name, int mode, int audit);
%}
@ -153,6 +157,7 @@ struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
char *var_val;
struct value_list *val_list;
int boolean;
struct named_transition transition;
}
%type <id> TOK_ID
@ -161,6 +166,7 @@ struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
%type <cod> profile
%type <cod> rules
%type <cod> hat
%type <cod> local_profile
%type <cod> cond_rule
%type <network_entry> network_rule
%type <user_entry> rule
@ -183,6 +189,8 @@ struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
%type <boolean> opt_audit_flag
%type <boolean> opt_owner_flag
%type <boolean> opt_profile_flag
%type <transition> opt_named_transition
%%
@ -623,6 +631,18 @@ rules: rules hat
$$ = $1;
};
/*
rules: rules local_profile
{
PDEBUG("Matched: hat rule\n");
if (!$2)
yyerror(_("Assert: 'local_profile rule' returned NULL."));
add_hat_to_policy($1, $2);
add_local_entry($2);
$$ = $1;
};
*/
rules: rules cond_rule
{
PDEBUG("Matched: conditional rules\n");
@ -780,23 +800,61 @@ expr: TOK_DEFINED TOK_BOOL_VAR
id_or_var: TOK_ID { $$ = $1; }
id_or_var: TOK_SET_VAR { $$ = $1; };
rule: id_or_var file_mode TOK_END_OF_RULE
opt_named_transition:
{ /* nothing */
$$.present = 0;
$$.namespace = NULL;
$$.name = NULL;
}
| TOK_ARROW id_or_var
{
$$ = do_file_rule(NULL, $1, $2, NULL);
$$.present = 1;
$$.namespace = NULL;
$$.name = $2;
}
| TOK_ARROW TOK_COLON id_or_var TOK_COLON id_or_var
{
$$.present = 1;
$$.namespace = $3;
$$.name = $5;
};
rule: file_mode id_or_var TOK_END_OF_RULE
rule: id_or_var file_mode opt_named_transition TOK_END_OF_RULE
{
$$ = do_file_rule(NULL, $2, $1 & ~ALL_AA_EXEC_UNSAFE, NULL);
$$ = do_file_rule($3.namespace, $1, $2, NULL, $3.name);
};
rule: file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
{
if ($2 && ($1 & ~AA_LINK_BITS))
yyerror(_("subset can only be used with link rules."));
if ($4.present && ($1 & AA_LINK_BITS) && ($1 & AA_EXEC_BITS))
yyerror(_("link and exec perms conflict on a file rule using ->"));
if ($4.present && $4.namespace && ($1 & AA_LINK_BITS))
yyerror(_("link perms are not allowed on a named profile transition.\n"));
if (($1 & AA_LINK_BITS)) {
$$ = do_file_rule(NULL, $3, $1 & ~ALL_AA_EXEC_UNSAFE,
$4.name, NULL);
$$->subset = $2;
} else {
$$ = do_file_rule($4.namespace, $3, $1 & ~ALL_AA_EXEC_UNSAFE, NULL, $4.name);
}
};
rule: TOK_UNSAFE file_mode id_or_var TOK_END_OF_RULE
rule: TOK_UNSAFE file_mode id_or_var opt_named_transition TOK_END_OF_RULE
{
int mode = (($2 & AA_EXEC_BITS) << 8) & ALL_AA_EXEC_UNSAFE;
if (!($2 & AA_EXEC_BITS))
yyerror(_("unsafe rule missing exec permissions"));
$$ = do_file_rule(NULL, $3, ($2 & ~ALL_AA_EXEC_UNSAFE) | mode,
NULL);
if ($4.present && ($2 & AA_LINK_BITS))
yyerror(_("link perms are not allowed on a named profile transtion.\n"));
$$ = do_file_rule($4.namespace, $3,
($2 & ~ALL_AA_EXEC_UNSAFE) | mode,
NULL, $4.name);
};
rule: id_or_var file_mode id_or_var
@ -813,28 +871,11 @@ rule: TOK_LINK opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
struct cod_entry *entry;
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
entry = new_entry(NULL, $3, AA_LINK_BITS, $5);
if (!entry)
yyerror(_("Memory allocation error."));
entry->subset = $2;
PDEBUG("rule.entry: link (%s)\n", entry->name);
$$ = entry;
};
rule: file_mode opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
PDEBUG("Matched: link tok_id (%s) -> (%s)\n", $3, $5);
if ($1 & ~AA_LINK_BITS)
yyerror(_("only link perms can be specified in a link rule."));
entry = new_entry(NULL, $3, AA_LINK_BITS, $5);
if (!entry)
yyerror(_("Memory allocation error."));
entry->subset = $2;
PDEBUG("rule.entry: link (%s)\n", entry->name);
$$ = entry;
};
rule: TOK_PTRACE TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
@ -883,6 +924,54 @@ hat: hat_start TOK_ID flags TOK_OPEN rules TOK_CLOSE
$$ = cod;
};
local_profile: opt_audit_flag opt_owner_flag TOK_ID file_mode TOK_ARROW TOK_OPEN rules TOK_CLOSE
{
int audit = 0, mode = $4;
if ($2 == 1)
mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
else if ($2 == 2)
mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
if ($1)
audit = mode & ~ALL_AA_EXEC_TYPE;
$$ = do_local_profile($7, $3, mode, audit);
};
local_profile: opt_audit_flag opt_owner_flag file_mode TOK_ID TOK_ARROW TOK_OPEN rules TOK_CLOSE
{
int audit = 0, mode = $3;
mode &= ~ALL_AA_EXEC_UNSAFE;
if ($2 == 1)
mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
else if ($2 == 2)
mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
if ($1)
audit = mode & ~ALL_AA_EXEC_TYPE;
$$ = do_local_profile($7, $4, mode, audit);
};
local_profile: opt_audit_flag opt_owner_flag TOK_UNSAFE file_mode TOK_ID TOK_ARROW TOK_OPEN rules TOK_CLOSE
{
int unsafe = (($4 & AA_EXEC_BITS) << 8) & ALL_AA_EXEC_UNSAFE;
int audit = 0, mode = ($4 & ~ALL_AA_EXEC_UNSAFE) | unsafe;
if ($2 == 1)
mode &= (AA_USER_PERMS | AA_SHARED_PERMS | AA_USER_PTRACE);
else if ($2 == 2)
mode &= (AA_OTHER_PERMS | AA_SHARED_PERMS | AA_OTHER_PTRACE);
if ($1)
audit = mode & ~ALL_AA_EXEC_TYPE;
$$ = do_local_profile($8, $5, mode, audit);
};
local_profile: TOK_PROFILE TOK_ID flags TOK_OPEN rules TOK_CLOSE
{
struct codomain *cod = do_local_profile($5, $2, 0, 0);
cod->flags = $3;
$$ = cod;
};
network_rule: TOK_NETWORK TOK_END_OF_RULE
{
int family;
@ -933,22 +1022,22 @@ file_mode: TOK_MODE
free($1);
}
change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_END_OF_RULE
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
PDEBUG("Matched change_profile: tok_id (%s)\n", $2);
entry = new_entry(NULL, $2, AA_CHANGE_PROFILE, NULL);
PDEBUG("Matched change_profile: tok_id (%s)\n", $3);
entry = new_entry(NULL, $3, AA_CHANGE_PROFILE, NULL);
if (!entry)
yyerror(_("Memory allocation error."));
PDEBUG("change_profile.entry: (%s)\n", entry->name);
$$ = entry;
};
change_profile: TOK_CHANGE_PROFILE TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
change_profile: TOK_CHANGE_PROFILE TOK_ARROW TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $3, $5);
entry = new_entry($3, $5, AA_CHANGE_PROFILE, NULL);
PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $4, $6);
entry = new_entry($4, $6, AA_CHANGE_PROFILE, NULL);
if (!entry)
yyerror(_("Memory allocation error."));
PDEBUG("change_profile.entry: (%s)\n", entry->name);
@ -1019,13 +1108,58 @@ void free_value_list(struct value_list *list)
}
struct cod_entry *do_file_rule(char *namespace, char *id, int mode,
char *link_id)
char *link_id, char *nt)
{
struct cod_entry *entry;
PDEBUG("Matched: tok_id (%s) tok_mode (0x%x)\n", id, mode);
entry = new_entry(namespace, id, mode, link_id);
if (!entry)
yyerror(_("Memory allocation error."));
entry->nt_name = nt;
PDEBUG("rule.entry: (%s)\n", entry->name);
return entry;
}
void add_local_entry(struct codomain *cod)
{
/* ugh this has to be called after the hat is attached to its parent */
if (cod->local_mode) {
struct cod_entry *entry;
char *trans = malloc(strlen(cod->parent->name) +
strlen(cod->name) + 3);
char *name = strdup(cod->name);
if (!trans)
yyerror(_("Memory allocation error."));
sprintf(name, "%s//%s", cod->parent->name, cod->name);
entry = new_entry(NULL, name, cod->local_mode, NULL);
entry->audit = cod->local_audit;
entry->nt_name = trans;
if (!entry)
yyerror(_("Memory allocation error."));
add_entry_to_policy(cod, entry);
}
}
struct codomain *do_local_profile(struct codomain *cod, char *name, int mode,
int audit)
{
PDEBUG("Matched: local profile trans (%s) open rules close\n", $1);
if (!cod) {
yyerror(_("Memory allocation error."));
}
cod->name = name;
if (force_complain)
cod->flags = force_complain_flags;
PDEBUG("profile %s: flags='%s%s'\n",
name,
cod->flags.complain ? "complain, " : "",
cod->flags.audit ? "audit" : "");
cod->local = 1;
cod->local_mode = mode;
cod->local_audit = audit;
return cod;
}

View File

@ -3,5 +3,5 @@
#=EXRESULT PASS
#
/usr/bin/foo {
change_profile /bin/foo,
change_profile -> /bin/foo,
}

View File

@ -3,5 +3,5 @@
#=EXRESULT PASS
#
/usr/bin/foo {
change_profile /bin/foo//bar,
change_profile -> /bin/foo//bar,
}

View File

@ -3,5 +3,5 @@
#=EXRESULT PASS
#
/usr/bin/foo {
change_profile :foo:/bin/foo,
change_profile -> :foo:/bin/foo,
}