aboutsummaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2017-09-12 10:57:53 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2017-09-12 10:57:53 -0400
commit5d6d3a301c4e749e04be6fcdcf4cb1ffa8bae524 (patch)
tree7315893f915b6f2f2821698e0371742141662f8e /fs/fuse
parent569dbb88e80deb68974ef6fdd6a13edb9d686261 (diff)
fuse: allow server to run in different pid_ns
Commit 0b6e9ea041e6 ("fuse: Add support for pid namespaces") broke Sandstorm.io development tools, which have been sending FUSE file descriptors across PID namespace boundaries since early 2014. The above patch added a check that prevented I/O on the fuse device file descriptor if the pid namespace of the reader/writer was different from the pid namespace of the mounter. With this change passing the device file descriptor to a different pid namespace simply doesn't work. The check was added because pids are transferred to/from the fuse userspace server in the namespace registered at mount time. To fix this regression, remove the checks and do the following: 1) the pid in the request header (the pid of the task that initiated the filesystem operation) is translated to the reader's pid namespace. If a mapping doesn't exist for this pid, then a zero pid is used. Note: even if a mapping would exist between the initiator task's pid namespace and the reader's pid namespace the pid will be zero if either mapping from initator's to mounter's namespace or mapping from mounter's to reader's namespace doesn't exist. 2) The lk.pid value in setlk/setlkw requests and getlk reply is left alone. Userspace should not interpret this value anyway. Also allow the setlk/setlkw operations if the pid of the task cannot be represented in the mounter's namespace (pid being zero in that case). Reported-by: Kenton Varda <kenton@sandstorm.io> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Fixes: 0b6e9ea041e6 ("fuse: Add support for pid namespaces") Cc: <stable@vger.kernel.org> # v4.12+ Cc: Eric W. Biederman <ebiederm@xmission.com> Cc: Seth Forshee <seth.forshee@canonical.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c13
-rw-r--r--fs/fuse/file.c3
2 files changed, 7 insertions, 9 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index c16d00e53264..13c65dd2d37d 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -1222,9 +1222,6 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
1222 struct fuse_in *in; 1222 struct fuse_in *in;
1223 unsigned reqsize; 1223 unsigned reqsize;
1224 1224
1225 if (task_active_pid_ns(current) != fc->pid_ns)
1226 return -EIO;
1227
1228 restart: 1225 restart:
1229 spin_lock(&fiq->waitq.lock); 1226 spin_lock(&fiq->waitq.lock);
1230 err = -EAGAIN; 1227 err = -EAGAIN;
@@ -1262,6 +1259,13 @@ static ssize_t fuse_dev_do_read(struct fuse_dev *fud, struct file *file,
1262 1259
1263 in = &req->in; 1260 in = &req->in;
1264 reqsize = in->h.len; 1261 reqsize = in->h.len;
1262
1263 if (task_active_pid_ns(current) != fc->pid_ns) {
1264 rcu_read_lock();
1265 in->h.pid = pid_vnr(find_pid_ns(in->h.pid, fc->pid_ns));
1266 rcu_read_unlock();
1267 }
1268
1265 /* If request is too large, reply with an error and restart the read */ 1269 /* If request is too large, reply with an error and restart the read */
1266 if (nbytes < reqsize) { 1270 if (nbytes < reqsize) {
1267 req->out.h.error = -EIO; 1271 req->out.h.error = -EIO;
@@ -1823,9 +1827,6 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
1823 struct fuse_req *req; 1827 struct fuse_req *req;
1824 struct fuse_out_header oh; 1828 struct fuse_out_header oh;
1825 1829
1826 if (task_active_pid_ns(current) != fc->pid_ns)
1827 return -EIO;
1828
1829 if (nbytes < sizeof(struct fuse_out_header)) 1830 if (nbytes < sizeof(struct fuse_out_header))
1830 return -EINVAL; 1831 return -EINVAL;
1831 1832
diff --git a/fs/fuse/file.c b/fs/fuse/file.c
index ab60051be6e5..6d8e65cec01a 100644
--- a/fs/fuse/file.c
+++ b/fs/fuse/file.c
@@ -2181,9 +2181,6 @@ static int fuse_setlk(struct file *file, struct file_lock *fl, int flock)
2181 if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX) 2181 if ((fl->fl_flags & FL_CLOSE_POSIX) == FL_CLOSE_POSIX)
2182 return 0; 2182 return 0;
2183 2183
2184 if (pid && pid_nr == 0)
2185 return -EOVERFLOW;
2186
2187 fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg); 2184 fuse_lk_fill(&args, file, fl, opcode, pid_nr, flock, &inarg);
2188 err = fuse_simple_request(fc, &args); 2185 err = fuse_simple_request(fc, &args);
2189 2186