[lxc-devel] [lxd/master] Apparmor namespaces

tych0 on Github lxc-bot at linuxcontainers.org
Fri Jun 17 18:17:35 UTC 2016


A non-text attachment was scrubbed...
Name: not available
Type: text/x-mailbox
Size: 301 bytes
Desc: not available
URL: <http://lists.linuxcontainers.org/pipermail/lxc-devel/attachments/20160617/ffbcb56b/attachment.bin>
-------------- next part --------------
From cf1e6bddb7adb70365c64f30a298f0a4f68152c2 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 17 Jun 2016 17:51:17 +0000
Subject: [PATCH 1/2] apparmor: create an apparmor namespace for each container

Note that this only allows privileged containers to load apparmor profiles, and
only then with something like:

diff --git a/config/apparmor/abstractions/container-base b/config/apparmor/abstractions/container-base
index fe24ff3..7138249 100644
--- a/config/apparmor/abstractions/container-base
+++ b/config/apparmor/abstractions/container-base
@@ -93,7 +93,7 @@
   mount fstype=sysfs -> /sys/,
   mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
   deny /sys/firmware/efi/efivars/** rwklx,
-  deny /sys/kernel/security/** rwklx,
+  # deny /sys/kernel/security/** rwklx,
   mount options=(move) /sys/fs/cgroup/cgmanager/ -> /sys/fs/cgroup/cgmanager.lower/,
   mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> /sys/fs/cgroup/,

We'll need to do something with the permissions on
/sys/kernel/security/apparmor to allow unprivileged users to write to it. I'll
be in touch with the security team about that, but for now I don't think this
hurts anything.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 lxd/apparmor.go      | 29 ++++++++++++++++++++---------
 lxd/container_lxc.go |  4 +++-
 test/suites/basic.sh |  5 +++--
 3 files changed, 26 insertions(+), 12 deletions(-)

diff --git a/lxd/apparmor.go b/lxd/apparmor.go
index ce25c50..2dabab9 100644
--- a/lxd/apparmor.go
+++ b/lxd/apparmor.go
@@ -49,7 +49,7 @@ const NESTING_AA_PROFILE = `
 
 const DEFAULT_AA_PROFILE = `
 #include <tunables/global>
-profile "%s" flags=(attach_disconnected,mediate_deleted) {
+profile "lxd-default" flags=(attach_disconnected,mediate_deleted) {
     #include <abstractions/lxc/container-base>
 
     # Special exception for cgroup namespaces
@@ -60,11 +60,14 @@ profile "%s" flags=(attach_disconnected,mediate_deleted) {
 
     # nesting support goes here if needed
     %s
-    change_profile -> "%s",
+    change_profile -> ":%s://*",
 }`
 
-func AAProfileFull(c container) string {
-	lxddir := shared.VarPath("")
+func AANamespace(c container) string {
+	/* / is not allowed in apparmor namespace names; let's also trim the
+	 * leading / so it doesn't look like "-var-lib-lxd"
+	 */
+	lxddir := strings.Replace(shared.VarPath("")[1:], "/", "-", -1)
 	if len(c.Name())+len(lxddir)+7 >= 253 {
 		hash := sha256.New()
 		io.WriteString(hash, lxddir)
@@ -74,6 +77,10 @@ func AAProfileFull(c container) string {
 	return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir)
 }
 
+func AAProfileFull(c container) string {
+	return fmt.Sprintf(":%s://lxd-default", AANamespace(c))
+}
+
 func AAProfileShort(c container) string {
 	return fmt.Sprintf("lxd-%s", c.Name())
 }
@@ -99,7 +106,7 @@ func getAAProfileContent(c container) string {
 		nesting = NESTING_AA_PROFILE
 	}
 
-	return fmt.Sprintf(DEFAULT_AA_PROFILE, AAProfileFull(c), AAProfileCgns(), rawApparmor, nesting, AAProfileFull(c))
+	return fmt.Sprintf(DEFAULT_AA_PROFILE, AAProfileCgns(), rawApparmor, nesting, AANamespace(c))
 }
 
 func runApparmor(command string, c container) error {
@@ -108,6 +115,8 @@ func runApparmor(command string, c container) error {
 	}
 
 	cmd := exec.Command("apparmor_parser", []string{
+		"-n",
+		AANamespace(c),
 		fmt.Sprintf("-%sWL", command),
 		path.Join(aaPath, "cache"),
 		path.Join(aaPath, "profiles", AAProfileShort(c)),
@@ -165,14 +174,16 @@ func AALoadProfile(c container) error {
 	return runApparmor(APPARMOR_CMD_LOAD, c)
 }
 
-// Ensure that the container's policy is unloaded to free kernel memory. This
-// does not delete the policy from disk or cache.
-func AAUnloadProfile(c container) error {
+// Ensure that the container's policy namespace is unloaded to free kernel
+// memory. This does not delete the policy from disk or cache.
+func AADestroyNamespace(c container) error {
 	if !aaAdmin {
 		return nil
 	}
 
-	return runApparmor(APPARMOR_CMD_UNLOAD, c)
+	content := []byte(fmt.Sprintf(":%s:", AANamespace(c)))
+
+	return ioutil.WriteFile("/sys/kernel/security/apparmor/.remove", content, 0)
 }
 
 // Parse the profile without loading it into the kernel.
diff --git a/lxd/container_lxc.go b/lxd/container_lxc.go
index 24ff128..969ffab 100644
--- a/lxd/container_lxc.go
+++ b/lxd/container_lxc.go
@@ -1423,7 +1423,9 @@ func (c *containerLXC) OnStop(target string) error {
 	}
 
 	// Unload the apparmor profile
-	AAUnloadProfile(c)
+	if err := AADestroyNamespace(c); err != nil {
+		shared.Log.Error("failed to destroy apparmor namespace", log.Ctx{"container": c.Name(), "err": err})
+	}
 
 	// FIXME: The go routine can go away once we can rely on LXC_TARGET
 	go func(c *containerLXC, target string, wg *sync.WaitGroup) {
diff --git a/test/suites/basic.sh b/test/suites/basic.sh
index 7e4f915..d2780e6 100644
--- a/test/suites/basic.sh
+++ b/test/suites/basic.sh
@@ -299,9 +299,10 @@ test_basic_usage() {
   # check that an apparmor profile is created for this container, that it is
   # unloaded on stop, and that it is deleted when the container is deleted
   lxc launch testimage lxd-apparmor-test
-  aa-status | grep "lxd-lxd-apparmor-test_<${LXD_DIR}>"
+  aa_namespace="lxd-lxd-apparmor-test_<$(echo ${LXD_DIR} | sed -e 's/\//-/g' -e 's/^.//')>"
+  aa-status | grep ":${aa_namespace}://lxd-default"
   lxc stop lxd-apparmor-test --force
-  ! aa-status | grep -q "lxd-lxd-apparmor-test_<${LXD_DIR}>"
+  ! aa-status | grep -q ":${aa_namespace}://lxd-default"
   lxc delete lxd-apparmor-test
   [ ! -f "${LXD_DIR}/security/apparmor/profiles/lxd-lxd-apparmor-test" ]
 

From 9a0d3ac58d281d5bd67932247e52a6923b1b2d64 Mon Sep 17 00:00:00 2001
From: Tycho Andersen <tycho.andersen at canonical.com>
Date: Fri, 17 Jun 2016 18:12:46 +0000
Subject: [PATCH 2/2] tests: fix hang

lxc asks about the fingerprint more now, so let's tell it that fingerprint
is okay.

Signed-off-by: Tycho Andersen <tycho.andersen at canonical.com>
---
 test/main.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/test/main.sh b/test/main.sh
index 8fb8476..532e7d9 100755
--- a/test/main.sh
+++ b/test/main.sh
@@ -138,7 +138,7 @@ gen_cert() {
   [ -f "${LXD_CONF}/${1}.crt" ] && return
   mv "${LXD_CONF}/client.crt" "${LXD_CONF}/client.crt.bak"
   mv "${LXD_CONF}/client.key" "${LXD_CONF}/client.key.bak"
-  lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true
+  echo y | lxc_remote remote add "$(uuidgen)" https://0.0.0.0 || true
   mv "${LXD_CONF}/client.crt" "${LXD_CONF}/${1}.crt"
   mv "${LXD_CONF}/client.key" "${LXD_CONF}/${1}.key"
   mv "${LXD_CONF}/client.crt.bak" "${LXD_CONF}/client.crt"


More information about the lxc-devel mailing list