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

View file

@ -702,6 +702,15 @@ int sd_serialize_top_profile(sd_serialize *p, struct codomain *profile)
if (!sd_write32(p, version))
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);
}
@ -746,16 +755,38 @@ int sd_serialize_codomain(int option, struct codomain *cod)
free(filename);
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) {
name = malloc(strlen(cod->name) + 3 +
strlen(cod->parent->name));
strlen(cod->parent->name) + len);
if (!name) {
PERROR(_("Unable to remove ^%s\n"), cod->name);
PERROR(_("Memory Allocation Error: Unable to remove ^%s\n"), cod->name);
error = -errno;
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 {
name = cod->name;
}
@ -763,7 +794,7 @@ int sd_serialize_codomain(int option, struct codomain *cod)
wsize = write(fd, name, size);
if (wsize < 0)
error = -errno;
if (cod->parent)
if (cod->parent || ns)
free(name);
} else {

View file

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

View file

@ -67,6 +67,7 @@ char *subdomainbase = NULL;
char *profilename;
char *match_string = NULL;
int regex_type = AARE_DFA;
char *profile_namespace = NULL;
extern int current_lineno;
@ -89,6 +90,7 @@ struct option long_options[] = {
{"stdout", 0, 0, 'S'},
{"match-string", 1, 0, 'm'},
{"quiet", 0, 0, 'q'},
{"namespace", 1, 0, 'n'},
{NULL, 0, 0, 0},
};
@ -119,6 +121,7 @@ static void display_usage(char *command)
"-f n, --subdomainfs n Set location of apparmor filesystem\n"
"-S, --stdout Write output to stdout\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);
}
@ -149,7 +152,7 @@ static int process_args(int argc, char *argv[])
int count = 0;
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) {
case 0:
@ -215,6 +218,9 @@ static int process_args(int argc, char *argv[])
case 'q':
conf_quiet = 1;
break;
case 'n':
profile_namespace = strdup(optarg);
break;
default:
display_usage(progname);
exit(0);

View file

@ -43,7 +43,20 @@ static int file_comp(const void *c1, const void *c2)
struct cod_entry **e1, **e2;
e1 = (struct cod_entry **)c1;
e2 = (struct cod_entry **)c2;
int res = 0;
//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);
}

View file

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

View file

@ -41,8 +41,20 @@ void *policy_list = NULL;
static int codomain_compare(const void *a, const void *b)
{
return strcmp(((struct codomain *) a)->name,
((struct codomain *) b)->name);
struct codomain *A = (struct codomain *) a;
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)

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))
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;
}

View file

@ -67,7 +67,7 @@ struct value_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) {
yyerror(_("Memory allocation error."));
}
if ($1[0] != '/')
yyerror(_("Profile names must begin with a '/'."));
cod->name = $1;
cod->flags = $2;
if (force_complain)
@ -251,6 +255,31 @@ profile: TOK_ID flags TOK_OPEN rules TOK_CLOSE
$$ = 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: varlist varassign
@ -567,36 +596,36 @@ expr: TOK_DEFINED TOK_BOOL_VAR
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
{
$$ = do_file_rule($1, $2);
$$ = do_file_rule(NULL, $1, $2);
};
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
{
$$ = 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
{
if (!($2 & AA_MAY_EXEC))
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
{
if (!($2 & AA_MAY_EXEC))
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
@ -937,7 +966,18 @@ change_profile: TOK_CHANGE_PROFILE TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
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)
yyerror(_("Memory allocation error."));
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;
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)
yyerror(_("Memory allocation error."));
PDEBUG("rule.entry: (%s)\n", entry->name);