diff options
author | Keno Fischer <keno@juliacomputing.com> | 2018-06-07 12:17:22 +0200 |
---|---|---|
committer | Greg Kurz <groug@kaod.org> | 2018-06-07 12:17:22 +0200 |
commit | 67e87345744ac96d6c9560827ea094264c88fbff (patch) | |
tree | 6ee8cc5aa67da158f5e9a7c1fccb34f65ef4d8ad /hw/9pfs | |
parent | 5b7b2f9a85bcc44485da713f60e371dd66a644b1 (diff) | |
download | qemu-67e87345744ac96d6c9560827ea094264c88fbff.zip qemu-67e87345744ac96d6c9560827ea094264c88fbff.tar.gz qemu-67e87345744ac96d6c9560827ea094264c88fbff.tar.bz2 |
9p: Properly check/translate flags in unlinkat
The 9p-local code previously relied on P9_DOTL_AT_REMOVEDIR and AT_REMOVEDIR
having the same numerical value and deferred any errorchecking to the
syscall itself. However, while the former assumption is true on Linux,
it is not true in general. 9p-handle did this properly however. Move
the translation code to the generic 9p server code and add an error
if unrecognized flags are passed.
Signed-off-by: Keno Fischer <keno@juliacomputing.com>
Signed-off-by: Greg Kurz <groug@kaod.org>
Diffstat (limited to 'hw/9pfs')
-rw-r--r-- | hw/9pfs/9p-handle.c | 8 | ||||
-rw-r--r-- | hw/9pfs/9p.c | 13 |
2 files changed, 12 insertions, 9 deletions
diff --git a/hw/9pfs/9p-handle.c b/hw/9pfs/9p-handle.c index 4dc0d2b..f3641db 100644 --- a/hw/9pfs/9p-handle.c +++ b/hw/9pfs/9p-handle.c @@ -559,19 +559,13 @@ static int handle_unlinkat(FsContext *ctx, V9fsPath *dir, { int dirfd, ret; HandleData *data = (HandleData *) ctx->private; - int rflags; dirfd = open_by_handle(data->mountfd, dir->data, O_PATH); if (dirfd < 0) { return dirfd; } - rflags = 0; - if (flags & P9_DOTL_AT_REMOVEDIR) { - rflags |= AT_REMOVEDIR; - } - - ret = unlinkat(dirfd, name, rflags); + ret = unlinkat(dirfd, name, flags); close(dirfd); return ret; diff --git a/hw/9pfs/9p.c b/hw/9pfs/9p.c index 4386d69..c842ec5 100644 --- a/hw/9pfs/9p.c +++ b/hw/9pfs/9p.c @@ -2522,7 +2522,7 @@ static void coroutine_fn v9fs_unlinkat(void *opaque) { int err = 0; V9fsString name; - int32_t dfid, flags; + int32_t dfid, flags, rflags = 0; size_t offset = 7; V9fsPath path; V9fsFidState *dfidp; @@ -2549,6 +2549,15 @@ static void coroutine_fn v9fs_unlinkat(void *opaque) goto out_nofid; } + if (flags & ~P9_DOTL_AT_REMOVEDIR) { + err = -EINVAL; + goto out_nofid; + } + + if (flags & P9_DOTL_AT_REMOVEDIR) { + rflags |= AT_REMOVEDIR; + } + dfidp = get_fid(pdu, dfid); if (dfidp == NULL) { err = -EINVAL; @@ -2567,7 +2576,7 @@ static void coroutine_fn v9fs_unlinkat(void *opaque) if (err < 0) { goto out_err; } - err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, flags); + err = v9fs_co_unlinkat(pdu, &dfidp->path, &name, rflags); if (!err) { err = offset; } |