mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 16:35:02 +01:00
Convert gen-xtrans from perl to python
The generated files are exactly the same, but the code is a bit more readable. Additional differences: - added test_gen_list() to verify the result of gen_list() - null_target has a non-empty value to avoid that it gets skipped in loops as empty value - invert_save has an additional entry for '' - copyright header added (based on git log of gen-xtrans.pl)
This commit is contained in:
parent
11d3218519
commit
6b96a9badc
3 changed files with 220 additions and 236 deletions
|
@ -23,7 +23,7 @@ tests: error_output caching minimize equality parser_sanity
|
|||
GEN_TRANS_DIRS=simple_tests/generated_x/ simple_tests/generated_perms_leading/ simple_tests/generated_perms_safe/ simple_tests/generated_dbus
|
||||
|
||||
gen_xtrans: $(GEN_TRANS_DIRS)
|
||||
./gen-xtrans.pl
|
||||
./gen-xtrans.py
|
||||
|
||||
$(GEN_TRANS_DIRS):
|
||||
mkdir $@
|
||||
|
|
|
@ -1,235 +0,0 @@
|
|||
#!/usr/bin/perl
|
||||
|
||||
use strict;
|
||||
use Locale::gettext;
|
||||
use POSIX;
|
||||
|
||||
setlocale(LC_MESSAGES, "");
|
||||
|
||||
my $prefix="simple_tests/generated_x";
|
||||
my $prefix_leading="simple_tests/generated_perms_leading";
|
||||
my $prefix_safe="simple_tests/generated_perms_safe";
|
||||
|
||||
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,
|
||||
);
|
||||
|
||||
my %safe_map = (
|
||||
"p" => "unsafe",
|
||||
"P" => "safe",
|
||||
"c" => "unsafe",
|
||||
"C" => "safe",
|
||||
"u" => "",
|
||||
"i" => "",
|
||||
);
|
||||
|
||||
my %invert_safe = (
|
||||
"safe" => "unsafe",
|
||||
"unsafe" => "safe",
|
||||
);
|
||||
|
||||
# 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();
|
||||
gen_leading_perms("exact", "/bin/cat", "/bin/cat");
|
||||
gen_leading_perms("exact-re", "/bin/*", "/bin/*");
|
||||
gen_leading_perms("overlap", "/*", "/bin/cat");
|
||||
gen_leading_perms("dominate", "/**", "/*");
|
||||
gen_leading_perms("ambiguous", "/a*", "/*b");
|
||||
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat");
|
||||
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*");
|
||||
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat");
|
||||
gen_safe_perms("dominate", "PASS", "", "/**", "/*");
|
||||
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b");
|
||||
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat");
|
||||
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*");
|
||||
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat");
|
||||
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*");
|
||||
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b");
|
||||
|
||||
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, $leading, $qual, $name, $perm, $target) = @_;
|
||||
if ($leading) {
|
||||
print $file "\t${qual} ${perm} ${name}";
|
||||
} else {
|
||||
print $file "\t${qual} ${name} ${perm}";
|
||||
}
|
||||
if ($target ne "") {
|
||||
print $file " -> $target";
|
||||
}
|
||||
print $file ",\n";
|
||||
}
|
||||
|
||||
sub gen_file($$$$$$$$$$$$) {
|
||||
my ($name, $xres, $leading1, $qual1, $rule1, $perm1, $target1, $leading2, $qual2, $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, $leading1, $qual1, $rule1, $perm1, $target1);
|
||||
print_rule($file, $leading2, $qual2, $rule2, $perm2, $target2);
|
||||
print $file "}\n";
|
||||
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, 0, $q, $rule1, $i, $t, 0, $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");
|
||||
}
|
||||
|
||||
|
||||
# test that rules that lead with permissions don't conflict with
|
||||
# the same rule using trailing permissions.
|
||||
sub gen_leading_perms($$$) {
|
||||
my ($name, $rule1, $rule2) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
my $file="${prefix_leading}/${name}-$q$i$t.sd";
|
||||
# print "$file\n";
|
||||
|
||||
gen_file($file, "PASS", 0, $q, $rule1, $i, $t, 1, $q, $rule2, $i, $t);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
# test for rules with leading safe or unsafe keywords.
|
||||
# check they are equivalent to their counter part,
|
||||
# or if $invert that they properly conflict with their counterpart
|
||||
sub gen_safe_perms($$$$$) {
|
||||
my ($name, $xres, $invert, $rule1, $rule2) = @_;
|
||||
|
||||
my @perms = gen_list();
|
||||
|
||||
foreach my $i (@perms) {
|
||||
foreach my $t (@{$named_trans{substr($i, 0, 1)}}) {
|
||||
foreach my $q (@qualifiers) {
|
||||
my $qual = $safe_map{substr($i, 0, 1)};
|
||||
if ($invert) {
|
||||
$qual = $invert_safe{$qual};
|
||||
}
|
||||
if (! $invert || $qual) {
|
||||
my $file="${prefix_safe}/${name}-$invert-$q${qual}-rule-$i$t.sd";
|
||||
# print "$file\n";
|
||||
gen_file($file, $xres, 0, "$q $qual", $rule1, $i, $t, 1, $q, $rule2, $i, $t);
|
||||
$file="${prefix_safe}/${name}-$invert-$q$qual${i}-rule-$t.sd";
|
||||
gen_file($file, $xres, 0, $q, $rule1, $i, $t, 1, "$q $qual", $rule2, $i, $t);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
219
parser/tst/gen-xtrans.py
Executable file
219
parser/tst/gen-xtrans.py
Executable file
|
@ -0,0 +1,219 @@
|
|||
#!/usr/bin/python3
|
||||
# ------------------------------------------------------------------
|
||||
#
|
||||
# Copyright (C) 2010-2011 Canonical Ltd.
|
||||
# Copyright (C) 2020 Christian Boltz
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
# ------------------------------------------------------------------
|
||||
|
||||
from testlib import write_file
|
||||
|
||||
prefix = "simple_tests/generated_x"
|
||||
prefix_leading = "simple_tests/generated_perms_leading"
|
||||
prefix_safe = "simple_tests/generated_perms_safe"
|
||||
|
||||
trans_types = ("p", "P", "c", "C", "u", "i")
|
||||
modifiers = ("i", "u")
|
||||
trans_modifiers = {
|
||||
"p": modifiers,
|
||||
"P": modifiers,
|
||||
"c": modifiers,
|
||||
"C": modifiers,
|
||||
}
|
||||
|
||||
targets = ("", "target", "target2")
|
||||
# null_target uses "_" instead of "" because "" gets skipped in some for loops. Replace with "" when actually using the value.
|
||||
null_target = ("_")
|
||||
|
||||
named_trans = {
|
||||
"p": targets,
|
||||
"P": targets,
|
||||
"c": targets,
|
||||
"C": targets,
|
||||
"u": null_target,
|
||||
"i": null_target,
|
||||
}
|
||||
|
||||
safe_map = {
|
||||
"p": "unsafe",
|
||||
"P": "safe",
|
||||
"c": "unsafe",
|
||||
"C": "safe",
|
||||
"u": "",
|
||||
"i": "",
|
||||
}
|
||||
|
||||
invert_safe = {
|
||||
"safe": "unsafe",
|
||||
"unsafe": "safe",
|
||||
'': '',
|
||||
}
|
||||
|
||||
# audit qualifier disabled for now it really shouldn't affect the conflict
|
||||
# test but it may be worth checking every once in awhile
|
||||
# qualifiers = ("", "owner", "audit", "audit owner")
|
||||
qualifiers = ("", "owner")
|
||||
|
||||
count = 0
|
||||
|
||||
def gen_list():
|
||||
output = []
|
||||
for trans in trans_types:
|
||||
if trans in trans_modifiers:
|
||||
for mod in trans_modifiers[trans]:
|
||||
output.append("%s%sx" % (trans, mod))
|
||||
|
||||
output.append("%sx" % trans)
|
||||
|
||||
return output
|
||||
|
||||
def test_gen_list():
|
||||
''' test if gen_list returns the expected output '''
|
||||
|
||||
expected = "pix pux px Pix Pux Px cix cux cx Cix Cux Cx ux ix".split()
|
||||
actual = gen_list()
|
||||
|
||||
if actual != expected:
|
||||
raise Exception("gen_list produced unexpected result, expected %s, got %s" % (expected, actual))
|
||||
|
||||
def build_rule(leading, qual, name, perm, target):
|
||||
rule = ''
|
||||
|
||||
if leading:
|
||||
rule += "\t%s %s %s" % (qual, perm, name)
|
||||
else:
|
||||
rule += "\t%s %s %s" % (qual, name, perm)
|
||||
|
||||
if target != "":
|
||||
rule += " -> %s" % target
|
||||
|
||||
rule += ",\n"
|
||||
|
||||
return rule
|
||||
|
||||
def gen_file (name, xres, leading1, qual1, rule1, perm1, target1, leading2, qual2, rule2, perm2, target2):
|
||||
global count
|
||||
count += 1
|
||||
|
||||
content = ''
|
||||
content += "#\n"
|
||||
content += "#=DESCRIPTION %s\n" % name
|
||||
content += "#=EXRESULT %s\n" % xres
|
||||
content += "#\n"
|
||||
content += "/usr/bin/foo {\n"
|
||||
content += build_rule(leading1, qual1, rule1, perm1, target1)
|
||||
content += build_rule(leading2, qual2, rule2, perm2, target2)
|
||||
content += "}\n"
|
||||
|
||||
write_file('', name, content)
|
||||
|
||||
|
||||
# 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
|
||||
def gen_files(name, rule1, rule2, default):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
for j in perms:
|
||||
for u in named_trans[j[0]]:
|
||||
if u == '_':
|
||||
u = ''
|
||||
for r in qualifiers:
|
||||
file = prefix + '/' + name + '-' + q + i + t + '-' + r + j + u + '.sd'
|
||||
|
||||
# override failures when transitions are the same
|
||||
xres = default
|
||||
if (i == j and t == u):
|
||||
xres = "PASS"
|
||||
|
||||
gen_file(file, xres, 0, q, rule1, i, t, 0, r, rule2, j, u)
|
||||
|
||||
def gen_conflicting_x():
|
||||
gen_files("conflict", "/bin/cat", "/bin/cat", "FAIL")
|
||||
|
||||
def gen_overlap_re_exact():
|
||||
gen_files("exact", "/bin/cat", "/bin/*", "PASS")
|
||||
|
||||
# we currently don't support this, once supported change to "PASS"
|
||||
def gen_dominate_re_re():
|
||||
gen_files("dominate", "/bin/*", "/bin/**", "FAIL")
|
||||
|
||||
def gen_ambiguous_re_re():
|
||||
gen_files("ambiguous", "/bin/a*", "/bin/*b", "FAIL")
|
||||
|
||||
|
||||
# test that rules that lead with permissions don't conflict with
|
||||
# the same rule using trailing permissions.
|
||||
def gen_leading_perms (name, rule1, rule2):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
file = prefix_leading + '/' + name + '-' + q + i + t + ".sd"
|
||||
gen_file(file, "PASS", 0, q, rule1, i, t, 1, q, rule2, i, t)
|
||||
|
||||
# test for rules with leading safe or unsafe keywords.
|
||||
# check they are equivalent to their counter part,
|
||||
# or if $invert that they properly conflict with their counterpart
|
||||
def gen_safe_perms(name, xres, invert, rule1, rule2):
|
||||
perms = gen_list()
|
||||
|
||||
for i in perms:
|
||||
for t in named_trans[i[0]]:
|
||||
if t == '_':
|
||||
t = ''
|
||||
for q in qualifiers:
|
||||
qual = safe_map[i[0]]
|
||||
if invert:
|
||||
qual = invert_safe[qual]
|
||||
|
||||
if (not invert or qual):
|
||||
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + '-' + 'rule-' + i + t + '.sd'
|
||||
gen_file(file, xres, 0, '%s %s' % (q, qual), rule1, i, t, 1, q, rule2, i, t)
|
||||
|
||||
file = prefix_safe + '/' + name + '-' + invert + '-' + q + qual + i + '-' + 'rule-' + t + '.sd'
|
||||
gen_file(file, xres, 0, q, rule1, i, t, 1, '%s %s' % (q, qual), rule2, i, t)
|
||||
|
||||
|
||||
test_gen_list()
|
||||
|
||||
gen_conflicting_x()
|
||||
gen_overlap_re_exact()
|
||||
gen_dominate_re_re()
|
||||
gen_ambiguous_re_re()
|
||||
gen_leading_perms("exact", "/bin/cat", "/bin/cat")
|
||||
gen_leading_perms("exact-re", "/bin/*", "/bin/*")
|
||||
gen_leading_perms("overlap", "/*", "/bin/cat")
|
||||
gen_leading_perms("dominate", "/**", "/*")
|
||||
gen_leading_perms("ambiguous", "/a*", "/*b")
|
||||
gen_safe_perms("exact", "PASS", "", "/bin/cat", "/bin/cat")
|
||||
gen_safe_perms("exact-re", "PASS", "", "/bin/*", "/bin/*")
|
||||
gen_safe_perms("overlap", "PASS", "", "/*", "/bin/cat")
|
||||
gen_safe_perms("dominate", "PASS", "", "/**", "/*")
|
||||
gen_safe_perms("ambiguous", "PASS", "", "/a*", "/*b")
|
||||
gen_safe_perms("exact", "FAIL", "inv", "/bin/cat", "/bin/cat")
|
||||
gen_safe_perms("exact-re", "FAIL", "inv", "/bin/*", "/bin/*")
|
||||
gen_safe_perms("overlap", "PASS", "inv", "/*", "/bin/cat")
|
||||
gen_safe_perms("dominate", "FAIL", "inv", "/**", "/*")
|
||||
gen_safe_perms("ambiguous", "FAIL", "inv", "/a*", "/*b")
|
||||
|
||||
print ("Generated %s xtransition interaction tests" % count)
|
Loading…
Add table
Reference in a new issue