aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/ptrace.c236
1 files changed, 77 insertions, 159 deletions
diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 196cc27bd39a..f8b89059e6ed 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -750,9 +750,13 @@ void ptrace_disable(struct task_struct *child)
750 } 750 }
751} 751}
752 752
753#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
754static const struct user_regset_view user_x86_32_view; /* Initialized below. */
755#endif
756
753long arch_ptrace(struct task_struct *child, long request, long addr, long data) 757long arch_ptrace(struct task_struct *child, long request, long addr, long data)
754{ 758{
755 int i, ret; 759 int ret;
756 unsigned long __user *datap = (unsigned long __user *)data; 760 unsigned long __user *datap = (unsigned long __user *)data;
757 761
758 switch (request) { 762 switch (request) {
@@ -805,82 +809,46 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
805 } 809 }
806 break; 810 break;
807 811
808 case PTRACE_GETREGS: { /* Get all gp regs from the child. */ 812 case PTRACE_GETREGS: /* Get all gp regs from the child. */
809 if (!access_ok(VERIFY_WRITE, datap, sizeof(struct user_regs_struct))) { 813 return copy_regset_to_user(child,
810 ret = -EIO; 814 task_user_regset_view(current),
811 break; 815 REGSET_GENERAL,
812 } 816 0, sizeof(struct user_regs_struct),
813 for (i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long)) { 817 datap);
814 __put_user(getreg(child, i), datap); 818
815 datap++; 819 case PTRACE_SETREGS: /* Set all gp regs in the child. */
816 } 820 return copy_regset_from_user(child,
817 ret = 0; 821 task_user_regset_view(current),
818 break; 822 REGSET_GENERAL,
819 } 823 0, sizeof(struct user_regs_struct),
820 824 datap);
821 case PTRACE_SETREGS: { /* Set all gp regs in the child. */ 825
822 unsigned long tmp; 826 case PTRACE_GETFPREGS: /* Get the child FPU state. */
823 if (!access_ok(VERIFY_READ, datap, sizeof(struct user_regs_struct))) { 827 return copy_regset_to_user(child,
824 ret = -EIO; 828 task_user_regset_view(current),
825 break; 829 REGSET_FP,
826 } 830 0, sizeof(struct user_i387_struct),
827 for (i = 0; i < sizeof(struct user_regs_struct); i += sizeof(long)) { 831 datap);
828 __get_user(tmp, datap); 832
829 putreg(child, i, tmp); 833 case PTRACE_SETFPREGS: /* Set the child FPU state. */
830 datap++; 834 return copy_regset_from_user(child,
831 } 835 task_user_regset_view(current),
832 ret = 0; 836 REGSET_FP,
833 break; 837 0, sizeof(struct user_i387_struct),
834 } 838 datap);
835
836 case PTRACE_GETFPREGS: { /* Get the child FPU state. */
837 if (!access_ok(VERIFY_WRITE, datap,
838 sizeof(struct user_i387_struct))) {
839 ret = -EIO;
840 break;
841 }
842 ret = 0;
843 if (!tsk_used_math(child))
844 init_fpu(child);
845 get_fpregs((struct user_i387_struct __user *)data, child);
846 break;
847 }
848
849 case PTRACE_SETFPREGS: { /* Set the child FPU state. */
850 if (!access_ok(VERIFY_READ, datap,
851 sizeof(struct user_i387_struct))) {
852 ret = -EIO;
853 break;
854 }
855 set_stopped_child_used_math(child);
856 set_fpregs(child, (struct user_i387_struct __user *)data);
857 ret = 0;
858 break;
859 }
860 839
861#ifdef CONFIG_X86_32 840#ifdef CONFIG_X86_32
862 case PTRACE_GETFPXREGS: { /* Get the child extended FPU state. */ 841 case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
863 if (!access_ok(VERIFY_WRITE, datap, 842 return copy_regset_to_user(child, &user_x86_32_view,
864 sizeof(struct user_fxsr_struct))) { 843 REGSET_XFP,
865 ret = -EIO; 844 0, sizeof(struct user_fxsr_struct),
866 break; 845 datap);
867 } 846
868 if (!tsk_used_math(child)) 847 case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
869 init_fpu(child); 848 return copy_regset_from_user(child, &user_x86_32_view,
870 ret = get_fpxregs((struct user_fxsr_struct __user *)data, child); 849 REGSET_XFP,
871 break; 850 0, sizeof(struct user_fxsr_struct),
872 } 851 datap);
873
874 case PTRACE_SETFPXREGS: { /* Set the child extended FPU state. */
875 if (!access_ok(VERIFY_READ, datap,
876 sizeof(struct user_fxsr_struct))) {
877 ret = -EIO;
878 break;
879 }
880 set_stopped_child_used_math(child);
881 ret = set_fpxregs(child, (struct user_fxsr_struct __user *)data);
882 break;
883 }
884#endif 852#endif
885 853
886#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION 854#if defined CONFIG_X86_32 || defined CONFIG_IA32_EMULATION
@@ -1243,90 +1211,40 @@ asmlinkage long sys32_ptrace(long request, u32 pid, u32 addr, u32 data)
1243 ret = putreg32(child, addr, data); 1211 ret = putreg32(child, addr, data);
1244 break; 1212 break;
1245 1213
1246 case PTRACE_GETREGS: { /* Get all gp regs from the child. */ 1214 case PTRACE_GETREGS: /* Get all gp regs from the child. */
1247 int i; 1215 return copy_regset_to_user(child, &user_x86_32_view,
1248 1216 REGSET_GENERAL,
1249 if (!access_ok(VERIFY_WRITE, datap, 16*4)) { 1217 0, sizeof(struct user_regs_struct32),
1250 ret = -EIO; 1218 datap);
1251 break; 1219
1252 } 1220 case PTRACE_SETREGS: /* Set all gp regs in the child. */
1253 ret = 0; 1221 return copy_regset_from_user(child, &user_x86_32_view,
1254 for (i = 0; i < sizeof(struct user_regs_struct32); i += sizeof(__u32)) { 1222 REGSET_GENERAL, 0,
1255 getreg32(child, i, &val); 1223 sizeof(struct user_regs_struct32),
1256 ret |= __put_user(val, (u32 __user *)datap); 1224 datap);
1257 datap += sizeof(u32); 1225
1258 } 1226 case PTRACE_GETFPREGS: /* Get the child FPU state. */
1259 break; 1227 return copy_regset_to_user(child, &user_x86_32_view,
1260 } 1228 REGSET_FP, 0,
1261 1229 sizeof(struct user_i387_ia32_struct),
1262 case PTRACE_SETREGS: { /* Set all gp regs in the child. */ 1230 datap);
1263 unsigned long tmp; 1231
1264 int i; 1232 case PTRACE_SETFPREGS: /* Set the child FPU state. */
1265 1233 return copy_regset_from_user(
1266 if (!access_ok(VERIFY_READ, datap, 16*4)) { 1234 child, &user_x86_32_view, REGSET_FP,
1267 ret = -EIO; 1235 0, sizeof(struct user_i387_ia32_struct), datap);
1268 break; 1236
1269 } 1237 case PTRACE_GETFPXREGS: /* Get the child extended FPU state. */
1270 ret = 0; 1238 return copy_regset_to_user(child, &user_x86_32_view,
1271 for (i = 0; i < sizeof(struct user_regs_struct32); i += sizeof(u32)) { 1239 REGSET_XFP, 0,
1272 ret |= __get_user(tmp, (u32 __user *)datap); 1240 sizeof(struct user32_fxsr_struct),
1273 putreg32(child, i, tmp); 1241 datap);
1274 datap += sizeof(u32); 1242
1275 } 1243 case PTRACE_SETFPXREGS: /* Set the child extended FPU state. */
1276 break; 1244 return copy_regset_from_user(child, &user_x86_32_view,
1277 } 1245 REGSET_XFP, 0,
1278 1246 sizeof(struct user32_fxsr_struct),
1279 case PTRACE_GETFPREGS: 1247 datap);
1280 ret = -EIO;
1281 if (!access_ok(VERIFY_READ, compat_ptr(data),
1282 sizeof(struct user_i387_struct)))
1283 break;
1284 save_i387_ia32(child, datap, childregs, 1);
1285 ret = 0;
1286 break;
1287
1288 case PTRACE_SETFPREGS:
1289 ret = -EIO;
1290 if (!access_ok(VERIFY_WRITE, datap,
1291 sizeof(struct user_i387_struct)))
1292 break;
1293 ret = 0;
1294 /* don't check EFAULT to be bug-to-bug compatible to i386 */
1295 restore_i387_ia32(child, datap, 1);
1296 break;
1297
1298 case PTRACE_GETFPXREGS: {
1299 struct user32_fxsr_struct __user *u = datap;
1300
1301 init_fpu(child);
1302 ret = -EIO;
1303 if (!access_ok(VERIFY_WRITE, u, sizeof(*u)))
1304 break;
1305 ret = -EFAULT;
1306 if (__copy_to_user(u, &child->thread.i387.fxsave, sizeof(*u)))
1307 break;
1308 ret = __put_user(childregs->cs, &u->fcs);
1309 ret |= __put_user(child->thread.ds, &u->fos);
1310 break;
1311 }
1312 case PTRACE_SETFPXREGS: {
1313 struct user32_fxsr_struct __user *u = datap;
1314
1315 unlazy_fpu(child);
1316 ret = -EIO;
1317 if (!access_ok(VERIFY_READ, u, sizeof(*u)))
1318 break;
1319 /*
1320 * no checking to be bug-to-bug compatible with i386.
1321 * but silence warning
1322 */
1323 if (__copy_from_user(&child->thread.i387.fxsave, u, sizeof(*u)))
1324 ;
1325 set_stopped_child_used_math(child);
1326 child->thread.i387.fxsave.mxcsr &= mxcsr_feature_mask;
1327 ret = 0;
1328 break;
1329 }
1330 1248
1331 case PTRACE_GETEVENTMSG: 1249 case PTRACE_GETEVENTMSG:
1332 ret = put_user(child->ptrace_message, 1250 ret = put_user(child->ptrace_message,