summaryrefslogtreecommitdiff
path: root/fs/io-wq.c
diff options
context:
space:
mode:
authorJens Axboe <axboe@kernel.dk>2019-11-25 08:52:30 -0700
committerJens Axboe <axboe@kernel.dk>2019-11-25 19:56:11 -0700
commit181e448d8709e517c9c7b523fcd209f24eb38ca7 (patch)
tree0245d1dc6356bd397fb604a28b5f9f716060b37f /fs/io-wq.c
parent576a347b7af8abfbddc80783fb6629c2894d036e (diff)
downloadlwn-181e448d8709e517c9c7b523fcd209f24eb38ca7.tar.gz
lwn-181e448d8709e517c9c7b523fcd209f24eb38ca7.zip
io_uring: async workers should inherit the user creds
If we don't inherit the original task creds, then we can confuse users like fuse that pass creds in the request header. See link below on identical aio issue. Link: https://lore.kernel.org/linux-fsdevel/26f0d78e-99ca-2f1b-78b9-433088053a61@scylladb.com/T/#u Signed-off-by: Jens Axboe <axboe@kernel.dk>
Diffstat (limited to 'fs/io-wq.c')
-rw-r--r--fs/io-wq.c10
1 files changed, 10 insertions, 0 deletions
diff --git a/fs/io-wq.c b/fs/io-wq.c
index 2b4276990571..31c5a10b0825 100644
--- a/fs/io-wq.c
+++ b/fs/io-wq.c
@@ -57,6 +57,7 @@ struct io_worker {
struct rcu_head rcu;
struct mm_struct *mm;
+ const struct cred *creds;
struct files_struct *restore_files;
};
@@ -111,6 +112,7 @@ struct io_wq {
struct task_struct *manager;
struct user_struct *user;
+ struct cred *creds;
struct mm_struct *mm;
refcount_t refs;
struct completion done;
@@ -136,6 +138,11 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker)
{
bool dropped_lock = false;
+ if (worker->creds) {
+ revert_creds(worker->creds);
+ worker->creds = NULL;
+ }
+
if (current->files != worker->restore_files) {
__acquire(&wqe->lock);
spin_unlock_irq(&wqe->lock);
@@ -442,6 +449,8 @@ next:
set_fs(USER_DS);
worker->mm = wq->mm;
}
+ if (!worker->creds)
+ worker->creds = override_creds(wq->creds);
if (test_bit(IO_WQ_BIT_CANCEL, &wq->state))
work->flags |= IO_WQ_WORK_CANCEL;
if (worker->mm)
@@ -995,6 +1004,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
/* caller must already hold a reference to this */
wq->user = data->user;
+ wq->creds = data->creds;
i = 0;
for_each_online_node(node) {