[PATCH 1/5] UBUNTU: SAUCE: apparmor: fix label parse for stacked labels
John Johansen
john.johansen at canonical.com
Fri Mar 31 12:05:04 UTC 2017
Stacked labels with two ns profile components specified and the ns only
specified on one of them are not being correctly parsed. That is
P//&:ns://A//&unconfined
is being parsed as if P and unconfined are in the same ns while A
is in :ns: ie. it is being parsed as the equiv of
P//&unconfined//&:ns://A
The apparmor label spec requires that profiles are ordered by ns so
:ns://A//&unconfined should be parsed as if it is
P//&:ns://A//&:ns://unconfined
Note: the above with a ns spec for each profile component is currently
parsed correctly and the ns spec is always relative to the label view.
BugLink: http://bugs.launchpad.net/bugs/1677959
Signed-off-by: John Johansen <john.johansen at canonical.com>
---
security/apparmor/include/lib.h | 1 +
security/apparmor/label.c | 29 ++++++++++++++++++++++++++---
security/apparmor/lib.c | 2 +-
3 files changed, 28 insertions(+), 4 deletions(-)
diff --git a/security/apparmor/include/lib.h b/security/apparmor/include/lib.h
index 954e22a..f44561b 100644
--- a/security/apparmor/include/lib.h
+++ b/security/apparmor/include/lib.h
@@ -59,6 +59,7 @@
extern int apparmor_initialized __initdata;
/* fn's in lib */
+const char *skipn_spaces(const char *str, size_t n);
char *aa_split_fqname(char *args, char **ns_name);
const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
size_t *ns_len);
diff --git a/security/apparmor/label.c b/security/apparmor/label.c
index 69a600b4..db0eaba 100644
--- a/security/apparmor/label.c
+++ b/security/apparmor/label.c
@@ -1850,6 +1850,23 @@ static int label_count_str_entries(const char *str)
return count;
}
+/*
+ * ensure stacks with components like
+ * :ns://A//&B
+ * have :ns: applied to both 'A' and 'B' by making the lookup relative
+ * to the base if the lookup specifies an ns, else making the stacked lookup
+ * relative to the last embedded ns in the string.
+ */
+static struct aa_profile *fqlookupn_profile(struct aa_label *base,
+ struct aa_label *currentbase,
+ const char *str, size_t n)
+{
+ const char *first = skipn_spaces(str, n);
+ if (first && *first == ':')
+ return aa_fqlookupn_profile(base, str, n);
+ return aa_fqlookupn_profile(currentbase, str, n);
+}
+
/**
* aa_label_parse - parse, validate and convert a text string to a label
* @base: base label to use for lookups (NOT NULL)
@@ -1865,7 +1882,7 @@ struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
gfp_t gfp, bool create, bool force_stack)
{
DEFINE_VEC(profile, vec);
- struct aa_label *label;
+ struct aa_label *label, *currbase = base;
int i, len, stack = 0, error;
char *split;
@@ -1889,15 +1906,21 @@ struct aa_label *aa_label_parse(struct aa_label *base, const char *str,
vec[i] = aa_get_profile(base->vec[i]);
for (split = strstr(str, "//&"), i = stack; split && i < len; i++) {
- vec[i] = aa_fqlookupn_profile(base, str, split - str);
+ vec[i] = fqlookupn_profile(base, currbase, str, split - str);
if (!vec[i])
goto fail;
+ /*
+ * if component specified a new ns it becomes the new base
+ * so that subsequent lookups are relative to it
+ */
+ if (vec[i]->ns != labels_ns(currbase))
+ currbase = &vec[i]->label;
str = split + 3;
split = strstr(str, "//&");
}
/* last element doesn't have a split so this should be the case but just to be safe */
if (i < len) {
- vec[i] = aa_fqlookupn_profile(base, str, strlen(str));
+ vec[i] = fqlookupn_profile(base, currbase, str, strlen(str));
if (!vec[i])
goto fail;
}
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c
index 52d4efc..783d498 100644
--- a/security/apparmor/lib.c
+++ b/security/apparmor/lib.c
@@ -76,7 +76,7 @@ char *aa_split_fqname(char *fqname, char **ns_name)
* if all whitespace will return NULL
*/
-static const char *skipn_spaces(const char *str, size_t n)
+const char *skipn_spaces(const char *str, size_t n)
{
for (;n && isspace(*str); --n)
++str;
--
2.9.3
More information about the kernel-team
mailing list