From: Mathieu Desnoyers Date: Sun, 16 Oct 2016 06:16:25 +0000 (+0200) Subject: Restartable sequences: clear rseq_cs even if non-nested X-Git-Url: http://git.efficios.com/?p=deliverable%2Flinux.git;a=commitdiff_plain;h=88833b353c257ba7b6bcb1bcc5a9f0ae388fa25b Restartable sequences: clear rseq_cs even if non-nested We can speed up the user-space fast path by removing the final "rseq_cs=NULL" assignment at the end of the critical section, since we check for both upper and lower bounds anyway in the fixup code. Take care of setting rseq_cs back to NULL even if we are not nested over an actual rseq critical section. Signed-off-by: Mathieu Desnoyers --- diff --git a/kernel/rseq.c b/kernel/rseq.c index a102fcc9994e..a24da12e6b08 100644 --- a/kernel/rseq.c +++ b/kernel/rseq.c @@ -160,6 +160,17 @@ static bool rseq_get_rseq_cs(struct task_struct *t, urseq_cs = (struct rseq_cs __user *)ptr; if (copy_from_user(&rseq_cs, urseq_cs, sizeof(rseq_cs))) return false; + /* + * We need to clear rseq_cs upon entry into a signal handler + * nested on top of a rseq assembly block, so the signal handler + * will not be fixed up if itself interrupted by a nested signal + * handler or preempted. We also need to clear rseq_cs if we + * preempt or deliver a signal on top of code outside of the + * rseq assembly block, to ensure that a following preemption or + * signal delivery will not try to perform a fixup needlessly. + */ + if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs))) + return false; *start_ip = (void __user *)rseq_cs.start_ip; *post_commit_ip = (void __user *)rseq_cs.post_commit_ip; *abort_ip = (void __user *)rseq_cs.abort_ip; @@ -186,15 +197,6 @@ static bool rseq_ip_fixup(struct pt_regs *regs) (void __user *)instruction_pointer(regs) < start_ip) return true; - /* - * We need to clear rseq_cs upon entry into a signal - * handler nested on top of a rseq assembly block, so - * the signal handler will not be fixed up if itself - * interrupted by a nested signal handler or preempted. - */ - if (clear_user(&t->rseq->rseq_cs, sizeof(t->rseq->rseq_cs))) - return false; - /* * We set this after potentially failing in * clear_user so that the signal arrives at the