提交 3b8ddc93 编写于 作者: J Jens Axboe 提交者: Joseph Qi

io_uring: async workers should inherit the user creds

commit 576a347b7af8abfbddc80783fb6629c2894d036e upstream.

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/#uSigned-off-by: NJens Axboe <axboe@kernel.dk>
Signed-off-by: NJoseph Qi <joseph.qi@linux.alibaba.com>
Acked-by: NXiaoguang Wang <xiaoguang.wang@linux.alibaba.com>
上级 844cf850
...@@ -54,6 +54,7 @@ struct io_worker { ...@@ -54,6 +54,7 @@ struct io_worker {
struct rcu_head rcu; struct rcu_head rcu;
struct mm_struct *mm; struct mm_struct *mm;
const struct cred *creds;
struct files_struct *restore_files; struct files_struct *restore_files;
}; };
...@@ -112,6 +113,7 @@ struct io_wq { ...@@ -112,6 +113,7 @@ struct io_wq {
struct task_struct *manager; struct task_struct *manager;
struct user_struct *user; struct user_struct *user;
struct cred *creds;
struct mm_struct *mm; struct mm_struct *mm;
refcount_t refs; refcount_t refs;
struct completion done; struct completion done;
...@@ -137,6 +139,11 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker) ...@@ -137,6 +139,11 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker)
{ {
bool dropped_lock = false; bool dropped_lock = false;
if (worker->creds) {
revert_creds(worker->creds);
worker->creds = NULL;
}
if (current->files != worker->restore_files) { if (current->files != worker->restore_files) {
__acquire(&wqe->lock); __acquire(&wqe->lock);
spin_unlock_irq(&wqe->lock); spin_unlock_irq(&wqe->lock);
...@@ -445,6 +452,8 @@ static void io_worker_handle_work(struct io_worker *worker) ...@@ -445,6 +452,8 @@ static void io_worker_handle_work(struct io_worker *worker)
set_fs(USER_DS); set_fs(USER_DS);
worker->mm = wq->mm; worker->mm = wq->mm;
} }
if (!worker->creds)
worker->creds = override_creds(wq->creds);
if (test_bit(IO_WQ_BIT_CANCEL, &wq->state)) if (test_bit(IO_WQ_BIT_CANCEL, &wq->state))
work->flags |= IO_WQ_WORK_CANCEL; work->flags |= IO_WQ_WORK_CANCEL;
if (worker->mm) if (worker->mm)
...@@ -994,6 +1003,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data) ...@@ -994,6 +1003,7 @@ struct io_wq *io_wq_create(unsigned bounded, struct io_wq_data *data)
/* caller must already hold a reference to this */ /* caller must already hold a reference to this */
wq->user = data->user; wq->user = data->user;
wq->creds = data->creds;
i = 0; i = 0;
refcount_set(&wq->refs, wq->nr_wqes); refcount_set(&wq->refs, wq->nr_wqes);
......
...@@ -41,6 +41,7 @@ typedef void (put_work_fn)(struct io_wq_work *); ...@@ -41,6 +41,7 @@ typedef void (put_work_fn)(struct io_wq_work *);
struct io_wq_data { struct io_wq_data {
struct mm_struct *mm; struct mm_struct *mm;
struct user_struct *user; struct user_struct *user;
struct cred *creds;
get_work_fn *get_work; get_work_fn *get_work;
put_work_fn *put_work; put_work_fn *put_work;
......
...@@ -236,6 +236,8 @@ struct io_ring_ctx { ...@@ -236,6 +236,8 @@ struct io_ring_ctx {
struct user_struct *user; struct user_struct *user;
struct cred *creds;
/* 0 is for ctx quiesce/reinit/free, 1 is for sqo_thread started */ /* 0 is for ctx quiesce/reinit/free, 1 is for sqo_thread started */
struct completion *completions; struct completion *completions;
...@@ -3157,6 +3159,7 @@ static int io_sq_thread(void *data) ...@@ -3157,6 +3159,7 @@ static int io_sq_thread(void *data)
{ {
struct io_ring_ctx *ctx = data; struct io_ring_ctx *ctx = data;
struct mm_struct *cur_mm = NULL; struct mm_struct *cur_mm = NULL;
const struct cred *old_cred;
mm_segment_t old_fs; mm_segment_t old_fs;
DEFINE_WAIT(wait); DEFINE_WAIT(wait);
unsigned long timeout; unsigned long timeout;
...@@ -3166,6 +3169,7 @@ static int io_sq_thread(void *data) ...@@ -3166,6 +3169,7 @@ static int io_sq_thread(void *data)
old_fs = get_fs(); old_fs = get_fs();
set_fs(USER_DS); set_fs(USER_DS);
old_cred = override_creds(ctx->creds);
timeout = jiffies + ctx->sq_thread_idle; timeout = jiffies + ctx->sq_thread_idle;
while (!kthread_should_park()) { while (!kthread_should_park()) {
...@@ -3263,6 +3267,7 @@ static int io_sq_thread(void *data) ...@@ -3263,6 +3267,7 @@ static int io_sq_thread(void *data)
unuse_mm(cur_mm); unuse_mm(cur_mm);
mmput(cur_mm); mmput(cur_mm);
} }
revert_creds(old_cred);
kthread_parkme(); kthread_parkme();
...@@ -3889,6 +3894,7 @@ static int io_sq_offload_start(struct io_ring_ctx *ctx, ...@@ -3889,6 +3894,7 @@ static int io_sq_offload_start(struct io_ring_ctx *ctx,
data.mm = ctx->sqo_mm; data.mm = ctx->sqo_mm;
data.user = ctx->user; data.user = ctx->user;
data.creds = ctx->creds;
data.get_work = io_get_work; data.get_work = io_get_work;
data.put_work = io_put_work; data.put_work = io_put_work;
...@@ -4244,6 +4250,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx) ...@@ -4244,6 +4250,7 @@ static void io_ring_ctx_free(struct io_ring_ctx *ctx)
io_unaccount_mem(ctx->user, io_unaccount_mem(ctx->user,
ring_pages(ctx->sq_entries, ctx->cq_entries)); ring_pages(ctx->sq_entries, ctx->cq_entries));
free_uid(ctx->user); free_uid(ctx->user);
put_cred(ctx->creds);
kfree(ctx->completions); kfree(ctx->completions);
kmem_cache_free(req_cachep, ctx->fallback_req); kmem_cache_free(req_cachep, ctx->fallback_req);
kfree(ctx); kfree(ctx);
...@@ -4600,6 +4607,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p) ...@@ -4600,6 +4607,7 @@ static int io_uring_create(unsigned entries, struct io_uring_params *p)
ctx->compat = in_compat_syscall(); ctx->compat = in_compat_syscall();
ctx->account_mem = account_mem; ctx->account_mem = account_mem;
ctx->user = user; ctx->user = user;
ctx->creds = prepare_creds();
ret = io_allocate_scq_urings(ctx, p); ret = io_allocate_scq_urings(ctx, p);
if (ret) if (ret)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册