Mike Christie
2021-Jun-24 03:08 UTC
[PATCH 1/3] kthread: allow caller to pass in user_struct
Currently, the kthreadd's user_struct has its processes checked against the RLIMIT_NPROC limit. In cases like for vhost where the driver is making a thread for userspace, we want the userspace process to have its processes count checked and incremented. This patch allows the kthread code to take a user_struct and pass it to copy_process. The next patches will then convert the fork/cred code. Signed-off-by: Mike Christie <michael.christie at oracle.com> --- include/linux/kthread.h | 5 ++++ include/linux/sched/task.h | 2 ++ kernel/kthread.c | 58 ++++++++++++++++++++++++++++++++------ 3 files changed, 56 insertions(+), 9 deletions(-) diff --git a/include/linux/kthread.h b/include/linux/kthread.h index 2484ed97e72f..3c64bd8bf34c 100644 --- a/include/linux/kthread.h +++ b/include/linux/kthread.h @@ -28,6 +28,11 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), kthread_create_on_node(threadfn, data, NUMA_NO_NODE, namefmt, ##arg) +struct task_struct *kthread_create_for_user(int (*threadfn)(void *data), + void *data, + struct user_struct *user, + const char namefmt[], ...); + struct task_struct *kthread_create_on_cpu(int (*threadfn)(void *data), void *data, unsigned int cpu, diff --git a/include/linux/sched/task.h b/include/linux/sched/task.h index ef02be869cf2..357e95679e33 100644 --- a/include/linux/sched/task.h +++ b/include/linux/sched/task.h @@ -34,6 +34,8 @@ struct kernel_clone_args { int io_thread; struct cgroup *cgrp; struct css_set *cset; + /* User to check RLIMIT_NPROC against */ + struct user_struct *user; }; /* diff --git a/kernel/kthread.c b/kernel/kthread.c index fe3f2a40d61e..9e7e4d04664f 100644 --- a/kernel/kthread.c +++ b/kernel/kthread.c @@ -41,6 +41,7 @@ struct kthread_create_info int (*threadfn)(void *data); void *data; int node; + struct user_struct *user; /* Result passed back to kthread_create() from kthreadd. */ struct task_struct *result; @@ -327,13 +328,21 @@ int tsk_fork_get_node(struct task_struct *tsk) static void create_kthread(struct kthread_create_info *create) { + /* We want our own signal handler (we take no signals by default). */ + struct kernel_clone_args clone_args = { + .flags = CLONE_FS | CLONE_FILES | CLONE_VM | + CLONE_UNTRACED, + .exit_signal = SIGCHLD, + .stack = (unsigned long)kthread, + .stack_size = (unsigned long)create, + .user = create->user, + }; int pid; #ifdef CONFIG_NUMA current->pref_node_fork = create->node; #endif - /* We want our own signal handler (we take no signals by default). */ - pid = kernel_thread(kthread, create, CLONE_FS | CLONE_FILES | SIGCHLD); + pid = kernel_clone(&clone_args); if (pid < 0) { /* If user was SIGKILLed, I release the structure. */ struct completion *done = xchg(&create->done, NULL); @@ -347,11 +356,11 @@ static void create_kthread(struct kthread_create_info *create) } } -static __printf(4, 0) +static __printf(5, 0) struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), - void *data, int node, - const char namefmt[], - va_list args) + void *data, int node, + struct user_struct *user, + const char namefmt[], va_list args) { DECLARE_COMPLETION_ONSTACK(done); struct task_struct *task; @@ -364,6 +373,7 @@ struct task_struct *__kthread_create_on_node(int (*threadfn)(void *data), create->data = data; create->node = node; create->done = &done; + create->user = user; spin_lock(&kthread_create_lock); list_add_tail(&create->list, &kthread_create_list); @@ -444,13 +454,43 @@ struct task_struct *kthread_create_on_node(int (*threadfn)(void *data), va_list args; va_start(args, namefmt); - task = __kthread_create_on_node(threadfn, data, node, namefmt, args); + task = __kthread_create_on_node(threadfn, data, node, NULL, namefmt, + args); va_end(args); return task; } EXPORT_SYMBOL(kthread_create_on_node); +/** + * kthread_create_for_user - create a kthread and check @user's RLIMIT_NPROC + * @threadfn: the function to run until signal_pending(current). + * @data: data ptr for @threadfn. + * @user: user_struct that will have its RLIMIT_NPROC checked + * @namefmt: printf-style name for the thread. + * + * This will create a kthread on the current node, leaving it in the stopped + * state. This is just a helper for kthread_create_on_node() that will check + * @user's process count against its RLIMIT_NPROC. See the + * kthread_create_on_node() documentation for more details. + */ +struct task_struct *kthread_create_for_user(int (*threadfn)(void *data), + void *data, + struct user_struct *user, + const char namefmt[], ...) +{ + struct task_struct *task; + va_list args; + + va_start(args, namefmt); + task = __kthread_create_on_node(threadfn, data, NUMA_NO_NODE, user, + namefmt, args); + va_end(args); + + return task; +} +EXPORT_SYMBOL(kthread_create_for_user); + static void __kthread_bind_mask(struct task_struct *p, const struct cpumask *mask, long state) { unsigned long flags; @@ -785,8 +825,8 @@ __kthread_create_worker(int cpu, unsigned int flags, if (cpu >= 0) node = cpu_to_node(cpu); - task = __kthread_create_on_node(kthread_worker_fn, worker, - node, namefmt, args); + task = __kthread_create_on_node(kthread_worker_fn, worker, node, NULL, + namefmt, args); if (IS_ERR(task)) goto fail_task; -- 2.25.1
kernel test robot
2021-Jun-24 04:34 UTC
[PATCH 1/3] kthread: allow caller to pass in user_struct
Hi Mike, Thank you for the patch! Perhaps something to improve: [auto build test WARNING on vhost/linux-next] [also build test WARNING on linux/master linus/master v5.13-rc7] [cannot apply to next-20210623] [If your patch is applied to the wrong git tree, kindly drop us a note. And when submitting patch, we suggest to use '--base' as documented in https://git-scm.com/docs/git-format-patch] url: https://github.com/0day-ci/linux/commits/Mike-Christie/kthread-pass-in-user-and-check-RLIMIT_NPROC/20210624-110925 base: https://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git linux-next config: um-x86_64_defconfig (attached as .config) compiler: gcc-9 (Debian 9.3.0-22) 9.3.0 reproduce (this is a W=1 build): # https://github.com/0day-ci/linux/commit/9b4a744e588ed25e06eed415174977e7533b24dc git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Mike-Christie/kthread-pass-in-user-and-check-RLIMIT_NPROC/20210624-110925 git checkout 9b4a744e588ed25e06eed415174977e7533b24dc # save the attached .config to linux build tree make W=1 ARCH=um SUBARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp at intel.com> All warnings (new ones prefixed by >>): cc1: warning: arch/um/include/uapi: No such file or directory [-Wmissing-include-dirs] kernel/kthread.c: In function 'kthread_create_for_user':>> kernel/kthread.c:466:6: warning: function 'kthread_create_for_user' might be a candidate for 'gnu_printf' format attribute [-Wsuggest-attribute=format]466 | namefmt, args); | ^~~~~~~ vim +466 kernel/kthread.c 443 444 /** 445 * kthread_create_for_user - create a kthread and check @user's RLIMIT_NPROC 446 * @threadfn: the function to run until signal_pending(current). 447 * @data: data ptr for @threadfn. 448 * @user: user_struct that will have its RLIMIT_NPROC checked 449 * @namefmt: printf-style name for the thread. 450 * 451 * This will create a kthread on the current node, leaving it in the stopped 452 * state. This is just a helper for kthread_create_on_node() that will check 453 * @user's process count against its RLIMIT_NPROC. See the 454 * kthread_create_on_node() documentation for more details. 455 */ 456 struct task_struct *kthread_create_for_user(int (*threadfn)(void *data), 457 void *data, 458 struct user_struct *user, 459 const char namefmt[], ...) 460 { 461 struct task_struct *task; 462 va_list args; 463 464 va_start(args, namefmt); 465 task = __kthread_create_on_node(threadfn, data, NUMA_NO_NODE, user, > 466 namefmt, args); 467 va_end(args); 468 469 return task; 470 } 471 EXPORT_SYMBOL(kthread_create_for_user); 472 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all at lists.01.org -------------- next part -------------- A non-text attachment was scrubbed... Name: .config.gz Type: application/gzip Size: 8593 bytes Desc: not available URL: <http://lists.linuxfoundation.org/pipermail/virtualization/attachments/20210624/0bbf33b0/attachment-0001.gz>