SELinux: Socket retains creator role and MLS attribute

The socket SID would be computed on creation and no longer inherit
its creator's SID by default. Socket may have a different type but
needs to retain the creator's role and MLS attribute in order not
to break labeled networking and network access control.

The kernel value for a class would be used to determine if the class
if one of socket classes. If security_compute_sid is called from
userspace the policy value for a class would be mapped to the relevant
kernel value first.

Signed-off-by: Harry Ciao <qingtao.cao@windriver.com>
Signed-off-by: Eric Paris <eparis@redhat.com>
Acked-by: Stephen Smalley <sds@tycho.nsa.gov>
diff --git a/security/selinux/ss/mls.c b/security/selinux/ss/mls.c
index 1ef8e4e..e961742 100644
--- a/security/selinux/ss/mls.c
+++ b/security/selinux/ss/mls.c
@@ -512,7 +512,8 @@
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
-		    struct context *newcontext)
+		    struct context *newcontext,
+		    bool sock)
 {
 	struct range_trans rtr;
 	struct mls_range *r;
@@ -531,7 +532,7 @@
 			return mls_range_set(newcontext, r);
 		/* Fallthrough */
 	case AVTAB_CHANGE:
-		if (tclass == policydb.process_class)
+		if ((tclass == policydb.process_class) || (sock == true))
 			/* Use the process MLS attributes. */
 			return mls_context_cpy(newcontext, scontext);
 		else
diff --git a/security/selinux/ss/mls.h b/security/selinux/ss/mls.h
index cd91526..037bf9d 100644
--- a/security/selinux/ss/mls.h
+++ b/security/selinux/ss/mls.h
@@ -49,7 +49,8 @@
 		    struct context *tcontext,
 		    u16 tclass,
 		    u32 specified,
-		    struct context *newcontext);
+		    struct context *newcontext,
+		    bool sock);
 
 int mls_setup_user_range(struct context *fromcon, struct user_datum *user,
 			 struct context *usercon);
diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c
index 2e36e03..3e7544d 100644
--- a/security/selinux/ss/services.c
+++ b/security/selinux/ss/services.c
@@ -201,6 +201,21 @@
 	return tclass;
 }
 
+/*
+ * Get kernel value for class from its policy value
+ */
+static u16 map_class(u16 pol_value)
+{
+	u16 i;
+
+	for (i = 1; i < current_mapping_size; i++) {
+		if (current_mapping[i].value == pol_value)
+			return i;
+	}
+
+	return pol_value;
+}
+
 static void map_decision(u16 tclass, struct av_decision *avd,
 			 int allow_unknown)
 {
@@ -1374,6 +1389,7 @@
 	struct avtab_node *node;
 	u16 tclass;
 	int rc = 0;
+	bool sock;
 
 	if (!ss_initialized) {
 		switch (orig_tclass) {
@@ -1391,10 +1407,13 @@
 
 	read_lock(&policy_rwlock);
 
-	if (kern)
+	if (kern) {
 		tclass = unmap_class(orig_tclass);
-	else
+		sock = security_is_socket_class(orig_tclass);
+	} else {
 		tclass = orig_tclass;
+		sock = security_is_socket_class(map_class(tclass));
+	}
 
 	scontext = sidtab_search(&sidtab, ssid);
 	if (!scontext) {
@@ -1425,7 +1444,7 @@
 	}
 
 	/* Set the role and type to default values. */
-	if (tclass == policydb.process_class) {
+	if ((tclass == policydb.process_class) || (sock == true)) {
 		/* Use the current role and type of process. */
 		newcontext.role = scontext->role;
 		newcontext.type = scontext->type;
@@ -1482,7 +1501,8 @@
 
 	/* Set the MLS attributes.
 	   This is done last because it may allocate memory. */
-	rc = mls_compute_sid(scontext, tcontext, tclass, specified, &newcontext);
+	rc = mls_compute_sid(scontext, tcontext, tclass, specified,
+			     &newcontext, sock);
 	if (rc)
 		goto out_unlock;