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

Commit 8209f53d authored by Linus Torvalds's avatar Linus Torvalds
Browse files
* 'ptrace' of git://git.kernel.org/pub/scm/linux/kernel/git/oleg/misc: (39 commits)
  ptrace: do_wait(traced_leader_killed_by_mt_exec) can block forever
  ptrace: fix ptrace_signal() && STOP_DEQUEUED interaction
  connector: add an event for monitoring process tracers
  ptrace: dont send SIGSTOP on auto-attach if PT_SEIZED
  ptrace: mv send-SIGSTOP from do_fork() to ptrace_init_task()
  ptrace_init_task: initialize child->jobctl explicitly
  has_stopped_jobs: s/task_is_stopped/SIGNAL_STOP_STOPPED/
  ptrace: make former thread ID available via PTRACE_GETEVENTMSG after PTRACE_EVENT_EXEC stop
  ptrace: wait_consider_task: s/same_thread_group/ptrace_reparented/
  ptrace: kill real_parent_is_ptracer() in in favor of ptrace_reparented()
  ptrace: ptrace_reparented() should check same_thread_group()
  redefine thread_group_leader() as exit_signal >= 0
  do not change dead_task->exit_signal
  kill task_detached()
  reparent_leader: check EXIT_DEAD instead of task_detached()
  make do_notify_parent() __must_check, update the callers
  __ptrace_detach: avoid task_detached(), check do_notify_parent()
  kill tracehook_notify_death()
  make do_notify_parent() return bool
  ptrace: s/tracehook_tracer_task()/ptrace_parent()/
  ...
parents 22a3b977 eac1b5e5
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -331,7 +331,7 @@ void __kprobes do_per_trap(struct pt_regs *regs)
{
{
	if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
	if (notify_die(DIE_SSTEP, "sstep", regs, 0, 0, SIGTRAP) == NOTIFY_STOP)
		return;
		return;
	if (tracehook_consider_fatal_signal(current, SIGTRAP))
	if (current->ptrace)
		force_sig(SIGTRAP, current);
		force_sig(SIGTRAP, current);
}
}


@@ -425,7 +425,7 @@ static void __kprobes illegal_op(struct pt_regs *regs, long pgm_int_code,
		if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
		if (get_user(*((__u16 *) opcode), (__u16 __user *) location))
			return;
			return;
		if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
		if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) {
			if (tracehook_consider_fatal_signal(current, SIGTRAP))
			if (current->ptrace)
				force_sig(SIGTRAP, current);
				force_sig(SIGTRAP, current);
			else
			else
				signal = SIGILL;
				signal = SIGILL;
+35 −0
Original line number Original line Diff line number Diff line
@@ -28,6 +28,7 @@
#include <linux/init.h>
#include <linux/init.h>
#include <linux/connector.h>
#include <linux/connector.h>
#include <linux/gfp.h>
#include <linux/gfp.h>
#include <linux/ptrace.h>
#include <asm/atomic.h>
#include <asm/atomic.h>
#include <asm/unaligned.h>
#include <asm/unaligned.h>


@@ -166,6 +167,40 @@ void proc_sid_connector(struct task_struct *task)
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}
}


void proc_ptrace_connector(struct task_struct *task, int ptrace_id)
{
	struct cn_msg *msg;
	struct proc_event *ev;
	struct timespec ts;
	__u8 buffer[CN_PROC_MSG_SIZE];
	struct task_struct *tracer;

	if (atomic_read(&proc_event_num_listeners) < 1)
		return;

	msg = (struct cn_msg *)buffer;
	ev = (struct proc_event *)msg->data;
	get_seq(&msg->seq, &ev->cpu);
	ktime_get_ts(&ts); /* get high res monotonic timestamp */
	put_unaligned(timespec_to_ns(&ts), (__u64 *)&ev->timestamp_ns);
	ev->what = PROC_EVENT_PTRACE;
	ev->event_data.ptrace.process_pid  = task->pid;
	ev->event_data.ptrace.process_tgid = task->tgid;
	if (ptrace_id == PTRACE_ATTACH) {
		ev->event_data.ptrace.tracer_pid  = current->pid;
		ev->event_data.ptrace.tracer_tgid = current->tgid;
	} else if (ptrace_id == PTRACE_DETACH) {
		ev->event_data.ptrace.tracer_pid  = 0;
		ev->event_data.ptrace.tracer_tgid = 0;
	} else
		return;

	memcpy(&msg->id, &cn_proc_event_id, sizeof(msg->id));
	msg->ack = 0; /* not used */
	msg->len = sizeof(*ev);
	cn_netlink_send(msg, CN_IDX_PROC, GFP_KERNEL);
}

void proc_exit_connector(struct task_struct *task)
void proc_exit_connector(struct task_struct *task)
{
{
	struct cn_msg *msg;
	struct cn_msg *msg;
+24 −3
Original line number Original line Diff line number Diff line
@@ -963,9 +963,18 @@ static int de_thread(struct task_struct *tsk)
		leader->group_leader = tsk;
		leader->group_leader = tsk;


		tsk->exit_signal = SIGCHLD;
		tsk->exit_signal = SIGCHLD;
		leader->exit_signal = -1;


		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
		BUG_ON(leader->exit_state != EXIT_ZOMBIE);
		leader->exit_state = EXIT_DEAD;
		leader->exit_state = EXIT_DEAD;

		/*
		 * We are going to release_task()->ptrace_unlink() silently,
		 * the tracer can sleep in do_wait(). EXIT_DEAD guarantees
		 * the tracer wont't block again waiting for this thread.
		 */
		if (unlikely(leader->ptrace))
			__wake_up_parent(leader, leader->parent);
		write_unlock_irq(&tasklist_lock);
		write_unlock_irq(&tasklist_lock);


		release_task(leader);
		release_task(leader);
@@ -1225,7 +1234,12 @@ int check_unsafe_exec(struct linux_binprm *bprm)
	unsigned n_fs;
	unsigned n_fs;
	int res = 0;
	int res = 0;


	bprm->unsafe = tracehook_unsafe_exec(p);
	if (p->ptrace) {
		if (p->ptrace & PT_PTRACE_CAP)
			bprm->unsafe |= LSM_UNSAFE_PTRACE_CAP;
		else
			bprm->unsafe |= LSM_UNSAFE_PTRACE;
	}


	n_fs = 1;
	n_fs = 1;
	spin_lock(&p->fs->lock);
	spin_lock(&p->fs->lock);
@@ -1353,6 +1367,7 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
	unsigned int depth = bprm->recursion_depth;
	unsigned int depth = bprm->recursion_depth;
	int try,retval;
	int try,retval;
	struct linux_binfmt *fmt;
	struct linux_binfmt *fmt;
	pid_t old_pid;


	retval = security_bprm_check(bprm);
	retval = security_bprm_check(bprm);
	if (retval)
	if (retval)
@@ -1362,6 +1377,11 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
	if (retval)
	if (retval)
		return retval;
		return retval;


	/* Need to fetch pid before load_binary changes it */
	rcu_read_lock();
	old_pid = task_pid_nr_ns(current, task_active_pid_ns(current->parent));
	rcu_read_unlock();

	retval = -ENOENT;
	retval = -ENOENT;
	for (try=0; try<2; try++) {
	for (try=0; try<2; try++) {
		read_lock(&binfmt_lock);
		read_lock(&binfmt_lock);
@@ -1381,7 +1401,8 @@ int search_binary_handler(struct linux_binprm *bprm,struct pt_regs *regs)
			bprm->recursion_depth = depth;
			bprm->recursion_depth = depth;
			if (retval >= 0) {
			if (retval >= 0) {
				if (depth == 0)
				if (depth == 0)
					tracehook_report_exec(fmt, bprm, regs);
					ptrace_event(PTRACE_EVENT_EXEC,
							old_pid);
				put_binfmt(fmt);
				put_binfmt(fmt);
				allow_write_access(bprm->file);
				allow_write_access(bprm->file);
				if (bprm->file)
				if (bprm->file)
@@ -1769,7 +1790,7 @@ static int zap_process(struct task_struct *start, int exit_code)


	t = start;
	t = start;
	do {
	do {
		task_clear_group_stop_pending(t);
		task_clear_jobctl_pending(t, JOBCTL_PENDING_MASK);
		if (t != current && t->mm) {
		if (t != current && t->mm) {
			sigaddset(&t->pending.signal, SIGKILL);
			sigaddset(&t->pending.signal, SIGKILL);
			signal_wake_up(t, 1);
			signal_wake_up(t, 1);
+1 −1
Original line number Original line Diff line number Diff line
@@ -172,7 +172,7 @@ static inline void task_state(struct seq_file *m, struct pid_namespace *ns,
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
		task_tgid_nr_ns(rcu_dereference(p->real_parent), ns) : 0;
	tpid = 0;
	tpid = 0;
	if (pid_alive(p)) {
	if (pid_alive(p)) {
		struct task_struct *tracer = tracehook_tracer_task(p);
		struct task_struct *tracer = ptrace_parent(p);
		if (tracer)
		if (tracer)
			tpid = task_pid_nr_ns(tracer, ns);
			tpid = task_pid_nr_ns(tracer, ns);
	}
	}
+1 −1
Original line number Original line Diff line number Diff line
@@ -216,7 +216,7 @@ static struct mm_struct *__check_mem_permission(struct task_struct *task)
	if (task_is_stopped_or_traced(task)) {
	if (task_is_stopped_or_traced(task)) {
		int match;
		int match;
		rcu_read_lock();
		rcu_read_lock();
		match = (tracehook_tracer_task(task) == current);
		match = (ptrace_parent(task) == current);
		rcu_read_unlock();
		rcu_read_unlock();
		if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
		if (match && ptrace_may_access(task, PTRACE_MODE_ATTACH))
			return mm;
			return mm;
Loading