Commit 67e87345 authored by Keno Fischer's avatar Keno Fischer Committed by Greg Kurz
Browse files

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: default avatarKeno Fischer <keno@juliacomputing.com>
Signed-off-by: default avatarGreg Kurz <groug@kaod.org>
parent 5b7b2f9a
Loading
Loading
Loading
Loading
+1 −7
Original line number Diff line number Diff line
@@ -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;
+11 −2
Original line number Diff line number Diff line
@@ -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;
    }