mirror of
https://gitlab.com/apparmor/apparmor.git
synced 2025-03-04 08:24:42 +01:00
parser: support matching xattr keys but not values
Support profiles that choose to match the presence of an extended attribute without validating its value. This lets AppArmor target xattrs with binary data, such as security.ima and security.evm values. For example, it's now possible to write a profile such as: profile signed_binaries /** xattrs=(security.ima) { # ... } Both presence and value matches can be used in the same profile. To match a signed xattr, target both the xattr and the security.ima value: profile python_script /** xattrs=( security.evm security.apparmor="python" ) { # ... } Updated to work using out of band matching instead of separate data array. Signed-off-by: Eric Chiang <ericchiang@google.com> Signed-off-by: John Johansen <john.johansen@canonical.com>
This commit is contained in:
parent
e5ea3e4a0d
commit
2416faac54
9 changed files with 88 additions and 12 deletions
|
@ -213,7 +213,7 @@ LIST_VALUE_ID_CHARS ([^ \t\n"!,]{-}[()]|\\[ ]|\\\t|\\\"|\\!|\\,|\\\(|\\\))
|
|||
LIST_VALUE_QUOTED_ID_CHARS [^\0"]|\\\"
|
||||
LIST_VALUE_ID {LIST_VALUE_ID_CHARS}+
|
||||
QUOTED_LIST_VALUE_ID \"{LIST_VALUE_QUOTED_ID_CHARS}+\"
|
||||
ID_CHARS_NOEQ [^ \t\n"!,]{-}[=]
|
||||
ID_CHARS_NOEQ [^ \t\n"!,]{-}[=)]
|
||||
LEADING_ID_CHARS_NOEQ [^ \t\n"!,]{-}[=()+&]
|
||||
ID_NOEQ {ID_CHARS_NOEQ}|(,{ID_CHARS_NOEQ})
|
||||
IDS_NOEQ {LEADING_ID_CHARS_NOEQ}{ID_NOEQ}*
|
||||
|
|
|
@ -1205,6 +1205,15 @@ network_rule: TOK_NETWORK TOK_ID TOK_ID TOK_END_OF_RULE
|
|||
$$ = entry;
|
||||
}
|
||||
|
||||
cond: TOK_CONDID
|
||||
{
|
||||
struct cond_entry *ent;
|
||||
ent = new_cond_entry($1, 0, NULL);
|
||||
if (!ent)
|
||||
yyerror(_("Memory allocation error."));
|
||||
$$ = ent;
|
||||
}
|
||||
|
||||
cond: TOK_CONDID TOK_EQUALS TOK_VALUE
|
||||
{
|
||||
struct cond_entry *ent;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#
|
||||
#=Description no xattrs value
|
||||
#=EXRESULT FAIL
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/xattrs-test xattrs=(myvalue) {
|
||||
/foo r,
|
7
parser/tst/simple_tests/xattrs/ok_11.sd
Normal file
7
parser/tst/simple_tests/xattrs/ok_11.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description multiple xattrs with no value
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/xattrs-test xattrs=(myvalue myvalue2) {
|
||||
/foo r,
|
||||
}
|
7
parser/tst/simple_tests/xattrs/ok_12.sd
Normal file
7
parser/tst/simple_tests/xattrs/ok_12.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description xattrs key followed by key value
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/xattrs-test xattrs=(myvalue user.foo=bar) {
|
||||
/foo r,
|
||||
}
|
7
parser/tst/simple_tests/xattrs/ok_13.sd
Normal file
7
parser/tst/simple_tests/xattrs/ok_13.sd
Normal file
|
@ -0,0 +1,7 @@
|
|||
#
|
||||
#=Description xattrs key after key and value
|
||||
#=EXRESULT PASS
|
||||
#
|
||||
/usr/bin/xattrs-test xattrs=(user.foo=bar myvalue) {
|
||||
/foo r,
|
||||
}
|
|
@ -379,10 +379,12 @@ sub gen_addimage($) {
|
|||
sub gen_xattr($) {
|
||||
my $rule = shift;
|
||||
my @rules = split (/:/, $rule);
|
||||
if (@rules != 3) {
|
||||
(!$nowarn) && print STDERR "Warning: invalid xattr description '$rule', ignored\n";
|
||||
} else {
|
||||
if (@rules == 3) {
|
||||
$xattrs{$rules[1]} = $rules[2];
|
||||
} elsif (@rules == 2) {
|
||||
$xattrs{$rules[1]} = "";
|
||||
} else {
|
||||
(!$nowarn) && print STDERR "Warning: invalid xattr description '$rule', ignored\n";
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -479,7 +481,10 @@ sub gen_from_args() {
|
|||
} else {
|
||||
print STDOUT " ";
|
||||
}
|
||||
print STDOUT "$xattr=$xattrs{$xattr}";
|
||||
print STDOUT "$xattr";
|
||||
if (not $xattrs{$xattr} eq "") {
|
||||
print STDOUT "=$xattrs{$xattr}";
|
||||
}
|
||||
}
|
||||
print STDOUT ") ";
|
||||
}
|
||||
|
|
|
@ -138,11 +138,7 @@ runchecktest "Profiles with xattrs and same path length" pass profile_1
|
|||
|
||||
clean_xattr
|
||||
|
||||
# xattr matching doesn't work if the xattr value has a null character. This
|
||||
# impacts matching security.ima and security.evm values.
|
||||
#
|
||||
# A kernel patch has been proposed to fix this:
|
||||
# https://lists.ubuntu.com/archives/apparmor/2018-December/011882.html
|
||||
# xattr value matching doesn't work if the xattr value has a null character.
|
||||
|
||||
genprofile "image=profile_1" \
|
||||
"addimage:$file" \
|
||||
|
@ -157,3 +153,48 @@ set_xattr "user.foo" "0x610062" # "a\0b"
|
|||
runchecktest "xattr values with null characters don't work" pass unconfined
|
||||
|
||||
clean_xattr
|
||||
|
||||
# All test cases below this use an xattr_key match
|
||||
requires_kernel_features domain/attach_conditions/xattr_key
|
||||
|
||||
# xattr value matching doesn't work if the xattr value has a null character.
|
||||
|
||||
genprofile "image=profile_1" \
|
||||
"addimage:$file" \
|
||||
"path:$file" \
|
||||
"/proc/*/attr/current:r" \
|
||||
"xattr:user.foo" \
|
||||
|
||||
runchecktest "Path with no xattrs" pass unconfined
|
||||
set_xattr "user.foo" "ab"
|
||||
runchecktest "matches value" pass profile_1
|
||||
set_xattr "user.foo" "0x610062" # "a\0b"
|
||||
runchecktest "xattr values with null characters don't work" pass profile_1
|
||||
|
||||
clean_xattr
|
||||
|
||||
# Test that xattr keys contribute to the priority of a profile
|
||||
|
||||
genprofile "image=profile_1" \
|
||||
"addimage:$file" \
|
||||
"path:$file" \
|
||||
"/proc/*/attr/current:r" \
|
||||
"xattr:user.foo:hello" \
|
||||
"xattr:user.bar:bye" \
|
||||
-- \
|
||||
"image=profile_2" \
|
||||
"addimage:$file" \
|
||||
"path:$file" \
|
||||
"/proc/*/attr/current:r" \
|
||||
"xattr:user.foo:hello" \
|
||||
"xattr:user.bar" \
|
||||
"xattr:user.spam"
|
||||
|
||||
runchecktest "Path with no xattrs" pass unconfined
|
||||
set_xattr "user.foo" "hello"
|
||||
set_xattr "user.bar" "bye"
|
||||
runchecktest "matches value" pass profile_1
|
||||
set_xattr "user.spam" "spam"
|
||||
runchecktest "matches more xattrs in profile_2" pass profile_2
|
||||
|
||||
clean_xattr
|
||||
|
|
|
@ -30,7 +30,7 @@ RE_PATH = '/\S*|"/[^"]*"' # filename (starting with '/') withou
|
|||
RE_PROFILE_PATH = '(?P<%s>(' + RE_PATH + '))' # quoted or unquoted filename. %s is the match group name
|
||||
RE_PROFILE_PATH_OR_VAR = '(?P<%s>(' + RE_PATH + '|@{\S+}\S*|"@{\S+}[^"]*"))' # quoted or unquoted filename or variable. %s is the match group name
|
||||
RE_SAFE_OR_UNSAFE = '(?P<execmode>(safe|unsafe))'
|
||||
RE_XATTRS = '(\s+xattrs\s*=\s*\((?P<xattrs>([^)=]+=[^)=]+\s?)+)\)\s*)?'
|
||||
RE_XATTRS = '(\s+xattrs\s*=\s*\((?P<xattrs>([^)=]+(=[^)=]+)?\s?)+)\)\s*)?'
|
||||
RE_FLAGS = '(\s+(flags\s*=\s*)?\((?P<flags>[^)]+)\))?'
|
||||
|
||||
RE_PROFILE_END = re.compile('^\s*\}' + RE_EOL)
|
||||
|
|
Loading…
Add table
Reference in a new issue