All of lore.kernel.org
 help / color / mirror / Atom feed
From: Oleg Nesterov <oleg@redhat.com>
To: Ingo Molnar <mingo@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
	Neil Brown <neilb@suse.de>, Evgeniy Polyakov <zbr@ioremap.net>,
	Stephen Smalley <sds@tycho.nsa.gov>,
	Alex Williamson <alex.williamson@redhat.com>,
	linux-kernel <linux-kernel@vger.kernel.org>,
	kvm <kvm@vger.kernel.org>
Subject: Re: [PATCH] signals: Generate warning when flush_signals() is called from non-kthread context
Date: Sun, 3 May 2015 19:34:02 +0200	[thread overview]
Message-ID: <20150503173401.GA22052@redhat.com> (raw)
In-Reply-To: <20150501193813.GA2812@gmail.com>

On 05/01, Ingo Molnar wrote:
>
> * Linus Torvalds <torvalds@linux-foundation.org> wrote:
>
> > On Fri, May 1, 2015 at 10:40 AM, Alex Williamson
> > <alex.williamson@redhat.com> wrote:
> > >
> > > - Flush signals on interrupted wait to retain polling interval (Alex Williamson)
> >
> > This cannot *possibly* be right. If I read this patch right, you're
> > randomly just getting rid of signals. No way in hell is that correct.
> >
> > "flush_signals()" is only for kernel threads, where it's a hacky
> > alternative to actually handling them (since kernel threads never
> > rreturn to user space and cannot really "handle" a signal). But you're
> > doing it in the ->remove handler for the device, which can be called
> > by arbitrary system processes. This is not a kernel thread thing, as
> > far as I can see.
> >
> > If you cannot handle signals, you damn well shouldn't be using
> > "wait_event_interruptible_timeout()" to begin with. Get rid of the
> > "interruptible", since it apparently *isn't* interruptible.
> >
> > So I'm not pulling this.
> >
> > Now I'm worried that other drivers do insane things like this. I
> > wonder if we should add some sanity test to flush_signals() to make
> > sure that it can only ever get called from a kernel thread.
> >
> > Oleg?
>
> So there are these uses:
>
>   triton:~/tip> git grep -lw flush_signals
>   arch/arm/common/bL_switcher.c
>
>
> Looks safe: used within the bL_switcher_thread() kthread.

safe but wrong at first glance... I mean, it is pointless. Looks like,
bL_switcher_thread() wrongly thinks that wait_event_interruptible() can
lead to signal_pending().

>   drivers/block/drbd/drbd_main.c
>   drivers/block/drbd/drbd_nl.c
>   drivers/block/drbd/drbd_receiver.c
>   drivers/block/drbd/drbd_worker.c


Oh, I didn't know this helper is abused so much. I'll try to recheck
tomorrow, but it seems that it should die...


>   drivers/md/md.c

I can't understand this code... The comment says:

	/* We need to wait INTERRUPTIBLE so that
	 * we don't add to the load-average.
	 * That means we need to be sure no signals are
	 * pending
	 */
	if (signal_pending(current))
		flush_signals(current);

and this is wrong. However, signal_pending() can be true because of
allow_signal(SIGKILL) above. But why it does allow_signal() ?


>   fs/lockd/svc.c
>   fs/nfs/callback.c
>   fs/nfsd/nfssvc.c
>
> Looks safe: lockd, nfsd plus nfsv4.%u-svc kthreads.

Yes, this case looks fine. But perhaps it makes sense to add another
helper... Or not, I'll try to think more.

> I also found a __flush_signals() use in:
>
>   security/selinux/hooks.c
>
> Now that's selinux_bprm_committed_creds(), apparently executed on
> exec(). Also does stuff like:
>
>                 memset(&itimer, 0, sizeof itimer);
>                 for (i = 0; i < 3; i++)
>                         do_setitimer(i, &itimer, NULL);
>
> and unblocks signals as well:
>
>                         sigemptyset(&current->blocked);
>
> but this appears to be kind of legit: the task failed to get the
> required permissions, and guns go off.

and I simply can't understand this code... but I feel that it can't
be correct ;) Will try to re-read tomorrow.


> In any case, it seems to me that the patch below would be justified?
> Totally untested and so. __flush_signals() not affected.

Yes, agreed, it can't be right if the caller is not kthread.


> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -427,6 +427,10 @@ void flush_signals(struct task_struct *t)
>  {
>  	unsigned long flags;
>
> +	/* Only kthreads are allowed to destroy signals: */
> +	if (WARN_ON_ONCE(!(current->flags & PF_KTHREAD)))
> +		return;
> +

But I am not sure this can't make some buggy driver even more buggy.
Just suppose it does something

	do {
		if (signal_pending())
			flush_signals();
	} while (wait_event_interruptible(...));

and this change will turn this into busy-wait loop.

So perhaps another change which just adds WARN_ON_RATELIMIT() without
"return" will be safer?

Oleg.


  parent reply	other threads:[~2015-05-03 17:34 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-05-01 17:40 [GIT PULL] VFIO fixes for v4.1-rc2 Alex Williamson
2015-05-01 18:37 ` Linus Torvalds
2015-05-01 18:48   ` Alex Williamson
2015-05-01 20:23     ` Linus Torvalds
2015-05-01 22:03       ` Alex Williamson
2015-05-01 19:38   ` [PATCH] signals: Generate warning when flush_signals() is called from non-kthread context Ingo Molnar
2015-05-02  8:30     ` NeilBrown
2015-05-02 16:27       ` Linus Torvalds
2015-05-07 12:54         ` Peter Zijlstra
2015-05-04 17:35       ` Oleg Nesterov
2015-05-07 13:33         ` Jiri Kosina
2015-05-07 22:37           ` NeilBrown
2015-05-02 11:56     ` Evgeniy Polyakov
2015-05-02 16:33     ` Richard Weinberger
2015-05-03 17:34     ` Oleg Nesterov [this message]
2015-05-04 16:45       ` [PATCH 0/1] signals: don't abuse __flush_signals() in selinux_bprm_committed_creds() Oleg Nesterov
2015-05-04 16:45         ` [PATCH 1/1] " Oleg Nesterov
2015-05-04 19:43           ` Paul Moore
2015-05-04 19:43             ` Paul Moore
2015-05-06 10:19       ` [PATCH] signals: Generate warning when flush_signals() is called from non-kthread context Ingo Molnar
2015-05-01 20:11   ` [GIT PULL] VFIO fixes for v4.1-rc2 Richard Weinberger
2015-05-01 21:09     ` Richard Weinberger

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20150503173401.GA22052@redhat.com \
    --to=oleg@redhat.com \
    --cc=alex.williamson@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@kernel.org \
    --cc=neilb@suse.de \
    --cc=sds@tycho.nsa.gov \
    --cc=torvalds@linux-foundation.org \
    --cc=zbr@ioremap.net \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.