diff options
author | Jens Axboe <axboe@kernel.dk> | 2020-09-19 05:13:06 +0300 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2020-11-01 14:45:35 +0300 |
commit | b6a6d1df552bbca5216595ad79f245484b98c5e7 (patch) | |
tree | 74c81dd399a7bb6b2936321fb6595bd5d1c4a5f6 | |
parent | 511abceaf0a00cb75f13bdc78f210a7b015e0478 (diff) | |
download | linux-b6a6d1df552bbca5216595ad79f245484b98c5e7.tar.xz |
io_uring: reference ->nsproxy for file table commands
commit 9b8284921513fc1ea57d87777283a59b05862f03 upstream.
If we don't get and assign the namespace for the async work, then certain
paths just don't work properly (like /dev/stdin, /proc/mounts, etc).
Anything that references the current namespace of the given task should
be assigned for async work on behalf of that task.
Cc: stable@vger.kernel.org # v5.5+
Reported-by: Al Viro <viro@zeniv.linux.org.uk>
Signed-off-by: Jens Axboe <axboe@kernel.dk>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
-rw-r--r-- | fs/io-wq.c | 4 | ||||
-rw-r--r-- | fs/io-wq.h | 1 | ||||
-rw-r--r-- | fs/io_uring.c | 3 |
3 files changed, 8 insertions, 0 deletions
diff --git a/fs/io-wq.c b/fs/io-wq.c index cb9e5a444fba..5257bb943d76 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -60,6 +60,7 @@ struct io_worker { const struct cred *cur_creds; const struct cred *saved_creds; struct files_struct *restore_files; + struct nsproxy *restore_nsproxy; struct fs_struct *restore_fs; }; @@ -153,6 +154,7 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker) task_lock(current); current->files = worker->restore_files; + current->nsproxy = worker->restore_nsproxy; task_unlock(current); } @@ -318,6 +320,7 @@ static void io_worker_start(struct io_wqe *wqe, struct io_worker *worker) worker->flags |= (IO_WORKER_F_UP | IO_WORKER_F_RUNNING); worker->restore_files = current->files; + worker->restore_nsproxy = current->nsproxy; worker->restore_fs = current->fs; io_wqe_inc_running(wqe, worker); } @@ -454,6 +457,7 @@ static void io_impersonate_work(struct io_worker *worker, if (work->files && current->files != work->files) { task_lock(current); current->files = work->files; + current->nsproxy = work->nsproxy; task_unlock(current); } if (work->fs && current->fs != work->fs) diff --git a/fs/io-wq.h b/fs/io-wq.h index 071f1a997800..9be6def2b5a6 100644 --- a/fs/io-wq.h +++ b/fs/io-wq.h @@ -88,6 +88,7 @@ struct io_wq_work { struct files_struct *files; struct mm_struct *mm; const struct cred *creds; + struct nsproxy *nsproxy; struct fs_struct *fs; unsigned flags; }; diff --git a/fs/io_uring.c b/fs/io_uring.c index ce6b241edd10..7e616aeebe5c 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -1456,6 +1456,7 @@ static void io_req_drop_files(struct io_kiocb *req) spin_unlock_irqrestore(&ctx->inflight_lock, flags); req->flags &= ~REQ_F_INFLIGHT; put_files_struct(req->work.files); + put_nsproxy(req->work.nsproxy); req->work.files = NULL; } @@ -5685,6 +5686,8 @@ static int io_grab_files(struct io_kiocb *req) return 0; req->work.files = get_files_struct(current); + get_nsproxy(current->nsproxy); + req->work.nsproxy = current->nsproxy; req->flags |= REQ_F_INFLIGHT; spin_lock_irq(&ctx->inflight_lock); |