mirror of
https://gitlab.com/libvirt/libvirt.git
synced 2025-01-22 12:35:17 +00:00
Make qemuOpenFile aware of per-VM DAC seclabel.
Function qemuOpenFile() haven't had any idea about seclabels applied to VMs only, so in case the seclabel differed from the "user:group" from configuration, there might have been issues with opening files. Make qemuOpenFile() VM-aware, but only optionally, passing NULL argument means skipping VM seclabel info completely. However, all current qemuOpenFile() calls look like they should use VM seclabel info in case there is any, so convert these calls as well. Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=869053
This commit is contained in:
parent
bba579b6e0
commit
849df2875d
@ -157,6 +157,16 @@ static int qemuDomainGetMaxVcpus(virDomainPtr dom);
|
|||||||
static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
|
static int qemuDomainManagedSaveLoad(virDomainObjPtr vm,
|
||||||
void *opaque);
|
void *opaque);
|
||||||
|
|
||||||
|
static int qemuOpenFile(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
const char *path, int oflags,
|
||||||
|
bool *needUnlink, bool *bypassSecurityDriver);
|
||||||
|
|
||||||
|
static int qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
|
||||||
|
bool dynamicOwnership,
|
||||||
|
const char *path, int oflags,
|
||||||
|
bool *needUnlink, bool *bypassSecurityDriver);
|
||||||
|
|
||||||
|
|
||||||
virQEMUDriverPtr qemu_driver = NULL;
|
virQEMUDriverPtr qemu_driver = NULL;
|
||||||
|
|
||||||
@ -2722,10 +2732,40 @@ qemuCompressGetCommand(virQEMUSaveFormat compression)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Internal function to properly create or open existing files, with
|
/* Internal function to properly create or open existing files, with
|
||||||
* ownership affected by qemu driver setup. */
|
* ownership affected by qemu driver setup and domain DAC label. */
|
||||||
static int
|
static int
|
||||||
qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
qemuOpenFile(virQEMUDriverPtr driver,
|
||||||
|
virDomainObjPtr vm,
|
||||||
|
const char *path, int oflags,
|
||||||
bool *needUnlink, bool *bypassSecurityDriver)
|
bool *needUnlink, bool *bypassSecurityDriver)
|
||||||
|
{
|
||||||
|
int ret = -1;
|
||||||
|
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
||||||
|
uid_t user = cfg->user;
|
||||||
|
gid_t group = cfg->group;
|
||||||
|
bool dynamicOwnership = cfg->dynamicOwnership;
|
||||||
|
virSecurityLabelDefPtr seclabel;
|
||||||
|
|
||||||
|
virObjectUnref(cfg);
|
||||||
|
|
||||||
|
/* TODO: Take imagelabel into account? */
|
||||||
|
if (vm &&
|
||||||
|
(seclabel = virDomainDefGetSecurityLabelDef(vm->def, "dac")) != NULL &&
|
||||||
|
(virParseOwnershipIds(seclabel->label, &user, &group) < 0))
|
||||||
|
goto cleanup;
|
||||||
|
|
||||||
|
ret = qemuOpenFileAs(user, group, dynamicOwnership,
|
||||||
|
path, oflags, needUnlink, bypassSecurityDriver);
|
||||||
|
|
||||||
|
cleanup:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int
|
||||||
|
qemuOpenFileAs(uid_t fallback_uid, gid_t fallback_gid,
|
||||||
|
bool dynamicOwnership,
|
||||||
|
const char *path, int oflags,
|
||||||
|
bool *needUnlink, bool *bypassSecurityDriver)
|
||||||
{
|
{
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
bool is_reg = true;
|
bool is_reg = true;
|
||||||
@ -2736,7 +2776,6 @@ qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
|||||||
int path_shared = virStorageFileIsSharedFS(path);
|
int path_shared = virStorageFileIsSharedFS(path);
|
||||||
uid_t uid = getuid();
|
uid_t uid = getuid();
|
||||||
gid_t gid = getgid();
|
gid_t gid = getgid();
|
||||||
virQEMUDriverConfigPtr cfg = virQEMUDriverGetConfig(driver);
|
|
||||||
|
|
||||||
/* path might be a pre-existing block dev, in which case
|
/* path might be a pre-existing block dev, in which case
|
||||||
* we need to skip the create step, and also avoid unlink
|
* we need to skip the create step, and also avoid unlink
|
||||||
@ -2746,7 +2785,7 @@ qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
|||||||
|
|
||||||
/* Don't force chown on network-shared FS
|
/* Don't force chown on network-shared FS
|
||||||
* as it is likely to fail. */
|
* as it is likely to fail. */
|
||||||
if (path_shared <= 0 || cfg->dynamicOwnership)
|
if (path_shared <= 0 || dynamicOwnership)
|
||||||
vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
|
vfoflags |= VIR_FILE_OPEN_FORCE_OWNER;
|
||||||
|
|
||||||
if (stat(path, &sb) == 0) {
|
if (stat(path, &sb) == 0) {
|
||||||
@ -2754,7 +2793,7 @@ qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
|||||||
/* If the path is regular file which exists
|
/* If the path is regular file which exists
|
||||||
* already and dynamic_ownership is off, we don't
|
* already and dynamic_ownership is off, we don't
|
||||||
* want to change it's ownership, just open it as-is */
|
* want to change it's ownership, just open it as-is */
|
||||||
if (is_reg && !cfg->dynamicOwnership) {
|
if (is_reg && !dynamicOwnership) {
|
||||||
uid = sb.st_uid;
|
uid = sb.st_uid;
|
||||||
gid = sb.st_gid;
|
gid = sb.st_gid;
|
||||||
}
|
}
|
||||||
@ -2773,10 +2812,10 @@ qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
|||||||
/* If we failed as root, and the error was permission-denied
|
/* If we failed as root, and the error was permission-denied
|
||||||
(EACCES or EPERM), assume it's on a network-connected share
|
(EACCES or EPERM), assume it's on a network-connected share
|
||||||
where root access is restricted (eg, root-squashed NFS). If the
|
where root access is restricted (eg, root-squashed NFS). If the
|
||||||
qemu user (cfg->user) is non-root, just set a flag to
|
qemu user is non-root, just set a flag to
|
||||||
bypass security driver shenanigans, and retry the operation
|
bypass security driver shenanigans, and retry the operation
|
||||||
after doing setuid to qemu user */
|
after doing setuid to qemu user */
|
||||||
if ((fd != -EACCES && fd != -EPERM) || cfg->user == getuid())
|
if ((fd != -EACCES && fd != -EPERM) || fallback_uid == getuid())
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
/* On Linux we can also verify the FS-type of the directory. */
|
/* On Linux we can also verify the FS-type of the directory. */
|
||||||
@ -2802,11 +2841,11 @@ qemuOpenFile(virQEMUDriverPtr driver, const char *path, int oflags,
|
|||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Retry creating the file as cfg->user */
|
/* Retry creating the file as qemu user */
|
||||||
|
|
||||||
if ((fd = virFileOpenAs(path, oflags,
|
if ((fd = virFileOpenAs(path, oflags,
|
||||||
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
|
S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP,
|
||||||
cfg->user, cfg->group,
|
fallback_uid, fallback_gid,
|
||||||
vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
|
vfoflags | VIR_FILE_OPEN_FORK)) < 0) {
|
||||||
virReportSystemError(-fd, oflags & O_CREAT
|
virReportSystemError(-fd, oflags & O_CREAT
|
||||||
? _("Error from child process creating '%s'")
|
? _("Error from child process creating '%s'")
|
||||||
@ -2827,7 +2866,6 @@ cleanup:
|
|||||||
*needUnlink = need_unlink;
|
*needUnlink = need_unlink;
|
||||||
if (bypassSecurityDriver)
|
if (bypassSecurityDriver)
|
||||||
*bypassSecurityDriver = bypass_security;
|
*bypassSecurityDriver = bypass_security;
|
||||||
virObjectUnref(cfg);
|
|
||||||
return fd;
|
return fd;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
@ -2902,7 +2940,8 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
fd = qemuOpenFile(driver, path, O_WRONLY | O_TRUNC | O_CREAT | directFlag,
|
fd = qemuOpenFile(driver, vm, path,
|
||||||
|
O_WRONLY | O_TRUNC | O_CREAT | directFlag,
|
||||||
&needUnlink, &bypassSecurityDriver);
|
&needUnlink, &bypassSecurityDriver);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -2935,7 +2974,7 @@ qemuDomainSaveMemory(virQEMUDriverPtr driver,
|
|||||||
if (virFileWrapperFdClose(wrapperFd) < 0)
|
if (virFileWrapperFdClose(wrapperFd) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
if ((fd = qemuOpenFile(driver, path, O_WRONLY, NULL, NULL)) < 0)
|
if ((fd = qemuOpenFile(driver, vm, path, O_WRONLY, NULL, NULL)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
|
||||||
memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
|
memcpy(header.magic, QEMU_SAVE_MAGIC, sizeof(header.magic));
|
||||||
@ -3359,7 +3398,7 @@ doCoreDump(virQEMUDriverPtr driver,
|
|||||||
/* Core dumps usually imply last-ditch analysis efforts are
|
/* Core dumps usually imply last-ditch analysis efforts are
|
||||||
* desired, so we intentionally do not unlink even if a file was
|
* desired, so we intentionally do not unlink even if a file was
|
||||||
* created. */
|
* created. */
|
||||||
if ((fd = qemuOpenFile(driver, path,
|
if ((fd = qemuOpenFile(driver, vm, path,
|
||||||
O_CREAT | O_TRUNC | O_WRONLY | directFlag,
|
O_CREAT | O_TRUNC | O_WRONLY | directFlag,
|
||||||
NULL, NULL)) < 0)
|
NULL, NULL)) < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -5165,7 +5204,7 @@ qemuDomainSaveImageOpen(virQEMUDriverPtr driver,
|
|||||||
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
if (!(caps = virQEMUDriverGetCapabilities(driver, false)))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
if ((fd = qemuOpenFile(driver, path, oflags, NULL, NULL)) < 0)
|
if ((fd = qemuOpenFile(driver, NULL, path, oflags, NULL, NULL)) < 0)
|
||||||
goto error;
|
goto error;
|
||||||
if (bypass_cache &&
|
if (bypass_cache &&
|
||||||
!(*wrapperFd = virFileWrapperFdNew(&fd, path,
|
!(*wrapperFd = virFileWrapperFdNew(&fd, path,
|
||||||
@ -12071,7 +12110,7 @@ qemuDomainSnapshotCreateSingleDiskActive(virQEMUDriverPtr driver,
|
|||||||
/* create the stub file and set selinux labels; manipulate disk in
|
/* create the stub file and set selinux labels; manipulate disk in
|
||||||
* place, in a way that can be reverted on failure. */
|
* place, in a way that can be reverted on failure. */
|
||||||
if (!reuse) {
|
if (!reuse) {
|
||||||
fd = qemuOpenFile(driver, source, O_WRONLY | O_TRUNC | O_CREAT,
|
fd = qemuOpenFile(driver, vm, source, O_WRONLY | O_TRUNC | O_CREAT,
|
||||||
&need_unlink, NULL);
|
&need_unlink, NULL);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -14488,7 +14527,7 @@ qemuDomainBlockCopy(virDomainObjPtr vm,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
|
if (!(flags & VIR_DOMAIN_BLOCK_REBASE_REUSE_EXT)) {
|
||||||
int fd = qemuOpenFile(driver, dest, O_WRONLY | O_TRUNC | O_CREAT,
|
int fd = qemuOpenFile(driver, vm, dest, O_WRONLY | O_TRUNC | O_CREAT,
|
||||||
&need_unlink, NULL);
|
&need_unlink, NULL);
|
||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto endjob;
|
goto endjob;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user