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