[ Upstream commit bbda86e988 ]

The way the per task_struct exit_code is used by kernel threads is not
quite compatible how it is used by userspace applications.  The low
byte of the userspace exit_code value encodes the exit signal.  While
kthreads just use the value as an int holding ordinary kernel function
exit status like -EPERM.

Add kthread_exit to clearly separate the two kinds of uses.

Signed-off-by: "Eric W. Biederman" <ebiederm@xmission.com>
Stable-dep-of: ca3574bd65 ("exit: Rename module_put_and_exit to module_put_and_kthread_exit")
Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
This commit is contained in:
Eric W. Biederman 2021-11-22 10:27:36 -06:00 коммит произвёл Greg Kroah-Hartman
Родитель de7e2adfc7
Коммит dd66630966
3 изменённых файлов: 21 добавлений и 4 удалений

Просмотреть файл

@ -95,6 +95,7 @@ void *kthread_probe_data(struct task_struct *k);
int kthread_park(struct task_struct *k); int kthread_park(struct task_struct *k);
void kthread_unpark(struct task_struct *k); void kthread_unpark(struct task_struct *k);
void kthread_parkme(void); void kthread_parkme(void);
void kthread_exit(long result) __noreturn;
int kthreadd(void *unused); int kthreadd(void *unused);
extern struct task_struct *kthreadd_task; extern struct task_struct *kthreadd_task;

Просмотреть файл

@ -268,6 +268,21 @@ void kthread_parkme(void)
} }
EXPORT_SYMBOL_GPL(kthread_parkme); EXPORT_SYMBOL_GPL(kthread_parkme);
/**
* kthread_exit - Cause the current kthread return @result to kthread_stop().
* @result: The integer value to return to kthread_stop().
*
* While kthread_exit can be called directly, it exists so that
* functions which do some additional work in non-modular code such as
* module_put_and_kthread_exit can be implemented.
*
* Does not return.
*/
void __noreturn kthread_exit(long result)
{
do_exit(result);
}
static int kthread(void *_create) static int kthread(void *_create)
{ {
/* Copy data: it's on kthread's stack */ /* Copy data: it's on kthread's stack */
@ -285,13 +300,13 @@ static int kthread(void *_create)
done = xchg(&create->done, NULL); done = xchg(&create->done, NULL);
if (!done) { if (!done) {
kfree(create); kfree(create);
do_exit(-EINTR); kthread_exit(-EINTR);
} }
if (!self) { if (!self) {
create->result = ERR_PTR(-ENOMEM); create->result = ERR_PTR(-ENOMEM);
complete(done); complete(done);
do_exit(-ENOMEM); kthread_exit(-ENOMEM);
} }
self->threadfn = threadfn; self->threadfn = threadfn;
@ -318,7 +333,7 @@ static int kthread(void *_create)
__kthread_parkme(self); __kthread_parkme(self);
ret = threadfn(data); ret = threadfn(data);
} }
do_exit(ret); kthread_exit(ret);
} }
/* called from kernel_clone() to get node information for about to be created task */ /* called from kernel_clone() to get node information for about to be created task */
@ -628,7 +643,7 @@ EXPORT_SYMBOL_GPL(kthread_park);
* instead of calling wake_up_process(): the thread will exit without * instead of calling wake_up_process(): the thread will exit without
* calling threadfn(). * calling threadfn().
* *
* If threadfn() may call do_exit() itself, the caller must ensure * If threadfn() may call kthread_exit() itself, the caller must ensure
* task_struct can't go away. * task_struct can't go away.
* *
* Returns the result of threadfn(), or %-EINTR if wake_up_process() * Returns the result of threadfn(), or %-EINTR if wake_up_process()

Просмотреть файл

@ -169,6 +169,7 @@ static bool __dead_end_function(struct objtool_file *file, struct symbol *func,
"panic", "panic",
"do_exit", "do_exit",
"do_task_dead", "do_task_dead",
"kthread_exit",
"make_task_dead", "make_task_dead",
"__module_put_and_exit", "__module_put_and_exit",
"complete_and_exit", "complete_and_exit",