[packages/kernel/LINUX_6_1] Backport ability to load apparmor profile hats before main profile is loaded.

arekm arekm at pld-linux.org
Fri Sep 15 18:03:34 CEST 2023


commit 5b9b6926302b41c0d4a3db978d862df50ba5d45e
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date:   Fri Sep 15 17:32:29 2023 +0200

    Backport ability to load apparmor profile hats before main profile is loaded.

 apparmor.patch | 133 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 kernel.spec    |   4 +-
 2 files changed, 136 insertions(+), 1 deletion(-)
---
diff --git a/kernel.spec b/kernel.spec
index baada061..97dd6cc6 100644
--- a/kernel.spec
+++ b/kernel.spec
@@ -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
 #
diff --git a/apparmor.patch b/apparmor.patch
new file mode 100644
index 00000000..9bb9ff38
--- /dev/null
+++ b/apparmor.patch
@@ -0,0 +1,133 @@
+commit 665b1856dc2399828d8ee07a18d4fd79868e729a
+Author: John Johansen <john.johansen at 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 at 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 */
================================================================

---- gitweb:

http://git.pld-linux.org/gitweb.cgi/packages/kernel.git/commitdiff/5b9b6926302b41c0d4a3db978d862df50ba5d45e



More information about the pld-cvs-commit mailing list