Skip to content

Commit 37c54f9

Browse files
Christoph Hellwigtorvalds
authored andcommitted
kernel: set USER_DS in kthread_use_mm
Some architectures like arm64 and s390 require USER_DS to be set for kernel threads to access user address space, which is the whole purpose of kthread_use_mm, but other like x86 don't. That has lead to a huge mess where some callers are fixed up once they are tested on said architectures, while others linger around and yet other like io_uring try to do "clever" optimizations for what usually is just a trivial asignment to a member in the thread_struct for most architectures. Make kthread_use_mm set USER_DS, and kthread_unuse_mm restore to the previous value instead. Signed-off-by: Christoph Hellwig <[email protected]> Signed-off-by: Andrew Morton <[email protected]> Tested-by: Jens Axboe <[email protected]> Reviewed-by: Jens Axboe <[email protected]> Acked-by: Michael S. Tsirkin <[email protected]> Cc: Alex Deucher <[email protected]> Cc: Al Viro <[email protected]> Cc: Felipe Balbi <[email protected]> Cc: Felix Kuehling <[email protected]> Cc: Jason Wang <[email protected]> Cc: Zhenyu Wang <[email protected]> Cc: Zhi Wang <[email protected]> Cc: Greg Kroah-Hartman <[email protected]> Link: http://lkml.kernel.org/r/[email protected] Signed-off-by: Linus Torvalds <[email protected]>
1 parent f5678e7 commit 37c54f9

File tree

5 files changed

+8
-17
lines changed

5 files changed

+8
-17
lines changed

drivers/usb/gadget/function/f_fs.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -824,13 +824,9 @@ static void ffs_user_copy_worker(struct work_struct *work)
824824
bool kiocb_has_eventfd = io_data->kiocb->ki_flags & IOCB_EVENTFD;
825825

826826
if (io_data->read && ret > 0) {
827-
mm_segment_t oldfs = get_fs();
828-
829-
set_fs(USER_DS);
830827
kthread_use_mm(io_data->mm);
831828
ret = ffs_copy_to_iter(io_data->buf, ret, &io_data->data);
832829
kthread_unuse_mm(io_data->mm);
833-
set_fs(oldfs);
834830
}
835831

836832
io_data->kiocb->ki_complete(io_data->kiocb, ret, ret);

drivers/vhost/vhost.c

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -329,9 +329,7 @@ static int vhost_worker(void *data)
329329
struct vhost_dev *dev = data;
330330
struct vhost_work *work, *work_next;
331331
struct llist_node *node;
332-
mm_segment_t oldfs = get_fs();
333332

334-
set_fs(USER_DS);
335333
kthread_use_mm(dev->mm);
336334

337335
for (;;) {
@@ -361,7 +359,6 @@ static int vhost_worker(void *data)
361359
}
362360
}
363361
kthread_unuse_mm(dev->mm);
364-
set_fs(oldfs);
365362
return 0;
366363
}
367364

fs/io-wq.c

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,6 @@ static bool __io_worker_unuse(struct io_wqe *wqe, struct io_worker *worker)
169169
dropped_lock = true;
170170
}
171171
__set_current_state(TASK_RUNNING);
172-
set_fs(KERNEL_DS);
173172
kthread_unuse_mm(worker->mm);
174173
mmput(worker->mm);
175174
worker->mm = NULL;
@@ -421,14 +420,11 @@ static void io_wq_switch_mm(struct io_worker *worker, struct io_wq_work *work)
421420
mmput(worker->mm);
422421
worker->mm = NULL;
423422
}
424-
if (!work->mm) {
425-
set_fs(KERNEL_DS);
423+
if (!work->mm)
426424
return;
427-
}
425+
428426
if (mmget_not_zero(work->mm)) {
429427
kthread_use_mm(work->mm);
430-
if (!worker->mm)
431-
set_fs(USER_DS);
432428
worker->mm = work->mm;
433429
/* hang on to this mm */
434430
work->mm = NULL;

fs/io_uring.c

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5989,15 +5989,12 @@ static int io_sq_thread(void *data)
59895989
{
59905990
struct io_ring_ctx *ctx = data;
59915991
const struct cred *old_cred;
5992-
mm_segment_t old_fs;
59935992
DEFINE_WAIT(wait);
59945993
unsigned long timeout;
59955994
int ret = 0;
59965995

59975996
complete(&ctx->sq_thread_comp);
59985997

5999-
old_fs = get_fs();
6000-
set_fs(USER_DS);
60015998
old_cred = override_creds(ctx->creds);
60025999

60036000
timeout = jiffies + ctx->sq_thread_idle;
@@ -6102,7 +6099,6 @@ static int io_sq_thread(void *data)
61026099
if (current->task_works)
61036100
task_work_run();
61046101

6105-
set_fs(old_fs);
61066102
io_sq_thread_drop_mm(ctx);
61076103
revert_creds(old_cred);
61086104

kernel/kthread.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ struct kthread {
5252
unsigned long flags;
5353
unsigned int cpu;
5454
void *data;
55+
mm_segment_t oldfs;
5556
struct completion parked;
5657
struct completion exited;
5758
#ifdef CONFIG_BLK_CGROUP
@@ -1235,6 +1236,9 @@ void kthread_use_mm(struct mm_struct *mm)
12351236

12361237
if (active_mm != mm)
12371238
mmdrop(active_mm);
1239+
1240+
to_kthread(tsk)->oldfs = get_fs();
1241+
set_fs(USER_DS);
12381242
}
12391243
EXPORT_SYMBOL_GPL(kthread_use_mm);
12401244

@@ -1249,6 +1253,8 @@ void kthread_unuse_mm(struct mm_struct *mm)
12491253
WARN_ON_ONCE(!(tsk->flags & PF_KTHREAD));
12501254
WARN_ON_ONCE(!tsk->mm);
12511255

1256+
set_fs(to_kthread(tsk)->oldfs);
1257+
12521258
task_lock(tsk);
12531259
sync_mm_rss(mm);
12541260
tsk->mm = NULL;

0 commit comments

Comments
 (0)