Skip to content
Snippets Groups Projects
Commit 3b68ee3a authored by Jamie Strandboge's avatar Jamie Strandboge Committed by Bazaar Package Importer
Browse files

Import upstream version 2.5.1~pre1393

parent f2a3ce35
No related branches found
No related tags found
No related merge requests found
Showing
with 513 additions and 108 deletions
EXTRA_DIST =Makefile.PL libapparmor_wrap.c LibAppArmor.pm examples/*.pl
noinst_DATA =LibAppArmor.so
if HAVE_PERL
noinst_DATA =LibAppArmor.so
libapparmor_wrap.c: $(srcdir)/../SWIG/libapparmor.i
$(SWIG) -perl -I$(srcdir)/../../src -module LibAppArmor -o $@ $(srcdir)/../SWIG/libapparmor.i
......@@ -27,4 +28,4 @@ clean-local:
#rm -f Makefile.perl Makefile.perl.old
rm -f *.so # *.o
endif
\ No newline at end of file
endif
......@@ -125,9 +125,20 @@ techdoc/index.html: techdoc.pdf
techdoc.txt: techdoc/index.html
w3m -dump $< > $@
all: $(TOOLS) $(MANPAGES) ${HTMLMANPAGES} techdoc.pdf
# targets arranged this way so that people who don't want full docs can
# pick specific targets they want.
main: $(TOOLS)
$(Q)make -C po all
$(Q)make -s tests
manpages: $(MANPAGES)
htmlmanpages: $(HTMLMANPAGES)
pdf: techdoc.pdf
docs: manpages htmlmanpages pdf
all: main docs tests
apparmor_parser: $(OBJECTS) $(PCREOBJECTS) $(AAREOBJECTS)
rm -f ./libstdc++.a
......@@ -191,7 +202,7 @@ __FILTER=$(shell echo $(strip $(FILTER_FAMILIES)) | sed -e 's/ /\\\|/g')
af_names.h: /usr/include/bits/socket.h
LC_ALL=C sed -n -e '/$(__FILTER)/d' -e "s/^\#define[ \\t]\\+PF_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9]\\+\\)\\(.*\\)\$$/#ifndef AF_\\1\\n# define AF_\\1 \\2\\n#endif\\nAA_GEN_NET_ENT(\"\\L\\1\", \\UAF_\\1)\\n/p" $< > $@
LC_ALL=C sed -n -e "s/^\#define[ \\t]\\+PF_MAX[ \\t]\\+\\([0-9]\\+\\)[ \\t]\\+.*/#define AA_AF_MAX \\1\n/p" $< >> $@
cat $@
# cat $@
cap_names.h: /usr/include/linux/capability.h
LC_ALL=C sed -n -e "/CAP_EMPTY_SET/d" -e "s/^\#define[ \\t]\\+CAP_\\([A-Z0-9_]\\+\\)[ \\t]\\+\\([0-9xa-f]\\+\\)\\(.*\\)\$$/\{\"\\L\\1\", \\UCAP_\\1\},/p" $< > $@
......@@ -214,7 +225,7 @@ check: tests
.SILENT: tests
tests: ${TESTS}
for test in ${TESTS} ; do echo "*** running $${test}" && ./$${test} $(BUILD_OUTPUT) ; done
sh -e -c 'for test in ${TESTS} ; do echo "*** running $${test}" && ./$${test} $(BUILD_OUTPUT) ; done'
$(Q)make -s -C tst tests
.SILENT: check
......
......@@ -149,11 +149,43 @@ 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.
Given twice, dumps its interpretation of the profile for checking.
=item -D n, --dump=n
Debug flag for dumping various structures and passes of policy compilation.
A single dump flag can be specified per --dump option, but the dump flag
can be passed multiple times. Note progress flags tend to also imply
the matching stats flag.
apparmor_parser --dump=dfa-stats --dump=trans-stats <file>
Use --help=dump to see a full list of which dump flags are supported
=item -O n, --optimize=n
Set the optimization flags used by policy compilation. A sinlge optimization
flag can be toggled per -O option, but the optimize flag can be passed
multiple times. Turning off some phases of the optimization can make
it so that policy can't complete compilation due to size constraints
(it is entirely possible to create a dfa with millions of states that will
take days or longer to compile).
Note: The parser is set to use a balanced default set of flags, that
will result in resonable compression but not take excessive amounts
of time to complete.
Use --help=optimize to see a full list of which optimization flags are
supported.
=item -h, --help
Give a quick reference guide.
......
......@@ -102,6 +102,7 @@
/* child 0 is left, child 1 is right */
Node *child[2];
unsigned int label; /* unique number for debug etc */
/**
* We need reference counting for AcceptNodes: sharing AcceptNodes
* avoids introducing duplicate States with identical accept values.
......@@ -1208,12 +1209,11 @@ regexp_error(Node **, const char *text, const char *error)
* Assign a consecutive number to each node. This is only needed for
* pretty-printing the debug output.
*/
map<Node *, int> node_label;
void label_nodes(Node *root)
{
int nodes = 0;
for (depth_first_traversal i(root); i; i++)
node_label.insert(make_pair(*i, nodes++));
i->label = nodes++;
}
/**
......@@ -1225,7 +1225,7 @@ ostream& operator<<(ostream& os, const State& state)
if (!state.empty()) {
State::iterator i = state.begin();
for(;;) {
os << node_label[*i];
os << (*i)->label;
if (++i == state.end())
break;
os << ',';
......@@ -1240,15 +1240,15 @@ ostream& operator<<(ostream& os, const State& state)
*/
void dump_syntax_tree(ostream& os, Node *node) {
for (depth_first_traversal i(node); i; i++) {
os << node_label[*i] << '\t';
os << i->label << '\t';
if ((*i)->child[0] == 0)
os << **i << '\t' << (*i)->followpos << endl;
else {
if ((*i)->child[1] == 0)
os << node_label[(*i)->child[0]] << **i;
os << (*i)->child[0]->label << **i;
else
os << node_label[(*i)->child[0]] << **i
<< node_label[(*i)->child[1]];
os << (*i)->child[0]->label << **i
<< (*i)->child[1]->label;
os << '\t' << (*i)->firstpos
<< (*i)->lastpos << endl;
}
......@@ -1370,6 +1370,13 @@ DFA::DFA(Node *root, dfaflags_t flags) : root(root)
here.cases.insert(*j);
}
}
for (depth_first_traversal i(root); i; i++) {
(*i)->firstpos.clear();
(*i)->lastpos.clear();
(*i)->followpos.clear();
}
if (flags & (DFA_DUMP_STATS))
fprintf(stderr, "\033[2KCreated dfa: states %ld\tmatching %d\tnonmatching %d\n", states.size(), match_count, nomatch_count);
......@@ -1715,7 +1722,9 @@ void DFA::minimize(dfaflags_t flags)
Trans::iterator j = trans.find(*i);
if (j != trans.end())
trans.erase(j);
State *s = *i;
states.erase(*i);
delete(s);
}
}
......@@ -2097,24 +2106,11 @@ bool TransitionTable::fits_in(vector <pair<size_t, size_t> > &free_list,
/* if it overflows the next_check array it fits in as we will
* resize */
if (c >= next_check.size())
goto resize;
return true;
if (next_check[c].second)
return false;
}
return true;
resize:
next_check.resize(base + cases.cases.rbegin()->first + 1);
size_t prev = pos;
size_t x = pos;
/* find last free list entry */
while (x) {
prev = x;
x = free_list[x].second;
}
x = free_list. size();
free_list.resize(base + cases.cases.rbegin()->first + 1);
init_free_list(free_list, prev, x);
return true;
}
......@@ -2126,6 +2122,7 @@ void TransitionTable::insert_state(vector <pair<size_t, size_t> > &free_list,
{
State *default_state = dfa.nonmatching;
size_t base = 0;
int resize;
Trans::iterator i = dfa.trans.find(from);
if (i == dfa.trans.end()) {
......@@ -2142,6 +2139,7 @@ void TransitionTable::insert_state(vector <pair<size_t, size_t> > &free_list,
goto do_insert;
repeat:
resize = 0;
/* get the first free entry that won't underflow */
while (x && (x < c)) {
prev = x;
......@@ -2154,15 +2152,24 @@ repeat:
x = free_list[x].second;
}
if (!x) {
/* expand next_check and free_list */
resize = 256 - cases.begin()->first;
x = free_list.size();
size_t range = cases.cases.rbegin()->first - cases.begin()->first + 1;
next_check.resize(next_check.size() + range);
free_list.resize(free_list.size() + range);
init_free_list(free_list, prev, x);
/* set prev to last free */
} else if (x + 255 - cases.begin()->first >= next_check.size()) {
resize = (255 - cases.begin()->first - (next_check.size() - 1 - x));
for (size_t y = x; y; y = free_list[y].second)
prev = y;
}
if (resize) {
/* expand next_check and free_list */
size_t old_size = free_list.size();
next_check.resize(next_check.size() + resize);
free_list.resize(free_list.size() + resize);
init_free_list(free_list, prev, old_size);
if (!first_free)
first_free = x;
goto repeat;
first_free = old_size;;
if (x == old_size)
goto repeat;
}
base = x - c;
......
......@@ -4,6 +4,9 @@
* Copyright (c) 1999, 2000, 2001, 2002, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
*
* Copyright (c) 2010
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
......@@ -14,7 +17,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
* along with this program; if not, contact Novell, Inc. or Canonical
* Ltd.
*/
#include <netinet/in.h>
......@@ -178,7 +182,7 @@ struct var_string {
extern int flag_changehat_version;
extern int read_implies_exec;
extern dfaflags_t dfaflags;
extern int preprocess_only;
#define PATH_CHROOT_REL 0x1
#define PATH_NS_REL 0x2
......@@ -280,12 +284,16 @@ extern struct cod_entry *copy_cod_entry(struct cod_entry *cod);
extern void free_cod_entries(struct cod_entry *list);
/* parser_symtab.c */
struct set_value {;
char *val;
struct set_value *next;
};
extern int add_boolean_var(const char *var, int boolean);
extern int get_boolean_var(const char *var);
extern int new_set_var(const char *var, const char *value);
extern int add_set_value(const char *var, const char *value);
extern void *get_set_var(const char *var);
extern char *get_next_set_value(void **context);
extern struct set_value *get_set_var(const char *var);
extern char *get_next_set_value(struct set_value **context);
extern void dump_symtab(void);
extern void dump_expanded_symtab(void);
void free_symtabs(void);
......@@ -312,7 +320,7 @@ extern void add_to_list(struct codomain *codomain);
extern void add_hat_to_policy(struct codomain *policy, struct codomain *hat);
extern void add_entry_to_policy(struct codomain *policy, struct cod_entry *entry);
extern void post_process_nt_entries(struct codomain *cod);
extern int post_process_policy(void);
extern int post_process_policy(int debug_only);
extern int process_hat_regex(struct codomain *cod);
extern int process_hat_variables(struct codomain *cod);
extern int post_merge_rules(void);
......
......@@ -270,3 +270,63 @@ static char *stripblanks(char *s)
*s = 0;
return c;
}
struct include_stack_t {
char *filename;
int lineno;
struct include_stack_t *next;
};
struct include_stack_t *include_stack_head = NULL;
static void start_include_position(char *filename)
{
if (current_filename)
free(current_filename);
current_filename = strdup(filename ? filename : "stdin");
current_lineno = 1;
}
void push_include_stack(char *filename)
{
struct include_stack_t *include = NULL;
include = malloc(sizeof(*include));
if (!include) {
perror("malloc of included file stack tracker");
/* failures in this area are non-fatal */
return;
}
include->filename = strdup(current_filename);
include->lineno = current_lineno;
include->next = include_stack_head;
include_stack_head = include;
start_include_position(filename);
}
void pop_include_stack(void)
{
struct include_stack_t *include = NULL;
if (!include_stack_head)
return;
include = include_stack_head;
include_stack_head = include->next;
if (current_filename)
free(current_filename);
current_filename = include->filename;
current_lineno = include->lineno;
free(include);
}
void reset_include_stack(char *filename)
{
while (include_stack_head)
pop_include_stack();
start_include_position(filename);
}
/* $Id$ */
/*
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
* Copyright (c) 2010
* Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
......@@ -14,13 +14,15 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
* along with this program; if not, contact Canonical, Ltd.
*/
#ifndef PARSER_INCLUDE_H
#define PARSER_INCLUDE_H
extern int preprocess_only;
extern int current_lineno;
extern char *current_filename;
extern int add_search_dir(char *dir);
extern void init_base_dir(void);
......@@ -29,4 +31,8 @@ extern void parse_default_paths(void);
extern int do_include_preprocessing(char *profilename);
FILE *search_path(char *filename, char **fullpath);
extern void push_include_stack(char *filename);
extern void pop_include_stack(void);
extern void reset_include_stack(char *filename);
#endif
......@@ -49,7 +49,10 @@
#endif
#define NPDEBUG(fmt, args...) /* Do nothing */
int current_lineno = 1;
#define DUMP_PREPROCESS do { if (preprocess_only) ECHO; } while (0)
int current_lineno = 1;
char *current_filename = NULL;
struct ignored_suffix_t {
char * text;
......@@ -80,14 +83,19 @@ 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");
}
if (!include_file)
yyerror(_("Could not open '%s'"), fullpath);
yyerror(_("Could not open '%s'"),
fullpath ? fullpath: filename);
if (fstat(fileno(include_file), &my_stat))
yyerror(_("fstat failed for '%s'"), fullpath);
......@@ -95,6 +103,7 @@ void include_filename(char *filename, int search)
if (S_ISREG(my_stat.st_mode)) {
yyin = include_file;
PDEBUG("Opened include \"%s\"\n", fullpath);
push_include_stack(fullpath);
yypush_buffer_state(yy_create_buffer( yyin, YY_BUF_SIZE ));
}
......@@ -139,8 +148,9 @@ void include_filename(char *filename, int search)
yyerror(_("stat failed for '%s'"), dirent_path);
if (S_ISREG(my_stat.st_mode)) {
if (!(yyin = fopen(dirent_path,"r")))
yyerror(_("Could not open '%s'"), filename);
PDEBUG("Opened include \"%s\"\n", filename);
yyerror(_("Could not open '%s' in '%s'"), dirent_path, filename);
PDEBUG("Opened include \"%s\" in \"%s\"\n", dirent_path, filename);
push_include_stack(dirent_path);
yypush_buffer_state(yy_create_buffer(yyin, YY_BUF_SIZE));
}
}
......@@ -227,6 +237,8 @@ LT_EQUAL <=
}
<<EOF>> {
fclose(yyin);
pop_include_stack();
yypop_buffer_state();
if ( !YY_CURRENT_BUFFER ) yyterminate();
}
......@@ -240,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);
......@@ -253,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);
......@@ -260,6 +274,7 @@ LT_EQUAL <=
}
[^\n] {
DUMP_PREPROCESS;
/* Something we didn't expect */
yyerror(_("Found unexpected character: '%s'"), yytext);
}
......@@ -274,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);
......@@ -287,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);
}
......@@ -302,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;
}
......@@ -393,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);
......@@ -406,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);
}
......@@ -421,127 +456,147 @@ LT_EQUAL <=
#include/.*\r?\n { /* include */
PDEBUG("Matched #include\n");
current_lineno++;
BEGIN(INCLUDE);
}
#.*\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 */
......@@ -573,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);
}
......
......@@ -4,6 +4,9 @@
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
*
* Copyright (c) 2010
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
......@@ -14,7 +17,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
* along with this program; if not, contact Novell, Inc. or Canonical,
* Ltd.
*/
#include <stdio.h>
......@@ -76,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;
......@@ -85,8 +90,6 @@ int perms_create = 0; /* perms contain create flag */
char *profile_namespace = NULL;
int flag_changehat_version = FLAG_CHANGEHAT_1_5;
extern int current_lineno;
/* per-profile settings */
int force_complain = 0;
char *profilename = NULL;
......@@ -121,6 +124,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},
};
......@@ -160,9 +164,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);
}
......@@ -224,8 +229,10 @@ void pwarn(char *fmt, ...)
if (conf_quiet || names_only || option == OPTION_REMOVE)
return;
rc = asprintf(&newfmt, _("Warning (%s line %d): %s"),
rc = asprintf(&newfmt, _("Warning from %s (%s%sline %d): %s"),
profilename ? profilename : "stdin",
current_filename ? current_filename : "",
current_filename ? " " : "",
current_lineno,
fmt);
if (!newfmt)
......@@ -244,7 +251,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:p", long_options, &o)) != -1)
{
switch (c) {
case 0:
......@@ -258,7 +265,7 @@ static int process_args(int argc, char *argv[])
break;
case 'd':
debug++;
skip_cache = 1;
skip_read_cache = 1;
break;
case 'h':
if (!optarg) {
......@@ -316,7 +323,7 @@ static int process_args(int argc, char *argv[])
subdomainbase = strndup(optarg, PATH_MAX);
break;
case 'D':
skip_cache = 1;
skip_read_cache = 1;
if (!optarg) {
dump_vars = 1;
} else if (strcmp(optarg, "variables") == 0) {
......@@ -359,7 +366,7 @@ static int process_args(int argc, char *argv[])
}
break;
case 'O':
skip_cache = 1;
skip_read_cache = 1;
if (strcmp(optarg, "0") == 0) {
dfaflags |= DFA_CONTROL_NO_TREE_NORMAL |
DFA_CONTROL_NO_TREE_SIMPLE |
......@@ -435,6 +442,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);
......@@ -695,12 +708,13 @@ int process_binary(int option, char *profilename)
return retval;
}
void reset_parser(void)
void reset_parser(char *filename)
{
free_aliases();
free_symtabs();
free_policies();
reset_regex();
reset_include_stack(filename);
}
int process_profile(int option, char *profilename)
......@@ -796,12 +810,15 @@ int process_profile(int option, char *profilename)
if (yyin)
yyrestart(yyin);
reset_parser();
reset_parser(profilename);
retval = yyparse();
if (retval != 0)
goto out;
if (preprocess_only)
goto out;
if (names_only) {
dump_policy_names();
goto out;
......@@ -812,7 +829,7 @@ int process_profile(int option, char *profilename)
goto out;
}
retval = post_process_policy();
retval = post_process_policy(debug);
if (retval != 0) {
PERROR(_("%s: Errors found in file. Aborting.\n"), progname);
goto out;
......
......@@ -4,6 +4,9 @@
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
*
* Copyright (c) 2010
* Canonical, Ltd. (All rights reserved)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
* License published by the Free Software Foundation.
......@@ -14,7 +17,8 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
* along with this program; if not, contact Novell, Inc. or Canonical,
* Ltd.
*/
#include <stdio.h>
......@@ -664,7 +668,7 @@ out:
return ret;
}
int post_process_policy(void)
int post_process_policy(int debug_only)
{
int retval = 0;
......@@ -696,11 +700,13 @@ int post_process_policy(void)
return retval;
}
retval = post_process_regex();
if (retval != 0) {
PERROR(_("%s: Errors found during regex postprocess. Aborting.\n"),
progname);
return retval;
if (!debug_only) {
retval = post_process_regex();
if (retval != 0) {
PERROR(_("%s: Errors found during regex postprocess. Aborting.\n"),
progname);
return retval;
}
}
return retval;
......
......@@ -33,11 +33,6 @@ enum var_type {
sd_set,
};
struct set_value {
char *val;
struct set_value *next;
};
struct symtab {
char *var_name;
enum var_type type;
......@@ -288,7 +283,7 @@ out:
/* returns a pointer to the value list, which should be used as the
* argument to the get_next_set_value() function. */
void *get_set_var(const char *var)
struct set_value *get_set_var(const char *var)
{
struct symtab *result;
struct set_value *valuelist = NULL;
......@@ -321,16 +316,17 @@ out:
}
/* iterator to walk the list of set values */
char *get_next_set_value(void **list)
char *get_next_set_value(struct set_value **list)
{
struct set_value **valuelist = (struct set_value **) list;
struct set_value *next;
char *ret;
if (!valuelist || !(*valuelist))
if (!list || !(*list))
return NULL;
ret = (*valuelist)->val;
(*valuelist) = (*valuelist)->next;
ret = (*list)->val;
next = (*list)->next;
(*list) = next;
return ret;
}
......@@ -569,7 +565,7 @@ int main(void)
{
int rc = 0;
int retval;
void *retptr;
struct set_value *retptr;
struct symtab *a, *b;
a = new_symtab_entry("blah");
......
......@@ -124,7 +124,7 @@ void free_var_string(struct var_string *var)
static int expand_entry_variables(struct cod_entry *entry)
{
void *valuelist;
struct set_value *valuelist;
int ret = TRUE;
char *value;
struct var_string *split_var;
......
%{
/* $Id$ */
/*
* Copyright (c) 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007
* NOVELL (All rights reserved)
* Copyright (c) 2010
* Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of version 2 of the GNU General Public
......@@ -15,7 +15,7 @@
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, contact Novell, Inc.
* along with this program; if not, contact Canonical, Ltd.
*/
#define YYERROR_VERBOSE 1
......@@ -32,6 +32,7 @@
/* #define DEBUG */
#include "parser.h"
#include "parser_include.h"
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
......@@ -63,10 +64,6 @@
#define CAP_TO_MASK(x) (1ull << (x))
/* from lex_config, for nice error messages */
/* extern char *current_file; */
extern int current_lineno;
struct value_list {
char *value;
struct value_list *next;
......@@ -1109,10 +1106,15 @@ void yyerror(char *msg, ...)
va_end(arg);
if (profilename) {
PERROR(_("AppArmor parser error in %s at line %d: %s\n"),
profilename, current_lineno, buf);
PERROR(_("AppArmor parser error for %s%s%s at line %d: %s\n"),
profilename,
current_filename ? " in " : "",
current_filename ? current_filename : "",
current_lineno, buf);
} else {
PERROR(_("AppArmor parser error, line %d: %s\n"),
PERROR(_("AppArmor parser error,%s%s line %d: %s\n"),
current_filename ? " in " : "",
current_filename ? current_filename : "",
current_lineno, buf);
}
......
#
# $Id$
#
PROVE=/usr/bin/prove
TESTS=simple.pl
PARSER_DIR=..
PARSER_BIN=apparmor_parser
PARSER=$(PARSER_DIR)/$(PARSER_BIN)
ifeq ($(VERBOSE),1)
PROVE_ARG=-v
......@@ -10,9 +11,23 @@ endif
all: tests
.PHONY: tests
tests: ../apparmor_parser
.PHONY: tests error_output parser_sanity
tests: error_output parser_sanity
error_output: $(PARSER)
$(PARSER) -S -I errors >/dev/null errors/okay.sd
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/single.sd | \
grep -q "AppArmor parser error for errors/single.sd in errors/single.sd at line 3: Could not open 'failure'"
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/double.sd | \
grep -q "AppArmor parser error for errors/double.sd in errors/includes/busted at line 67: Could not open 'does-not-exist'"
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/modefail.sd | \
grep -q "AppArmor parser error for errors/modefail.sd in errors/modefail.sd at line 6: syntax error"
LANG=C $(PARSER) -S -I errors 2>&1 >/dev/null errors/multi_include.sd | \
grep -q "AppArmor parser error for errors/multi_include.sd in errors/multi_include.sd at line 12: Could not open 'failure'"
@echo "Error Output: PASS"
parser_sanity: $(PARSER)
$(Q)${PROVE} ${PROVE_ARG} ${TESTS}
../apparmor_parser:
make -C .. apparmor_parser
$(PARSER):
make -C $(PARSER_DIR) $(PARSER_BIN)
......@@ -64,5 +64,3 @@ The simple script looks for a few special comments in the profile,
loop.
Otherwise, the profile is passed on as-is to the subdomain parser.
$Id$
#
/does/not/exist {
#include <includes/base>
#include <includes/busted>
}
# $Id$
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# (Note that the ldd profile has inlined this file; if you make
# modifications here, please consider including them in the ldd
# profile as well.)
# The __canary_death_handler function writes a time-stamped log
# message to /dev/log for logging by syslogd. So, /dev/log, timezones,
# and localisations of date should be available EVERYWHERE, so
# StackGuard, FormatGuard, etc., alerts can be properly logged.
/dev/log w,
/dev/urandom r,
/etc/locale/** r,
/etc/localtime r,
/usr/share/locale/** r,
/usr/share/zoneinfo/** r,
/usr/lib64/locale/** r,
/usr/lib64/gconv/*.so r,
/usr/lib64/gconv/gconv-modules* r,
/usr/lib/locale/** r,
/usr/lib/gconv/*.so r,
/usr/lib/gconv/gconv-modules* r,
# used by glibc when binding to ephemeral ports
/etc/bindresvport.blacklist r,
# ld.so.cache and ld are used to load shared libraries; they are best
# available everywhere
/etc/ld.so.cache r,
# 'px' requires a profile to be available for the transition to
# function; without a loaded profile, the kernel will fail the exec.
/lib/ld-*.so px,
/lib64/ld-*.so px,
/opt/*-linux-uclibc/lib/ld-uClibc*so* px,
# we might as well allow everything to use common libraries
/lib/lib*.so* r,
/lib/tls/lib*.so* r,
/lib/power4/lib*.so* r,
/lib/power5/lib*.so* r,
/lib/power5+/lib*.so* r,
/lib64/power4/lib*.so* r,
/lib64/power5/lib*.so* r,
/lib64/power5+/lib*.so* r,
/usr/lib/*.so* r,
/usr/lib/tls/lib*.so* r,
/usr/lib/power4/lib*.so* r,
/usr/lib/power5/lib*.so* r,
/usr/lib/power5+/lib*.so* r,
/lib64/lib*.so* r,
/lib64/tls/lib*.so* r,
/usr/lib64/*.so* r,
/usr/lib64/tls/lib*.so* r,
# /dev/null is pretty harmless and frequently used
/dev/null rw,
# as is /dev/zero
/dev/zero rw,
# Sometimes used to determine kernel/user interfaces to use
/proc/sys/kernel/version r,
# Depending on which glibc routine uses this file, base may not be the
# best place -- but many profiles require it, and it is quite harmless.
/proc/sys/kernel/ngroups_max r,
# glibc's sysconf(3) routine to determine free memory, etc
/proc/meminfo r,
/proc/stat r,
/proc/cpuinfo r,
# $Id$
# ------------------------------------------------------------------
#
# Copyright (C) 2002-2005 Novell/SUSE
#
# This program is free software; you can redistribute it and/or
# modify it under the terms of version 2 of the GNU General Public
# License published by the Free Software Foundation.
#
# ------------------------------------------------------------------
# (Note that the ldd profile has inlined this file; if you make
# modifications here, please consider including them in the ldd
# profile as well.)
# The __canary_death_handler function writes a time-stamped log
# message to /dev/log for logging by syslogd. So, /dev/log, timezones,
# and localisations of date should be available EVERYWHERE, so
# StackGuard, FormatGuard, etc., alerts can be properly logged.
/dev/log w,
/dev/urandom r,
/etc/locale/** r,
/etc/localtime r,
/usr/share/locale/** r,
/usr/share/zoneinfo/** r,
/usr/lib64/locale/** r,
/usr/lib64/gconv/*.so r,
/usr/lib64/gconv/gconv-modules* r,
/usr/lib/locale/** r,
/usr/lib/gconv/*.so r,
/usr/lib/gconv/gconv-modules* r,
# used by glibc when binding to ephemeral ports
/etc/bindresvport.blacklist r,
# ld.so.cache and ld are used to load shared libraries; they are best
# available everywhere
/etc/ld.so.cache r,
# 'px' requires a profile to be available for the transition to
# function; without a loaded profile, the kernel will fail the exec.
/lib/ld-*.so px,
/lib64/ld-*.so px,
/opt/*-linux-uclibc/lib/ld-uClibc*so* px,
# we might as well allow everything to use common libraries
/lib/lib*.so* r,
/lib/tls/lib*.so* r,
/lib/power4/lib*.so* r,
/lib/power5/lib*.so* r,
/lib/power5+/lib*.so* r,
/lib64/power4/lib*.so* r,
/lib64/power5/lib*.so* r,
/lib64/power5+/lib*.so* r,
/usr/lib/*.so* r,
/usr/lib/tls/lib*.so* r,
/usr/lib/power4/lib*.so* r,
/usr/lib/power5/lib*.so* r,
/usr/lib/power5+/lib*.so* r,
/lib64/lib*.so* r,
/lib64/tls/lib*.so* r,
/usr/lib64/*.so* r,
/usr/lib64/tls/lib*.so* r,
#include <does-not-exist>
# /dev/null is pretty harmless and frequently used
/dev/null rw,
# as is /dev/zero
/dev/zero rw,
# Sometimes used to determine kernel/user interfaces to use
/proc/sys/kernel/version r,
# Depending on which glibc routine uses this file, base may not be the
# best place -- but many profiles require it, and it is quite harmless.
/proc/sys/kernel/ngroups_max r,
# glibc's sysconf(3) routine to determine free memory, etc
/proc/meminfo r,
/proc/stat r,
/proc/cpuinfo r,
# 1
# 2
# 3
/does/not/exist { # 4
/lib/lib*.so rm, # 5
/fail abcdefgh, # 6
} # 7
#
#
#
/does/not/exist {
#include <includes/base>
#include <includes/base>
#include <includes/base>
#include <includes/base>
/bin/true rix,
#include <failure>
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment