From e413754b267e0e47ed38b3eacfa7178f21aca883 Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Tue, 10 Sep 2019 15:04:08 +0200 Subject: [PATCH] fuse: add nocreds to fuse_args In some cases it makes no sense to set pid/uid/gid fields in the request header. Allow fuse_simple_background() to omit these. This is only required in the "force" case, so for now just WARN if set otherwise. Fold fuse_get_req_nofail_nopages() into its only caller. Comment is obsolete anyway. Signed-off-by: Miklos Szeredi --- fs/fuse/dev.c | 44 +++++++++++++++----------------------------- fs/fuse/fuse_i.h | 1 + 2 files changed, 16 insertions(+), 29 deletions(-) diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c index 19114b23e95f..9f1549166a5d 100644 --- a/fs/fuse/dev.c +++ b/fs/fuse/dev.c @@ -242,34 +242,6 @@ struct fuse_req *fuse_get_req_for_background(struct fuse_conn *fc, } EXPORT_SYMBOL_GPL(fuse_get_req_for_background); -/* - * Gets a requests for a file operation, always succeeds - * - * This is used for sending the FLUSH request, which must get to - * userspace, due to POSIX locks which may need to be unlocked. - * - * If allocation fails due to OOM, use the reserved request in - * fuse_file. - * - * This is very unlikely to deadlock accidentally, since the - * filesystem should not have it's own file open. If deadlock is - * intentional, it can still be broken by "aborting" the filesystem. - */ -static struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc) -{ - struct fuse_req *req; - - atomic_inc(&fc->num_waiting); - req = __fuse_request_alloc(0, GFP_KERNEL | __GFP_NOFAIL); - - req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid()); - req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid()); - req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); - - __set_bit(FR_WAITING, &req->flags); - return req; -} - void fuse_put_request(struct fuse_conn *fc, struct fuse_req *req) { if (refcount_dec_and_test(&req->count)) { @@ -565,15 +537,29 @@ static void fuse_adjust_compat(struct fuse_conn *fc, struct fuse_args *args) } } +static void fuse_force_creds(struct fuse_conn *fc, struct fuse_req *req) +{ + req->in.h.uid = from_kuid_munged(fc->user_ns, current_fsuid()); + req->in.h.gid = from_kgid_munged(fc->user_ns, current_fsgid()); + req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns); +} + ssize_t fuse_simple_request(struct fuse_conn *fc, struct fuse_args *args) { struct fuse_req *req; ssize_t ret; if (args->force) { - req = fuse_get_req_nofail_nopages(fc); + atomic_inc(&fc->num_waiting); + req = __fuse_request_alloc(0, GFP_KERNEL | __GFP_NOFAIL); + + if (!args->nocreds) + fuse_force_creds(fc, req); + + __set_bit(FR_WAITING, &req->flags); __set_bit(FR_FORCE, &req->flags); } else { + WARN_ON(args->nocreds); req = fuse_get_req(fc, 0); if (IS_ERR(req)) return PTR_ERR(req); diff --git a/fs/fuse/fuse_i.h b/fs/fuse/fuse_i.h index e6a8e47d0e0b..43ae5b7f4dd4 100644 --- a/fs/fuse/fuse_i.h +++ b/fs/fuse/fuse_i.h @@ -293,6 +293,7 @@ struct fuse_args { unsigned short out_numargs; bool force:1; bool noreply:1; + bool nocreds:1; bool out_argvar:1; struct fuse_in_arg in_args[3]; struct fuse_arg out_args[2];