linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal()
@ 2015-11-05 20:17 Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 1/3] signal: change sig_task_ignored(force) to take sig_kernel_only() into account Oleg Nesterov
                   ` (3 more replies)
  0 siblings, 4 replies; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-05 20:17 UTC (permalink / raw)
  To: Andrew Morton, Dmitry Vyukov
  Cc: Roland McGrath, amanieu, pmoore, Ingo Molnar, vdavydov,
	qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

On 11/05, Oleg Nesterov wrote:
>
> Cough... and on the second thought this patch needs v2. Sorry Andrew, please
> drop signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> I'll send the updated version.
>
> With this patch the parent namespace can use any fatal signal (not only SIGKILL)
> to kill the init process in container. I do not think this is actually bad, but
> in any case this should not silently come as a side effect. And this is not
> consistent with SIGNAL_UNKILLABLE/sig_kernel_only() check in get_signal().
>
> Most probably I will just resend this patch as 2/2, while 1/2 will change
> sig_task_ignored() because afaics it is not actually right too (albeit not
> really buggy).

So this replaces
signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
2/3 is actually the same change, just the changelog was updated.

I'll try to send the cleanups tomorrow. sig_task_ignored() doesn't
look nice, sig_handler_ignored() must die, SIGNAL_UNKILLABLE checks
in sig_task_ignored() and get_signal() should be unified.

And to remind, we need to fix more problems I found yesterday.

Oleg.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* [PATCH v2 1/3] signal: change sig_task_ignored(force) to take sig_kernel_only() into account
  2015-11-05 20:17 [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
@ 2015-11-05 20:17 ` Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 2/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-05 20:17 UTC (permalink / raw)
  To: Andrew Morton, Dmitry Vyukov
  Cc: Roland McGrath, amanieu, pmoore, Ingo Molnar, vdavydov,
	qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

sig_task_ignored(force => true) returns false unless sig_kernel_ignore().
This makes no sense if !sig_kernel_only(), the signal will be dropped in
get_signal() anyway.

This patch simplifies the next change and allows us to do more cleanups,
in particular we can unify the SIGNAL_UNKILLABLE/sig_kernel_only() check
in sig_task_ignored() and get_signal().

The user-visible change is that, since we drop the SIG_DFL signal early,
it won't be reported to debugger. I think this is fine, but probably we
will change this later, we need to fix this logic anyway. Currently we
rely on the fact that (say) send_sigtrap() uses force_sig_info() which
clears SIGNAL_UNKILLABLE, and this is really bad.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/signal.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index d64efad..87209e5 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -72,7 +72,7 @@ static int sig_task_ignored(struct task_struct *t, int sig, bool force)
 	handler = sig_handler(t, sig);
 
 	if (unlikely(t->signal->flags & SIGNAL_UNKILLABLE) &&
-			handler == SIG_DFL && !force)
+	    handler == SIG_DFL && !(force && sig_kernel_only(sig)))
 		return 1;
 
 	return sig_handler_ignored(handler, sig);
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 2/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal()
  2015-11-05 20:17 [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 1/3] signal: change sig_task_ignored(force) to take sig_kernel_only() into account Oleg Nesterov
@ 2015-11-05 20:17 ` Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 3/3] signal: change complete_signal() to use for_each_thread() Oleg Nesterov
  2015-11-05 23:33 ` [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Andrew Morton
  3 siblings, 0 replies; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-05 20:17 UTC (permalink / raw)
  To: Andrew Morton, Dmitry Vyukov
  Cc: Roland McGrath, amanieu, pmoore, Ingo Molnar, vdavydov,
	qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

complete_signal() checks SIGNAL_UNKILLABLE before it starts to destroy the
thread group, today this is unnecessary and even not 100% correct.

After the previous change we can rely on sig_task_ignored(); sig_fatal(sig)
&& SIGNAL_UNKILLABLE can only be true if we actually want to kill this task.

And it does not look right. fatal_signal_pending() should always imply that
the whole thread group (except ->group_exit_task if it is not NULL) is killed,
this check breaks the rule.

This explains WARN_ON(!JOBCTL_STOP_PENDING) in task_participate_group_stop()
triggered by the test-case from Dmitry:

	int main()
	{
		int pid = 1;
		ptrace(PTRACE_ATTACH, pid, 0, 0);
		ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL);
		sleep(1);
		return 0;
	}

do_signal_stop()->signal_group_exit() returns false because SIGNAL_GROUP_EXIT
is not set, but task_set_jobctl_pending() checks fatal_signal_pending() and
does not set JOBCTL_STOP_PENDING.

The test-case above needs root and (correctly) crashes the kernel, but we can
trigger the same warning inside the container or using another test-case:

	static int init(void *arg)
	{
		for (;;)
			pause();
	}

	int main(void)
	{
		char stack[16 * 1024];

		for (;;) {
			int pid = clone(init, stack + sizeof(stack)/2,
					CLONE_NEWPID | SIGCHLD, NULL);
			assert(pid > 0);

			assert(ptrace(PTRACE_ATTACH, pid, 0, 0) == 0);
			assert(waitpid(-1, NULL, WSTOPPED) == pid);

			assert(ptrace(PTRACE_DETACH, pid, 0, SIGSTOP) == 0);
			assert(syscall(__NR_tkill, pid, SIGKILL) == 0);
			assert(pid == wait(NULL));
		}
	}

Reported-by: Dmitry Vyukov <dvyukov@google.com>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/signal.c |    2 +-
 1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 87209e5..7e9f6fa 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -914,7 +914,7 @@ static void complete_signal(int sig, struct task_struct *p, int group)
 	 * then start taking the whole group down immediately.
 	 */
 	if (sig_fatal(p, sig) &&
-	    !(signal->flags & (SIGNAL_UNKILLABLE | SIGNAL_GROUP_EXIT)) &&
+	    !(signal->flags & SIGNAL_GROUP_EXIT) &&
 	    !sigismember(&t->real_blocked, sig) &&
 	    (sig == SIGKILL || !t->ptrace)) {
 		/*
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* [PATCH v2 3/3] signal: change complete_signal() to use for_each_thread()
  2015-11-05 20:17 [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 1/3] signal: change sig_task_ignored(force) to take sig_kernel_only() into account Oleg Nesterov
  2015-11-05 20:17 ` [PATCH v2 2/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
@ 2015-11-05 20:17 ` Oleg Nesterov
  2015-11-05 23:33 ` [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Andrew Morton
  3 siblings, 0 replies; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-05 20:17 UTC (permalink / raw)
  To: Andrew Morton, Dmitry Vyukov
  Cc: Roland McGrath, amanieu, pmoore, Ingo Molnar, vdavydov,
	qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

change complete_signal() to use for_each_thread().

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
---
 kernel/signal.c |    5 ++---
 1 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/kernel/signal.c b/kernel/signal.c
index 7e9f6fa..8cdde5f 100644
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -930,12 +930,11 @@ static void complete_signal(int sig, struct task_struct *p, int group)
 			signal->flags = SIGNAL_GROUP_EXIT;
 			signal->group_exit_code = sig;
 			signal->group_stop_count = 0;
-			t = p;
-			do {
+			for_each_thread(p, t) {
 				task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
 				sigaddset(&t->pending.signal, SIGKILL);
 				signal_wake_up(t, 1);
-			} while_each_thread(p, t);
+			}
 			return;
 		}
 	}
-- 
1.5.5.1


^ permalink raw reply related	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal()
  2015-11-05 20:17 [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
                   ` (2 preceding siblings ...)
  2015-11-05 20:17 ` [PATCH v2 3/3] signal: change complete_signal() to use for_each_thread() Oleg Nesterov
@ 2015-11-05 23:33 ` Andrew Morton
  2015-11-06 14:32   ` Oleg Nesterov
  3 siblings, 1 reply; 7+ messages in thread
From: Andrew Morton @ 2015-11-05 23:33 UTC (permalink / raw)
  To: Oleg Nesterov
  Cc: Dmitry Vyukov, Roland McGrath, amanieu, pmoore, Ingo Molnar,
	vdavydov, qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

On Thu, 5 Nov 2015 21:17:20 +0100 Oleg Nesterov <oleg@redhat.com> wrote:

> On 11/05, Oleg Nesterov wrote:
> >
> > Cough... and on the second thought this patch needs v2. Sorry Andrew, please
> > drop signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> > I'll send the updated version.
> >
> > With this patch the parent namespace can use any fatal signal (not only SIGKILL)
> > to kill the init process in container. I do not think this is actually bad, but
> > in any case this should not silently come as a side effect. And this is not
> > consistent with SIGNAL_UNKILLABLE/sig_kernel_only() check in get_signal().
> >
> > Most probably I will just resend this patch as 2/2, while 1/2 will change
> > sig_task_ignored() because afaics it is not actually right too (albeit not
> > really buggy).
> 
> So this replaces
> signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> 2/3 is actually the same change, just the changelog was updated.

It's awfully late.  Do you see any reason why we should jam this into 4.4?

^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal()
  2015-11-05 23:33 ` [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Andrew Morton
@ 2015-11-06 14:32   ` Oleg Nesterov
  2015-11-06 19:16     ` Oleg Nesterov
  0 siblings, 1 reply; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-06 14:32 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Dmitry Vyukov, Roland McGrath, amanieu, pmoore, Ingo Molnar,
	vdavydov, qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

On 11/05, Andrew Morton wrote:
>
> On Thu, 5 Nov 2015 21:17:20 +0100 Oleg Nesterov <oleg@redhat.com> wrote:
>
> > On 11/05, Oleg Nesterov wrote:
> > >
> > > Cough... and on the second thought this patch needs v2. Sorry Andrew, please
> > > drop signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> > > I'll send the updated version.
> > >
> > > With this patch the parent namespace can use any fatal signal (not only SIGKILL)
> > > to kill the init process in container. I do not think this is actually bad, but
> > > in any case this should not silently come as a side effect. And this is not
> > > consistent with SIGNAL_UNKILLABLE/sig_kernel_only() check in get_signal().
> > >
> > > Most probably I will just resend this patch as 2/2, while 1/2 will change
> > > sig_task_ignored() because afaics it is not actually right too (albeit not
> > > really buggy).
> >
> > So this replaces
> > signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> > 2/3 is actually the same change, just the changelog was updated.
>
> It's awfully late.  Do you see any reason why we should jam this into 4.4?

No, I think this can wait till 4.5.

Oleg.


^ permalink raw reply	[flat|nested] 7+ messages in thread

* Re: [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal()
  2015-11-06 14:32   ` Oleg Nesterov
@ 2015-11-06 19:16     ` Oleg Nesterov
  0 siblings, 0 replies; 7+ messages in thread
From: Oleg Nesterov @ 2015-11-06 19:16 UTC (permalink / raw)
  To: Andrew Morton
  Cc: Dmitry Vyukov, Roland McGrath, amanieu, pmoore, Ingo Molnar,
	vdavydov, qiaowei.ren, dave, palmer, syzkaller, Kostya Serebryany,
	Alexander Potapenko, Sasha Levin, linux-kernel

On 11/06, Oleg Nesterov wrote:
>
> On 11/05, Andrew Morton wrote:
> >
> > On Thu, 5 Nov 2015 21:17:20 +0100 Oleg Nesterov <oleg@redhat.com> wrote:
> >
> > > So this replaces
> > > signal-kill-the-obsolete-signal_unkillable-check-in-complete_signal.patch
> > > 2/3 is actually the same change, just the changelog was updated.
> >
> > It's awfully late.  Do you see any reason why we should jam this into 4.4?
>
> No, I think this can wait till 4.5.

Oh. Andrew, please ignore this version too. I'll send v3.

Because when I tried to make the promised cleanups I have found yet another
ptrace/SIGKILL/SIGNAL_UNKILLABLE bug, and it seems that it needs to change
the same code paths again. I need to think.

Dmitry, do you realize how much I hate you? ;)

Oleg.


^ permalink raw reply	[flat|nested] 7+ messages in thread

end of thread, other threads:[~2015-11-06 18:20 UTC | newest]

Thread overview: 7+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-11-05 20:17 [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
2015-11-05 20:17 ` [PATCH v2 1/3] signal: change sig_task_ignored(force) to take sig_kernel_only() into account Oleg Nesterov
2015-11-05 20:17 ` [PATCH v2 2/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Oleg Nesterov
2015-11-05 20:17 ` [PATCH v2 3/3] signal: change complete_signal() to use for_each_thread() Oleg Nesterov
2015-11-05 23:33 ` [PATCH 0/3] signal: kill the obsolete SIGNAL_UNKILLABLE check in complete_signal() Andrew Morton
2015-11-06 14:32   ` Oleg Nesterov
2015-11-06 19:16     ` Oleg Nesterov

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).