7 Bug-Reported-by: Nikolay Borisov <nborisov@suse.com>
8 Bug-Reference-ID: <1a715205-06ce-413b-c1c0-2f5639ce06c0@suse.com>
9 Bug-Reference-URL: https://lists.gnu.org/archive/html/bug-bash/2020-11/msg00091.html
13 There is a possible race condition that arises when a child process receives
14 a signal trapped by the parent before it can reset the signal dispositions.
15 The child process is not supposed to trap the signal in this circumstance.
17 Patch (apply with `patch -p0'):
19 *** ../bash-20201118/command.h 2020-08-14 15:04:39.000000000 -0400
20 --- command.h 2020-11-27 15:18:02.000000000 -0500
24 #define SUBSHELL_COPROC 0x40 /* subshell from a coproc pipeline */
25 #define SUBSHELL_RESETTRAP 0x80 /* subshell needs to reset trap strings on first call to trap */
26 + #define SUBSHELL_IGNTRAP 0x100 /* subshell should reset trapped signals from trap_handler */
28 /* A structure which represents a word. */
30 *** ../bash-20201118/execute_cmd.c 2020-11-23 14:16:48.000000000 -0500
31 --- execute_cmd.c 2020-11-27 16:43:25.000000000 -0500
35 reset_signal_handlers ();
36 subshell_environment |= SUBSHELL_RESETTRAP;
37 + /* Note that signal handlers have been reset, so we should no longer
38 + reset the handler and resend trapped signals to ourselves. */
39 + subshell_environment &= ~SUBSHELL_IGNTRAP;
41 /* We are in a subshell, so forget that we are running a trap handler or
44 cmdflags |= CMD_NO_FORK;
46 ! subshell_environment = SUBSHELL_FORK; /* XXX */
47 if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
48 subshell_environment |= SUBSHELL_PIPE;
50 cmdflags |= CMD_NO_FORK;
52 ! /* We redo some of what make_child() does with SUBSHELL_IGNTRAP */
53 ! subshell_environment = SUBSHELL_FORK|SUBSHELL_IGNTRAP; /* XXX */
54 if (pipe_in != NO_PIPE || pipe_out != NO_PIPE)
55 subshell_environment |= SUBSHELL_PIPE;
59 reset_signal_handlers ();
60 subshell_environment |= SUBSHELL_RESETTRAP;
61 + subshell_environment &= ~SUBSHELL_IGNTRAP;
67 /* Cancel traps, in trap.c. */
68 restore_original_signals ();
69 + subshell_environment &= ~SUBSHELL_IGNTRAP;
71 #if defined (JOB_CONTROL)
73 *** ../bash-20201118/jobs.c 2020-08-04 10:17:39.000000000 -0400
74 --- jobs.c 2020-11-27 16:39:56.000000000 -0500
80 + subshell_environment |= SUBSHELL_IGNTRAP;
82 /* If this ends up being changed to modify or use `command' in the
83 child process, go back and change callers who free `command' in
84 diff -rC 2 ../bash-20201118/nojobs.c nojobs.c
85 *** ../bash-20201118/nojobs.c 2020-07-08 10:11:25.000000000 -0400
86 --- nojobs.c 2020-11-27 16:38:36.000000000 -0500
92 + subshell_environment |= SUBSHELL_IGNTRAP;
94 default_tty_job_signals ();
97 *** ../bash-20201118/sig.c 2020-11-23 13:22:17.000000000 -0500
98 --- sig.c 2020-11-28 10:21:43.000000000 -0500
103 ! extern void initialize_siglist ();
105 #if !defined (JOB_CONTROL)
109 ! extern void initialize_siglist PARAMS((void));
110 ! extern void set_original_signal PARAMS((int, SigHandler *));
112 #if !defined (JOB_CONTROL)
116 XHANDLER(i) = oact.sa_handler;
117 XSAFLAGS(i) = oact.sa_flags;
120 + set_original_signal (XSIG(i), XHANDLER(i)); /* optimization */
122 + set_original_signal (XSIG(i), act.sa_handler); /* optimization */
125 /* Don't do anything with signals that are ignored at shell entry
126 if the shell is not interactive. */
128 *** ../bash-20201118/subst.c 2020-11-16 10:33:15.000000000 -0500
129 --- subst.c 2020-11-27 16:07:00.000000000 -0500
133 /* Cancel traps, in trap.c. */
134 restore_original_signals (); /* XXX - what about special builtins? bash-4.2 */
135 + subshell_environment &= ~SUBSHELL_IGNTRAP;
136 QUIT; /* catch any interrupts we got post-fork */
137 setup_async_signals ();
141 QUIT; /* catch any interrupts we got post-fork */
142 subshell_environment |= SUBSHELL_RESETTRAP;
143 + subshell_environment &= ~SUBSHELL_IGNTRAP;
147 diff -rC 2 ../bash-20201118/trap.c trap.c
148 *** ../bash-20201118/trap.c 2020-11-28 12:04:07.000000000 -0500
149 --- trap.c 2020-11-28 10:22:10.000000000 -0500
155 + /* This means we're in a subshell, but have not yet reset the handler for
156 + trapped signals. We're not supposed to execute the trap in this situation;
157 + we should restore the original signal and resend the signal to ourselves
158 + to preserve the Posix "signal traps that are not being ignored shall be
159 + set to the default action" semantics. */
160 + if ((subshell_environment & SUBSHELL_IGNTRAP) && trap_list[sig] != (char *)IGNORE_SIG)
165 + if (original_signals[sig] == IMPOSSIBLE_TRAP_HANDLER)
166 + original_signals[sig] = SIG_DFL;
168 + restore_signal (sig);
170 + /* Make sure we let the signal we just caught through */
171 + sigemptyset (&mask);
172 + sigprocmask (SIG_SETMASK, (sigset_t *)NULL, &mask);
173 + sigdelset (&mask, sig);
174 + sigprocmask (SIG_SETMASK, &mask, (sigset_t *)NULL);
176 + kill (getpid (), sig);
182 (trap_list[sig] == (char *)DEFAULT_SIG) ||
184 *** ../bash-5.1/patchlevel.h 2020-06-22 14:51:03.000000000 -0400
185 --- patchlevel.h 2020-10-01 11:01:28.000000000 -0400
188 looks for to find the patch level (for the sccs version string). */
190 ! #define PATCHLEVEL 11
192 #endif /* _PATCHLEVEL_H_ */
194 looks for to find the patch level (for the sccs version string). */
196 ! #define PATCHLEVEL 12
198 #endif /* _PATCHLEVEL_H_ */