File CVE-2015-1334-Don-t-use-the-container-s-proc-during-.patch of Package lxc.openSUSE_13.1_Update

From: =?UTF-8?q?St=C3=A9phane=20Graber?= <stgraber@ubuntu.com>
Date: Thu, 16 Jul 2015 16:37:51 -0400
Subject: CVE-2015-1334: Don't use the container's /proc during attach
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Patch-mainline: yes
Git-commit: 5c3fcae78b63ac9dd56e36075903921bd9461f9e
References: bnc#938523

A user could otherwise over-mount /proc and prevent the apparmor profile
or selinux label from being written which combined with a modified
/bin/sh or other commonly used binary would lead to unconfined code
execution.

Reported-by: Roman Fiedler
Signed-off-by: Stéphane Graber <stgraber@ubuntu.com>
Signed-off-by: Jiri Slaby <jslaby@suse.com> [backport to 0.9]
---
 src/lxc/lxc_attach.c |   53 ++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 52 insertions(+), 1 deletion(-)

--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -24,9 +24,11 @@
 #define _GNU_SOURCE
 #include <unistd.h>
 #include <errno.h>
+#include <fcntl.h>
 #include <pwd.h>
 #include <stdlib.h>
 #include <sys/param.h>
+#include <sys/stat.h>
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <sys/wait.h>
@@ -140,6 +142,48 @@ Options :\n\
 	.checker  = NULL,
 };
 
+static int lsm_set_label_at(int procfd, char *lsm_label)
+{
+	int labelfd = -1;
+	int ret = 0;
+	int size;
+	char *command = NULL;
+
+	labelfd = openat(procfd, "self/attr/current", O_RDWR);
+	if (labelfd < 0) {
+		SYSERROR("Unable to open LSM label");
+		ret = -1;
+		goto out;
+	}
+
+	command = malloc(strlen(lsm_label) + strlen("changeprofile ") + 1);
+	if (!command) {
+		SYSERROR("Failed to write apparmor profile");
+		ret = -1;
+		goto out;
+	}
+
+	size = sprintf(command, "changeprofile %s", lsm_label);
+	if (size < 0) {
+		SYSERROR("Failed to write apparmor profile");
+		ret = -1;
+		goto out;
+	}
+
+	if (write(labelfd, command, size + 1) < 0) {
+		SYSERROR("Unable to set LSM label");
+		ret = -1;
+		goto out;
+	}
+out:
+	free(command);
+
+	if (labelfd != -1)
+		close(labelfd);
+
+	return ret;
+}
+
 int main(int argc, char *argv[])
 {
 	int ret;
@@ -395,10 +439,17 @@ int main(int argc, char *argv[])
 		close(cgroup_ipc_sockets[1]);
 
 		if ((namespace_flags & CLONE_NEWNS)) {
-			if (attach_apparmor(init_ctx->aa_profile) < 0) {
+			int procfd = open("/proc", O_DIRECTORY | O_RDONLY);
+			if (procfd < 0) {
+				SYSERROR("Unable to open /proc");
+				return -1;
+			}
+			if (lsm_set_label_at(procfd, init_ctx->aa_profile) < 0) {
 				ERROR("failed switching apparmor profiles");
 				return -1;
 			}
+			/* we don't need proc anymore */
+			close(procfd);
 		}
 
 		/* A description of the purpose of this functionality is
openSUSE Build Service is sponsored by