Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 0b44bf9a authored by Eric W. Biederman's avatar Eric W. Biederman
Browse files

signal: Simplify and fix kdb_send_sig



- Rename from kdb_send_sig_info to kdb_send_sig
  As there is no meaningful siginfo sent

- Use SEND_SIG_PRIV instead of generating a siginfo for a kdb
  signal.  The generated siginfo had a bogus rationale and was
  not correct in the face of pid namespaces.  SEND_SIG_PRIV
  is simpler and actually correct.

- As the code grabs siglock just send the signal with siglock
  held instead of dropping siglock and attempting to grab it again.

- Move the sig_valid test into kdb_kill where it can generate
  a good error message.

Signed-off-by: default avatarEric W. Biederman <ebiederm@xmission.com>
parent 30a7acd5
Loading
Loading
Loading
Loading
+2 −8
Original line number Original line Diff line number Diff line
@@ -2441,7 +2441,6 @@ static int kdb_kill(int argc, const char **argv)
	long sig, pid;
	long sig, pid;
	char *endp;
	char *endp;
	struct task_struct *p;
	struct task_struct *p;
	struct siginfo info;


	if (argc != 2)
	if (argc != 2)
		return KDB_ARGCOUNT;
		return KDB_ARGCOUNT;
@@ -2449,7 +2448,7 @@ static int kdb_kill(int argc, const char **argv)
	sig = simple_strtol(argv[1], &endp, 0);
	sig = simple_strtol(argv[1], &endp, 0);
	if (*endp)
	if (*endp)
		return KDB_BADINT;
		return KDB_BADINT;
	if (sig >= 0) {
	if ((sig >= 0) || !valid_signal(-sig)) {
		kdb_printf("Invalid signal parameter.<-signal>\n");
		kdb_printf("Invalid signal parameter.<-signal>\n");
		return 0;
		return 0;
	}
	}
@@ -2470,12 +2469,7 @@ static int kdb_kill(int argc, const char **argv)
		return 0;
		return 0;
	}
	}
	p = p->group_leader;
	p = p->group_leader;
	info.si_signo = sig;
	kdb_send_sig(p, sig);
	info.si_errno = 0;
	info.si_code = SI_USER;
	info.si_pid = pid;  /* same capabilities as process being signalled */
	info.si_uid = 0;    /* kdb has root authority */
	kdb_send_sig_info(p, &info);
	return 0;
	return 0;
}
}


+1 −1
Original line number Original line Diff line number Diff line
@@ -208,7 +208,7 @@ extern unsigned long kdb_task_state(const struct task_struct *p,
extern void kdb_ps_suppressed(void);
extern void kdb_ps_suppressed(void);
extern void kdb_ps1(const struct task_struct *p);
extern void kdb_ps1(const struct task_struct *p);
extern void kdb_print_nameval(const char *name, unsigned long val);
extern void kdb_print_nameval(const char *name, unsigned long val);
extern void kdb_send_sig_info(struct task_struct *p, struct siginfo *info);
extern void kdb_send_sig(struct task_struct *p, int sig);
extern void kdb_meminfo_proc_show(void);
extern void kdb_meminfo_proc_show(void);
extern char *kdb_getstr(char *, size_t, const char *);
extern char *kdb_getstr(char *, size_t, const char *);
extern void kdb_gdb_state_pass(char *buf);
extern void kdb_gdb_state_pass(char *buf);
+7 −7
Original line number Original line Diff line number Diff line
@@ -3684,26 +3684,25 @@ void __init signals_init(void)
#ifdef CONFIG_KGDB_KDB
#ifdef CONFIG_KGDB_KDB
#include <linux/kdb.h>
#include <linux/kdb.h>
/*
/*
 * kdb_send_sig_info - Allows kdb to send signals without exposing
 * kdb_send_sig - Allows kdb to send signals without exposing
 * signal internals.  This function checks if the required locks are
 * signal internals.  This function checks if the required locks are
 * available before calling the main signal code, to avoid kdb
 * available before calling the main signal code, to avoid kdb
 * deadlocks.
 * deadlocks.
 */
 */
void
void kdb_send_sig(struct task_struct *t, int sig)
kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
{
{
	static struct task_struct *kdb_prev_t;
	static struct task_struct *kdb_prev_t;
	int sig, new_t;
	int new_t, ret;
	if (!spin_trylock(&t->sighand->siglock)) {
	if (!spin_trylock(&t->sighand->siglock)) {
		kdb_printf("Can't do kill command now.\n"
		kdb_printf("Can't do kill command now.\n"
			   "The sigmask lock is held somewhere else in "
			   "The sigmask lock is held somewhere else in "
			   "kernel, try again later\n");
			   "kernel, try again later\n");
		return;
		return;
	}
	}
	spin_unlock(&t->sighand->siglock);
	new_t = kdb_prev_t != t;
	new_t = kdb_prev_t != t;
	kdb_prev_t = t;
	kdb_prev_t = t;
	if (t->state != TASK_RUNNING && new_t) {
	if (t->state != TASK_RUNNING && new_t) {
		spin_unlock(&t->sighand->siglock);
		kdb_printf("Process is not RUNNING, sending a signal from "
		kdb_printf("Process is not RUNNING, sending a signal from "
			   "kdb risks deadlock\n"
			   "kdb risks deadlock\n"
			   "on the run queue locks. "
			   "on the run queue locks. "
@@ -3712,8 +3711,9 @@ kdb_send_sig_info(struct task_struct *t, struct siginfo *info)
			   "the deadlock.\n");
			   "the deadlock.\n");
		return;
		return;
	}
	}
	sig = info->si_signo;
	ret = send_signal(sig, SEND_SIG_PRIV, t, false);
	if (send_sig_info(sig, info, t))
	spin_unlock(&t->sighand->siglock);
	if (ret)
		kdb_printf("Fail to deliver Signal %d to process %d.\n",
		kdb_printf("Fail to deliver Signal %d to process %d.\n",
			   sig, t->pid);
			   sig, t->pid);
	else
	else