]> git.pld-linux.org Git - packages/kernel.git/commitdiff
Backport ability to load apparmor profile hats before main profile is loaded. auto/th/kernel-6.1-6.1.53-2
authorArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 15 Sep 2023 15:32:29 +0000 (17:32 +0200)
committerArkadiusz Miśkiewicz <arekm@maven.pl>
Fri, 15 Sep 2023 15:32:29 +0000 (17:32 +0200)
apparmor.patch [new file with mode: 0644]
kernel.spec

diff --git a/apparmor.patch b/apparmor.patch
new file mode 100644 (file)
index 0000000..9bb9ff3
--- /dev/null
@@ -0,0 +1,133 @@
+commit 665b1856dc2399828d8ee07a18d4fd79868e729a
+Author: John Johansen <john.johansen@canonical.com>
+Date:   Mon Oct 3 06:06:26 2022 -0700
+
+    apparmor: Fix loading of child before parent
+    
+    Unfortunately it is possible for some userspace's to load children
+    profiles before the parent profile. This can even happen when the
+    child and the parent are in different load sets.
+    
+    Fix this by creating a null place holder profile that grants no permissions
+    and can be replaced by the parent once it is loaded.
+    
+    Signed-off-by: John Johansen <john.johansen@canonical.com>
+
+diff --git a/security/apparmor/policy.c b/security/apparmor/policy.c
+index c17ccedd35f1..66034cf96f4c 100644
+--- a/security/apparmor/policy.c
++++ b/security/apparmor/policy.c
+@@ -423,6 +423,57 @@ static struct aa_policy *__lookup_parent(struct aa_ns *ns,
+       return &profile->base;
+ }
++/**
++ * __create_missing_ancestors - create place holders for missing ancestores
++ * @ns: namespace to lookup profile in (NOT NULL)
++ * @hname: hierarchical profile name to find parent of (NOT NULL)
++ * @gfp: type of allocation.
++ *
++ * Returns: NULL on error, parent profile on success
++ *
++ * Requires: ns mutex lock held
++ *
++ * Returns: unrefcounted parent policy or NULL if error creating
++ *          place holder profiles.
++ */
++static struct aa_policy *__create_missing_ancestors(struct aa_ns *ns,
++                                                  const char *hname,
++                                                  gfp_t gfp)
++{
++      struct aa_policy *policy;
++      struct aa_profile *parent, *profile = NULL;
++      char *split;
++
++      AA_BUG(!ns);
++      AA_BUG(!hname);
++
++      policy = &ns->base;
++
++      for (split = strstr(hname, "//"); split;) {
++              parent = profile;
++              profile = __strn_find_child(&policy->profiles, hname,
++                                          split - hname);
++              if (!profile) {
++                      const char *name = kstrndup(hname, split - hname,
++                                                  gfp);
++                      if (!name)
++                              return NULL;
++                      profile = aa_alloc_null(parent, name, gfp);
++                      kfree(name);
++                      if (!profile)
++                              return NULL;
++                      if (!parent)
++                              profile->ns = aa_get_ns(ns);
++              }
++              policy = &profile->base;
++              hname = split + 2;
++              split = strstr(hname, "//");
++      }
++      if (!profile)
++              return &ns->base;
++      return &profile->base;
++}
++
+ /**
+  * __lookupn_profile - lookup the profile matching @hname
+  * @base: base list to start looking up profile name from  (NOT NULL)
+@@ -1032,6 +1083,7 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
+       /* setup parent and ns info */
+       list_for_each_entry(ent, &lh, list) {
+               struct aa_policy *policy;
++              struct aa_profile *p;
+               if (aa_g_export_binary)
+                       ent->new->rawdata = aa_get_loaddata(udata);
+@@ -1056,21 +1108,38 @@ ssize_t aa_replace_profiles(struct aa_ns *policy_ns, struct aa_label *label,
+                       continue;
+               /* no ref on policy only use inside lock */
++              p = NULL;
+               policy = __lookup_parent(ns, ent->new->base.hname);
+               if (!policy) {
+-                      struct aa_profile *p;
++                      /* first check for parent in the load set */
+                       p = __list_lookup_parent(&lh, ent->new);
+                       if (!p) {
+-                              error = -ENOENT;
+-                              info = "parent does not exist";
+-                              goto fail_lock;
++                              /*
++                               * fill in missing parent with null
++                               * profile that doesn't have
++                               * permissions. This allows for
++                               * individual profile loading where
++                               * the child is loaded before the
++                               * parent, and outside of the current
++                               * atomic set. This unfortunately can
++                               * happen with some userspaces.  The
++                               * null profile will be replaced once
++                               * the parent is loaded.
++                               */
++                              policy = __create_missing_ancestors(ns,
++                                                      ent->new->base.hname,
++                                                      GFP_KERNEL);
++                              if (!policy) {
++                                      error = -ENOENT;
++                                      info = "parent does not exist";
++                                      goto fail_lock;
++                              }
+                       }
+-                      rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
+-              } else if (policy != &ns->base) {
+-                      /* released on profile replacement or free_profile */
+-                      struct aa_profile *p = (struct aa_profile *) policy;
+-                      rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
+               }
++              if (!p && policy != &ns->base)
++                      /* released on profile replacement or free_profile */
++                      p = (struct aa_profile *) policy;
++              rcu_assign_pointer(ent->new->parent, aa_get_profile(p));
+       }
+       /* create new fs entries for introspection if needed */
index baada061586d341216d24aab7dcbdb04a581d25d..97dd6cc6dcddac4f919c5b5308fee9e7471e0d8f 100644 (file)
@@ -65,7 +65,7 @@
 %define                have_pcmcia     0
 %endif
 
-%define                rel             1
+%define                rel             2
 %define                basever         6.1
 %define                postver         .53
 
@@ -155,6 +155,7 @@ Patch2:             android-enable-building-binder-as-module.patch
 # http://dev.gentoo.org/~spock/projects/fbcondecor/archive/fbcondecor-0.9.4-2.6.25-rc6.patch
 Patch3:                kernel-fbcondecor.patch
 Patch6:                linux-wistron-nx.patch
+Patch7:                apparmor.patch
 
 # netfilter related stuff mostly based on patch-o-matic-ng
 # snapshot 20070806 with some fixes. Some modules
@@ -615,6 +616,7 @@ cd linux-%{basever}
 %patch3 -p1
 %endif
 %patch6 -p1
+%patch7 -p1
 
 ## netfilter
 #
This page took 0.235076 seconds and 4 git commands to generate.