Hi tech@, The below patch removes calls to realpath(3) when looking up a qcow2 base image. Previous thread: https://marc.info/?t=161562496400002&r=1&w=2
In short, the calls were failing inside vmctl, because of unveil. The other thread has alternative solutions but I think this is simplest. I included a regression test demonstrating the vmctl bug, in case there's interest. I tested vmd manually as described in the other thread. I also added a check in case dirname(3) fails --- I don't think it currently can, but better safe than sorry, I figure. (Noticed by Dave in the other thread.) - James diff --git a/regress/usr.sbin/Makefile b/regress/usr.sbin/Makefile index 60e2178d3c7..146f9c9f322 100644 --- a/regress/usr.sbin/Makefile +++ b/regress/usr.sbin/Makefile @@ -15,6 +15,7 @@ SUBDIR += rpki-client SUBDIR += snmpd SUBDIR += switchd SUBDIR += syslogd +SUBDIR += vmctl .if ${MACHINE} == "amd64" || ${MACHINE} == "i386" SUBDIR += vmd diff --git a/regress/usr.sbin/vmctl/Makefile b/regress/usr.sbin/vmctl/Makefile new file mode 100644 index 00000000000..8fa87f0f6f0 --- /dev/null +++ b/regress/usr.sbin/vmctl/Makefile @@ -0,0 +1,34 @@ +# $OpenBSD$ + +REGRESS_TARGETS = run-regress-convert-with-base-path + +run-regress-convert-with-base-path: + # non-relative base path + rm -f *.qcow2 + vmctl create -s 1m base.qcow2 + vmctl create -b ${PWD}/base.qcow2 source.qcow2 + vmctl create -i source.qcow2 dest.qcow2 + + # relative base path; two base images + rm -f *.qcow2 + vmctl create -s 1m base0.qcow2 + vmctl create -b base0.qcow2 base1.qcow2 + vmctl create -b base1.qcow2 source.qcow2 + vmctl create -i source.qcow2 dest.qcow2 + + # copy from a different directory + rm -rf dir *.qcow2 + vmctl create -s 1m base.qcow2 + vmctl create -b base.qcow2 source.qcow2 + mkdir dir + cd dir; vmctl create -i ../source.qcow2 dest.qcow2 + + # base accessed through symlink + rm -rf dir sym *.qcow2 + mkdir dir + cd dir; vmctl create -s 1m base.qcow2 + cd dir; vmctl create -b base.qcow2 source.qcow2 + ln -s dir sym + vmctl create -i sym/source.qcow2 dest.qcow2 + +.include <bsd.regress.mk> diff --git a/usr.sbin/vmd/vioqcow2.c b/usr.sbin/vmd/vioqcow2.c index 34d0f116cc4..be8609f1644 100644 --- a/usr.sbin/vmd/vioqcow2.c +++ b/usr.sbin/vmd/vioqcow2.c @@ -145,8 +145,8 @@ virtio_qcow2_init(struct virtio_backing *file, off_t *szp, int *fd, size_t nfd) ssize_t virtio_qcow2_get_base(int fd, char *path, size_t npath, const char *dpath) { + char pathbuf[PATH_MAX]; char dpathbuf[PATH_MAX]; - char expanded[PATH_MAX]; struct qcheader header; uint64_t backingoff; uint32_t backingsz; @@ -180,27 +180,23 @@ virtio_qcow2_get_base(int fd, char *path, size_t npath, const char *dpath) * rather than relative to the directory vmd happens to be running in, * since this is the only userful interpretation. */ - if (path[0] == '/') { - if (realpath(path, expanded) == NULL || - strlcpy(path, expanded, npath) >= npath) { - log_warnx("unable to resolve %s", path); + if (path[0] != '/') { + if (strlcpy(pathbuf, path, sizeof(pathbuf)) >= + sizeof(pathbuf)) { + log_warnx("path too long: %s", path); return -1; } - } else { if (strlcpy(dpathbuf, dpath, sizeof(dpathbuf)) >= sizeof(dpathbuf)) { log_warnx("path too long: %s", dpath); return -1; } - s = dirname(dpathbuf); - if (snprintf(expanded, sizeof(expanded), - "%s/%s", s, path) >= (int)sizeof(expanded)) { - log_warnx("path too long: %s/%s", s, path); + if ((s = dirname(dpathbuf)) == NULL) { + log_warn("dirname"); return -1; } - if (npath < PATH_MAX || - realpath(expanded, path) == NULL) { - log_warnx("unable to resolve %s", path); + if (snprintf(path, npath, "%s/%s", s, pathbuf) >= (int)npath) { + log_warnx("path too long: %s/%s", s, path); return -1; } }