2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-30 22:05:27 +00:00

parser: add support for matching based on extended file attributes

Add userland support for matching based on extended file attributes.
This leverages DFA based matching already in the kernel:

https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=8e51f908
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=73f488cd

Matching is exposed via flags on the profile:

  /usr/bin/* xattrs=(user.foo=bar user.bar=**) {
      # ...
  }

Profiles list the set of extended attributes that a file MUST have, and
a regex to match the value of that extended attributes. Additional
extended attributes on the file don't effect the match.

Signed-off-by: Eric Chiang <ericchiang@google.com>
This commit is contained in:
Eric Chiang
2018-12-06 10:54:46 -08:00
parent 6804731892
commit a42fd8c6f4
23 changed files with 246 additions and 8 deletions

View File

@@ -432,12 +432,29 @@ static const char *local_name(const char *name)
return name;
}
/*
* get_xattr_value returns the value of an xattr expression, performing NULL
* checks along the way. The method returns NULL if the xattr match doesn't
* have an xattrs (though this case currently isn't permitted by the parser).
*/
char *get_xattr_value(struct cond_entry *entry)
{
if (!entry->eq)
return NULL;
if (!entry->vals)
return NULL;
return entry->vals->value;
}
static int process_profile_name_xmatch(Profile *prof)
{
std::string tbuf;
pattern_t ptype;
const char *name;
struct cond_entry *entry;
const char *xattr_value;
/* don't filter_slashes for profile names */
if (prof->attachment)
name = prof->attachment;
@@ -451,7 +468,7 @@ static int process_profile_name_xmatch(Profile *prof)
if (ptype == ePatternInvalid) {
PERROR(_("%s: Invalid profile name '%s' - bad regular expression\n"), progname, name);
return FALSE;
} else if (ptype == ePatternBasic && !(prof->altnames || prof->attachment)) {
} else if (ptype == ePatternBasic && !(prof->altnames || prof->attachment || prof->xattrs.list)) {
/* no regex so do not set xmatch */
prof->xmatch = NULL;
prof->xmatch_len = 0;
@@ -479,6 +496,28 @@ static int process_profile_name_xmatch(Profile *prof)
}
}
}
if (prof->xattrs.list) {
for (entry = prof->xattrs.list; entry; entry = entry->next) {
xattr_value = get_xattr_value(entry);
if (!xattr_value)
xattr_value = "**"; // Default to allowing any value.
/* len is measured because it's required to
* convert the regex to pcre, but doesn't impact
* xmatch_len. The kernel uses the number of
* xattrs matched to prioritized in addition to
* xmatch_len.
*/
int len;
tbuf.clear();
convert_aaregex_to_pcre(xattr_value, 0,
glob_default, tbuf,
&len);
if (!rules->append_rule(tbuf.c_str(), dfaflags)) {
delete rules;
return FALSE;
}
}
}
prof->xmatch = rules->create_dfa(&prof->xmatch_size, &prof->xmatch_len, dfaflags);
delete rules;
if (!prof->xmatch)