Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 79852
b: refs/heads/master
c: df5d438
h: refs/heads/master
v: v3
  • Loading branch information
Roland McGrath authored and Ingo Molnar committed Jan 30, 2008
1 parent 90b8b2a commit fd40fc3
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 5 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 91394eb0975b3771dde7071a0825c6df6c20ff8a
refs/heads/master: df5d438e33d7fc914ba9b6e0d6b019a8966c5fcc
35 changes: 31 additions & 4 deletions trunk/arch/x86/kernel/ptrace_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include <asm/pgtable.h>
#include <asm/system.h>
#include <asm/processor.h>
#include <asm/prctl.h>
#include <asm/i387.h>
#include <asm/debugreg.h>
#include <asm/ldt.h>
Expand Down Expand Up @@ -260,12 +261,22 @@ static int putreg(struct task_struct *child,
case offsetof(struct user_regs_struct,fs_base):
if (value >= TASK_SIZE_OF(child))
return -EIO;
child->thread.fs = value;
/*
* When changing the segment base, use do_arch_prctl
* to set either thread.fs or thread.fsindex and the
* corresponding GDT slot.
*/
if (child->thread.fs != value)
return do_arch_prctl(child, ARCH_SET_FS, value);
return 0;
case offsetof(struct user_regs_struct,gs_base):
/*
* Exactly the same here as the %fs handling above.
*/
if (value >= TASK_SIZE_OF(child))
return -EIO;
child->thread.gs = value;
if (child->thread.gs != value)
return do_arch_prctl(child, ARCH_SET_GS, value);
return 0;
case offsetof(struct user_regs_struct, eflags):
value &= FLAG_MASK;
Expand Down Expand Up @@ -296,9 +307,25 @@ static unsigned long getreg(struct task_struct *child, unsigned long regno)
case offsetof(struct user_regs_struct, es):
return child->thread.es;
case offsetof(struct user_regs_struct, fs_base):
return child->thread.fs;
/*
* do_arch_prctl may have used a GDT slot instead of
* the MSR. To userland, it appears the same either
* way, except the %fs segment selector might not be 0.
*/
if (child->thread.fs != 0)
return child->thread.fs;
if (child->thread.fsindex != FS_TLS_SEL)
return 0;
return get_desc_base(&child->thread.tls_array[FS_TLS]);
case offsetof(struct user_regs_struct, gs_base):
return child->thread.gs;
/*
* Exactly the same here as the %fs handling above.
*/
if (child->thread.gs != 0)
return child->thread.gs;
if (child->thread.gsindex != GS_TLS_SEL)
return 0;
return get_desc_base(&child->thread.tls_array[GS_TLS]);
default:
regno = regno - sizeof(struct pt_regs);
val = get_stack_long(child, regno);
Expand Down

0 comments on commit fd40fc3

Please sign in to comment.