lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite: Windows password security audit tool. GUI, reports in PDF.
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <caa13441-5f95-b7d6-dd5d-1cf49e709714@I-love.SAKURA.ne.jp>
Date:   Sat, 4 Feb 2023 09:48:39 +0900
From:   Tetsuo Handa <penguin-kernel@...ove.SAKURA.ne.jp>
To:     Peter Zijlstra <peterz@...radead.org>
Cc:     Ingo Molnar <mingo@...nel.org>,
        "Rafael J. Wysocki" <rafael.j.wysocki@...el.com>,
        linux-kernel@...r.kernel.org, mcgrof@...nel.org,
        Linus Torvalds <torvalds@...ux-foundation.org>,
        syzkaller-bugs@...glegroups.com,
        syzbot <syzbot+6cd18e123583550cf469@...kaller.appspotmail.com>,
        Hillf Danton <hdanton@...a.com>
Subject: Re: [syzbot] WARNING: locking bug in umh_complete

On 2023/02/03 23:31, Peter Zijlstra wrote:
> Yes, I meant something like so.
> 
> 
> diff --git a/kernel/umh.c b/kernel/umh.c
> index 850631518665..0e69e1e4b6fe 100644
> --- a/kernel/umh.c
> +++ b/kernel/umh.c
> @@ -438,21 +438,24 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
>  	if (wait == UMH_NO_WAIT)	/* task has freed sub_info */
>  		goto unlock;
>  
> -	if (wait & UMH_KILLABLE)
> -		state |= TASK_KILLABLE;
> -
> -	if (wait & UMH_FREEZABLE)
> +	if (wait & UMH_FREEZABLE) {
>  		state |= TASK_FREEZABLE;
>  
> -	retval = wait_for_completion_state(&done, state);
> -	if (!retval)
> -		goto wait_done;
> -
>  	if (wait & UMH_KILLABLE) {
> +		retval = wait_for_completion_state(&done, state | TASK_KILLABLE);
> +		if (!retval)
> +			goto wait_done;
> +
>  		/* umh_complete() will see NULL and free sub_info */
>  		if (xchg(&sub_info->complete, NULL))
>  			goto unlock;
> +
> +		/*
> +		 * fallthrough; in case of -ERESTARTSYS now do uninterruptible
> +		 * wait_for_completion().
> +		 */
>  	}
> +	wait_for_completion_state(&done, state);
>  
>  wait_done:
>  	retval = sub_info->retval;

Please fold below diff, provided that wait_for_completion_state(TASK_FREEZABLE)
does not return when the current thread was frozen. (If
wait_for_completion_state(TASK_FREEZABLE) returns when the current thread was
frozen, we will fail to execute the

  retval = sub_info->retval;

line in order to get the exit code after the current thread is thawed...)

diff --git a/kernel/umh.c b/kernel/umh.c
index 0e69e1e4b6fe..a776920ec051 100644
--- a/kernel/umh.c
+++ b/kernel/umh.c
@@ -431,35 +431,38 @@ int call_usermodehelper_exec(struct subprocess_info *sub_info, int wait)
 	 * This makes it possible to use umh_complete to free
 	 * the data structure in case of UMH_NO_WAIT.
 	 */
 	sub_info->complete = (wait == UMH_NO_WAIT) ? NULL : &done;
 	sub_info->wait = wait;
 
 	queue_work(system_unbound_wq, &sub_info->work);
 	if (wait == UMH_NO_WAIT)	/* task has freed sub_info */
 		goto unlock;
 
-	if (wait & UMH_FREEZABLE) {
+	if (wait & UMH_FREEZABLE)
 		state |= TASK_FREEZABLE;
 
 	if (wait & UMH_KILLABLE) {
 		retval = wait_for_completion_state(&done, state | TASK_KILLABLE);
 		if (!retval)
 			goto wait_done;
 
 		/* umh_complete() will see NULL and free sub_info */
 		if (xchg(&sub_info->complete, NULL))
 			goto unlock;
 
 		/*
 		 * fallthrough; in case of -ERESTARTSYS now do uninterruptible
-		 * wait_for_completion().
+		 * wait_for_completion_state(). Since umh_complete() shall call
+		 * complete() in a moment if xchg() above returned NULL, this
+		 * uninterruptible wait_for_completion_state() will not block
+		 * SIGKILL'ed process for so long.
 		 */
 	}
 	wait_for_completion_state(&done, state);
 
 wait_done:
 	retval = sub_info->retval;
 out:
 	call_usermodehelper_freeinfo(sub_info);
 unlock:
 	helper_unlock();

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ