[lxc-devel] [lxd/master] apparmor: create an apparmor namespace for each container

2016-09-26 Thread tych0 on Github
The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/2428

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
Signed-off-by: Tycho Andersen 
From a00486e1e740de120edf734c3f9bb4f6a9452040 Mon Sep 17 00:00:00 2001
From: Tycho Andersen 
Date: Fri, 17 Jun 2016 17:51:17 +
Subject: [PATCH] apparmor: create an apparmor namespace for each container

Signed-off-by: Tycho Andersen 
---
 lxd/apparmor.go  | 101 ---
 lxd/container_lxc.go |  26 +++--
 lxd/daemon.go|  43 ++
 test/suites/basic.sh |  13 +--
 4 files changed, 163 insertions(+), 20 deletions(-)

diff --git a/lxd/apparmor.go b/lxd/apparmor.go
index b4d73f3..1adeadd 100644
--- a/lxd/apparmor.go
+++ b/lxd/apparmor.go
@@ -94,7 +94,7 @@ const AA_PROFILE_BASE = `
   mount fstype=sysfs -> /sys/,
   mount options=(rw, nosuid, nodev, noexec, remount) -> /sys/,
   deny /sys/firmware/efi/efivars/** rwklx,
-  deny /sys/kernel/security/** rwklx,
+  # note, /sys/kernel/security/** handled below
   mount options=(move) /sys/fs/cgroup/cgmanager/ -> 
/sys/fs/cgroup/cgmanager.lower/,
   mount options=(ro, nosuid, nodev, noexec, remount, strictatime) -> 
/sys/fs/cgroup/,
 
@@ -186,7 +186,7 @@ const AA_PROFILE_BASE = `
   deny /proc/sys/n[^e]*{,/**} wklx,
   deny /proc/sys/ne[^t]*{,/**} wklx,
   deny /proc/sys/net?*{,/**} wklx,
-  deny /sys/[^fdc]*{,/**} wklx,
+  deny /sys/[^fdck]*{,/**} wklx,
   deny /sys/c[^l]*{,/**} wklx,
   deny /sys/cl[^a]*{,/**} wklx,
   deny /sys/cla[^s]*{,/**} wklx,
@@ -250,14 +250,28 @@ const AA_PROFILE_NESTING = `
   mount options=bind /var/lib/lxd/shmounts/** -> /var/lib/lxd/**,
 `
 
-func AAProfileFull(c container) string {
-   lxddir := shared.VarPath("")
-   if len(c.Name())+len(lxddir)+7 >= 253 {
+func mkApparmorName(name string) string {
+   if len(name)+7 >= 253 {
hash := sha256.New()
-   io.WriteString(hash, lxddir)
-   lxddir = fmt.Sprintf("%x", hash.Sum(nil))
+   io.WriteString(hash, name)
+   return fmt.Sprintf("%x", hash.Sum(nil))
}
 
+   return name
+}
+
+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(strings.Trim(shared.VarPath(""), "/"), "/", 
"-", -1)
+   lxddir = mkApparmorName(lxddir)
+   return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir)
+}
+
+func AAProfileFull(c container) string {
+   lxddir := shared.VarPath("")
+   lxddir = mkApparmorName(lxddir)
return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir)
 }
 
@@ -289,11 +303,50 @@ func getAAProfileContent(c container) string {
profile += "  mount fstype=cgroup -> /sys/fs/cgroup/**,\n"
}
 
-   // Apply nesting bits
+   if aaStacking {
+   profile += "\n  ### Feature: apparmor stacking\n"
+
+   if c.IsPrivileged() {
+   profile += "\n  ### Configuration: apparmor loading 
disabled in privileged containers\n"
+   profile += "  deny /sys/k*{,/**} rwklx,\n"
+   } else {
+   profile += `  ### Configuration: apparmor loading in 
unprivileged containers
+  deny /sys/k[^e]*{,/**} wklx,
+  deny /sys/ke[^r]*{,/**} wklx,
+  deny /sys/ker[^n]*{,/**} wklx,
+  deny /sys/kern[^e]*{,/**} wklx,
+  deny /sys/kerne[^l]*{,/**} wklx,
+  deny /sys/kernel/[^s]*{,/**} wklx,
+  deny /sys/kernel/s[^e]*{,/**} wklx,
+  deny /sys/kernel/se[^c]*{,/**} wklx,
+  deny /sys/kernel/sec[^u]*{,/**} wklx,
+  deny /sys/kernel/secu[^r]*{,/**} wklx,
+  deny /sys/kernel/secur[^i]*{,/**} wklx,
+  deny /sys/kernel/securi[^t]*{,/**} wklx,
+  deny /sys/kernel/securit[^y]*{,/**} wklx,
+  deny /sys/kernel/security/[^a]*{,/**} wklx,
+  deny /sys/kernel/security/a[^p]*{,/**} wklx,
+  deny /sys/kernel/security/ap[^p]*{,/**} wklx,
+  deny /sys/kernel/security/app[^a]*{,/**} wklx,
+  deny /sys/kernel/security/appa[^r]*{,/**} wklx,
+  deny /sys/kernel/security/appar[^m]*{,/**} wklx,
+  deny /sys/kernel/security/apparm[^o]*{,/**} wklx,
+  deny /sys/kernel/security/apparmo[^r]*{,/**} wklx,
+  deny /sys/kernel/security/apparmor?*{,/**} wklx,
+  deny /sys/kernel/security?*{,/**} wklx,
+  deny /sys/kernel?*{,/**} wklx,
+`
+   profile += fmt.Sprintf("  change_profile -> 
\":%s://*\",\n", AANamespace(c))
+   }
+   }
+
if c.IsNesting() {
+   // Apply nesting bits
profile += "\n  ### Configuration: nesting\n"
profile += strings.TrimLeft(AA_PROFILE_NESTING, "\n")
-   profile += fmt.Sprintf("  change_profile -> \"%s\",\n", 
AAProfileFull(c))
+   if !a

[lxc-devel] [lxd/master] apparmor: create an apparmor namespace for each container

2016-06-23 Thread tych0 on Github
The following pull request was submitted through Github.
It can be accessed and reviewed at: https://github.com/lxc/lxd/pull/2151

This e-mail was sent by the LXC bot, direct replies will not reach the author
unless they happen to be subscribed to this list.

=== Description (from pull-request) ===
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 
From 2f93569e660ded55d554a4a4e6a8065d94835b42 Mon Sep 17 00:00:00 2001
From: Tycho Andersen 
Date: Fri, 17 Jun 2016 17:51:17 +
Subject: [PATCH] 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 
---
 lxd/apparmor.go  | 87 
 lxd/container_lxc.go | 25 +--
 lxd/daemon.go| 11 +++
 test/suites/basic.sh |  5 +--
 4 files changed, 111 insertions(+), 17 deletions(-)

diff --git a/lxd/apparmor.go b/lxd/apparmor.go
index ce25c50..c2c2327 100644
--- a/lxd/apparmor.go
+++ b/lxd/apparmor.go
@@ -47,6 +47,22 @@ const NESTING_AA_PROFILE = `
   signal,
 `
 
+const DEFAULT_AA_NAMESPACE_PROFILE = `
+#include 
+profile "lxd-default" flags=(attach_disconnected,mediate_deleted) {
+#include 
+
+# Special exception for cgroup namespaces
+%s
+
+# user input raw.apparmor below here
+%s
+
+# nesting support goes here if needed
+%s
+change_profile -> ":%s://*",
+}`
+
 const DEFAULT_AA_PROFILE = `
 #include 
 profile "%s" flags=(attach_disconnected,mediate_deleted) {
@@ -63,17 +79,35 @@ profile "%s" flags=(attach_disconnected,mediate_deleted) {
 change_profile -> "%s",
 }`
 
-func AAProfileFull(c container) string {
-   lxddir := shared.VarPath("")
-   if len(c.Name())+len(lxddir)+7 >= 253 {
+func mkApparmorName(name string) string {
+   if len(name)+7 >= 253 {
hash := sha256.New()
-   io.WriteString(hash, lxddir)
-   lxddir = fmt.Sprintf("%x", hash.Sum(nil))
+   io.WriteString(hash, name)
+   return fmt.Sprintf("%x", hash.Sum(nil))
}
 
+   return name
+}
+
+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)
+   lxddir = mkApparmorName(lxddir)
return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir)
 }
 
+func AAProfileFull(c container) string {
+   if aaStacking {
+   return fmt.Sprintf(":%s://lxd-default", AANamespace(c))
+   } else {
+   lxddir := shared.VarPath("")
+   lxddir = mkApparmorName(lxddir)
+   return fmt.Sprintf("lxd-%s_<%s>", c.Name(), lxddir)
+   }
+}
+
 func AAProfileShort(c container) string {
return fmt.Sprintf("lxd-%s", c.Name())
 }
@@ -99,7 +133,26 @@ func getAAProfileContent(c container) string {
nesting = NESTING_AA_PROFILE
}
 
-   return fmt.Sprintf(DEFAULT_AA_PROFILE, AAProfileFull(c), 
AAProfileCgns(), rawA