[lxc-devel] [lxd/master] apparmor: create an apparmor namespace for each container
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
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