2
0
mirror of https://gitlab.com/apparmor/apparmor synced 2025-08-22 01:57:43 +00:00

Merge parser: fix variable expansion

When the variable was being expanded, it needed to be reevaluated to
check if there was still unresolved variables. That allowed for a
weird bug to happen: If the string contained a variable preceded by @,
like in "user@@{uid}" and the variable was resolved to a case where {
is used, like in @{uid}={[0-9],[1-9][0-9]}, then on the second pass,
the parser would try to resolve the following variable
@{[0-9],[1-9][0-9]}, which is incorrect behavior. Fix it by not
including part of the string that was already resolved on the
subsequent passes.

Signed-off-by: Georgia Garcia <georgia.garcia@canonical.com>

MR: https://gitlab.com/apparmor/apparmor/-/merge_requests/1756
Approved-by: Steve Beattie <steve+gitlab@nxnw.org>
Merged-by: Steve Beattie <steve+gitlab@nxnw.org>
This commit is contained in:
Steve Beattie 2025-07-31 22:55:32 -07:00
commit d61295a249
2 changed files with 31 additions and 10 deletions

View File

@ -0,0 +1,7 @@
#=DESCRIPTION expansion of alternation after extra, unescaped @
#=EXRESULT PASS
@{uid} = {[0-9],[1-9][0-9]}
/usr/bin/foo {
/sys/fs/cgroup/user.slice/user-@{uid}.slice/user@@{uid}.service/cpu.max r,
}

View File

@ -189,11 +189,23 @@ static void trim_trailing_slash(std::string& str)
str.clear(); // str is all '/' str.clear(); // str is all '/'
} }
int copy_value_to_name(std::string value, char **name)
{
free(*name);
*name = strdup(value.c_str());
if (!*name) {
errno = ENOMEM;
return -1;
}
return 0;
}
int variable::expand_by_alternation(char **name) int variable::expand_by_alternation(char **name)
{ {
std::string expanded_name = ""; std::string expanded_name = "";
bool filter_leading_slash = false; bool filter_leading_slash = false;
bool filter_trailing_slash = false; bool filter_trailing_slash = false;
int ret = 0;
if (!name) { if (!name) {
PERROR("ASSERT: name to be expanded cannot be NULL\n"); PERROR("ASSERT: name to be expanded cannot be NULL\n");
@ -226,8 +238,6 @@ int variable::expand_by_alternation(char **name)
return 1; return 1;
} }
free(*name);
size_t setsize = ref->expanded.size(); size_t setsize = ref->expanded.size();
auto i = ref->expanded.begin(); auto i = ref->expanded.begin();
@ -252,15 +262,19 @@ int variable::expand_by_alternation(char **name)
if (setsize > 1) { if (setsize > 1) {
expanded_name += "}"; expanded_name += "}";
} }
/* don't include prefix */
expanded_name = prefix + expanded_name + suffix; expanded_name = expanded_name + suffix;
*name = strdup(expanded_name.c_str()); ret = copy_value_to_name(expanded_name, name);
if (!*name) { if (ret)
errno = ENOMEM; return ret;
return -1;
}
/* recursive until no variables are found in *name */ /* recursive until no variables are found in *name */
return expand_by_alternation(name); ret = expand_by_alternation(name);
if (ret == 0) {
/* return prefix to name */
expanded_name = prefix + std::string(*name);
ret = copy_value_to_name(expanded_name, name);
}
return ret;
} }
int variable::expand_variable() int variable::expand_variable()