Skip to content

Commit 287c55e

Browse files
committed
Merge branch 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace
Pull kernel thread signal handling fix from Eric Biederman: "I overlooked the fact that kernel threads are created with all signals set to SIG_IGN, and accidentally caused a regression in cifs and drbd when replacing force_sig with send_sig. This is my fix for that regression. I add a new function allow_kernel_signal which allows kernel threads to receive signals sent from the kernel, but continues to ignore all signals sent from userspace. This ensures the user space interface for cifs and drbd remain the same. These kernel threads depend on blocking networking calls which block until something is received or a signal is pending. Making receiving of signals somewhat necessary for these kernel threads. Perhaps someday we can cleanup those interfaces and remove allow_kernel_signal. If not allow_kernel_signal is pretty trivial and clearly documents what is going on so I don't think we will mind carrying it" * 'siginfo-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/ebiederm/user-namespace: signal: Allow cifs and drbd to receive their terminating signals
2 parents 0682150 + 33da8e7 commit 287c55e

File tree

4 files changed

+22
-2
lines changed

4 files changed

+22
-2
lines changed

drivers/block/drbd/drbd_main.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,8 @@ static int drbd_thread_setup(void *arg)
322322
thi->name[0],
323323
resource->name);
324324

325+
allow_kernel_signal(DRBD_SIGKILL);
326+
allow_kernel_signal(SIGXCPU);
325327
restart:
326328
retval = thi->function(thi);
327329

fs/cifs/connect.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1113,7 +1113,7 @@ cifs_demultiplex_thread(void *p)
11131113
mempool_resize(cifs_req_poolp, length + cifs_min_rcv);
11141114

11151115
set_freezable();
1116-
allow_signal(SIGKILL);
1116+
allow_kernel_signal(SIGKILL);
11171117
while (server->tcpStatus != CifsExiting) {
11181118
if (try_to_freeze())
11191119
continue;

include/linux/signal.h

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,27 @@ extern void signal_setup_done(int failed, struct ksignal *ksig, int stepping);
282282
extern void exit_signals(struct task_struct *tsk);
283283
extern void kernel_sigaction(int, __sighandler_t);
284284

285+
#define SIG_KTHREAD ((__force __sighandler_t)2)
286+
#define SIG_KTHREAD_KERNEL ((__force __sighandler_t)3)
287+
285288
static inline void allow_signal(int sig)
286289
{
287290
/*
288291
* Kernel threads handle their own signals. Let the signal code
289292
* know it'll be handled, so that they don't get converted to
290293
* SIGKILL or just silently dropped.
291294
*/
292-
kernel_sigaction(sig, (__force __sighandler_t)2);
295+
kernel_sigaction(sig, SIG_KTHREAD);
296+
}
297+
298+
static inline void allow_kernel_signal(int sig)
299+
{
300+
/*
301+
* Kernel threads handle their own signals. Let the signal code
302+
* know signals sent by the kernel will be handled, so that they
303+
* don't get silently dropped.
304+
*/
305+
kernel_sigaction(sig, SIG_KTHREAD_KERNEL);
293306
}
294307

295308
static inline void disallow_signal(int sig)

kernel/signal.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,11 @@ static bool sig_task_ignored(struct task_struct *t, int sig, bool force)
9090
handler == SIG_DFL && !(force && sig_kernel_only(sig)))
9191
return true;
9292

93+
/* Only allow kernel generated signals to this kthread */
94+
if (unlikely((t->flags & PF_KTHREAD) &&
95+
(handler == SIG_KTHREAD_KERNEL) && !force))
96+
return true;
97+
9398
return sig_handler_ignored(handler, sig);
9499
}
95100

0 commit comments

Comments
 (0)