aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEric W. Biederman <ebiederm@xmission.com>2018-02-21 11:52:06 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2018-03-20 12:11:44 -0400
commitc9582eb0ff7d2b560be60eafab29183882cdc82b (patch)
tree2622564e341542e5e23140deb6194f23d4eabec2
parentdbf107b2a7f36fa635b40e0b554514f599c75b33 (diff)
fuse: Fail all requests with invalid uids or gids
Upon a cursory examinination the uid and gid of a fuse request are necessary for correct operation. Failing a fuse request where those values are not reliable seems a straight forward and reliable means of ensuring that fuse requests with bad data are not sent or processed. In most cases the vfs will avoid actions it suspects will cause an inode write back of an inode with an invalid uid or gid. But that does not map precisely to what fuse is doing, so test for this and solve this at the fuse level as well. Performing this work in fuse_req_init_context is cheap as the code is already performing the translation here and only needs to check the result of the translation to see if things are not representable in a form the fuse server can handle. [SzM] Don't zero the context for the nofail case, just keep using the munging version (makes sense for debugging and doesn't hurt). Signed-off-by: Eric W. Biederman <ebiederm@xmission.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
-rw-r--r--fs/fuse/dev.c22
1 files changed, 13 insertions, 9 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 6e005da03aed..4852f8803156 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -112,13 +112,6 @@ static void __fuse_put_request(struct fuse_req *req)
112 refcount_dec(&req->count); 112 refcount_dec(&req->count);
113} 113}
114 114
115static void fuse_req_init_context(struct fuse_conn *fc, struct fuse_req *req)
116{
117 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
118 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
119 req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
120}
121
122void fuse_set_initialized(struct fuse_conn *fc) 115void fuse_set_initialized(struct fuse_conn *fc)
123{ 116{
124 /* Make sure stores before this are seen on another CPU */ 117 /* Make sure stores before this are seen on another CPU */
@@ -163,11 +156,19 @@ static struct fuse_req *__fuse_get_req(struct fuse_conn *fc, unsigned npages,
163 goto out; 156 goto out;
164 } 157 }
165 158
166 fuse_req_init_context(fc, req); 159 req->in.h.uid = from_kuid(&init_user_ns, current_fsuid());
160 req->in.h.gid = from_kgid(&init_user_ns, current_fsgid());
161 req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
162
167 __set_bit(FR_WAITING, &req->flags); 163 __set_bit(FR_WAITING, &req->flags);
168 if (for_background) 164 if (for_background)
169 __set_bit(FR_BACKGROUND, &req->flags); 165 __set_bit(FR_BACKGROUND, &req->flags);
170 166
167 if (unlikely(req->in.h.uid == ((uid_t)-1) ||
168 req->in.h.gid == ((gid_t)-1))) {
169 fuse_put_request(fc, req);
170 return ERR_PTR(-EOVERFLOW);
171 }
171 return req; 172 return req;
172 173
173 out: 174 out:
@@ -256,7 +257,10 @@ struct fuse_req *fuse_get_req_nofail_nopages(struct fuse_conn *fc,
256 if (!req) 257 if (!req)
257 req = get_reserved_req(fc, file); 258 req = get_reserved_req(fc, file);
258 259
259 fuse_req_init_context(fc, req); 260 req->in.h.uid = from_kuid_munged(&init_user_ns, current_fsuid());
261 req->in.h.gid = from_kgid_munged(&init_user_ns, current_fsgid());
262 req->in.h.pid = pid_nr_ns(task_pid(current), fc->pid_ns);
263
260 __set_bit(FR_WAITING, &req->flags); 264 __set_bit(FR_WAITING, &req->flags);
261 __clear_bit(FR_BACKGROUND, &req->flags); 265 __clear_bit(FR_BACKGROUND, &req->flags);
262 return req; 266 return req;