From: ebiederm@xmission.com (Eric W. Biederman)
To: Oleg Nesterov <oleg@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>,
Andrew Morton <akpm@linux-foundation.org>,
<linux-kernel@vger.kernel.org>
Subject: Re: [Bug 200447] infinite loop in fork syscall
Date: Tue, 10 Jul 2018 11:00:55 -0500 [thread overview]
Message-ID: <878t6jkrm0.fsf@xmission.com> (raw)
In-Reply-To: <20180710134639.GA2453@redhat.com> (Oleg Nesterov's message of "Tue, 10 Jul 2018 15:46:39 +0200")
Oleg Nesterov <oleg@redhat.com> writes:
> On 07/09, Linus Torvalds wrote:
>>
>> But the patch was written for testing and feedback more than anything
>> else. Comments?
>
> see my reply on bugzilla. Can't we add lkml?
Done.
> Perhaps we can do another change? Not sure it is actually better, but I think
> it is always good to discuss the alternatives.
>
> 1. Once again, we turn "int group" argument into thread/process/pgid enum, and
> change kill_pgrp/tty_signal_session_leader to pass "group = pgid", imo this
> makes sense in any case.
I agree. There are a lot more multi-process signals cases than handled
in Linus's patch. I believe this will clean that up.
> 2. To simplify, lets suppose we add the new PF_INFORK flag. Yes, this is bad,
> we can do better. I think we can simply add "struct hlist_head forking_threads"
> into signal_struct, so complete_signal() can just do hlist_for_each_entry()
> rather than for_each_thread() + PF_INFORK check. We don't even need a new
> member in task_struct.
We still need the distinction between multi-process signals and single
process signals (which is the hard part). For good performance of
signal delivery to multi-threaded tasks we still need a new member in
signal_struct. Plus it is a bit more work to update the list or even
walk the list than a sequence counter.
So I think adding a sequence counter to let us know about multiprocess
signals is the local optimum.
If we ever need to remove the restart case entirely from fork and queue
all new multi-process signals for the newly created task. Going through
the list of forking
>
> 3. copy_process() can simply block/unblock all signals (except KILL/STOP), see
> the "patch" below.
All signals are effectively blocked for the duration of the fork for the
calling task. Where we get into trouble and where we need a fix for
correctness is that another thread can dequeue the signal. Blocking
signals of the forking task does not change that.
I think that reveals another bug in our current logic. For blocked
multi-process signals we don't ensure they get delivered to both the
parent and the child if the signal logically comes in after the fork.
Multi-threaded b0rked ness and blocked signal b0rkenness, plus periodic
timers making for take forever for no good reason. This business of
ensuring a signal is logically delvered before or after a fork is
tricky.
Eric
> diff --git a/kernel/fork.c b/kernel/fork.c
> index 9440d61..652ef09 100644
> --- a/kernel/fork.c
> +++ b/kernel/fork.c
> @@ -1591,6 +1591,23 @@ static __latent_entropy struct task_struct *copy_process(
> int retval;
> struct task_struct *p;
>
> + spin_lock_irq(¤t->sighand->siglock);
> + recalc_sigpending_tsk(current);
> + if (signal_pending(current)) {
> + retval = -ERESTARTNOINTR;
> + } else {
> + // Yes, yes, this is wrong, just to explain the idea.
> + // We should not block SIGKILL, we need to clear PF_INFORK
> + // and restore ->blocked in error paths, we need helper(s).
> + retval = 0;
> + current->flags |= PF_INFORK;
> + current->saved_sigmask = current->blocked;
> + sigfillset(¤t->blocked);
> + }
> + spin_unlock_irq(¤t->sighand->siglock);
> + if (retval)
> + return retval;
> +
> /*
> * Don't allow sharing the root directory with processes in a different
> * namespace
> @@ -1918,8 +1935,14 @@ static __latent_entropy struct task_struct *copy_process(
> * A fatal signal pending means that current will exit, so the new
> * thread can't slip out of an OOM kill (or normal SIGKILL).
> */
> - recalc_sigpending();
> - if (signal_pending(current)) {
> + // check signal_pending() before __set_task_blocked() which does
> + // recalc_sigpending(). Again, this is just to explain the idea,
> + // __set_task_blocked() is not exported, it is suboptimal, we can
> + // do better.
> + bool eintr = signal_pending();
> + current->flags &= ~PF_INFORK;
> + __set_task_blocked(current, ¤t->saved_sigmask);
> + if (eintr) {
> retval = -ERESTARTNOINTR;
> goto bad_fork_cancel_cgroup;
> }
> diff --git a/kernel/signal.c b/kernel/signal.c
> index 8d8a940..3433e66 100644
> --- a/kernel/signal.c
> +++ b/kernel/signal.c
> @@ -900,6 +900,14 @@ static void complete_signal(int sig, struct task_struct *p, int group)
> struct signal_struct *signal = p->signal;
> struct task_struct *t;
>
> + // kill_pgrp/etc.
> + if (group == 2) {
> + for_each_thread(p, t) {
> + if (p->flags & PF_INFORK && !sigismember(&p->saved_sigmask, sig))
> + signal_wake_up(t, 0);
> + }
> + }
> +
> /*
> * Now find a thread we can wake up to take the signal off the queue.
> *
next parent reply other threads:[~2018-07-10 16:01 UTC|newest]
Thread overview: 96+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <bug-200447-5873-b2kAsSyE1X@https.bugzilla.kernel.org/>
[not found] ` <CA+55aFyOaEGc_wjRuAxYZH7D4zi4xUQTqUwMmUzxFJQ__2pXuQ@mail.gmail.com>
[not found] ` <87h8l9p7bg.fsf@xmission.com>
[not found] ` <20180709104158.GA23796@redhat.com>
[not found] ` <87sh4so5jv.fsf@xmission.com>
[not found] ` <20180709145726.GA26149@redhat.com>
[not found] ` <877em4nxo0.fsf@xmission.com>
[not found] ` <CA+55aFwq90_KeRUesktap7L_4Hp3gatKZ28RYw1jXBYeOqUoeA@mail.gmail.com>
[not found] ` <87lgakm4ol.fsf@xmission.com>
[not found] ` <CA+55aFz1XFvOgJySKVNQD9VS4hys0J7rozxqd3s5ND0z80tfVw@mail.gmail.com>
[not found] ` <20180710134639.GA2453@redhat.com>
2018-07-10 16:00 ` Eric W. Biederman [this message]
2018-07-11 12:08 ` Oleg Nesterov
[not found] ` <CA+55aFxcjSYAj-CZFEuDwiwZyMg+prV_jeP_Vuh06RJA0BboSw@mail.gmail.com>
2018-07-11 2:41 ` [RFC][PATCH 0/11] PIDTYPE_TGID and fewer fork restarts Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 01/11] pids: Initialize leader_pid in init_task Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 02/11] pids: Move task_pid_type into sched/signal.h Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 03/11] pids: Compute task_tgid using signal->leader_pid Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 04/11] kvm: Don't open code task_pid in kvm_vcpu_ioctl Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 05/11] pids: Move the pgrp and session pid pointers from task_struct to signal_struct Eric W. Biederman
2018-07-17 11:59 ` Oleg Nesterov
2018-07-11 2:44 ` [RFC][PATCH 06/11] pid: Implement PIDTYPE_TGID Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 07/11] signal: Deliver group signals via PIDTYPE_TGID not PIDTYPE_PID Eric W. Biederman
2018-07-16 12:51 ` Oleg Nesterov
2018-07-16 14:50 ` Eric W. Biederman
2018-07-16 17:17 ` Linus Torvalds
2018-07-16 18:01 ` Eric W. Biederman
2018-07-16 18:40 ` Linus Torvalds
2018-07-17 9:56 ` Oleg Nesterov
2018-07-17 10:18 ` Oleg Nesterov
2018-07-20 23:41 ` Eric W. Biederman
2018-07-17 16:38 ` Linus Torvalds
2018-07-20 23:27 ` Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 08/11] signal: Use PIDTYPE_TGID to clearly store where file signals will be sent Eric W. Biederman
2018-07-11 2:44 ` [RFC][PATCH 09/11] tty_io: Use do_send_sig_info in __do_SACK to forcibly kill tasks Eric W. Biederman
2018-07-16 14:55 ` Oleg Nesterov
2018-07-16 15:08 ` Eric W. Biederman
2018-07-16 16:50 ` Linus Torvalds
2018-07-16 19:17 ` Eric W. Biederman
2018-07-16 19:36 ` Linus Torvalds
2018-07-17 1:48 ` Eric W. Biederman
2018-07-17 10:58 ` Oleg Nesterov
2018-07-11 2:44 ` [RFC][PATCH 10/11] signal: Push pid type from signal senders down into __send_signal Eric W. Biederman
2018-07-11 3:11 ` Linus Torvalds
2018-07-11 2:44 ` [RFC][PATCH 11/11] signal: Ignore all but multi-process signals that come in during fork Eric W. Biederman
2018-07-11 14:14 ` Oleg Nesterov
2018-07-11 16:02 ` Eric W. Biederman
2018-07-12 13:42 ` Oleg Nesterov
2018-07-12 17:11 ` Eric W. Biederman
2018-07-13 14:51 ` Eric W. Biederman
2018-07-24 3:22 ` [PATCH 00/20] PIDTYPE_TGID removal of fork restarts Eric W. Biederman
2018-07-24 3:24 ` [PATCH 01/20] pids: Initialize leader_pid in init_task Eric W. Biederman
2018-07-24 3:24 ` [PATCH 02/20] pids: Move task_pid_type into sched/signal.h Eric W. Biederman
2018-07-24 3:24 ` [PATCH 03/20] pids: Compute task_tgid using signal->leader_pid Eric W. Biederman
2018-07-24 3:24 ` [PATCH 04/20] kvm: Don't open code task_pid in kvm_vcpu_ioctl Eric W. Biederman
2018-07-24 3:24 ` [PATCH 05/20] pids: Move the pgrp and session pid pointers from task_struct to signal_struct Eric W. Biederman
2018-07-24 3:24 ` [PATCH 06/20] pid: Implement PIDTYPE_TGID Eric W. Biederman
2018-07-24 3:24 ` [PATCH 07/20] signal: Use PIDTYPE_TGID to clearly store where file signals will be sent Eric W. Biederman
2018-08-16 4:04 ` [PATCH] signal: Don't send signals to tasks that don't exist Eric W. Biederman
2018-08-17 17:34 ` Dmitry Vyukov
2018-08-17 18:46 ` Eric W. Biederman
2018-08-17 19:24 ` Andrew Morton
2018-08-18 5:51 ` Eric W. Biederman
2018-08-20 19:26 ` J. Bruce Fields
2018-07-24 3:24 ` [PATCH 08/20] posix-timers: Noralize good_sigevent Eric W. Biederman
2018-07-24 3:24 ` [PATCH 09/20] signal: Pass pid and pid type into send_sigqueue Eric W. Biederman
2018-07-24 3:24 ` [PATCH 10/20] signal: Pass pid type into group_send_sig_info Eric W. Biederman
2018-07-24 3:24 ` [PATCH 11/20] signal: Pass pid type into send_sigio_to_task & send_sigurg_to_task Eric W. Biederman
2018-07-24 3:24 ` [PATCH 12/20] signal: Pass pid type into do_send_sig_info Eric W. Biederman
2018-07-24 3:24 ` [PATCH 13/20] signal: Push pid type down into send_signal Eric W. Biederman
2018-07-24 3:24 ` [PATCH 14/20] signal: Push pid type down into __send_signal Eric W. Biederman
2018-07-24 3:24 ` [PATCH 15/20] signal: Push pid type down into complete_signal Eric W. Biederman
2018-07-24 3:24 ` [PATCH 16/20] fork: Move and describe why the code examines PIDNS_ADDING Eric W. Biederman
2018-07-24 3:24 ` [PATCH 17/20] fork: Unconditionally exit if a fatal signal is pending Eric W. Biederman
2018-07-24 3:24 ` [PATCH 18/20] signal: Add calculate_sigpending() Eric W. Biederman
2018-07-26 13:20 ` Oleg Nesterov
2018-07-26 15:13 ` Eric W. Biederman
2018-07-26 16:24 ` Oleg Nesterov
2018-07-24 3:24 ` [PATCH 19/20] fork: Have new threads join on-going signal group stops Eric W. Biederman
2018-07-24 3:24 ` [PATCH 20/20] signal: Don't restart fork when signals come in Eric W. Biederman
2018-07-24 17:27 ` Linus Torvalds
2018-07-24 17:58 ` Eric W. Biederman
2018-07-24 18:29 ` Linus Torvalds
2018-07-24 20:05 ` Eric W. Biederman
2018-07-24 20:15 ` Linus Torvalds
2018-07-24 20:40 ` [PATCH v2 " Eric W. Biederman
2018-07-24 20:56 ` Linus Torvalds
2018-07-24 21:24 ` Eric W. Biederman
2018-07-25 3:56 ` [PATCH v3 " Eric W. Biederman
2018-07-26 13:41 ` Oleg Nesterov
2018-07-26 14:42 ` Eric W. Biederman
2018-07-26 15:55 ` Oleg Nesterov
2018-08-09 6:19 ` Eric W. Biederman
2018-07-26 16:21 ` Oleg Nesterov
2018-07-24 17:29 ` [PATCH 00/20] PIDTYPE_TGID removal of fork restarts Linus Torvalds
2018-07-25 16:05 ` Oleg Nesterov
2018-07-25 16:58 ` Eric W. Biederman
2018-08-09 6:53 ` [PATCH v5 0/6] Not restarting for due to signals Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 1/6] fork: Move and describe why the code examines PIDNS_ADDING Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 2/6] fork: Unconditionally exit if a fatal signal is pending Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 3/6] signal: Add calculate_sigpending() Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 4/6] fork: Skip setting TIF_SIGPENDING in ptrace_init_task Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 5/6] fork: Have new threads join on-going signal group stops Eric W. Biederman
2018-08-09 6:56 ` [PATCH v5 6/6] signal: Don't restart fork when signals come in Eric W. Biederman
2018-08-09 17:15 ` Linus Torvalds
2018-08-09 17:42 ` Eric W. Biederman
2018-08-09 18:09 ` [PATCH v6 " Eric W. Biederman
2018-08-09 17:16 ` [PATCH v5 0/6] Not restarting for due to signals Linus Torvalds
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=878t6jkrm0.fsf@xmission.com \
--to=ebiederm@xmission.com \
--cc=akpm@linux-foundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=oleg@redhat.com \
--cc=torvalds@linux-foundation.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
Powered by JetHome