int copy_user(struct task_struct *task,saddr_t useraddr, addr_t copyaddr, int len, int tofromuser, int writingtouser) { int copylen=0,copymax; addr_t realuseraddr; saddr_t enduseraddr; unsigned long mask; #ifdef CONFIG_S390_SUPPORT if (current->thread.flags & S390_FLAG_31BIT) { /* adjust user offsets to 64 bit structure */ if (useraddr < PT_PSWADDR / 2) useraddr = 2 * useraddr; else if(useraddr < PT_ACR0 / 2) useraddr = 2 * useraddr + sizeof(addr_t) / 2; else if(useraddr < PT_ACR0 / 2 + (PT_ORIGGPR2 - PT_ACR0)) useraddr = useraddr + PT_ACR0 / 2; else if(useraddr < PT_ACR0 / 2 + (sizeof(struct user_regs_struct) - sizeof(addr_t) / 2 - PT_ACR0)) useraddr = useraddr + PT_ACR0 / 2 + sizeof(addr_t) / 2; } #endif enduseraddr=useraddr+len; if (useraddr < 0 || enduseraddr > sizeof(struct user)|| (useraddr < PT_ENDREGS && (useraddr&3))|| (enduseraddr < PT_ENDREGS && (enduseraddr&3))) return (-EIO); while(len>0) { mask=PSW_ADDR_MASK; if(useraddr<PT_FPC) { realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr; if(useraddr<PT_PSWMASK) { copymax=PT_PSWMASK; } else if(useraddr<(PT_PSWMASK+8)) { copymax=(PT_PSWMASK+8); if(writingtouser) mask=PSW_MASK_DEBUGCHANGE; } else if(useraddr<(PT_PSWADDR+8)) { copymax=PT_PSWADDR+8; mask=PSW_ADDR_DEBUGCHANGE; } else copymax=PT_FPC; } else if(useraddr<(PT_FPR15+sizeof(freg_t))) { copymax=(PT_FPR15+sizeof(freg_t)); realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]); } else if(useraddr<sizeof(struct user_regs_struct)) { copymax=sizeof(struct user_regs_struct); realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]); } else { copymax=sizeof(struct user); realuseraddr=(addr_t)NULL; } copylen=copymax-useraddr; copylen=(copylen>len ? len:copylen); if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask)) return (-EIO); copyaddr+=copylen; len-=copylen; useraddr+=copylen; } FixPerRegisters(task); return(0); }
int copy_user(struct task_struct *task,saddr_t useraddr,addr_t copyaddr,int len,int tofromuser,int writingtouser) { int copylen=0,copymax; addr_t realuseraddr; saddr_t enduseraddr=useraddr+len; u32 mask; if (useraddr < 0 || enduseraddr > sizeof(struct user)|| (useraddr < PT_ENDREGS && (useraddr&3))|| (enduseraddr < PT_ENDREGS && (enduseraddr&3))) return (-EIO); while(len>0) { mask=0xffffffff; if(useraddr<PT_FPC) { realuseraddr=((addr_t) __KSTK_PTREGS(task)) + useraddr; if(useraddr<PT_PSWMASK) { copymax=PT_PSWMASK; } else if(useraddr<(PT_PSWMASK+4)) { copymax=(PT_PSWMASK+4); if(writingtouser) mask=PSW_MASK_DEBUGCHANGE; } else if(useraddr<(PT_PSWADDR+4)) { copymax=PT_PSWADDR+4; mask=PSW_ADDR_DEBUGCHANGE; } else copymax=PT_FPC; } else if(useraddr<(PT_FPR15_LO+4)) { copymax=(PT_FPR15_LO+4); realuseraddr=(addr_t)&(((u8 *)&task->thread.fp_regs)[useraddr-PT_FPC]); } else if(useraddr<sizeof(struct user_regs_struct)) { copymax=sizeof(struct user_regs_struct); realuseraddr=(addr_t)&(((u8 *)&task->thread.per_info)[useraddr-PT_CR_9]); } else { copymax=sizeof(struct user); realuseraddr=(addr_t)NULL; } copylen=copymax-useraddr; copylen=(copylen>len ? len:copylen); if(ptrace_usercopy(realuseraddr,copyaddr,copylen,tofromuser,writingtouser,mask)) return (-EIO); copyaddr+=copylen; len-=copylen; useraddr+=copylen; } FixPerRegisters(task); return(0); }