This patch adds back in the -p flag, allowing the dumping of a

flattened profile to stdout.

It currently does not do anymore than flattening the include
files.  The expansions of variables etc can be added later.
This commit is contained in:
John Johansen 2010-06-26 13:13:52 -07:00
parent 2d2897f426
commit 49530d5fe5
5 changed files with 128 additions and 21 deletions

View file

@ -80,6 +80,10 @@ Produce a list of policies from a given set of profiles (implies -K).
Writes a binary (cached) profile to stdout (implies -K and -T).
=item -o file, --ofile file
Writes a binary (cached) profile to the specified file (implies -K and -T)
=item -b n, --base n
Set the base directory for resolving #include directives
@ -149,6 +153,11 @@ Report on the profiles as they are loaded, and show warnings.
Print the version number and exit.
=item -p, --preprocess
Dump the input profile to stdout out applying preprocessing flattening
includes into the output profile.
=item -d, --debug
Given once, only checks the profiles to ensure syntactic correctness.

View file

@ -172,6 +172,7 @@ struct var_string {
#define OPTION_REMOVE 2
#define OPTION_REPLACE 3
#define OPTION_STDOUT 4
#define OPTION_OFILE 5
#define AARE_NONE 0
#define AARE_PCRE 1
@ -182,7 +183,8 @@ struct var_string {
extern int flag_changehat_version;
extern int read_implies_exec;
extern dfaflags_t dfaflags;
extern int preprocess_only;
extern FILE *ofile;
#define PATH_CHROOT_REL 0x1
#define PATH_NS_REL 0x2

View file

@ -133,6 +133,9 @@ int load_codomain(int option, struct codomain *cod)
PERROR(_("%s: Unable to write to stdout\n"),
progname);
break;
case OPTION_OFILE:
PERROR(_("%s: Unable to write to output file\n"),
progname);
default:
PERROR(_("%s: ASSERT: Invalid option: %d\n"),
progname, option);
@ -155,6 +158,7 @@ int load_codomain(int option, struct codomain *cod)
cod->name);
break;
case OPTION_STDOUT:
case OPTION_OFILE:
break;
default:
PERROR(_("%s: ASSERT: Invalid option: %d\n"),
@ -837,22 +841,29 @@ int sd_serialize_codomain(int option, struct codomain *cod)
filename = "stdout";
fd = dup(1);
break;
case OPTION_OFILE:
fd = dup(fileno(ofile));
break;
default:
error = -EINVAL;
goto exit;
break;
}
if (kernel_load && fd < 0) {
PERROR(_("Unable to open %s - %s\n"), filename,
strerror(errno));
if (fd < 0) {
if (kernel_load)
PERROR(_("Unable to open %s - %s\n"), filename,
strerror(errno));
else
PERROR(_("Unable to open output file - %s\n"),
strerror(errno));
error = -errno;
goto exit;
}
error = 0;
if (option != OPTION_STDOUT)
if (option != OPTION_STDOUT && option != OPTION_OFILE)
free(filename);
if (option == OPTION_REMOVE) {
@ -918,7 +929,7 @@ int sd_serialize_codomain(int option, struct codomain *cod)
}
size = work_area->pos - work_area->buffer;
if (kernel_load || option == OPTION_STDOUT) {
if (kernel_load || option == OPTION_STDOUT || option == OPTION_OFILE) {
wsize = write(fd, work_area->buffer, size);
if (wsize < 0) {
error = -errno;
@ -941,7 +952,7 @@ int sd_serialize_codomain(int option, struct codomain *cod)
free_sd_serial(work_area);
}
if (kernel_load) close(fd);
close(fd);
if (cod->hat_table && regex_type == AARE_DFA && option != OPTION_REMOVE) {
if (load_flattened_hats(cod) != 0)

View file

@ -49,6 +49,8 @@
#endif
#define NPDEBUG(fmt, args...) /* Do nothing */
#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
int current_lineno = 1;
char *current_filename = NULL;
@ -81,8 +83,12 @@ void include_filename(char *filename, int search)
char *fullpath = NULL;
if (search) {
if (preprocess_only)
fprintf(yyout, "\n\n##included <%s>\n", filename);
include_file = search_path(filename, &fullpath);
} else {
if (preprocess_only)
fprintf(yyout, "\n\n##included \"%s\"\n", filename);
fullpath = strdup(filename);
include_file = fopen(fullpath, "r");
}
@ -246,6 +252,7 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processunquoted(yytext, yyleng);
PDEBUG("Found sub name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
@ -259,6 +266,7 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processquoted(yytext, yyleng);
PDEBUG("Found sub name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
@ -266,6 +274,7 @@ LT_EQUAL <=
}
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}
@ -280,6 +289,7 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processunquoted(yytext, yyleng);
PDEBUG("Found sub name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
@ -293,14 +303,16 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processquoted(yytext, yyleng);
PDEBUG("Found sub name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
return TOK_ID;
}
{WS}+ { /* Ignoring whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}
@ -308,85 +320,99 @@ LT_EQUAL <=
<FLAGS_MODE>{
{FLAGOPEN_PAREN} {
DUMP_PREPROCESS;
PDEBUG("FLag (\n");
return TOK_FLAG_OPENPAREN;
}
{FLAGCLOSE_PAREN} {
DUMP_PREPROCESS;
PDEBUG("Flag )\n");
BEGIN(INITIAL);
return TOK_FLAG_CLOSEPAREN;
}
{WS}+ { /* Eat whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
{FLAGSEP} {
DUMP_PREPROCESS;
PDEBUG("Flag , \n");
return TOK_FLAG_SEP;
}
{EQUALS} {
DUMP_PREPROCESS;
PDEBUG("Flag = \n");
return TOK_EQUALS;
}
{KEYWORD} {
DUMP_PREPROCESS;
yylval.flag_id = strdup(yytext);
PDEBUG("Found flag: \"%s\"\n", yylval.flag_id);
return TOK_FLAG_ID;
}
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}
}
<ASSIGN_MODE>{
{WS}+ { /* Eat whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
{ID}+ {
DUMP_PREPROCESS;
yylval.var_val = processunquoted(yytext, yyleng);
PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
return TOK_VALUE;
}
{QUOTED_ID} {
DUMP_PREPROCESS;
yylval.var_val = processquoted(yytext, yyleng);
PDEBUG("Found assignment value: \"%s\"\n", yylval.var_val);
return TOK_VALUE;
}
\\\n { current_lineno++ ; }
\\\n { DUMP_PREPROCESS; current_lineno++ ; }
\r?\n {
DUMP_PREPROCESS;
current_lineno++;
BEGIN(INITIAL);
}
}
<NETWORK_MODE>{
{WS}+ { /* Eat whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
{ID}+ {
DUMP_PREPROCESS;
yylval.id = strdup(yytext);
return TOK_ID;
}
{END_OF_RULE} {
DUMP_PREPROCESS;
BEGIN(INITIAL);
return TOK_END_OF_RULE;
}
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yylval.id = strdup(yytext);
yyerror(_("(network_mode) Found unexpected character: '%s'"), yylval.id);
}
\r?\n {
DUMP_PREPROCESS;
current_lineno++;
}
}
<CHANGE_PROFILE_MODE>{
{ARROW} {
DUMP_PREPROCESS;
PDEBUG("Matched a change profile arrow\n");
return TOK_ARROW;
}
@ -399,6 +425,7 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processunquoted(yytext, yyleng);
PDEBUG("Found change profile name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
@ -412,14 +439,16 @@ LT_EQUAL <=
* a longer match). So now, when I want to
* match any random string, I go into a
* separate state. */
DUMP_PREPROCESS;
yylval.id = processquoted(yytext, yyleng);
PDEBUG("Found change profile quoted name: \"%s\"\n", yylval.id);
BEGIN(INITIAL);
return TOK_ID;
}
{WS}+ { /* Ignoring whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}
@ -431,122 +460,143 @@ LT_EQUAL <=
}
#.*\r?\n { /* normal comment */
DUMP_PREPROCESS;
PDEBUG("comment(%d): %s\n", current_lineno, yytext);
current_lineno++;
BEGIN(INITIAL);
}
{END_OF_RULE} { return TOK_END_OF_RULE; }
{END_OF_RULE} { DUMP_PREPROCESS; return TOK_END_OF_RULE; }
{SEPARATOR} {
DUMP_PREPROCESS;
PDEBUG("Matched a separator\n");
BEGIN(SUB_NAME);
return TOK_SEP;
}
{ARROW} {
DUMP_PREPROCESS;
PDEBUG("Matched a arrow\n");
return TOK_ARROW;
}
{EQUALS} {
DUMP_PREPROCESS;
PDEBUG("Matched equals for assignment\n");
BEGIN(ASSIGN_MODE);
return TOK_EQUALS;
}
{ADD_ASSIGN} {
DUMP_PREPROCESS;
PDEBUG("Matched additive value assignment\n");
BEGIN(ASSIGN_MODE);
return TOK_ADD_ASSIGN;
}
<RLIMIT_MODE>{
{WS}+ { /* Eat whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Eat whitespace */ }
-?{NUMBER}[kKMG]? {
DUMP_PREPROCESS;
yylval.var_val = strdup(yytext);
return TOK_VALUE;
}
{KEYWORD} {
DUMP_PREPROCESS;
yylval.id = strdup(yytext);
if (strcmp(yytext, "infinity") == 0)
return TOK_VALUE;
return TOK_ID;
}
{LT_EQUAL} { return TOK_LE; }
{LT_EQUAL} { DUMP_PREPROCESS; return TOK_LE; }
{END_OF_RULE} {
DUMP_PREPROCESS;
BEGIN(INITIAL);
return TOK_END_OF_RULE;
}
\\\n {
DUMP_PREPROCESS;
current_lineno++;
BEGIN(INITIAL);
}
\r?\n {
DUMP_PREPROCESS;
current_lineno++;
BEGIN(INITIAL);
}
}
{SET_VARIABLE} {
DUMP_PREPROCESS;
yylval.set_var = strdup(yytext);
PDEBUG("Found set variable %s\n", yylval.set_var);
return TOK_SET_VAR;
}
{BOOL_VARIABLE} {
DUMP_PREPROCESS;
yylval.bool_var = strdup(yytext);
PDEBUG("Found boolean variable %s\n", yylval.bool_var);
return TOK_BOOL_VAR;
}
{OPEN_BRACE} {
DUMP_PREPROCESS;
PDEBUG("Open Brace\n");
return TOK_OPEN;
}
{CLOSE_BRACE} {
DUMP_PREPROCESS;
PDEBUG("Close Brace\n");
return TOK_CLOSE;
}
{PATHNAME} {
DUMP_PREPROCESS;
yylval.id = processunquoted(yytext, yyleng);
PDEBUG("Found id: \"%s\"\n", yylval.id);
return TOK_ID;
}
{QPATHNAME} {
DUMP_PREPROCESS;
yylval.id = processquoted(yytext, yyleng);
PDEBUG("Found id: \"%s\"\n", yylval.id);
return TOK_ID;
}
{MODES} {
DUMP_PREPROCESS;
yylval.mode = strdup(yytext);
PDEBUG("Found modes: %s\n", yylval.mode);
return TOK_MODE;
}
{HAT} {
DUMP_PREPROCESS;
BEGIN(SUB_NAME2);
return TOK_HAT;
}
{COLON} {
DUMP_PREPROCESS;
PDEBUG("Found a colon\n");
return TOK_COLON;
}
{FLAGOPEN_PAREN} {
DUMP_PREPROCESS;
PDEBUG("FLag (\n");
BEGIN(FLAGS_MODE);
return TOK_FLAG_OPENPAREN;
}
{VARIABLE_NAME} {
DUMP_PREPROCESS;
int token = get_keyword_token(yytext);
/* special cases */
@ -578,11 +628,13 @@ LT_EQUAL <=
return token;
}
{WS}+ { /* Ignoring whitespace */ }
{WS}+ { DUMP_PREPROCESS; /* Ignoring whitespace */ }
\r?\n { current_lineno++ ; }
\r?\n { DUMP_PREPROCESS; current_lineno++ ; }
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}

View file

@ -80,6 +80,7 @@ int read_implies_exec = 1;
#else
int read_implies_exec = 0;
#endif
int preprocess_only = 0;
char *subdomainbase = NULL;
char *match_string = NULL;
@ -88,6 +89,7 @@ int regex_type = AARE_DFA;
int perms_create = 0; /* perms contain create flag */
char *profile_namespace = NULL;
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
FILE *ofile = NULL;
/* per-profile settings */
int force_complain = 0;
@ -108,6 +110,7 @@ struct option long_options[] = {
{"remove", 0, 0, 'R'},
{"names", 0, 0, 'N'},
{"stdout", 0, 0, 'S'},
{"ofile", 1, 0, 'o'},
{"match-string", 1, 0, 'm'},
{"quiet", 0, 0, 'q'},
{"skip-kernel-load", 0, 0, 'Q'},
@ -123,6 +126,7 @@ struct option long_options[] = {
{"Dump", 1, 0, 'D'},
{"optimize", 1, 0, 'O'},
{"Optimize", 1, 0, 'O'},
{"preprocess", 0, 0, 'p'},
{NULL, 0, 0, 0},
};
@ -147,6 +151,7 @@ static void display_usage(char *command)
"-B, --binary Input is precompiled profile\n"
"-N, --names Dump names of profiles in input.\n"
"-S, --stdout Dump compiled profile to stdout\n"
"-o n, --ofile n Write output to file n\n"
"-b n, --base n Set base dir and cwd\n"
"-I n, --Include n Add n to the search path\n"
"-f n, --subdomainfs n Set location of apparmor filesystem\n"
@ -162,9 +167,10 @@ static void display_usage(char *command)
"-Q, --skip-kernel-load Do everything except loading into kernel\n"
"-V, --version Display version info and exit\n"
"-d, --debug Debug apparmor definitions\n"
"-p, --preprocess Dump preprocessed profile\n"
"-D [n], --dump Dump internal info for debugging\n"
"-O [n], --Optimize Control dfa optimizations\n"
"-h [command], --help Display this text or info about command\n"
"-h [cmd], --help[=cmd] Display this text or info about cmd\n"
,command);
}
@ -248,7 +254,7 @@ static int process_args(int argc, char *argv[])
int count = 0;
option = OPTION_ADD;
while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:", long_options, &o)) != -1)
while ((c = getopt_long(argc, argv, "adf:h::rRVvI:b:BCD:NSm:qQn:XKTWkO:po:", long_options, &o)) != -1)
{
switch (c) {
case 0:
@ -289,6 +295,7 @@ static int process_args(int argc, char *argv[])
case 'R':
count++;
option = OPTION_REMOVE;
skip_cache = 1;
break;
case 'V':
display_version();
@ -301,10 +308,12 @@ static int process_args(int argc, char *argv[])
set_base_dir(optarg);
break;
case 'B':
binary_input =1;
binary_input = 1;
skip_cache = 1;
break;
case 'C':
opt_force_complain = 1;
skip_cache = 1;
break;
case 'N':
names_only = 1;
@ -316,6 +325,18 @@ static int process_args(int argc, char *argv[])
skip_read_cache = 1;
kernel_load = 0;
break;
case 'o':
count++;
option = OPTION_OFILE;
skip_read_cache = 1;
kernel_load = 0;
ofile = fopen(optarg, "w");
if (!ofile) {
PERROR("%s: Could not open file %s\n",
progname, optarg);
exit(1);
}
break;
case 'f':
subdomainbase = strndup(optarg, PATH_MAX);
break;
@ -439,6 +460,12 @@ static int process_args(int argc, char *argv[])
case 'Q':
kernel_load = 0;
break;
case 'p':
count++;
kernel_load = 0;
skip_cache = 1;
preprocess_only = 1;
break;
default:
display_usage(progname);
exit(0);
@ -807,6 +834,9 @@ int process_profile(int option, char *profilename)
if (retval != 0)
goto out;
if (preprocess_only)
goto out;
if (names_only) {
dump_policy_names();
goto out;
@ -974,5 +1004,8 @@ int main(int argc, char *argv[])
profilename = NULL;
}
if (ofile)
fclose(ofile);
return retval;
}