[libvirt] [sandbox][PATCH 0/2] AppArmor support

Hi all, Here are 2 patches: one to get apparmor support for virt-sandbox and virt-sandbox-service and 1 to get services with disk image actually start. The AppArmor support doesn't add any parameter to the user, virt-sandbox, just uses either apparmor or selinux depending on the one available... as those can't be running at the same time. Cédric Bosdonnat (2): AppArmor support virt-sandbox-service: mount /var after all other file systems bin/virt-sandbox-service | 21 ++++++++++++-------- libvirt-sandbox/libvirt-sandbox-builder.c | 32 +++++++++++++++++++++++++++++++ 2 files changed, 45 insertions(+), 8 deletions(-) -- 2.1.2

Implement construction of apparmor security labels. The choice between selinux and apparmor model isn't exposed to the user, but guessed depending on what the host supports. --- bin/virt-sandbox-service | 15 ++++++++------- libvirt-sandbox/libvirt-sandbox-builder.c | 32 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 5a3f6ab..7f72107 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -315,24 +315,25 @@ class Container: context.undefine() def get_security_model(self): - # XXX selinux is the default for the while, needs to be configurable someday - model = "selinux" - supported = False + model = None # Make sure we have a connection self.connect() # Loop over the security models from the host capabilities + # The first in "selinux" and "apparmor" will be the returned model + # Those two models can't coexist on a machine configCaps = self.conn.get_capabilities() hostCaps = configCaps.get_host() secmodels = hostCaps.get_secmodels() for secmodel in secmodels: - if secmodel.get_model() == model: - supported = True + if secmodel.get_model() == "selinux": + model = "selinux" + break + elif secmodel.get_model() == "apparmor": + model = "apparmor" break - if not supported: - model = None return model diff --git a/libvirt-sandbox/libvirt-sandbox-builder.c b/libvirt-sandbox/libvirt-sandbox-builder.c index 48fc9bc..bcad652 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder.c +++ b/libvirt-sandbox/libvirt-sandbox-builder.c @@ -358,6 +358,31 @@ static gboolean gvir_sandbox_builder_construct_security_selinux (GVirSandboxBuil return TRUE; } +static gboolean gvir_sandbox_builder_construct_security_apparmor(GVirSandboxBuilder *builder, + GVirSandboxConfig *config, + GVirConfigDomain *domain, + GError **error) +{ + GVirConfigDomainSeclabel *sec = gvir_config_domain_seclabel_new(); + const char *label = gvir_sandbox_config_get_security_label(config); + + gvir_config_domain_seclabel_set_model(sec, "apparmor"); + if (gvir_sandbox_config_get_security_dynamic(config)) { + gvir_config_domain_seclabel_set_type(sec, + GVIR_CONFIG_DOMAIN_SECLABEL_DYNAMIC); + } else { + gvir_config_domain_seclabel_set_type(sec, + GVIR_CONFIG_DOMAIN_SECLABEL_STATIC); + if (label) + gvir_config_domain_seclabel_set_label(sec, label); + } + + gvir_config_domain_set_seclabel(domain, sec); + g_object_unref(sec); + + return TRUE; +} + static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *builder, GVirSandboxConfig *config, const gchar *statedir G_GNUC_UNUSED, @@ -369,6 +394,7 @@ static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *buil GVirConfigCapabilitiesHost *hostCapabilities; GList *secmodels, *iter; gboolean supportsSelinux = FALSE; + gboolean supportsAppArmor = FALSE; /* What security models are available on the host? */ if (!(configCapabilities = gvir_connection_get_capabilities(connection, error))) { @@ -383,6 +409,9 @@ static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *buil if (g_str_equal(gvir_config_capabilities_host_secmodel_get_model( GVIR_CONFIG_CAPABILITIES_HOST_SECMODEL(iter->data)), "selinux")) supportsSelinux = TRUE; + if (g_str_equal(gvir_config_capabilities_host_secmodel_get_model( + GVIR_CONFIG_CAPABILITIES_HOST_SECMODEL(iter->data)), "apparmor")) + supportsAppArmor = TRUE; g_object_unref(iter->data); } @@ -394,6 +423,9 @@ static gboolean gvir_sandbox_builder_construct_security(GVirSandboxBuilder *buil if (supportsSelinux) return gvir_sandbox_builder_construct_security_selinux(builder, config, domain, error); + else if (supportsAppArmor) + return gvir_sandbox_builder_construct_security_apparmor(builder, config, + domain, error); return TRUE; } -- 2.1.2

On Tue, Nov 25, 2014 at 02:29:25PM +0100, Cédric Bosdonnat wrote:
Implement construction of apparmor security labels. The choice between selinux and apparmor model isn't exposed to the user, but guessed depending on what the host supports. --- bin/virt-sandbox-service | 15 ++++++++------- libvirt-sandbox/libvirt-sandbox-builder.c | 32 +++++++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 7 deletions(-)
[...]
diff --git a/libvirt-sandbox/libvirt-sandbox-builder.c b/libvirt-sandbox/libvirt-sandbox-builder.c index 48fc9bc..bcad652 100644 --- a/libvirt-sandbox/libvirt-sandbox-builder.c +++ b/libvirt-sandbox/libvirt-sandbox-builder.c @@ -358,6 +358,31 @@ static gboolean gvir_sandbox_builder_construct_security_selinux (GVirSandboxBuil return TRUE; }
+static gboolean gvir_sandbox_builder_construct_security_apparmor(GVirSandboxBuilder *builder, + GVirSandboxConfig *config, + GVirConfigDomain *domain, + GError **error) +{ + GVirConfigDomainSeclabel *sec = gvir_config_domain_seclabel_new(); + const char *label = gvir_sandbox_config_get_security_label(config); + + gvir_config_domain_seclabel_set_model(sec, "apparmor"); + if (gvir_sandbox_config_get_security_dynamic(config)) { + gvir_config_domain_seclabel_set_type(sec, + GVIR_CONFIG_DOMAIN_SECLABEL_DYNAMIC);
There probably isn't something like a 'baselabel' in apparmor, right? Because that could be set if there is a label in the config. Anyway, ACK, Martin

When creating a sandbox with an image file, the /var folder contains the mounted image. If we mount it before other file systems, how could we possibly mount them? The new /var won't contain the mounted image. --- bin/virt-sandbox-service | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 7f72107..701bd6e 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -658,7 +658,7 @@ WantedBy=multi-user.target self.config.add_mount(mount) for d in self.BIND_SYSTEM_DIRS: - if os.path.exists(d): + if d != "/var" and os.path.exists(d): source = "%s%s" % ( self.dest, d) self.add_bind_mount(source, d) @@ -677,6 +677,10 @@ WantedBy=multi-user.target if not found: source = "%s%s" % ( self.dest, d) self.add_bind_mount(source, d) + + # /var contains the mounted image if there is an image: should be the + # last thing to mount + self.add_bind_mount(source, "/var") self.add_mounts() def get_expanded_unit_template(self, unit): -- 2.1.2

On Tue, Nov 25, 2014 at 02:29:26PM +0100, Cédric Bosdonnat wrote:
When creating a sandbox with an image file, the /var folder contains the mounted image. If we mount it before other file systems, how could we possibly mount them? The new /var won't contain the mounted image. --- bin/virt-sandbox-service | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/bin/virt-sandbox-service b/bin/virt-sandbox-service index 7f72107..701bd6e 100755 --- a/bin/virt-sandbox-service +++ b/bin/virt-sandbox-service @@ -658,7 +658,7 @@ WantedBy=multi-user.target self.config.add_mount(mount)
for d in self.BIND_SYSTEM_DIRS: - if os.path.exists(d): + if d != "/var" and os.path.exists(d): source = "%s%s" % ( self.dest, d) self.add_bind_mount(source, d)
@@ -677,6 +677,10 @@ WantedBy=multi-user.target if not found: source = "%s%s" % ( self.dest, d) self.add_bind_mount(source, d) + + # /var contains the mounted image if there is an image: should be the + # last thing to mount + self.add_bind_mount(source, "/var")
You have the source set from a random value from self.dirs, ACK if you use "%s/var" % self.dist instead of source. Martin
self.add_mounts()
def get_expanded_unit_template(self, unit): -- 2.1.2
-- libvir-list mailing list libvir-list@redhat.com https://www.redhat.com/mailman/listinfo/libvir-list

Hi Martin, On Wed, 2014-11-26 at 05:32 +0100, Martin Kletzander wrote:
+ + # /var contains the mounted image if there is an image: should be the + # last thing to mount + self.add_bind_mount(source, "/var")
You have the source set from a random value from self.dirs, ACK if you use "%s/var" % self.dist instead of source.
Nice catch! Pushed them both with that change. -- Cedric
participants (3)
-
Cedric Bosdonnat
-
Cédric Bosdonnat
-
Martin Kletzander