Allow the 'file' keyword to be optionally used on file rules.

Add the optional 'file' keyword to the language/grammer.  The main reason
for doing this is to support false token injection.  Which is needed
to move towards the parser being broken out into an api that can be
used to parse individual rule types, separate from parsing the whole file.

Since we are adding the token to the grammar expose it to userspace with
the 'file' keyword.  While not needed it helps bring consistency, as all
the other rule types start with a keyword (capability, network, rlimit, ...).

Also allow the bare keyword to be used to represent allowing all file
operations, just as with network and capability.  Domain transitions are
defaulted to ix.  Thus

  file,

is equivalent to

  /** rwlkmix,

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-by: Kees Cook <kees@ubuntu.com>
This commit is contained in:
John Johansen 2012-02-16 08:06:04 -08:00
parent dd7427d1eb
commit e087db57b2
31 changed files with 352 additions and 19 deletions

View file

@ -77,6 +77,7 @@ static struct keyword_table keyword_table[] = {
{"alias", TOK_ALIAS},
{"rewrite", TOK_ALIAS},
{"ptrace", TOK_PTRACE},
{"file", TOK_FILE},
/* terminate */
{NULL, 0}
};

View file

@ -116,6 +116,7 @@ void add_local_entry(struct codomain *cod);
%token TOK_OPENPAREN
%token TOK_CLOSEPAREN
%token TOK_COMMA
%token TOK_FILE
/* rlimits */
%token TOK_RLIMIT
@ -175,6 +176,10 @@ void add_local_entry(struct codomain *cod);
%type <cod> cond_rule
%type <network_entry> network_rule
%type <user_entry> rule
%type <user_entry> file_rule
%type <user_entry> file_rule_tail
%type <user_entry> link_rule
%type <user_entry> ptrace_rule
%type <user_entry> frule
%type <flags> flags
%type <flags> flagvals
@ -197,6 +202,7 @@ void add_local_entry(struct codomain *cod);
%type <id> opt_id
%type <transition> opt_named_transition
%type <boolean> opt_unsafe
%type <boolean> opt_file
%%
@ -891,24 +897,16 @@ opt_named_transition:
$$.name = $5;
};
rule: file_rule { $$ = $1; }
| link_rule { $$ = $1; }
| ptrace_rule {$$ = $1; }
opt_unsafe: { /* nothing */ $$ = 0; }
| TOK_UNSAFE { $$ = 1; };
| TOK_SAFE { $$ = 2; };
rule: opt_unsafe frule
{
if ($1) {
if (!($2->mode & AA_EXEC_BITS))
yyerror(_("unsafe rule missing exec permissions"));
if ($1 == 1) {
$2->mode |= (($2->mode & AA_EXEC_BITS) << 8) &
ALL_AA_EXEC_UNSAFE;
}
else if ($1 == 2)
$2->mode &= ~ALL_AA_EXEC_UNSAFE;
}
$$ = $2;
};
opt_file: { /* nothing */ $$ = 0; }
| TOK_FILE { $$ = 1; }
frule: id_or_var file_mode opt_named_transition TOK_END_OF_RULE
{
@ -932,16 +930,43 @@ frule: file_mode opt_subset_flag id_or_var opt_named_transition TOK_END_OF_RULE
}
};
rule: opt_unsafe id_or_var file_mode id_or_var
file_rule: TOK_FILE TOK_END_OF_RULE
{
char *path = strdup("/**");
if (!path)
yyerror(_("Memory allocation error."));
$$ = do_file_rule(NULL, path, ((AA_BASE_PERMS & ~AA_EXEC_TYPE) |
(AA_EXEC_INHERIT | AA_MAY_EXEC)),
NULL, NULL);
}
| opt_file file_rule_tail { $$ = $2; }
file_rule_tail: opt_unsafe frule
{
if ($1) {
if (!($2->mode & AA_EXEC_BITS))
yyerror(_("unsafe rule missing exec permissions"));
if ($1 == 1) {
$2->mode |= (($2->mode & AA_EXEC_BITS) << 8) &
ALL_AA_EXEC_UNSAFE;
}
else if ($1 == 2)
$2->mode &= ~ALL_AA_EXEC_UNSAFE;
}
$$ = $2;
};
file_rule_tail: opt_unsafe id_or_var file_mode id_or_var
{
/* Oopsie, we appear to be missing an EOL marker. If we
* were *smart*, we could work around it. Since we're
* obviously not smart, we'll just punt with a more
* sensible error. */
yyerror(_("missing an end of line character? (entry: %s)"), $1);
yyerror(_("missing an end of line character? (entry: %s)"), $2);
};
rule: TOK_LINK opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
link_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);
@ -951,7 +976,7 @@ rule: TOK_LINK opt_subset_flag TOK_ID TOK_ARROW TOK_ID TOK_END_OF_RULE
$$ = entry;
};
rule: TOK_PTRACE TOK_ID TOK_END_OF_RULE
ptrace_rule: TOK_PTRACE TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
entry = new_entry(NULL, $2, AA_USER_PTRACE | AA_OTHER_PTRACE, NULL);
@ -960,7 +985,7 @@ rule: TOK_PTRACE TOK_ID TOK_END_OF_RULE
$$ = entry;
};
rule: TOK_PTRACE TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
ptrace_rule: TOK_PTRACE TOK_COLON TOK_ID TOK_COLON TOK_ID TOK_END_OF_RULE
{
struct cod_entry *entry;
entry = new_entry($3, $5, AA_USER_PTRACE | AA_OTHER_PTRACE, NULL);

View file

@ -0,0 +1,7 @@
#
#=Description basic file rule
#=EXRESULT FAIL
#
/usr/bin/foo {
file rw,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION w and a conflict
#=EXRESULT FAIL
#
/usr/bin/foo {
file /a wa,
}

View file

@ -0,0 +1,7 @@
k#
#=DESCRIPTION comma in pathname
#=EXRESULT FAIL
#
/usr/bin/foo {
file /foobar, r,
}

View file

@ -0,0 +1,6 @@
#=DESCRIPTION Simple test case for embedded spaces
#=EXRESULT FAIL
/bin/foo {
file /abc\ def r,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION k to be lower case
#=EXRESULT FAIL
#
/usr/bin/foo {
file /bin/ls K,
}

View file

@ -0,0 +1,41 @@
# vim:syntax=subdomain
# Last Modified: Wed Aug 31 11:14:09 2005
#=DESCRIPTION dos line endings
#=EXRESULT PASS
/usr/lib/RealPlayer10/realplay {
#include <includes/base>
#include <includes/fonts>
file /bin/bash ix,
file /bin/sed ixr,
file /bin/true ixr,
file /etc/opt/gnome/pango/pango.modules r,
file /opt/gnome/lib/gtk-2.0/2.4.0/loaders/* r,
file /opt/gnome/lib/lib*so* r,
file /opt/gnome/lib/pango/1.4.0/modules/* r,
file /opt/gnome/share/icons r,
file /opt/gnome/share/icons/** r,
file /opt/gnome/bin/nautilus rux,
file /root r,
file /root/.Xauthority r,
file /root/.fonts.cache-1 r,
file /root/.realplayerrc rw,
file /home/*/ r,
file /home/*/.Xauthority r,
file /home/*/.fonts.cache-1 r,
file /home/*/.realplayerrc rw,
file /usr/X11R6/lib/Acrobat7/Resource/Font/* r,
file /usr/X11R6/lib/Acrobat7/Resource/Font/PFM/* r,
file /usr/lib/RealPlayer10/** r,
file /usr/lib/RealPlayer10/realplay.bin ixr,
file /usr/lib/jvm/java-1.4.2-sun-1.4.2.06/jre/lib/fonts/** r,
file /usr/lib/ooo-2.0/share/fonts/** r,
file /opt/MozillaFirefox/bin/firefox.sh pxr,
file /opt/MozillaFirefox/lib/firefox-bin pxr,
file /opt/MozillaFirefox/lib/init.d r,
file /usr/bin/opera pxr,
file /usr/share/icons r,
file /usr/share/icons/** r,
file /opt/gnome/share/pixmaps r,
file /opt/gnome/share/pixmaps/** r,
}

View file

@ -0,0 +1,24 @@
#
#=DESCRIPTION perms before pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file r /foo1,
file w /foo1,
file a /foo1,
file k /foo1,
file m /foo1,
file l /foo1,
file px /foo1,
file Px /foo2,
file ux /foo3,
file Ux /foo4,
file ix /foo5,
file unsafe px /foo6,
file unsafe Px /foo7,
file unsafe ux /foo8,
file unsafe Ux /foo9,
file unsafe ix /foo10,
}

View file

@ -0,0 +1,7 @@
#
#=Description basic file rule
#=EXRESULT PASS
#
/usr/bin/foo {
file /usr/bin/foo r,
}

View file

@ -0,0 +1,7 @@
#
#=Description basic file rule
#=EXRESULT PASS
#
/usr/bin/foo {
file,
}

View file

@ -0,0 +1,9 @@
#
#=DESCRIPTION A simple successful profile
#=EXRESULT PASS
#
/usr/bin/foo {
file /usr/bin/foo r,
file /usr/bin/blah rix,
}

View file

@ -0,0 +1,13 @@
#
#=DESCRIPTION test append
#=EXRESULT PASS
#
/usr/bin/foo {
file /bin/cat a,
file /bin/true ra,
file /bin/false ma,
file /lib/libc.so la,
file /bin/less ixa,
file /bin/more pxa,
file /a uxa,
}

View file

@ -0,0 +1,7 @@
#
#=DESCRIPTION carat in pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file /foo^bar r,
}

View file

@ -0,0 +1,7 @@
#
#=DESCRIPTION trailing carat in pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file /foo/bar^ r,
}

View file

@ -0,0 +1,7 @@
#
#=DESCRIPTION comma in pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file /foo,bar r,
}

View file

@ -0,0 +1,7 @@
#
#=DESCRIPTION comma at end of pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file "/foobar," r,
}

View file

@ -0,0 +1,6 @@
#=DESCRIPTION Simple test case for embedded spaces
#=EXRESULT PASS
/bin/foo {
file "/abc\ def" r,
}

View file

@ -0,0 +1,6 @@
#=DESCRIPTION Simple test case for embedded spaces
#=EXRESULT PASS
/bin/foo {
file "/abc def" r,
}

View file

@ -0,0 +1,6 @@
#=DESCRIPTION Simple test case for embedded spaces
#=EXRESULT PASS
"/bin/fo o" {
file "/abc def" r,
}

View file

@ -0,0 +1,7 @@
#
#=DESCRIPTION carat in pathname
#=EXRESULT PASS
#
/usr/bin/foo {
file /foo[^me]bar r,
}

View file

@ -0,0 +1,17 @@
#
#=DESCRIPTION k and other perms do not conflict
#=EXRESULT PASS
#
/usr/bin/foo {
file /bin/a k,
file /bin/b rk,
file /bin/c wk,
file /bin/d ak,
file /bin/e lk,
file /bin/e mk,
file /bin/f pxk,
file /bin/g Pxk,
file /bin/h ixk,
file /bin/i uxk,
file /bin/j Uxk,
}

View file

@ -0,0 +1,12 @@
#
#=DESCRIPTION m and [uUpPi]x do not conflict
#=EXRESULT PASS
#
/usr/bin/foo {
file /bin/cat mix,
file /bin/true mpx,
file /bin/false mux,
file /lib/libc.so rwlm,
file /bin/less mUx,
file /bin/more mPx,
}

View file

@ -0,0 +1,14 @@
#
#=DESCRIPTION m and [upi]x do not conflict, seperate rules
#=EXRESULT PASS
#
/usr/bin/foo {
file /bin/cat rm,
file /bin/cat ix,
file /bin/true px,
file /bin/true m,
file /bin/false m,
file /bin/false ux,
file /lib/libc.so rwl,
file /lib/libc.so m,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION owner can not follow path name
#=EXRESULT FAIL
#
/usr/bin/foo {
file /foo owner rw,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION owner cannot follow permission
#=EXRESULT FAIL
#
/usr/bin/foo {
file /foo rw owner,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION owner rules must have comma termination
#=EXRESULT FAIL
#
/usr/bin/foo {
owner file /foo rw
file /bar rw,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION owner not allowed after forward perm
#=EXRESULT FAIL
#
/usr/bin/foo {
file rw owner /foo,
}

View file

@ -0,0 +1,8 @@
#
#=DESCRIPTION owner not allowed after pathname in forward rule
#=EXRESULT FAIL
#
/usr/bin/foo {
file rw /foo owner,
}

View file

@ -0,0 +1,9 @@
#
#=DESCRIPTION owner block needs } termination
#=EXRESULT FAIL
#
/usr/bin/foo {
owner {
file rw foo,
}

View file

@ -0,0 +1,25 @@
#
#=DESCRIPTION test owner flag for file rules
#=EXRESULT PASS
#
/usr/bin/foo {
owner file /foo rw,
owner file /foo/** rw,
owner file rw /bar,
owner file rw /bar/**,
owner {
file /one rw,
file /one/** rw,
file rw /two,
file rw /two/**,
}
owner {
}
}