From e2d745442133f625e715f713c0441f0f2a7ea6ad Mon Sep 17 00:00:00 2001
From: John Johansen <john.johansen@canonical.com>
Date: Fri, 29 Jun 2012 17:34:01 -0700
Subject: [PATCH 4/6] apparmor: Ensure apparmor does not mediate kernel based
 sockets

Currently apparmor makes the assumption that kernel sockets are unmediated
because mediation is only done against tasks that have a profile attached.
Ensure we never get in a situation where a kernel socket is being mediated
by tagging the sk_security field for kernel sockets.

Signed-off-by: John Johansen <john.johansen@canonical.com>
---
 security/apparmor/include/net.h |    2 ++
 security/apparmor/lsm.c         |   18 ++++++++++++++++++
 security/apparmor/net.c         |    3 +++
 3 files changed, 23 insertions(+)

diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
index cb8a121..bc8198b 100644
--- a/security/apparmor/include/net.h
+++ b/security/apparmor/include/net.h
@@ -19,6 +19,8 @@
 
 #include "apparmorfs.h"
 
+#define AA_SOCK_KERN 0xAA
+
 /* struct aa_net - network confinement data
  * @allowed: basic network families permissions
  * @audit_network: which network permissions to force audit
diff --git a/security/apparmor/lsm.c b/security/apparmor/lsm.c
index f628734..a172d01 100644
--- a/security/apparmor/lsm.c
+++ b/security/apparmor/lsm.c
@@ -630,6 +630,16 @@ static int apparmor_socket_create(int family, int type, int protocol, int kern)
 	return error;
 }
 
+static int apparmor_socket_post_create(struct socket *sock, int family,
+				       int type, int protocol, int kern)
+{
+	if (kern)
+		/* tag kernel sockets so we don't mediate them later */
+		sock->sk->sk_security = (void *) AA_SOCK_KERN;
+
+	return 0;
+}
+
 static int apparmor_socket_bind(struct socket *sock,
 				struct sockaddr *address, int addrlen)
 {
@@ -713,6 +723,12 @@ static int apparmor_socket_shutdown(struct socket *sock, int how)
 	return aa_revalidate_sk(OP_SOCK_SHUTDOWN, sk);
 }
 
+static void apparmor_sk_clone_security(const struct sock *sk,
+				       struct sock *newsk)
+{
+	newsk->sk_security = sk->sk_security;
+}
+
 static struct security_operations apparmor_ops = {
 	.name =				"apparmor",
 
@@ -746,6 +762,7 @@ static struct security_operations apparmor_ops = {
 	.setprocattr =			apparmor_setprocattr,
 
 	.socket_create =		apparmor_socket_create,
+	.socket_post_create =		apparmor_socket_post_create,
 	.socket_bind =			apparmor_socket_bind,
 	.socket_connect =		apparmor_socket_connect,
 	.socket_listen =		apparmor_socket_listen,
@@ -757,6 +774,7 @@ static struct security_operations apparmor_ops = {
 	.socket_getsockopt =		apparmor_socket_getsockopt,
 	.socket_setsockopt =		apparmor_socket_setsockopt,
 	.socket_shutdown =		apparmor_socket_shutdown,
+	.sk_clone_security =		apparmor_sk_clone_security,
 
 	.cred_alloc_blank =		apparmor_cred_alloc_blank,
 	.cred_free =			apparmor_cred_free,
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
index 6e6e5c9..baa4df1 100644
--- a/security/apparmor/net.c
+++ b/security/apparmor/net.c
@@ -153,6 +153,9 @@ int aa_revalidate_sk(int op, struct sock *sk)
 	if (in_interrupt())
 		return 0;
 
+	if (sk->sk_security == (void *) AA_SOCK_KERN)
+		return 0;
+
 	profile = __aa_current_profile();
 	if (!unconfined(profile))
 		error = aa_net_perm(op, profile, sk->sk_family, sk->sk_type,
-- 
1.7.10.4

