2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 10:07:12 +00:00

Fix two x transition conflict bugs.

The is_merged_x_consistend macro was incorrect in that is tested for
USER_EXEC_TYPE to determine if there was an x transition.  This fails
for unconfined execs so an unconfined exec would not correctly conflict
with another exec type.

The dfa match flag table for xtransitions was not large enough and not
indexed properly for pux, and cux transitions.  The index calculation did
not take into account the pux flag so that pux and px aliased to the same
location and cux and cx aliased to the same location.

This would result in the first rule being processed defining what the
transition type was for all following rules of the type following.  So
if a px transition was processed first all pux, transitions in the profile
would be treated pux.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>

Add auto generation of xtransition conflict tests

All the combiniation of xtransition conflics where not well represented in
the regression test suite.  Instead of relying on multiple static test
files, automatically generate all possible conflicts.

Signed-off-by: John Johansen <john.johansen@canonical.com>
Acked-By: Steve Beattie <sbeattie@ubuntu.com>
This commit is contained in:
Steve Beattie 2011-01-07 12:46:15 -08:00
parent 9c3f87c34b
commit 2207e0b264
6 changed files with 170 additions and 9 deletions

1
.bzrignore Normal file
View File

@ -0,0 +1 @@
parser/tst/simple_tests/generated_x/*.sd

View File

@ -148,12 +148,12 @@ enum pattern_t {
#include <stdio.h> #include <stdio.h>
static inline int is_merged_x_consistent(int a, int b) static inline int is_merged_x_consistent(int a, int b)
{ {
if ((a & AA_USER_EXEC_TYPE) && (b & AA_USER_EXEC_TYPE) && if ((a & AA_USER_EXEC) && (b & AA_USER_EXEC) &&
((a & AA_USER_EXEC_TYPE) != (b & AA_USER_EXEC_TYPE))) ((a & AA_USER_EXEC_TYPE) != (b & AA_USER_EXEC_TYPE)))
{ fprintf(stderr, "failed user merge 0x%x 0x%x\n", a, b); { fprintf(stderr, "failed user merge 0x%x 0x%x\n", a, b);
return 0; return 0;
} }
if ((a & AA_OTHER_EXEC_TYPE) && (b & AA_OTHER_EXEC_TYPE) && if ((a & AA_OTHER_EXEC) && (b & AA_OTHER_EXEC) &&
((a & AA_OTHER_EXEC_TYPE) != (b & AA_OTHER_EXEC_TYPE))) ((a & AA_OTHER_EXEC_TYPE) != (b & AA_OTHER_EXEC_TYPE)))
{ fprintf(stderr, "failed other merge 0x%x 0x%x\n", a, b); { fprintf(stderr, "failed other merge 0x%x 0x%x\n", a, b);
return 0; return 0;

View File

@ -2581,9 +2581,9 @@ extern "C" int aare_add_rule(aare_ruleset_t *rules, char *rule, int deny,
#define MATCH_FLAGS_SIZE (sizeof(uint32_t) * 8 - 1) #define MATCH_FLAGS_SIZE (sizeof(uint32_t) * 8 - 1)
MatchFlag *match_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE]; MatchFlag *match_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
DenyMatchFlag *deny_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE]; DenyMatchFlag *deny_flags[FLAGS_WIDTH][MATCH_FLAGS_SIZE];
#define EXEC_MATCH_FLAGS_SIZE ((AA_EXEC_COUNT << 2) * 2) #define EXEC_MATCH_FLAGS_SIZE (AA_EXEC_COUNT *2 * 2 * 2) /* double for each of ix pux, unsafe x bits * u::o */
MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix *u::o*/ MatchFlag *exec_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE]; /* mods + unsafe + ix + pux * u::o*/
ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE];/* mods + unsafe +ix *u::o*/ ExactMatchFlag *exact_match_flags[FLAGS_WIDTH][EXEC_MATCH_FLAGS_SIZE];/* mods + unsafe + ix + pux *u::o*/
extern "C" void aare_reset_matchflags(void) extern "C" void aare_reset_matchflags(void)
{ {
@ -2644,8 +2644,8 @@ extern "C" int aare_add_rule_vec(aare_ruleset_t *rules, int deny,
flip_tree(tree); flip_tree(tree);
/* 0x3f == 4 bits x mods + 1 bit unsafe mask + 1 bit ix, after shift */ /* 0x7f == 4 bits x mods + 1 bit unsafe mask + 1 bit ix, + 1 pux after shift */
#define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 8)) & 0x3f) #define EXTRACT_X_INDEX(perm, shift) (((perm) >> (shift + 7)) & 0x7f)
//if (perms & ALL_AA_EXEC_TYPE && (!perms & AA_EXEC_BITS)) //if (perms & ALL_AA_EXEC_TYPE && (!perms & AA_EXEC_BITS))
// fprintf(stderr, "adding X rule without MAY_EXEC: 0x%x %s\n", perms, rulev[0]); // fprintf(stderr, "adding X rule without MAY_EXEC: 0x%x %s\n", perms, rulev[0]);

View File

@ -11,8 +11,11 @@ endif
all: tests all: tests
.PHONY: tests error_output parser_sanity caching .PHONY: tests error_output gen_xtrans parser_sanity caching
tests: error_output parser_sanity caching tests: error_output gen_xtrans parser_sanity caching
gen_xtrans:
perl ./gen-xtrans.pl
error_output: $(PARSER) error_output: $(PARSER)
$(PARSER) -S -I errors >/dev/null errors/okay.sd $(PARSER) -S -I errors >/dev/null errors/okay.sd
@ -34,3 +37,6 @@ caching: $(PARSER)
$(PARSER): $(PARSER):
make -C $(PARSER_DIR) $(PARSER_BIN) make -C $(PARSER_DIR) $(PARSER_BIN)
clean:
rm -f simple_tests/generated_x/*

152
parser/tst/gen-xtrans.pl Normal file
View File

@ -0,0 +1,152 @@
#!/usr/bin/perl
use strict;
use Locale::gettext;
use POSIX;
setlocale(LC_MESSAGES, "");
my $prefix="simple_tests/generated_x";
my @trans_types = ("p", "P", "c", "C", "u", "i");
my @modifiers = ("i", "u");
my %trans_modifiers = (
"p" => \@modifiers,
"P" => \@modifiers,
"c" => \@modifiers,
"C" => \@modifiers,
);
my @targets = ("", "target", "target2");
my @null_target = ("");
my %named_trans = (
"p" => \@targets,
"P" => \@targets,
"c" => \@targets,
"C" => \@targets,
"u" => \@null_target,
"i" => \@null_target,
);
# audit qualifier disabled for now it really shouldn't affect the conflict
# test but it may be worth checking every once in awhile
#my @qualifiers = ("", "owner", "audit", "audit owner");
my @qualifiers = ("", "owner");
my $count = 0;
gen_conflicting_x();
gen_overlap_re_exact();
gen_dominate_re_re();
gen_ambiguous_re_re();
print "Generated $count xtransition interaction tests\n";
sub gen_list {
my @output;
foreach my $trans (@trans_types) {
if ($trans_modifiers{$trans}) {
foreach my $mod (@{$trans_modifiers{$trans}}) {
push @output, "${trans}${mod}x";
}
}
push @output, "${trans}x";
}
return @output;
}
sub print_rule($$$$) {
my ($file, $name, $perm, $target) = @_;
print $file "\t${name} ${perm}";
if ($target ne "") {
print $file " -> $target";
}
print $file ",\n";
}
sub gen_file($$$$$$$$) {
my ($name, $xres, $rule1, $perm1, $target1, $rule2, $perm2, $target2) = @_;
# print "$xres $rule1 $perm1 $target1 $rule2 $perm2 $target2\n";
my $file;
unless (open $file, ">$name") {
print("couldn't open $name\n");
exit 1;
}
print $file "#\n";
print $file "#=DESCRIPTION ${name}\n";
print $file "#=EXRESULT ${xres}\n";
print $file "#\n";
print $file "/usr/bin/foo {\n";
print_rule($file, $rule1, $perm1, $target1);
print_rule($file, $rule2, $perm2, $target2);
print $file "}";
close($file);
$count++;
}
#NOTE: currently we don't do px to cx, or cx to px conversion
# so
# /foo {
# /* px -> /foo//bar,
# /* cx -> bar,
#
# will conflict
#
#NOTE: conflict tests don't tests leading permissions or using unsafe keywords
# It is assumed that there are extra tests to verify 1 to 1 coorispondance
sub gen_files($$$$) {
my ($name, $rule1, $rule2, $default) = @_;
my @perms = gen_list();
# print "@perms\n";
foreach my $i (@perms) {
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
foreach my $q (@qualifiers) {
foreach my $j (@perms) {
foreach my $u (@{$named_trans{substr($j, 0, 1)}}) {
foreach my $r (@qualifiers) {
my $file="${prefix}/${name}-$q$i$t-$r$j$u.sd";
# print "$file\n";
#override failures when transitions are the same
my $xres = ${default};
if ($i eq $j && $t eq $u) {
$xres = "PASS";
}
# print "foo $xres $rule1 $i $t $rule2 $j $u\n";
gen_file($file, $xres, "$q $rule1", $i, $t, "$r $rule2", $j, $u);
}
}
}
}
}
}
}
sub gen_conflicting_x {
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL");
}
sub gen_overlap_re_exact {
gen_files("exact", "/bin/cat", "/bin/*", "PASS");
}
# we currently don't support this, once supported change to "PASS"
sub gen_dominate_re_re {
gen_files("dominate", "/bin/*", "/bin/**", "FAIL");
}
sub gen_ambiguous_re_re {
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL");
}

View File

@ -0,0 +1,2 @@
Directory for auto generated x-transition tests