summaryrefslogtreecommitdiffstats
path: root/fs/fuse
diff options
context:
space:
mode:
authorKirill Tkhai <ktkhai@virtuozzo.com>2018-11-08 04:05:42 -0500
committerMiklos Szeredi <mszeredi@redhat.com>2019-02-13 07:15:13 -0500
commitb782911b5297c4be0c2de88fc3b36a760eca6321 (patch)
treeb74ae0e6193a1f48779a6b9fa0d0cdf794633322 /fs/fuse
parent7407a10de57f5810f3f0e778eb1db0923d24ab16 (diff)
fuse: Verify userspace asks to requeue interrupt that we really sent
When queue_interrupt() is called from fuse_dev_do_write(), it came from userspace directly. Userspace may pass any request id, even the request's we have not interrupted (or even background's request). This patch adds sanity check to make kernel safe against that. Signed-off-by: Kirill Tkhai <ktkhai@virtuozzo.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Diffstat (limited to 'fs/fuse')
-rw-r--r--fs/fuse/dev.c13
1 files changed, 10 insertions, 3 deletions
diff --git a/fs/fuse/dev.c b/fs/fuse/dev.c
index 682c7914a0a0..ed9318d4e7dc 100644
--- a/fs/fuse/dev.c
+++ b/fs/fuse/dev.c
@@ -479,9 +479,15 @@ put_request:
479 fuse_put_request(fc, req); 479 fuse_put_request(fc, req);
480} 480}
481 481
482static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req) 482static int queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
483{ 483{
484 spin_lock(&fiq->waitq.lock); 484 spin_lock(&fiq->waitq.lock);
485 /* Check for we've sent request to interrupt this req */
486 if (unlikely(!test_bit(FR_INTERRUPTED, &req->flags))) {
487 spin_unlock(&fiq->waitq.lock);
488 return -EINVAL;
489 }
490
485 if (list_empty(&req->intr_entry)) { 491 if (list_empty(&req->intr_entry)) {
486 list_add_tail(&req->intr_entry, &fiq->interrupts); 492 list_add_tail(&req->intr_entry, &fiq->interrupts);
487 /* 493 /*
@@ -492,12 +498,13 @@ static void queue_interrupt(struct fuse_iqueue *fiq, struct fuse_req *req)
492 if (test_bit(FR_FINISHED, &req->flags)) { 498 if (test_bit(FR_FINISHED, &req->flags)) {
493 list_del_init(&req->intr_entry); 499 list_del_init(&req->intr_entry);
494 spin_unlock(&fiq->waitq.lock); 500 spin_unlock(&fiq->waitq.lock);
495 return; 501 return 0;
496 } 502 }
497 wake_up_locked(&fiq->waitq); 503 wake_up_locked(&fiq->waitq);
498 kill_fasync(&fiq->fasync, SIGIO, POLL_IN); 504 kill_fasync(&fiq->fasync, SIGIO, POLL_IN);
499 } 505 }
500 spin_unlock(&fiq->waitq.lock); 506 spin_unlock(&fiq->waitq.lock);
507 return 0;
501} 508}
502 509
503static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req) 510static void request_wait_answer(struct fuse_conn *fc, struct fuse_req *req)
@@ -1962,7 +1969,7 @@ static ssize_t fuse_dev_do_write(struct fuse_dev *fud,
1962 else if (oh.error == -ENOSYS) 1969 else if (oh.error == -ENOSYS)
1963 fc->no_interrupt = 1; 1970 fc->no_interrupt = 1;
1964 else if (oh.error == -EAGAIN) 1971 else if (oh.error == -EAGAIN)
1965 queue_interrupt(&fc->iq, req); 1972 err = queue_interrupt(&fc->iq, req);
1966 1973
1967 fuse_put_request(fc, req); 1974 fuse_put_request(fc, req);
1968 1975