On Wed, Feb 12, 2020 at 10:38 AM Michael Stapelberg <michael+lkml@xxxxxxxxxxxxx> wrote: > > Unfortunately not: when I change the code like so: > > bool async; > uint32_t opcode_early = req->args->opcode; > > if (test_and_set_bit(FR_FINISHED, &req->flags)) > goto put_request; > > async = req->args->end; > > …gdb only reports: > > (gdb) bt > #0 0x000000a700000001 in ?? () > #1 0xffffffff8137fc99 in fuse_copy_finish (cs=0x20000ffffffff) at > fs/fuse/dev.c:681 > Backtrace stopped: previous frame inner to this frame (corrupt stack?) > > But maybe that’s a hint in and of itself? Yep, it's a stack use after return bug. Attached patch should fix it, though I haven't tested it. Thanks, Miklos
--- fs/fuse/dev.c | 6 +++--- fs/fuse/fuse_i.h | 2 ++ 2 files changed, 5 insertions(+), 3 deletions(-) --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -276,12 +276,10 @@ static void flush_bg_queue(struct fuse_c void fuse_request_end(struct fuse_conn *fc, struct fuse_req *req) { struct fuse_iqueue *fiq = &fc->iq; - bool async; if (test_and_set_bit(FR_FINISHED, &req->flags)) goto put_request; - async = req->args->end; /* * test_and_set_bit() implies smp_mb() between bit * changing and below intr_entry check. Pairs with @@ -324,7 +322,7 @@ void fuse_request_end(struct fuse_conn * wake_up(&req->waitq); } - if (async) + if (test_bit(FR_ASYNC, &req->flags)) req->args->end(fc, req->args, req->out.h.error); put_request: fuse_put_request(fc, req); @@ -471,6 +469,8 @@ static void fuse_args_to_req(struct fuse req->in.h.opcode = args->opcode; req->in.h.nodeid = args->nodeid; req->args = args; + if (args->end) + set_bit(FR_ASYNC, &req->flags); } ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -301,6 +301,7 @@ struct fuse_io_priv { * FR_SENT: request is in userspace, waiting for an answer * FR_FINISHED: request is finished * FR_PRIVATE: request is on private list + * FR_ASYNC: request is asynchronous */ enum fuse_req_flag { FR_ISREPLY, @@ -314,6 +315,7 @@ enum fuse_req_flag { FR_SENT, FR_FINISHED, FR_PRIVATE, + FR_ASYNC, }; /**