author: Jens Axboe <axboe@kernel.dk> 2021-02-15 13:40:22 -0700
committer: Jens Axboe <axboe@kernel.dk> 2021-02-21 17:25:22 -0700
commit: 4379bf8bd70b5de6bba7d53015b0c36c57a634ee
parent: 44526bedc2ff8fcd58552e3c5bae928524b6f13c
Commit Summary:
Diffstat:
1 file changed, 25 insertions, 0 deletions
diff --git a/fs/io-wq.c b/fs/io-wq.c
index 41042119bf0f..acc67ed3a52c 100644
--- a/fs/io-wq.c
+++ b/fs/io-wq.c
@@ -53,6 +53,9 @@ struct io_worker {
struct io_wq_work *cur_work;
spinlock_t lock;
+ const struct cred *cur_creds;
+ const struct cred *saved_creds;
+
struct rcu_head rcu;
};
@@ -171,6 +174,11 @@ static void io_worker_exit(struct io_worker *worker)
worker->flags = 0;
preempt_enable();
+ if (worker->saved_creds) {
+ revert_creds(worker->saved_creds);
+ worker->cur_creds = worker->saved_creds = NULL;
+ }
+
raw_spin_lock_irq(&wqe->lock);
hlist_nulls_del_rcu(&worker->nulls_node);
list_del_rcu(&worker->all_list);
@@ -312,6 +320,10 @@ static void __io_worker_idle(struct io_wqe *wqe, struct io_worker *worker)
worker->flags |= IO_WORKER_F_FREE;
hlist_nulls_add_head_rcu(&worker->nulls_node, &wqe->free_list);
}
+ if (worker->saved_creds) {
+ revert_creds(worker->saved_creds);
+ worker->cur_creds = worker->saved_creds = NULL;
+ }
}
static inline unsigned int io_get_work_hash(struct io_wq_work *work)
@@ -359,6 +371,18 @@ static void io_flush_signals(void)
}
}
+static void io_wq_switch_creds(struct io_worker *worker,
+ struct io_wq_work *work)
+{
+ const struct cred *old_creds = override_creds(work->creds);
+
+ worker->cur_creds = work->creds;
+ if (worker->saved_creds)
+ put_cred(old_creds); /* creds set by previous switch */
+ else
+ worker->saved_creds = old_creds;
+}
+
static void io_assign_current_work(struct io_worker *worker,
struct io_wq_work *work)
{
@@ -407,6 +431,8 @@ get_next:
unsigned int hash = io_get_work_hash(work);
next_hashed = wq_next_work(work);
+ if (work->creds && worker->cur_creds != work->creds)
+ io_wq_switch_creds(worker, work);
wq->do_work(work);
io_assign_current_work(worker, NULL);