This eliminates the warning message reported in:
https://bugzilla.redhat.com/show_bug.cgi?id=624447
It was caused by a failure to open an image file that is not
accessible by root (the uid libvirtd is running as) because it's on a
root-squash NFS share, owned by a different user, with permissions of
660 (or maybe 600).
The solution is to re-try the open using virFileOpenAs() when
appropriate. The codepath that generates the error is during
qemuSetupDiskCGroup(), but the actual open() is in a lower-level
generic function called from many places (virDomainDiskDefForeachPath),
so some other pieces of the code were touched just to add dummy (or
possibly useful) uid and gid arguments.
Eliminating this warning message has the nice side effect that the
requested opearation may even succeed (which in this case isn't
necessary, but shouldn't hurt anything either).
---
src/conf/domain_conf.c | 13 ++++++++++++-
src/conf/domain_conf.h | 1 +
src/qemu/qemu_cgroup.c | 2 ++
src/security/security_dac.c | 1 +
src/security/security_selinux.c | 7 +++++++
src/security/virt-aa-helper.c | 6 +++++-
6 files changed, 28 insertions(+), 2 deletions(-)
diff --git a/src/conf/domain_conf.c b/src/conf/domain_conf.c
index 180dd2b..2b7ec91 100644
--- a/src/conf/domain_conf.c
+++ b/src/conf/domain_conf.c
@@ -13370,6 +13370,7 @@ done:
int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
bool allowProbing,
bool ignoreOpenFailure,
+ uid_t uid, gid_t gid,
virDomainDiskDefPathIterator iter,
void *opaque)
{
@@ -13425,8 +13426,18 @@ int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
disk->src);
goto cleanup;
}
+ fd = open(path, O_RDONLY);
+ if ((fd < 0) && (errno == EACCES || errno == EPERM) &&
+ (uid > 0 || gid > 0)) {
+ fd = virFileOpenAs(path, O_RDONLY, 0, uid, gid, VIR_FILE_OPEN_AS_UID);
+ if (fd < 0) {
+ /* open() and virFileOpenAs() have different semantics */
+ errno = -fd;
+ fd = -1;
+ }
+ }
- if ((fd = open(path, O_RDONLY)) < 0) {
+ if (fd < 0) {
if (ignoreOpenFailure) {
char ebuf[1024];
VIR_WARN("Ignoring open failure on %s: %s", path,
diff --git a/src/conf/domain_conf.h b/src/conf/domain_conf.h
index 3d5d4f8..2ea7861 100644
--- a/src/conf/domain_conf.h
+++ b/src/conf/domain_conf.h
@@ -1935,6 +1935,7 @@ typedef int (*virDomainDiskDefPathIterator)(virDomainDiskDefPtr
disk,
int virDomainDiskDefForeachPath(virDomainDiskDefPtr disk,
bool allowProbing,
bool ignoreOpenFailure,
+ uid_t uid, gid_t gid,
virDomainDiskDefPathIterator iter,
void *opaque);
diff --git a/src/qemu/qemu_cgroup.c b/src/qemu/qemu_cgroup.c
index 2d970d6..a07b6cd 100644
--- a/src/qemu/qemu_cgroup.c
+++ b/src/qemu/qemu_cgroup.c
@@ -96,6 +96,7 @@ int qemuSetupDiskCgroup(struct qemud_driver *driver,
return virDomainDiskDefForeachPath(disk,
driver->allowDiskFormatProbing,
true,
+ driver->user, driver->group,
qemuSetupDiskPathAllow,
&data);
}
@@ -137,6 +138,7 @@ int qemuTeardownDiskCgroup(struct qemud_driver *driver,
return virDomainDiskDefForeachPath(disk,
driver->allowDiskFormatProbing,
true,
+ driver->user, driver->group,
qemuTeardownDiskPathDeny,
&data);
}
diff --git a/src/security/security_dac.c b/src/security/security_dac.c
index 2fb4a14..3e1a72f 100644
--- a/src/security/security_dac.c
+++ b/src/security/security_dac.c
@@ -186,6 +186,7 @@ virSecurityDACSetSecurityImageLabel(virSecurityManagerPtr mgr,
return virDomainDiskDefForeachPath(disk,
virSecurityManagerGetAllowDiskFormatProbing(mgr),
false,
+ priv->user, priv->group,
virSecurityDACSetSecurityFileLabel,
mgr);
}
diff --git a/src/security/security_selinux.c b/src/security/security_selinux.c
index c2dceca..8c8e4f8 100644
--- a/src/security/security_selinux.c
+++ b/src/security/security_selinux.c
@@ -670,9 +670,16 @@ SELinuxSetSecurityImageLabel(virSecurityManagerPtr mgr,
if (disk->type == VIR_DOMAIN_DISK_TYPE_NETWORK)
return 0;
+ /* XXX On one hand, it would be nice to have the driver's uid:gid
+ * here so we could retry opens with it. On the other hand, it
+ * probably doesn't matter because in practice that's only useful
+ * for files on root-squashed NFS shares, and NFS doesn't properly
+ * support selinux anyway.
+ */
return virDomainDiskDefForeachPath(disk,
allowDiskFormatProbing,
true,
+ -1, -1, /* current process uid:gid */
SELinuxSetSecurityFileLabel,
secdef);
}
diff --git a/src/security/virt-aa-helper.c b/src/security/virt-aa-helper.c
index 4561bb9..015ef2f 100644
--- a/src/security/virt-aa-helper.c
+++ b/src/security/virt-aa-helper.c
@@ -909,10 +909,14 @@ get_files(vahControl * ctl)
/* XXX passing ignoreOpenFailure = true to get back to the behavior
* from before using virDomainDiskDefForeachPath. actually we should
* be passing ignoreOpenFailure = false and handle open errors more
- * careful than just ignoring them */
+ * careful than just ignoring them.
+ * XXX2 - if we knew the qemu user:group here we could send it in
+ * so that the open could be re-tried as that user:group.
+ */
int ret = virDomainDiskDefForeachPath(ctl->def->disks[i],
ctl->allowDiskFormatProbing,
true,
+ -1, -1 /* current uid:gid */
add_file_path,
&buf);
if (ret != 0)
--
1.7.7.5