Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=c63855d04034c96db791a7217954c93aa66d24cb
Commit:     c63855d04034c96db791a7217954c93aa66d24cb
Parent:     c1f766b5519f9b5a51b0e6884ed9e02bce775ea8
Author:     Roland McGrath <[EMAIL PROTECTED]>
AuthorDate: Wed Feb 6 22:39:44 2008 +0100
Committer:  Ingo Molnar <[EMAIL PROTECTED]>
CommitDate: Wed Feb 6 22:39:44 2008 +0100

    x86 ptrace: disallow null cs/ss
    
    In my revamp of the x86 ptrace code for setting register values,
    I accidentally omitted a check that was there in the old code.
    Allowing %cs to be 0 causes a bad crash in recovery from iret failure.
    This patch fixes that regression against 2.6.24, and adds a comment
    that should help prevent this subtlety from being overlooked again.
    
    Signed-off-by: Roland McGrath <[EMAIL PROTECTED]>
    Signed-off-by: Thomas Gleixner <[EMAIL PROTECTED]>
    Signed-off-by: Ingo Molnar <[EMAIL PROTECTED]>
---
 arch/x86/kernel/ptrace.c |   25 +++++++++++++++++++++++--
 1 files changed, 23 insertions(+), 2 deletions(-)

diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 96286df..702c33e 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -103,9 +103,26 @@ static int set_segment_reg(struct task_struct *task,
        if (invalid_selector(value))
                return -EIO;
 
-       if (offset != offsetof(struct user_regs_struct, gs))
+       /*
+        * For %cs and %ss we cannot permit a null selector.
+        * We can permit a bogus selector as long as it has USER_RPL.
+        * Null selectors are fine for other segment registers, but
+        * we will never get back to user mode with invalid %cs or %ss
+        * and will take the trap in iret instead.  Much code relies
+        * on user_mode() to distinguish a user trap frame (which can
+        * safely use invalid selectors) from a kernel trap frame.
+        */
+       switch (offset) {
+       case offsetof(struct user_regs_struct, cs):
+       case offsetof(struct user_regs_struct, ss):
+               if (unlikely(value == 0))
+                       return -EIO;
+
+       default:
                *pt_regs_access(task_pt_regs(task), offset) = value;
-       else {
+               break;
+
+       case offsetof(struct user_regs_struct, gs):
                task->thread.gs = value;
                if (task == current)
                        /*
@@ -227,12 +244,16 @@ static int set_segment_reg(struct task_struct *task,
                 * Can't actually change these in 64-bit mode.
                 */
        case offsetof(struct user_regs_struct,cs):
+               if (unlikely(value == 0))
+                       return -EIO;
 #ifdef CONFIG_IA32_EMULATION
                if (test_tsk_thread_flag(task, TIF_IA32))
                        task_pt_regs(task)->cs = value;
 #endif
                break;
        case offsetof(struct user_regs_struct,ss):
+               if (unlikely(value == 0))
+                       return -EIO;
 #ifdef CONFIG_IA32_EMULATION
                if (test_tsk_thread_flag(task, TIF_IA32))
                        task_pt_regs(task)->ss = value;
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to