mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-11 15:27:47 +00:00
Set a security context on /dev and /dev/pts mounts
To allow the container to access /dev and /dev/pts when under sVirt, set an explicit mount option. Also set a max size on the /dev mount to prevent DOS on memory usage * src/lxc/lxc_container.c: Set /dev mount context * src/lxc/lxc_controller.c: Set /dev/pts mount context
This commit is contained in:
parent
0f01192e7e
commit
5df67cdcd3
@ -36,6 +36,10 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <mntent.h>
|
#include <mntent.h>
|
||||||
|
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
# include <selinux/selinux.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Yes, we want linux private one, for _syscall2() macro */
|
/* Yes, we want linux private one, for _syscall2() macro */
|
||||||
#include <linux/unistd.h>
|
#include <linux/unistd.h>
|
||||||
|
|
||||||
@ -420,7 +424,6 @@ err:
|
|||||||
static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
||||||
{
|
{
|
||||||
const struct {
|
const struct {
|
||||||
bool onlyPivotRoot;
|
|
||||||
bool needPrefix;
|
bool needPrefix;
|
||||||
const char *src;
|
const char *src;
|
||||||
const char *dst;
|
const char *dst;
|
||||||
@ -434,16 +437,19 @@ static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
|||||||
* mount point in the main OS becomes readonly too which is not what
|
* mount point in the main OS becomes readonly too which is not what
|
||||||
* we want. Hence some things have two entries here.
|
* we want. Hence some things have two entries here.
|
||||||
*/
|
*/
|
||||||
{ true, false, "devfs", "/dev", "tmpfs", "mode=755", MS_NOSUID },
|
{ false, "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
||||||
{ false, false, "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV },
|
{ false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
|
||||||
{ false, false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND },
|
{ false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
||||||
{ false, false, "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
{ true, "/sys", "/sys", NULL, NULL, MS_BIND },
|
||||||
{ false, true, "/sys", "/sys", NULL, NULL, MS_BIND },
|
{ true, "/sys", "/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
||||||
{ false, true, "/sys", "/sys", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
{ true, "/selinux", "/selinux", NULL, NULL, MS_BIND },
|
||||||
{ false, true, "/selinux", "/selinux", NULL, NULL, MS_BIND },
|
{ true, "/selinux", "/selinux", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
||||||
{ false, true, "/selinux", "/selinux", NULL, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY },
|
|
||||||
};
|
};
|
||||||
int i, rc = -1;
|
int i, rc = -1;
|
||||||
|
char *opts = NULL;
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
security_context_t con;
|
||||||
|
#endif
|
||||||
|
|
||||||
VIR_DEBUG("Mounting basic filesystems %s pivotRoot=%d", NULLSTR(srcprefix), pivotRoot);
|
VIR_DEBUG("Mounting basic filesystems %s pivotRoot=%d", NULLSTR(srcprefix), pivotRoot);
|
||||||
|
|
||||||
@ -451,10 +457,8 @@ static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
|||||||
char *src = NULL;
|
char *src = NULL;
|
||||||
const char *srcpath = NULL;
|
const char *srcpath = NULL;
|
||||||
|
|
||||||
VIR_DEBUG("Consider %s onlyPivotRoot=%d",
|
VIR_DEBUG("Processing %s -> %s",
|
||||||
mnts[i].src, mnts[i].onlyPivotRoot);
|
mnts[i].src, mnts[i].dst);
|
||||||
if (mnts[i].onlyPivotRoot && !pivotRoot)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (virFileMakePath(mnts[i].dst) < 0) {
|
if (virFileMakePath(mnts[i].dst) < 0) {
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
@ -475,8 +479,10 @@ static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
|||||||
|
|
||||||
/* Skip if mount doesn't exist in source */
|
/* Skip if mount doesn't exist in source */
|
||||||
if ((srcpath[0] == '/') &&
|
if ((srcpath[0] == '/') &&
|
||||||
(access(srcpath, R_OK) < 0))
|
(access(srcpath, R_OK) < 0)) {
|
||||||
|
VIR_FREE(src);
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
VIR_DEBUG("Mount %s on %s type=%s flags=%x, opts=%s",
|
VIR_DEBUG("Mount %s on %s type=%s flags=%x, opts=%s",
|
||||||
srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts);
|
srcpath, mnts[i].dst, mnts[i].type, mnts[i].mflags, mnts[i].opts);
|
||||||
@ -490,15 +496,47 @@ static int lxcContainerMountBasicFS(const char *srcprefix, bool pivotRoot)
|
|||||||
VIR_FREE(src);
|
VIR_FREE(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pivotRoot) {
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
if (getfilecon("/", &con) < 0 &&
|
||||||
|
errno != ENOTSUP) {
|
||||||
|
virReportSystemError(errno, "%s",
|
||||||
|
_("Failed to query file context on /"));
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/*
|
||||||
|
* tmpfs is limited to 64kb, since we only have device nodes in there
|
||||||
|
* and don't want to DOS the entire OS RAM usage
|
||||||
|
*/
|
||||||
|
if (virAsprintf(&opts, "mode=755,size=65536%s%s%s",
|
||||||
|
con ? ",context=\"" : "",
|
||||||
|
con ? (const char *)con : "",
|
||||||
|
con ? "\"" : "") < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Mount devfs on /dev type=tmpfs flags=%x, opts=%s",
|
||||||
|
MS_NOSUID, opts);
|
||||||
|
if (mount("devfs", "/dev", "tmpfs", MS_NOSUID, opts) < 0) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to mount %s on %s type %s"),
|
||||||
|
"devfs", "/dev", "tmpfs");
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
rc = 0;
|
rc = 0;
|
||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
VIR_DEBUG("rc=%d", rc);
|
VIR_DEBUG("rc=%d", rc);
|
||||||
|
VIR_FREE(opts);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static int lxcContainerMountDevFS(virDomainFSDefPtr root)
|
static int lxcContainerMountFSDevPTS(virDomainFSDefPtr root)
|
||||||
{
|
{
|
||||||
char *devpts = NULL;
|
char *devpts = NULL;
|
||||||
int rc = -1;
|
int rc = -1;
|
||||||
@ -1070,8 +1108,8 @@ static int lxcContainerSetupPivotRoot(virDomainDefPtr vmDef,
|
|||||||
if (lxcContainerMountBasicFS("/.oldroot", true) < 0)
|
if (lxcContainerMountBasicFS("/.oldroot", true) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Mounts /dev and /dev/pts */
|
/* Mounts /dev/pts */
|
||||||
if (lxcContainerMountDevFS(root) < 0)
|
if (lxcContainerMountFSDevPTS(root) < 0)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
/* Populates device nodes in /dev/ */
|
/* Populates device nodes in /dev/ */
|
||||||
|
@ -52,6 +52,9 @@
|
|||||||
# define NUMA_VERSION1_COMPATIBILITY 1
|
# define NUMA_VERSION1_COMPATIBILITY 1
|
||||||
# include <numa.h>
|
# include <numa.h>
|
||||||
#endif
|
#endif
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
# include <selinux/selinux.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
#include "virterror_internal.h"
|
#include "virterror_internal.h"
|
||||||
#include "logging.h"
|
#include "logging.h"
|
||||||
@ -1433,6 +1436,10 @@ lxcControllerRun(virDomainDefPtr def,
|
|||||||
* marked as shared
|
* marked as shared
|
||||||
*/
|
*/
|
||||||
if (root) {
|
if (root) {
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
security_context_t con;
|
||||||
|
#endif
|
||||||
|
char *opts;
|
||||||
VIR_DEBUG("Setting up private /dev/pts");
|
VIR_DEBUG("Setting up private /dev/pts");
|
||||||
|
|
||||||
if (!virFileExists(root->src)) {
|
if (!virFileExists(root->src)) {
|
||||||
@ -1467,16 +1474,35 @@ lxcControllerRun(virDomainDefPtr def,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if HAVE_SELINUX
|
||||||
|
if (getfilecon(root->src, &con) < 0 &&
|
||||||
|
errno != ENOTSUP) {
|
||||||
|
virReportSystemError(errno,
|
||||||
|
_("Failed to query file context on %s"),
|
||||||
|
root->src);
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
/* XXX should we support gid=X for X!=5 for distros which use
|
/* XXX should we support gid=X for X!=5 for distros which use
|
||||||
* a different gid for tty? */
|
* a different gid for tty? */
|
||||||
VIR_DEBUG("Mounting 'devpts' on %s", devpts);
|
if (virAsprintf(&opts, "newinstance,ptmxmode=0666,mode=0620,gid=5%s%s%s",
|
||||||
if (mount("devpts", devpts, "devpts", 0,
|
con ? ",context=\"" : "",
|
||||||
"newinstance,ptmxmode=0666,mode=0620,gid=5") < 0) {
|
con ? (const char *)con : "",
|
||||||
|
con ? "\"" : "") < 0) {
|
||||||
|
virReportOOMError();
|
||||||
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
|
VIR_DEBUG("Mount devpts on %s type=tmpfs flags=%x, opts=%s",
|
||||||
|
devpts, MS_NOSUID, opts);
|
||||||
|
if (mount("devpts", devpts, "devpts", MS_NOSUID, opts) < 0) {
|
||||||
|
VIR_FREE(opts);
|
||||||
virReportSystemError(errno,
|
virReportSystemError(errno,
|
||||||
_("Failed to mount devpts on %s"),
|
_("Failed to mount devpts on %s"),
|
||||||
devpts);
|
devpts);
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
VIR_FREE(opts);
|
||||||
|
|
||||||
if (access(devptmx, R_OK) < 0) {
|
if (access(devptmx, R_OK) < 0) {
|
||||||
VIR_WARN("Kernel does not support private devpts, using shared devpts");
|
VIR_WARN("Kernel does not support private devpts, using shared devpts");
|
||||||
|
Loading…
Reference in New Issue
Block a user