From eb6d21cc0e55fcaf9abd224f60dd799dea69da68 Mon Sep 17 00:00:00 2001 From: "Daniel P. Berrange" Date: Mon, 29 Jun 2009 17:09:42 +0000 Subject: [PATCH] Reduce LXC capabilities --- ChangeLog | 9 ++++++ src/lxc_container.c | 66 +++++++++++++++++++++++++++++--------------- src/lxc_controller.c | 28 +++++++++++++++++++ 3 files changed, 81 insertions(+), 22 deletions(-) diff --git a/ChangeLog b/ChangeLog index dc89e19cf3..90047c98dc 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,12 @@ +Mon Jun 29 18:01:20 BST 2009 Daniel P. Berrange + + Reduce LXC capabilities + * src/lxc_container.c: Use libcap-ng to clear capabilities, + and also drop SYS_MODULE, SYS_TIME, AUDIT_CONTROL, and + MAC_ADMIN, in addition to SYS_BOOT. + * src/lxc_controller.c: Drop all capabilities once container + has been spawned. + Mon Jun 29 12:48:20 BST 2009 Daniel P. Berrange Use libcap-ng to clear capabilities for many child processes diff --git a/src/lxc_container.c b/src/lxc_container.c index 2592b10803..950dd50215 100644 --- a/src/lxc_container.c +++ b/src/lxc_container.c @@ -41,8 +41,9 @@ /* For MS_MOVE */ #include -#include -#include +#if HAVE_CAPNG +#include +#endif #include "virterror_internal.h" #include "logging.h" @@ -642,27 +643,48 @@ static int lxcContainerSetupMounts(virDomainDefPtr vmDef, return lxcContainerSetupExtraMounts(vmDef); } -static int lxcContainerDropCapabilities(virDomainDefPtr vmDef ATTRIBUTE_UNUSED) -{ -#ifdef PR_CAPBSET_DROP - int i; - const struct { - int id; - const char *name; - } caps[] = { -#define ID_STRING(name) name, #name - { ID_STRING(CAP_SYS_BOOT) }, - }; - for (i = 0 ; i < ARRAY_CARDINALITY(caps) ; i++) { - if (prctl(PR_CAPBSET_DROP, caps[i].id, 0, 0, 0)) { - lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, - _("failed to drop %s"), caps[i].name); - return -1; - } +/* + * This is running as the 'init' process insid the container. + * It removes some capabilities that could be dangerous to + * host system, since they are not currently "containerized" + */ +static int lxcContainerDropCapabilities(void) +{ +#if HAVE_CAPNG + int ret; + + capng_get_caps_process(); + + if ((ret = capng_updatev(CAPNG_DROP, + CAPNG_EFFECTIVE | CAPNG_PERMITTED | + CAPNG_INHERITABLE | CAPNG_BOUNDING_SET, + CAP_SYS_BOOT, /* No use of reboot */ + CAP_SYS_MODULE, /* No kernel module loading */ + CAP_SYS_TIME, /* No changing the clock */ + CAP_AUDIT_CONTROL, /* No messing with auditing status */ + CAP_MAC_ADMIN, /* No messing with LSM config */ + -1 /* sentinal */)) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to remove capabilities %d"), ret); + return -1; } -#else /* ! PR_CAPBSET_DROP */ - VIR_WARN0(_("failed to drop capabilities PR_CAPBSET_DROP undefined")); + + if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to apply capabilities: %d"), ret); + return -1; + } + + /* Need to prevent them regaining any caps on exec */ + if ((ret = capng_lock()) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to lock capabilities: %d"), ret); + return -1; + } + +#else + VIR_WARN0(_("libcap-ng support not compiled in, unable to clear capabilities")); #endif return 0; } @@ -735,7 +757,7 @@ static int lxcContainerChild( void *data ) return -1; /* drop a set of root capabilities */ - if (lxcContainerDropCapabilities(vmDef) < 0) + if (lxcContainerDropCapabilities() < 0) return -1; /* this function will only return if an error occured */ diff --git a/src/lxc_controller.c b/src/lxc_controller.c index 356ecb80b4..08fbbe43fb 100644 --- a/src/lxc_controller.c +++ b/src/lxc_controller.c @@ -35,6 +35,10 @@ #include #include +#if HAVE_CAPNG +#include +#endif + #include "virterror_internal.h" #include "logging.h" #include "util.h" @@ -210,6 +214,25 @@ cleanup: return rc; } + +static int lxcControllerClearCapabilities(void) +{ +#if HAVE_CAPNG + int ret; + + capng_clear(CAPNG_SELECT_BOTH); + + if ((ret = capng_apply(CAPNG_SELECT_BOTH)) < 0) { + lxcError(NULL, NULL, VIR_ERR_INTERNAL_ERROR, + _("failed to apply capabilities: %d"), ret); + return -1; + } +#else + VIR_WARN0(_("libcap-ng support not compiled in, unable to clear capabilities")); +#endif + return 0; +} + typedef struct _lxcTtyForwardFd_t { int fd; int active; @@ -562,6 +585,11 @@ lxcControllerRun(virDomainDefPtr def, if (lxcContainerSendContinue(control[0]) < 0) goto cleanup; + /* Now the container is running, there's no need for us to keep + any elevated capabilities */ + if (lxcControllerClearCapabilities() < 0) + goto cleanup; + rc = lxcControllerMain(monitor, client, appPty, containerPty); cleanup: