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

Commit 2ce413ec authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge branch 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull rseq fixes from Thomas Gleixer:
 "A pile of rseq related fixups:

   - Prevent infinite recursion when delivering SIGSEGV

   - Remove the abort of rseq critical section on fork() as syscalls
     inside rseq critical sections are explicitely forbidden. So no
     point in doing the abort on the child.

   - Align the rseq structure on 32 bytes in the ARM selftest code.

   - Fix file permissions of the test script"

* 'sched-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  rseq: Avoid infinite recursion when delivering SIGSEGV
  rseq/cleanup: Do not abort rseq c.s. in child on fork()
  rseq/selftests/arm: Align 'struct rseq_cs' on 32 bytes
  rseq/selftests: Make run_param_test.sh executable
parents 64dd7655 784e0300
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -544,7 +544,7 @@ static void handle_signal(struct ksignal *ksig, struct pt_regs *regs)
	 * Increment event counter and perform fixup for the pre-signal
	 * Increment event counter and perform fixup for the pre-signal
	 * frame.
	 * frame.
	 */
	 */
	rseq_signal_deliver(regs);
	rseq_signal_deliver(ksig, regs);


	/*
	/*
	 * Set up the stack frame
	 * Set up the stack frame
@@ -666,7 +666,7 @@ do_work_pending(struct pt_regs *regs, unsigned int thread_flags, int syscall)
			} else {
			} else {
				clear_thread_flag(TIF_NOTIFY_RESUME);
				clear_thread_flag(TIF_NOTIFY_RESUME);
				tracehook_notify_resume(regs);
				tracehook_notify_resume(regs);
				rseq_handle_notify_resume(regs);
				rseq_handle_notify_resume(NULL, regs);
			}
			}
		}
		}
		local_irq_disable();
		local_irq_disable();
+2 −2
Original line number Original line Diff line number Diff line
@@ -134,7 +134,7 @@ static void do_signal(struct task_struct *tsk)
	/* Re-enable the breakpoints for the signal stack */
	/* Re-enable the breakpoints for the signal stack */
	thread_change_pc(tsk, tsk->thread.regs);
	thread_change_pc(tsk, tsk->thread.regs);


	rseq_signal_deliver(tsk->thread.regs);
	rseq_signal_deliver(&ksig, tsk->thread.regs);


	if (is32) {
	if (is32) {
        	if (ksig.ka.sa.sa_flags & SA_SIGINFO)
        	if (ksig.ka.sa.sa_flags & SA_SIGINFO)
@@ -170,7 +170,7 @@ void do_notify_resume(struct pt_regs *regs, unsigned long thread_info_flags)
	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
	if (thread_info_flags & _TIF_NOTIFY_RESUME) {
		clear_thread_flag(TIF_NOTIFY_RESUME);
		clear_thread_flag(TIF_NOTIFY_RESUME);
		tracehook_notify_resume(regs);
		tracehook_notify_resume(regs);
		rseq_handle_notify_resume(regs);
		rseq_handle_notify_resume(NULL, regs);
	}
	}


	user_enter();
	user_enter();
+1 −1
Original line number Original line Diff line number Diff line
@@ -164,7 +164,7 @@ static void exit_to_usermode_loop(struct pt_regs *regs, u32 cached_flags)
		if (cached_flags & _TIF_NOTIFY_RESUME) {
		if (cached_flags & _TIF_NOTIFY_RESUME) {
			clear_thread_flag(TIF_NOTIFY_RESUME);
			clear_thread_flag(TIF_NOTIFY_RESUME);
			tracehook_notify_resume(regs);
			tracehook_notify_resume(regs);
			rseq_handle_notify_resume(regs);
			rseq_handle_notify_resume(NULL, regs);
		}
		}


		if (cached_flags & _TIF_USER_RETURN_NOTIFY)
		if (cached_flags & _TIF_USER_RETURN_NOTIFY)
+1 −1
Original line number Original line Diff line number Diff line
@@ -692,7 +692,7 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
	 * Increment event counter and perform fixup for the pre-signal
	 * Increment event counter and perform fixup for the pre-signal
	 * frame.
	 * frame.
	 */
	 */
	rseq_signal_deliver(regs);
	rseq_signal_deliver(ksig, regs);


	/* Set up the stack frame */
	/* Set up the stack frame */
	if (is_ia32_frame(ksig)) {
	if (is_ia32_frame(ksig)) {
+12 −11
Original line number Original line Diff line number Diff line
@@ -1799,20 +1799,22 @@ static inline void rseq_set_notify_resume(struct task_struct *t)
		set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
		set_tsk_thread_flag(t, TIF_NOTIFY_RESUME);
}
}


void __rseq_handle_notify_resume(struct pt_regs *regs);
void __rseq_handle_notify_resume(struct ksignal *sig, struct pt_regs *regs);


static inline void rseq_handle_notify_resume(struct pt_regs *regs)
static inline void rseq_handle_notify_resume(struct ksignal *ksig,
					     struct pt_regs *regs)
{
{
	if (current->rseq)
	if (current->rseq)
		__rseq_handle_notify_resume(regs);
		__rseq_handle_notify_resume(ksig, regs);
}
}


static inline void rseq_signal_deliver(struct pt_regs *regs)
static inline void rseq_signal_deliver(struct ksignal *ksig,
				       struct pt_regs *regs)
{
{
	preempt_disable();
	preempt_disable();
	__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
	__set_bit(RSEQ_EVENT_SIGNAL_BIT, &current->rseq_event_mask);
	preempt_enable();
	preempt_enable();
	rseq_handle_notify_resume(regs);
	rseq_handle_notify_resume(ksig, regs);
}
}


/* rseq_preempt() requires preemption to be disabled. */
/* rseq_preempt() requires preemption to be disabled. */
@@ -1831,9 +1833,7 @@ static inline void rseq_migrate(struct task_struct *t)


/*
/*
 * If parent process has a registered restartable sequences area, the
 * If parent process has a registered restartable sequences area, the
 * child inherits. Only applies when forking a process, not a thread. In
 * child inherits. Only applies when forking a process, not a thread.
 * case a parent fork() in the middle of a restartable sequence, set the
 * resume notifier to force the child to retry.
 */
 */
static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
{
{
@@ -1847,7 +1847,6 @@ static inline void rseq_fork(struct task_struct *t, unsigned long clone_flags)
		t->rseq_len = current->rseq_len;
		t->rseq_len = current->rseq_len;
		t->rseq_sig = current->rseq_sig;
		t->rseq_sig = current->rseq_sig;
		t->rseq_event_mask = current->rseq_event_mask;
		t->rseq_event_mask = current->rseq_event_mask;
		rseq_preempt(t);
	}
	}
}
}


@@ -1864,10 +1863,12 @@ static inline void rseq_execve(struct task_struct *t)
static inline void rseq_set_notify_resume(struct task_struct *t)
static inline void rseq_set_notify_resume(struct task_struct *t)
{
{
}
}
static inline void rseq_handle_notify_resume(struct pt_regs *regs)
static inline void rseq_handle_notify_resume(struct ksignal *ksig,
					     struct pt_regs *regs)
{
{
}
}
static inline void rseq_signal_deliver(struct pt_regs *regs)
static inline void rseq_signal_deliver(struct ksignal *ksig,
				       struct pt_regs *regs)
{
{
}
}
static inline void rseq_preempt(struct task_struct *t)
static inline void rseq_preempt(struct task_struct *t)
Loading