]> git.hungrycats.org Git - linux/commitdiff
[PATCH] ppc32: Fix racy access to TI_FLAGS
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>
Thu, 25 Mar 2004 13:59:54 +0000 (05:59 -0800)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Thu, 25 Mar 2004 13:59:54 +0000 (05:59 -0800)
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).

arch/ppc/kernel/entry.S
include/asm-ppc/ptrace.h
include/asm-ppc/thread_info.h

index f4cba07bc75c04064b6b9d2fe671f163f8db1366..d05ff48582bf1d6c437c7761f6056b2e2cb41937 100644 (file)
@@ -171,9 +171,10 @@ _GLOBAL(DoSyscall)
        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 @@ ret_from_syscall:
        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 */
index a157e6ce6b67cafd99ff4e123daf5600ca2346f7..f13233eacb94effc30a53647123fd6da29fd4552 100644 (file)
@@ -49,7 +49,10 @@ struct pt_regs {
 #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
index 440394a197c68311f2aca557d4bfbf60ed89f13c..62aeec9804ea1e1581ec7b69685423dded541e16 100644 (file)
@@ -18,6 +18,7 @@ struct thread_info {
        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 @@ struct thread_info {
        .task =         &tsk,                   \
        .exec_domain =  &default_exec_domain,   \
        .flags =        0,                      \
+       .local_flags =  0,                      \
        .cpu =          0,                      \
        .preempt_count = 1,                     \
        .restart_block = {                      \
@@ -69,8 +71,9 @@ static inline struct thread_info *current_thread_info(void)
 #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 @@ static inline struct thread_info *current_thread_info(void)
 #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__ */