]> git.proxmox.com Git - mirror_ubuntu-zesty-kernel.git/commitdiff
UBUNTU: SAUCE: apparmor: fix label parse for stacked labels
authorJohn Johansen <john.johansen@canonical.com>
Fri, 31 Mar 2017 12:05:04 +0000 (05:05 -0700)
committerTim Gardner <tim.gardner@canonical.com>
Mon, 3 Apr 2017 14:14:28 +0000 (15:14 +0100)
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@canonical.com>
Signed-off-by: Tim Gardner <tim.gardner@canonical.com>
security/apparmor/include/lib.h
security/apparmor/label.c
security/apparmor/lib.c

index 954e22ae83429dd8ca7810f5729bc64a234e7cdd..f44561b6075b5ffcf9818d6a3359129c77a37098 100644 (file)
@@ -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);
index 69a600b4c1a154560bf8843f9fbc0ee4846b4736..db0eaba829cbe6a4a075e1913fbeef2c8a7a676b 100644 (file)
@@ -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;
        }
index 52d4efcad23740115f1a3dd28a929f8edc510746..783d49859bca67d9b9edb7123b8c83e97480fc92 100644 (file)
@@ -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;