This patch enables lxc-attach to join the profile of the container it
is attaching to.  Builds/runs fine with apparmor enabled and disabled.

Export new aa_get_profile(), and use it for attach_apparmor, but also
handle profile names longer than 100 chars in lxc_start apparmor
support.

Signed-off-by: Serge Hallyn <serge.hal...@ubuntu.com>
---
 src/lxc/apparmor.c   | 105 ++++++++++++++++++++++++++++++++++++++++-----------
 src/lxc/apparmor.h   |  22 ++++++++++-
 src/lxc/attach.c     |   2 +
 src/lxc/attach.h     |   1 +
 src/lxc/lxc_attach.c |   6 +++
 5 files changed, 111 insertions(+), 25 deletions(-)

diff --git a/src/lxc/apparmor.c b/src/lxc/apparmor.c
index ae3d8f7..c2d1d2f 100644
--- a/src/lxc/apparmor.c
+++ b/src/lxc/apparmor.c
@@ -1,4 +1,5 @@
 #include <stdio.h>
+#include <stdlib.h>
 #include <unistd.h>
 #include <errno.h>
 #include <sys/types.h>
@@ -16,21 +17,58 @@ lxc_log_define(lxc_apparmor, lxc);
 #define AA_MOUNT_RESTR "/sys/kernel/security/apparmor/features/mount/mask"
 #define AA_ENABLED_FILE "/sys/module/apparmor/parameters/enabled"
 
-static int aa_am_unconfined(void)
+
+/* caller must free the returned profile */
+extern char *aa_get_profile(pid_t pid)
 {
+       char path[100], *space;
        int ret;
-       char path[100], p[100];
-       sprintf(path, "/proc/%d/attr/current", getpid());
-       FILE *f = fopen(path, "r");
-       if (!f)
-               return 0;
-       ret = fscanf(f, "%99s", p);
+       char *buf = NULL;
+       int sz = 0;
+       FILE *f;
+
+       ret = snprintf(path, 100, "/proc/%d/attr/current", pid);
+       if (ret < 0 || ret >= 100) {
+               ERROR("path name too long");
+               return NULL;
+       }
+again:
+       f = fopen(path, "r");
+       if (!f) {
+               SYSERROR("opening %s\n", path);
+               return NULL;
+       }
+       sz += 1024;
+       buf = realloc(buf, sz);
+       if (!buf) {
+               ERROR("out of memory");
+               fclose(f);
+               return NULL;
+       }
+       ret = fread(buf, 1, sz, f);
        fclose(f);
-       if (ret < 1)
-               return 0;
-       if (strcmp(p, "unconfined") == 0)
-               return 1;
-       return 0;
+       if (ret >= sz)
+               goto again;
+       if (ret < 0) {
+               ERROR("reading %s\n", path);
+               free(buf);
+               return NULL;
+       }
+       space = index(buf, ' ');
+       if (space)
+               *space = '\0';
+       return buf;
+}
+
+static int aa_am_unconfined(void)
+{
+       char *p = aa_get_profile(getpid());
+       int ret = 0;
+       if (!p || strcmp(p, "unconfined") == 0)
+               ret = 1;
+       if (p)
+               free(p);
+       return ret;
 }
 
 /* aa_getcon is not working right now.  Use our hand-rolled version below */
@@ -61,36 +99,57 @@ extern void apparmor_handler_init(struct lxc_handler 
*handler)
 }
 
 #define AA_DEF_PROFILE "lxc-container-default"
-extern int apparmor_load(struct lxc_handler *handler)
+
+extern int do_apparmor_load(int aa_enabled, char *aa_profile,
+                                  int umount_proc, int dropprivs)
 {
-       if (!handler->aa_enabled) {
+       if (!aa_enabled) {
                INFO("apparmor not enabled");
                return 0;
        }
        INFO("setting up apparmor");
 
-       if (!handler->conf->aa_profile)
-               handler->conf->aa_profile = AA_DEF_PROFILE;
+       if (!aa_profile)
+               aa_profile = AA_DEF_PROFILE;
 
-       if (strcmp(handler->conf->aa_profile, "unconfined") == 0 &&
-           aa_am_unconfined()) {
+       if (strcmp(aa_profile, "unconfined") == 0 && !dropprivs && 
aa_am_unconfined()) {
                INFO("apparmor profile unchanged");
                return 0;
        }
 
-       //if (aa_change_onexec(handler->conf->aa_profile) < 0) {
-       if (aa_change_profile(handler->conf->aa_profile) < 0) {
-               SYSERROR("failed to change apparmor profile to %s", 
handler->conf->aa_profile);
+       //if (aa_change_onexec(aa_profile) < 0) {
+       if (aa_change_profile(aa_profile) < 0) {
+               SYSERROR("failed to change apparmor profile to %s", aa_profile);
                return -1;
        }
-       if (handler->conf->lsm_umount_proc == 1)
+       if (umount_proc == 1)
                umount("/proc");
 
-       INFO("changed apparmor profile to %s", handler->conf->aa_profile);
+       INFO("changed apparmor profile to %s", aa_profile);
 
        return 0;
 }
 
+extern int apparmor_load(struct lxc_handler *handler)
+{
+       if (!handler->conf->aa_profile)
+               handler->conf->aa_profile = AA_DEF_PROFILE;
+       return do_apparmor_load(handler->aa_enabled, 
+                               handler->conf->aa_profile,
+                               handler->conf->lsm_umount_proc, 0);
+}
+
+extern int attach_apparmor(char *profile)
+{
+       if (!profile)
+               return 0;
+       if (!check_apparmor_enabled())
+               return 0;
+       if (strcmp(profile, "unconfined") == 0)
+               return 0;
+       return do_apparmor_load(1, profile, 0, 1);
+}
+
 /*
  * this will likely move to a generic lsm.c, as selinux and smack will both
  * also want proc mounted in the container so as to transition
diff --git a/src/lxc/apparmor.h b/src/lxc/apparmor.h
index af879c0..d714478 100644
--- a/src/lxc/apparmor.h
+++ b/src/lxc/apparmor.h
@@ -3,16 +3,34 @@
 
 struct lxc_handler;
 
+/*
+ * apparmor_handler_init is really just a wrapper around check_apparmor_enabled
+ * to allow us to keep from having #ifdef APPARMOR in start.c
+ */
+extern void apparmor_handler_init(struct lxc_handler *handler);
+
 #if HAVE_APPARMOR
+extern char *aa_get_profile(pid_t pid);
+extern int do_apparmor_load(int aa_enabled, char *aa_profile,
+                                  int umount_proc, int dropprivs);
 extern int apparmor_load(struct lxc_handler *handler);
+extern int attach_apparmor(char *profile);
 extern int lsm_mount_proc_if_needed(char *root_src, char *rootfs_tgt);
-extern void apparmor_handler_init(struct lxc_handler *handler);
 #else
+static inline char *aa_get_profile(pid_t pid) {
+       return NULL;
+}
+static inline int do_apparmor_load(int aa_enabled, char *aa_profile,
+                                  int umount_proc, int dropprivs) {
+       return 0;
+}
+static inline int attach_apparmor(char *profile) {
+       return 0;
+}
 static inline int apparmor_load(struct lxc_handler *handler) {
        return 0;
 }
 static inline int lsm_mount_proc_if_needed(char *root_src, char *rootfs_tgt) {
        return 0;
 }
-extern void apparmor_handler_init(struct lxc_handler *handler);
 #endif
diff --git a/src/lxc/attach.c b/src/lxc/attach.c
index b86d2f4..af3d7a0 100644
--- a/src/lxc/attach.c
+++ b/src/lxc/attach.c
@@ -44,6 +44,7 @@
 #include "caps.h"
 #include "cgroup.h"
 #include "config.h"
+#include "apparmor.h"
 
 lxc_log_define(lxc_attach, lxc);
 
@@ -137,6 +138,7 @@ struct lxc_proc_context_info 
*lxc_proc_get_context_info(pid_t pid)
                errno = ENOENT;
                goto out_error;
        }
+       info->aa_profile = aa_get_profile(pid);
 
        return info;
 
diff --git a/src/lxc/attach.h b/src/lxc/attach.h
index aab47e3..4d4f719 100644
--- a/src/lxc/attach.h
+++ b/src/lxc/attach.h
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 
 struct lxc_proc_context_info {
+       char *aa_profile;
        unsigned long personality;
        unsigned long long capability_mask;
 };
diff --git a/src/lxc/lxc_attach.c b/src/lxc/lxc_attach.c
index 370bfbc..e1511ef 100644
--- a/src/lxc/lxc_attach.c
+++ b/src/lxc/lxc_attach.c
@@ -41,6 +41,7 @@
 #include "sync.h"
 #include "log.h"
 #include "namespace.h"
+#include "apparmor.h"
 
 #if HAVE_SYS_PERSONALITY_H
 #include <sys/personality.h>
@@ -265,6 +266,11 @@ int main(int argc, char *argv[])
                lxc_sync_fini_parent(handler);
                lxc_cgroup_dispose_attach(cgroup_data);
 
+               if (attach_apparmor(init_ctx->aa_profile) < 0) {
+                       ERROR("failed switching apparmor profiles");
+                       return -1;
+               }
+
                /* A description of the purpose of this functionality is
                 * provided in the lxc-attach(1) manual page. We have to
                 * remount here and not in the parent process, otherwise
-- 
1.8.1.2


------------------------------------------------------------------------------
Everyone hates slow websites. So do we.
Make your web apps faster with AppDynamics
Download AppDynamics Lite for free today:
http://p.sf.net/sfu/appdyn_d2d_feb
_______________________________________________
Lxc-devel mailing list
Lxc-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/lxc-devel

Reply via email to