add basic handling of profile namespaces

This commit is contained in:
John Johansen 2007-11-16 09:18:48 +00:00
parent 11d8181d0d
commit a4721bd02d
9 changed files with 160 additions and 24 deletions

View file

@ -36,7 +36,8 @@ struct cod_pattern {
}; };
struct cod_entry { struct cod_entry {
char * name ; char *namespace;
char *name ;
struct codomain *codomain ; /* Special codomain defined struct codomain *codomain ; /* Special codomain defined
* just for this executable */ * just for this executable */
int mode ; /* mode is 'or' of AA_* bits */ int mode ; /* mode is 'or' of AA_* bits */
@ -67,6 +68,7 @@ struct aa_network_entry {
}; };
struct codomain { struct codomain {
char *namespace;
char *name; /* codomain name */ char *name; /* codomain name */
char *sub_name; /* subdomain name or NULL */ char *sub_name; /* subdomain name or NULL */
int default_deny; /* TRUE or FALSE */ int default_deny; /* TRUE or FALSE */
@ -176,6 +178,7 @@ struct var_string {
extern char *progname; extern char *progname;
extern char *subdomainbase; extern char *subdomainbase;
extern char *profilename; extern char *profilename;
extern char *profile_namespace;
/* from parser_main */ /* from parser_main */
extern int force_complain; extern int force_complain;
@ -201,7 +204,7 @@ extern char *processunquoted(char *string, int len);
extern int get_keyword_token(const char *keyword); extern int get_keyword_token(const char *keyword);
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 struct cod_entry *new_entry(char *id, int mode); extern struct cod_entry *new_entry(char *namespace, char *id, int mode);
extern struct cod_net_entry *new_network_entry(int action, extern struct cod_net_entry *new_network_entry(int action,
struct ipv4_endpoints *addrs, struct ipv4_endpoints *addrs,
char *interface); char *interface);

View file

@ -702,6 +702,15 @@ int sd_serialize_top_profile(sd_serialize *p, struct codomain *profile)
if (!sd_write32(p, version)) if (!sd_write32(p, version))
return 0; return 0;
if (profile_namespace) {
if (!sd_write_string(p, profile_namespace, "namespace"))
return 0;
} else if (profile->namespace) {
if (!sd_write_string(p, profile->namespace, "namespace"))
return 0;
}
return sd_serialize_profile(p, profile, profile->parent ? 1 : 0); return sd_serialize_profile(p, profile, profile->parent ? 1 : 0);
} }
@ -746,16 +755,38 @@ int sd_serialize_codomain(int option, struct codomain *cod)
free(filename); free(filename);
if (option == OPTION_REMOVE) { if (option == OPTION_REMOVE) {
char *name; char *name, *ns = NULL;
int len = 0;
if (profile_namespace) {
len += strlen(profile_namespace) + 1;
ns = profile_namespace;
} else if (cod->namespace) {
len += strlen(cod->namespace) + 1;
ns = cod->namespace;
}
if (cod->parent) { if (cod->parent) {
name = malloc(strlen(cod->name) + 3 + name = malloc(strlen(cod->name) + 3 +
strlen(cod->parent->name)); strlen(cod->parent->name) + len);
if (!name) { if (!name) {
PERROR(_("Unable to remove ^%s\n"), cod->name); PERROR(_("Memory Allocation Error: Unable to remove ^%s\n"), cod->name);
error = -errno; error = -errno;
goto exit; goto exit;
} }
sprintf(name, "%s//%s", cod->parent->name, cod->name); if (ns)
sprintf(name, "%s:%s//%s", ns,
cod->parent->name, cod->name);
else
sprintf(name, "%s//%s", cod->parent->name,
cod->name);
} else if (ns) {
name = malloc(len + strlen(cod->name) + 1);
if (!name) {
PERROR(_("Memory Allocation Error: Unable to remove %s:%s."), ns, cod->name);
error = -errno;
goto exit;
}
sprintf(name, "%s:%s", ns, cod->name);
} else { } else {
name = cod->name; name = cod->name;
} }
@ -763,7 +794,7 @@ int sd_serialize_codomain(int option, struct codomain *cod)
wsize = write(fd, name, size); wsize = write(fd, name, size);
if (wsize < 0) if (wsize < 0)
error = -errno; error = -errno;
if (cod->parent) if (cod->parent || ns)
free(name); free(name);
} else { } else {

View file

@ -346,14 +346,21 @@ ADD_ASSIGN \+=
return TOK_HAT; return TOK_HAT;
} }
{KEYWORD} { {COLON} {
PDEBUG("Found a colon\n");
return TOK_COLON;
}
{VARIABLE_NAME} {
int token = get_keyword_token(yytext); int token = get_keyword_token(yytext);
/* special cases */ /* special cases */
switch (token) { switch (token) {
case -1: case -1:
/* no token found */ /* no token found */
yyerror(_("Found unexpected keyword: '%s'"), yytext); yylval = (YYSTYPE) processunquoted(yytext, yyleng);
PDEBUG("Found id: \"%s\"\n", yylval);
return TOK_ID;
break; break;
case TOK_VIA: case TOK_VIA:
BEGIN(IF_MODE); /* look for an interface name next */ BEGIN(IF_MODE); /* look for an interface name next */

View file

@ -67,6 +67,7 @@ char *subdomainbase = NULL;
char *profilename; char *profilename;
char *match_string = NULL; char *match_string = NULL;
int regex_type = AARE_DFA; int regex_type = AARE_DFA;
char *profile_namespace = NULL;
extern int current_lineno; extern int current_lineno;
@ -89,6 +90,7 @@ struct option long_options[] = {
{"stdout", 0, 0, 'S'}, {"stdout", 0, 0, 'S'},
{"match-string", 1, 0, 'm'}, {"match-string", 1, 0, 'm'},
{"quiet", 0, 0, 'q'}, {"quiet", 0, 0, 'q'},
{"namespace", 1, 0, 'n'},
{NULL, 0, 0, 0}, {NULL, 0, 0, 0},
}; };
@ -119,6 +121,7 @@ static void display_usage(char *command)
"-f n, --subdomainfs n Set location of apparmor filesystem\n" "-f n, --subdomainfs n Set location of apparmor filesystem\n"
"-S, --stdout Write output to stdout\n" "-S, --stdout Write output to stdout\n"
"-m n, --match-string n Use only match features n\n" "-m n, --match-string n Use only match features n\n"
"-n n, --namespace n Set Namespace for the profile\n"
"-q, --quiet Don't emit warnings\n", command); "-q, --quiet Don't emit warnings\n", command);
} }
@ -149,7 +152,7 @@ static int process_args(int argc, char *argv[])
int count = 0; int count = 0;
option = OPTION_ADD; option = OPTION_ADD;
while ((c = getopt_long(argc, argv, "adf:hrRvpI:b:CNSm:q", long_options, &o)) != -1) while ((c = getopt_long(argc, argv, "adf:hrRvpI:b:CNSm:qn:", long_options, &o)) != -1)
{ {
switch (c) { switch (c) {
case 0: case 0:
@ -215,6 +218,9 @@ static int process_args(int argc, char *argv[])
case 'q': case 'q':
conf_quiet = 1; conf_quiet = 1;
break; break;
case 'n':
profile_namespace = strdup(optarg);
break;
default: default:
display_usage(progname); display_usage(progname);
exit(0); exit(0);

View file

@ -43,7 +43,20 @@ static int file_comp(const void *c1, const void *c2)
struct cod_entry **e1, **e2; struct cod_entry **e1, **e2;
e1 = (struct cod_entry **)c1; e1 = (struct cod_entry **)c1;
e2 = (struct cod_entry **)c2; e2 = (struct cod_entry **)c2;
int res = 0;
//PERROR("strcmp %s %s\n", (*e1)->name, (*e2)->name); //PERROR("strcmp %s %s\n", (*e1)->name, (*e2)->name);
if ((*e1)->namespace) {
if ((*e2)->namespace)
res = strcmp((*e1)->namespace, (*e2)->namespace);
else
return 1;
} else if ((*e2)->namespace) {
return -1;
}
if (res)
return res;
return strcmp((*e1)->name, (*e2)->name); return strcmp((*e1)->name, (*e2)->name);
} }

View file

@ -632,7 +632,7 @@ struct cod_net_entry *new_network_entry(int action,
return entry; return entry;
} }
struct cod_entry *new_entry(char *id, int mode) struct cod_entry *new_entry(char *namespace, char *id, int mode)
{ {
struct cod_entry *entry = NULL; struct cod_entry *entry = NULL;
@ -640,7 +640,8 @@ struct cod_entry *new_entry(char *id, int mode)
if (!entry) if (!entry)
return NULL; return NULL;
entry->name = id ? id : NULL; entry->namespace = namespace;
entry->name = id;
entry->mode = mode; entry->mode = mode;
entry->deny = FALSE; entry->deny = FALSE;
@ -662,6 +663,7 @@ struct cod_entry *copy_cod_entry(struct cod_entry *orig)
if (!entry) if (!entry)
return NULL; return NULL;
entry->namespace = orig->namespace ? strdup(orig->namespace) : NULL;
entry->name = strdup(orig->name); entry->name = strdup(orig->name);
entry->mode = orig->mode; entry->mode = orig->mode;
entry->deny = orig->deny; entry->deny = orig->deny;
@ -693,6 +695,8 @@ 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->namespace)
free(list->namespace);
if (list->name) if (list->name)
free(list->name); free(list->name);
if (list->pat.regex) if (list->pat.regex)
@ -765,8 +769,13 @@ void debug_cod_entries(struct cod_entry *list)
if (item->name) if (item->name)
printf("\tName:\t(%s)\n", item->name); printf("\tName:\t(%s)\n", item->name);
else else
printf("\tName:\tNULL\n"); printf("\tName:\tNULL\n");
if (item->namespace)
printf("\tNamespace:\t(%s)\n", item->namespace);
} }
} }
@ -865,6 +874,9 @@ const char *capability_to_name(unsigned int cap)
void debug_cod_list(struct codomain *cod) void debug_cod_list(struct codomain *cod)
{ {
unsigned int i; unsigned int i;
if (cod->namespace)
printf("Namespcae:\t\t%s\n", cod->namespace);
if (cod->name) if (cod->name)
printf("Name:\t\t%s\n", cod->name); printf("Name:\t\t%s\n", cod->name);
else else

View file

@ -41,8 +41,20 @@ void *policy_list = NULL;
static int codomain_compare(const void *a, const void *b) static int codomain_compare(const void *a, const void *b)
{ {
return strcmp(((struct codomain *) a)->name, struct codomain *A = (struct codomain *) a;
((struct codomain *) b)->name); struct codomain *B = (struct codoamin *) b;
int res = 0;
if (A->namespace) {
if (B->namespace)
res = strcmp(A->namespace, B->namespace);
else
res = -1;
} else if (B->namespace)
res = 1;
if (res)
return res;
return strcmp(A->name, B->name);
} }
void add_to_list(struct codomain *codomain) void add_to_list(struct codomain *codomain)

View file

@ -502,6 +502,18 @@ static int process_dfa_entry(aare_ruleset_t *dfarules, struct cod_entry *entry)
if (!aare_add_rule(dfarules, tbuf, entry->mode)) if (!aare_add_rule(dfarules, tbuf, entry->mode))
ret = FALSE; ret = FALSE;
if (entry->mode & AA_CHANGE_PROFILE) {
char lbuf[2*PATH_MAX + 8];
if (entry->namespace)
sprintf(lbuf, "%s//%s", entry->namespace, entry->name);
else
sprintf(lbuf, "%s", entry->namespace, entry->name);
ptype = convert_aaregex_to_pcre(lbuf, 0, tbuf, 2*PATH_MAX + 8);
if (ptype == ePatternInvalid)
return FALSE;
if (!aare_add_rule(dfarules, tbuf, AA_CHANGE_PROFILE))
return FALSE;
}
return ret; return ret;
} }

View file

@ -67,7 +67,7 @@ struct value_list {
}; };
void free_value_list(struct value_list *list); void free_value_list(struct value_list *list);
struct cod_entry *do_file_rule(char *id, int mode); struct cod_entry *do_file_rule(char *namespace, char *id, int mode);
%} %}
@ -238,6 +238,10 @@ profile: TOK_ID flags TOK_OPEN rules TOK_CLOSE
if (!cod) { if (!cod) {
yyerror(_("Memory allocation error.")); yyerror(_("Memory allocation error."));
} }
if ($1[0] != '/')
yyerror(_("Profile names must begin with a '/'."));
cod->name = $1; cod->name = $1;
cod->flags = $2; cod->flags = $2;
if (force_complain) if (force_complain)
@ -251,6 +255,31 @@ profile: TOK_ID flags TOK_OPEN rules TOK_CLOSE
$$ = cod; $$ = cod;
}; };
profile: TOK_ID TOK_COLON TOK_ID flags TOK_OPEN rules TOK_CLOSE
{
struct codomain *cod = $6;
PDEBUG("Matched: id (%s:%s) open rules close\n", $1, $3);
if (!cod) {
yyerror(_("Memory allocation error."));
}
if ($3[0] != '/')
yyerror(_("Profile names must begin with a '/'."));
cod->namespace = $1;
cod->name = $3;
cod->flags = $4;
if (force_complain)
cod->flags = force_complain_flags;
PDEBUG("%s: flags='%s%s'\n",
$1,
cod->flags.complain ? "complain, " : "",
cod->flags.audit ? "audit" : "");
$$ = cod;
};
varlist: { /* nothing */ } varlist: { /* nothing */ }
varlist: varlist varassign varlist: varlist varassign
@ -567,36 +596,36 @@ expr: TOK_DEFINED TOK_BOOL_VAR
rule: TOK_ID file_mode TOK_END_OF_RULE rule: TOK_ID file_mode TOK_END_OF_RULE
{ {
$$ = do_file_rule($1, $2); $$ = do_file_rule(NULL, $1, $2);
}; };
rule: TOK_SET_VAR file_mode TOK_END_OF_RULE rule: TOK_SET_VAR file_mode TOK_END_OF_RULE
{ {
$$ = do_file_rule($1, $2); $$ = do_file_rule(NULL, $1, $2);
}; };
rule: file_mode TOK_ID TOK_END_OF_RULE rule: file_mode TOK_ID TOK_END_OF_RULE
{ {
$$ = do_file_rule($2, $1 & ~AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $2, $1 & ~AA_EXEC_UNSAFE);
}; };
rule: file_mode TOK_SET_VAR TOK_END_OF_RULE rule: file_mode TOK_SET_VAR TOK_END_OF_RULE
{ {
$$ = do_file_rule($2, $1 & ~AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $2, $1 & ~AA_EXEC_UNSAFE);
}; };
rule: TOK_UNSAFE file_mode TOK_ID TOK_END_OF_RULE rule: TOK_UNSAFE file_mode TOK_ID TOK_END_OF_RULE
{ {
if (!($2 & AA_MAY_EXEC)) if (!($2 & AA_MAY_EXEC))
yyerror(_("unsafe rule missing exec permissions")); yyerror(_("unsafe rule missing exec permissions"));
$$ = do_file_rule($3, $2 | AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $3, $2 | AA_EXEC_UNSAFE);
}; };
rule: TOK_UNSAFE file_mode TOK_SET_VAR TOK_END_OF_RULE rule: TOK_UNSAFE file_mode TOK_SET_VAR TOK_END_OF_RULE
{ {
if (!($2 & AA_MAY_EXEC)) if (!($2 & AA_MAY_EXEC))
yyerror(_("unsafe rule missing exec permissions")); yyerror(_("unsafe rule missing exec permissions"));
$$ = do_file_rule($3, $2 | AA_EXEC_UNSAFE); $$ = do_file_rule(NULL, $3, $2 | AA_EXEC_UNSAFE);
}; };
rule: TOK_ID file_mode TOK_ID rule: TOK_ID file_mode TOK_ID
@ -937,7 +966,18 @@ change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_END_OF_RULE
{ {
struct cod_entry *entry; struct cod_entry *entry;
PDEBUG("Matched change_profile: tok_id (%s)\n", $2); PDEBUG("Matched change_profile: tok_id (%s)\n", $2);
entry = new_entry($2, AA_CHANGE_PROFILE); entry = new_entry(NULL, $2, AA_CHANGE_PROFILE);
if (!entry)
yyerror(_("Memory allocation error."));
PDEBUG("change_profile.entry: (%s)\n", entry->name);
$$ = entry;
};
change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
PDEBUG("Matched change_profile: tok_id (%s:%s)\n", $2, $4);
entry = new_entry($2, $4, AA_CHANGE_PROFILE);
if (!entry) if (!entry)
yyerror(_("Memory allocation error.")); yyerror(_("Memory allocation error."));
PDEBUG("change_profile.entry: (%s)\n", entry->name); PDEBUG("change_profile.entry: (%s)\n", entry->name);
@ -1017,11 +1057,11 @@ void free_value_list(struct value_list *list)
} }
} }
struct cod_entry *do_file_rule(char *id, int mode) struct cod_entry *do_file_rule(char *namespace, char *id, int mode)
{ {
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(id, mode); entry = new_entry(namespace, id, mode);
if (!entry) if (!entry)
yyerror(_("Memory allocation error.")); yyerror(_("Memory allocation error."));
PDEBUG("rule.entry: (%s)\n", entry->name); PDEBUG("rule.entry: (%s)\n", entry->name);