ppc32: Fix racy access to TI_FLAGS
PATCH 1/1 ppc32: Fix racy access to TI_FLAGS
Hi !
The ppc32 syscall entry code could access the thread info flags in a racy way, thus potentially losing bits sets there at interrupt time or by another CPU, like NEED_RESCHED or SIGPENDING (ouch !).
This fixes it by moving the potentially racy bit to a different field (I preferred that rather than turning the access into an atomic operation for performances reasons).
Please apply,
Ben.
arch/ppc/kernel/entry.S +5 -4
@@ -171,9 +171,10 @@ bl do_show_syscall #endif /* SHOW_SYSCALLS */ rlwinm r10,r1,0,0,18 /* current_thread_info() */ + lwz r11,TI_LOCAL_FLAGS(r10) + rlwinm r11,r11,0,~_TIFL_FORCE_NOERROR + stw r11,TI_LOCAL_FLAGS(r10) lwz r11,TI_FLAGS(r10) - rlwinm r11,r11,0,~_TIF_FORCE_NOERROR - stw r11,TI_FLAGS(r10) andi. r11,r11,_TIF_SYSCALL_TRACE bne- syscall_dotrace syscall_dotrace_cont:
@@ -196,8 +197,8 @@ cmpl 0,r3,r11 rlwinm r12,r1,0,0,18 /* current_thread_info() */ blt+ 30f - lwz r11,TI_FLAGS(r12) - andi. r11,r11,_TIF_FORCE_NOERROR + lwz r11,TI_LOCAL_FLAGS(r12) + andi. r11,r11,_TIFL_FORCE_NOERROR bne 30f neg r3,r3 lwz r10,_CCR(r1) /* Set SO bit in CR */
include/asm-ppc/ptrace.h +4 -1
@@ -49,7 +49,10 @@#define instruction_pointer (regs) ((regs)->nip)#define user_mode (regs) (((regs)->msr & MSR_PR) != 0) -#define force_successful_syscall_return () set_thread_flag(TIF_FORCE_NOERROR) +#define force_successful_syscall_return () \ + do { \ + current_thread_info()->local_flags |= _TIFL_FORCE_NOERROR; \ + } while(0)/* * We use the least-significant bit of the trap field to indicate
include/asm-ppc/thread_info.h +15 -6
@@ -18,6 +18,7 @@struct task_struct *task;/* main task structure */ struct exec_domain *exec_domain;/* execution domain */ unsigned long flags;/* low level flags */ +unsigned long local_flags;/* non-racy flags */ int cpu;/* cpu we're on */ int preempt_count;struct restart_block restart_block;
@@ -28,6 +29,7 @@ .task = &tsk, \ .exec_domain = &default_exec_domain, \ .flags = 0, \ + .local_flags = 0, \ .cpu = 0, \ .preempt_count = 1, \ .restart_block = { \
@@ -69,8 +71,9 @@#define TI_TASK 0#define TI_EXECDOMAIN 4#define TI_FLAGS 8 -#define TI_CPU 12 -#define TI_PREEMPT 16 +#define TI_LOCAL_FLAGS 12 +#define TI_CPU 16 +#define TI_PREEMPT 20#define PREEMPT_ACTIVE 0x4000000
@@ -83,16 +86,22 @@#define TIF_NEED_RESCHED 3/* rescheduling necessary */ #define TIF_POLLING_NRFLAG 4/* true if poll_idle() is polling TIF_NEED_RESCHED */ -#define TIF_FORCE_NOERROR 5/* don't return error from current -syscall even if result < 0 */ -/* as above, but as bit values */ #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)#define _TIF_SIGPENDING (1<<TIF_SIGPENDING)#define _TIF_NEED_RESCHED (1<<TIF_NEED_RESCHED)#define _TIF_POLLING_NRFLAG (1<<TIF_POLLING_NRFLAG) -#define _TIF_FORCE_NOERROR (1<<TIF_FORCE_NOERROR) + +/* +* Non racy (local) flags bit numbers +*/ +#define TIFL_FORCE_NOERROR 0/* don't return error from current +syscall even if result < 0 */ + +/* as above, but as bit values */ +#define _TIFL_FORCE_NOERROR (1<<TIFL_FORCE_NOERROR) +#endif /* __KERNEL__ */