Commit 6cbe5e95 authored by Jonas Bonn's avatar Jonas Bonn
Browse files

openrisc: sanitize use of orig_gpr11



The pt_regs struct had both a 'syscallno' field and an 'orig_gpr11' field
and it wasn't really clear how these were supposed to be used.  This patch
removes the syscallno field altogether and makes orig_gpr11 work more
like other architectures: keep track of syscall number in progress or
hold -1 for non-syscall exceptions.

Signed-off-by: default avatarJonas Bonn <jonas@southpole.se>
parent 2f099a28
Loading
Loading
Loading
Loading
+5 −1
Original line number Diff line number Diff line
@@ -73,9 +73,13 @@ struct pt_regs {
		};
	};
	long  pc;
	/* For restarting system calls:
	 * Set to syscall number for syscall exceptions,
	 * -1 for all other exceptions.
	 */
	long  orig_gpr11;	/* For restarting system calls */
	long  syscallno;	/* Syscall number (used by strace) */
	long dummy;		/* Cheap alignment fix */
	long dummy2;		/* Cheap alignment fix */
};

/* TODO: Rename this to REDZONE because that's what it is */
+2 −5
Original line number Diff line number Diff line
@@ -25,7 +25,7 @@
static inline int
syscall_get_nr(struct task_struct *task, struct pt_regs *regs)
{
	return regs->syscallno ? regs->syscallno : -1;
	return regs->orig_gpr11;
}

static inline void
@@ -50,10 +50,7 @@ static inline void
syscall_set_return_value(struct task_struct *task, struct pt_regs *regs,
			 int error, long val)
{
	if (error)
		regs->gpr[11] = -error;
	else
		regs->gpr[11] = val;
	regs->gpr[11] = (long) error ?: val;
}

static inline void
+8 −8
Original line number Diff line number Diff line
@@ -95,7 +95,6 @@ handler: ;\
	/* r1, EPCR, ESR a already saved */			;\
	l.sw	PT_GPR2(r1),r2					;\
	l.sw    PT_GPR3(r1),r3					;\
	l.sw    PT_ORIG_GPR11(r1),r11				;\
	/* r4 already save */					;\
	l.sw    PT_GPR5(r1),r5					;\
	l.sw    PT_GPR6(r1),r6					;\
@@ -125,7 +124,9 @@ handler: ;\
	/* r30 already save */					;\
/*        l.sw    PT_GPR30(r1),r30*/					;\
	l.sw    PT_GPR31(r1),r31					;\
	l.sw    PT_SYSCALLNO(r1),r0
	/* Store -1 in orig_gpr11 for non-syscall exceptions */	;\
	l.addi	r30,r0,-1					;\
	l.sw	PT_ORIG_GPR11(r1),r30

#define UNHANDLED_EXCEPTION(handler,vector)			\
	.global	handler						;\
@@ -133,7 +134,6 @@ handler: ;\
	/* r1, EPCR, ESR already saved */			;\
	l.sw    PT_GPR2(r1),r2					;\
	l.sw    PT_GPR3(r1),r3					;\
	l.sw    PT_ORIG_GPR11(r1),r11				;\
	l.sw    PT_GPR5(r1),r5					;\
	l.sw    PT_GPR6(r1),r6					;\
	l.sw    PT_GPR7(r1),r7					;\
@@ -162,7 +162,9 @@ handler: ;\
	/* r31 already saved */					;\
	l.sw    PT_GPR30(r1),r30					;\
/*        l.sw    PT_GPR31(r1),r31	*/				;\
	l.sw    PT_SYSCALLNO(r1),r0				;\
	/* Store -1 in orig_gpr11 for non-syscall exceptions */	;\
	l.addi	r30,r0,-1					;\
	l.sw	PT_ORIG_GPR11(r1),r30				;\
	l.addi	r3,r1,0						;\
	/* r4 is exception EA */				;\
	l.addi	r5,r0,vector					;\
@@ -554,6 +556,7 @@ ENTRY(_sys_call_handler)
	l.sw    PT_GPR9(r1),r9
	/* r10 already saved */
	l.sw    PT_GPR11(r1),r11
	/* orig_gpr11 must be set for syscalls */
	l.sw    PT_ORIG_GPR11(r1),r11
	/* r12,r13 already saved */

@@ -567,9 +570,6 @@ ENTRY(_sys_call_handler)
	/* r30 is the only register we clobber in the fast path */
	/* r30 already saved */
/*	l.sw    PT_GPR30(r1),r30 */
	/* This is used by do_signal to determine whether to check for
	 * syscall restart or not */
	l.sw    PT_SYSCALLNO(r1),r11

_syscall_check_trace_enter:
	/* If TIF_SYSCALL_TRACE is set, then we want to do syscall tracing */
@@ -731,7 +731,7 @@ _syscall_trace_enter:
	 * so that we can do the syscall for real and return to the syscall
	 * hot path.
	 */
	l.lwz	r11,PT_SYSCALLNO(r1)
	l.lwz	r11,PT_GPR11(r1)
	l.lwz	r3,PT_GPR3(r1)
	l.lwz	r4,PT_GPR4(r1)
	l.lwz	r5,PT_GPR5(r1)
+2 −2
Original line number Diff line number Diff line
@@ -188,11 +188,11 @@ asmlinkage long do_syscall_trace_enter(struct pt_regs *regs)
		 */
		ret = -1L;

	audit_syscall_entry(audit_arch(), regs->syscallno,
	audit_syscall_entry(audit_arch(), regs->gpr[11],
			    regs->gpr[3], regs->gpr[4],
			    regs->gpr[5], regs->gpr[6]);

	return ret ? : regs->syscallno;
	return ret ? : regs->gpr[11];
}

asmlinkage void do_syscall_trace_leave(struct pt_regs *regs)
+1 −1
Original line number Diff line number Diff line
@@ -305,7 +305,7 @@ void do_signal(struct pt_regs *regs)
	 * below mean that the syscall executed to completion and no
	 * restart is necessary.
	 */
	if (regs->syscallno) {
	if (regs->orig_gpr11) {
		int restart = 0;

		switch (regs->gpr[11]) {
Loading