diff options
Diffstat (limited to 'arch/x86/kernel/ptrace.c')
-rw-r--r-- | arch/x86/kernel/ptrace.c | 31 |
1 files changed, 30 insertions, 1 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c index d862e396b099..d5904eef1d31 100644 --- a/arch/x86/kernel/ptrace.c +++ b/arch/x86/kernel/ptrace.c | |||
@@ -323,6 +323,16 @@ static int putreg(struct task_struct *child, | |||
323 | return set_flags(child, value); | 323 | return set_flags(child, value); |
324 | 324 | ||
325 | #ifdef CONFIG_X86_64 | 325 | #ifdef CONFIG_X86_64 |
326 | /* | ||
327 | * Orig_ax is really just a flag with small positive and | ||
328 | * negative values, so make sure to always sign-extend it | ||
329 | * from 32 bits so that it works correctly regardless of | ||
330 | * whether we come from a 32-bit environment or not. | ||
331 | */ | ||
332 | case offsetof(struct user_regs_struct, orig_ax): | ||
333 | value = (long) (s32) value; | ||
334 | break; | ||
335 | |||
326 | case offsetof(struct user_regs_struct,fs_base): | 336 | case offsetof(struct user_regs_struct,fs_base): |
327 | if (value >= TASK_SIZE_OF(child)) | 337 | if (value >= TASK_SIZE_OF(child)) |
328 | return -EIO; | 338 | return -EIO; |
@@ -544,6 +554,8 @@ static int ptrace_set_debugreg(struct task_struct *child, | |||
544 | return 0; | 554 | return 0; |
545 | } | 555 | } |
546 | 556 | ||
557 | #ifdef X86_BTS | ||
558 | |||
547 | static int ptrace_bts_get_size(struct task_struct *child) | 559 | static int ptrace_bts_get_size(struct task_struct *child) |
548 | { | 560 | { |
549 | if (!child->thread.ds_area_msr) | 561 | if (!child->thread.ds_area_msr) |
@@ -826,6 +838,7 @@ void ptrace_bts_take_timestamp(struct task_struct *tsk, | |||
826 | 838 | ||
827 | ptrace_bts_write_record(tsk, &rec); | 839 | ptrace_bts_write_record(tsk, &rec); |
828 | } | 840 | } |
841 | #endif /* X86_BTS */ | ||
829 | 842 | ||
830 | /* | 843 | /* |
831 | * Called by kernel/ptrace.c when detaching.. | 844 | * Called by kernel/ptrace.c when detaching.. |
@@ -839,7 +852,9 @@ void ptrace_disable(struct task_struct *child) | |||
839 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); | 852 | clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); |
840 | #endif | 853 | #endif |
841 | if (child->thread.ds_area_msr) { | 854 | if (child->thread.ds_area_msr) { |
855 | #ifdef X86_BTS | ||
842 | ptrace_bts_realloc(child, 0, 0); | 856 | ptrace_bts_realloc(child, 0, 0); |
857 | #endif | ||
843 | child->thread.debugctlmsr &= ~ds_debugctl_mask(); | 858 | child->thread.debugctlmsr &= ~ds_debugctl_mask(); |
844 | if (!child->thread.debugctlmsr) | 859 | if (!child->thread.debugctlmsr) |
845 | clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); | 860 | clear_tsk_thread_flag(child, TIF_DEBUGCTLMSR); |
@@ -961,6 +976,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
961 | break; | 976 | break; |
962 | #endif | 977 | #endif |
963 | 978 | ||
979 | /* | ||
980 | * These bits need more cooking - not enabled yet: | ||
981 | */ | ||
982 | #ifdef X86_BTS | ||
964 | case PTRACE_BTS_CONFIG: | 983 | case PTRACE_BTS_CONFIG: |
965 | ret = ptrace_bts_config | 984 | ret = ptrace_bts_config |
966 | (child, data, (struct ptrace_bts_config __user *)addr); | 985 | (child, data, (struct ptrace_bts_config __user *)addr); |
@@ -988,6 +1007,7 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
988 | ret = ptrace_bts_drain | 1007 | ret = ptrace_bts_drain |
989 | (child, data, (struct bts_struct __user *) addr); | 1008 | (child, data, (struct bts_struct __user *) addr); |
990 | break; | 1009 | break; |
1010 | #endif | ||
991 | 1011 | ||
992 | default: | 1012 | default: |
993 | ret = ptrace_request(child, request, addr, data); | 1013 | ret = ptrace_request(child, request, addr, data); |
@@ -1035,10 +1055,17 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 value) | |||
1035 | R32(esi, si); | 1055 | R32(esi, si); |
1036 | R32(ebp, bp); | 1056 | R32(ebp, bp); |
1037 | R32(eax, ax); | 1057 | R32(eax, ax); |
1038 | R32(orig_eax, orig_ax); | ||
1039 | R32(eip, ip); | 1058 | R32(eip, ip); |
1040 | R32(esp, sp); | 1059 | R32(esp, sp); |
1041 | 1060 | ||
1061 | case offsetof(struct user32, regs.orig_eax): | ||
1062 | /* | ||
1063 | * Sign-extend the value so that orig_eax = -1 | ||
1064 | * causes (long)orig_ax < 0 tests to fire correctly. | ||
1065 | */ | ||
1066 | regs->orig_ax = (long) (s32) value; | ||
1067 | break; | ||
1068 | |||
1042 | case offsetof(struct user32, regs.eflags): | 1069 | case offsetof(struct user32, regs.eflags): |
1043 | return set_flags(child, value); | 1070 | return set_flags(child, value); |
1044 | 1071 | ||
@@ -1226,12 +1253,14 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data) | |||
1226 | case PTRACE_SETOPTIONS: | 1253 | case PTRACE_SETOPTIONS: |
1227 | case PTRACE_SET_THREAD_AREA: | 1254 | case PTRACE_SET_THREAD_AREA: |
1228 | case PTRACE_GET_THREAD_AREA: | 1255 | case PTRACE_GET_THREAD_AREA: |
1256 | #ifdef X86_BTS | ||
1229 | case PTRACE_BTS_CONFIG: | 1257 | case PTRACE_BTS_CONFIG: |
1230 | case PTRACE_BTS_STATUS: | 1258 | case PTRACE_BTS_STATUS: |
1231 | case PTRACE_BTS_SIZE: | 1259 | case PTRACE_BTS_SIZE: |
1232 | case PTRACE_BTS_GET: | 1260 | case PTRACE_BTS_GET: |
1233 | case PTRACE_BTS_CLEAR: | 1261 | case PTRACE_BTS_CLEAR: |
1234 | case PTRACE_BTS_DRAIN: | 1262 | case PTRACE_BTS_DRAIN: |
1263 | #endif | ||
1235 | return sys_ptrace(request, pid, addr, data); | 1264 | return sys_ptrace(request, pid, addr, data); |
1236 | 1265 | ||
1237 | default: | 1266 | default: |