A buggy guest using the 9p2000.u protocol can issue a create request and pass an empty string as the extension argument. This causes QEMU to crash in the case of a hard link or a special file, and leads to undefined behavior, depending on the backend, in the case of a symbolic link.
This patch causes the request to fail with EINVAL in these scenarios. Signed-off-by: Greg Kurz <gr...@kaod.org> --- hw/9pfs/9p.c | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 7b1dfe4e47cb..dc65c3125006 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -2150,6 +2150,11 @@ static void v9fs_create(void *opaque) } fidp->fid_type = P9_FID_DIR; } else if (perm & P9_STAT_MODE_SYMLINK) { + if (extension.data == NULL) { + err = -EINVAL; + goto out; + } + err = v9fs_co_symlink(pdu, fidp, &name, extension.data, -1 , &stbuf); if (err < 0) { @@ -2161,8 +2166,15 @@ static void v9fs_create(void *opaque) } v9fs_path_copy(&fidp->path, &path); } else if (perm & P9_STAT_MODE_LINK) { - int32_t ofid = atoi(extension.data); - V9fsFidState *ofidp = get_fid(pdu, ofid); + V9fsFidState *ofidp; + + if (extension.data == NULL) { + err = -EINVAL; + goto out; + } + + ofidp = get_fid(pdu, atoi(extension.data)); + if (ofidp == NULL) { err = -EINVAL; goto out; @@ -2188,6 +2200,11 @@ static void v9fs_create(void *opaque) uint32_t major, minor; mode_t nmode = 0; + if (extension.data == NULL) { + err = -EINVAL; + goto out; + } + if (sscanf(extension.data, "%c %u %u", &ctype, &major, &minor) != 3) { err = -errno; goto out;