⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sys_ia32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
			       "ia32.putreg: attempt to set invalid segment register %d = %x\n",			       regno, value);		break;	      case PT_CS:		if (value != __USER_CS)			printk(KERN_ERR			       "ia32.putreg: attempt to to set invalid segment register %d = %x\n",			       regno, value);		break;	      default:		printk(KERN_ERR "ia32.putreg: unknown register %d\n", regno);		break;	}}static voidput_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,	   struct switch_stack *swp, int tos){	struct _fpreg_ia32 *f;	char buf[32];	f = (struct _fpreg_ia32 *)(((unsigned long)buf + 15) & ~15);	if ((regno += tos) >= 8)		regno -= 8;	switch (regno) {	      case 0:		ia64f2ia32f(f, &ptp->f8);		break;	      case 1:		ia64f2ia32f(f, &ptp->f9);		break;	      case 2:		ia64f2ia32f(f, &ptp->f10);		break;	      case 3:		ia64f2ia32f(f, &ptp->f11);		break;	      case 4:	      case 5:	      case 6:	      case 7:		ia64f2ia32f(f, &swp->f12 + (regno - 4));		break;	}	copy_to_user(reg, f, sizeof(*reg));}static voidget_fpreg (int regno, struct _fpreg_ia32 __user *reg, struct pt_regs *ptp,	   struct switch_stack *swp, int tos){	if ((regno += tos) >= 8)		regno -= 8;	switch (regno) {	      case 0:		copy_from_user(&ptp->f8, reg, sizeof(*reg));		break;	      case 1:		copy_from_user(&ptp->f9, reg, sizeof(*reg));		break;	      case 2:		copy_from_user(&ptp->f10, reg, sizeof(*reg));		break;	      case 3:		copy_from_user(&ptp->f11, reg, sizeof(*reg));		break;	      case 4:	      case 5:	      case 6:	      case 7:		copy_from_user(&swp->f12 + (regno - 4), reg, sizeof(*reg));		break;	}	return;}intsave_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos;	if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))		return -EFAULT;	__put_user(tsk->thread.fcr & 0xffff, &save->cwd);	__put_user(tsk->thread.fsr & 0xffff, &save->swd);	__put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);	__put_user(tsk->thread.fir, &save->fip);	__put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);	__put_user(tsk->thread.fdr, &save->foo);	__put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);	/*	 *  Stack frames start with 16-bytes of temp space	 */	swp = (struct switch_stack *)(tsk->thread.ksp + 16);	ptp = task_pt_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 7;	for (i = 0; i < 8; i++)		put_fpreg(i, &save->st_space[i], ptp, swp, tos);	return 0;}static intrestore_ia32_fpstate (struct task_struct *tsk, struct ia32_user_i387_struct __user *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos;	unsigned int fsrlo, fsrhi, num32;	if (!access_ok(VERIFY_READ, save, sizeof(*save)))		return(-EFAULT);	__get_user(num32, (unsigned int __user *)&save->cwd);	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);	__get_user(fsrlo, (unsigned int __user *)&save->swd);	__get_user(fsrhi, (unsigned int __user *)&save->twd);	num32 = (fsrhi << 16) | fsrlo;	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;	__get_user(num32, (unsigned int __user *)&save->fip);	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;	__get_user(num32, (unsigned int __user *)&save->foo);	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;	/*	 *  Stack frames start with 16-bytes of temp space	 */	swp = (struct switch_stack *)(tsk->thread.ksp + 16);	ptp = task_pt_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 7;	for (i = 0; i < 8; i++)		get_fpreg(i, &save->st_space[i], ptp, swp, tos);	return 0;}intsave_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos;	unsigned long mxcsr=0;	unsigned long num128[2];	if (!access_ok(VERIFY_WRITE, save, sizeof(*save)))		return -EFAULT;	__put_user(tsk->thread.fcr & 0xffff, &save->cwd);	__put_user(tsk->thread.fsr & 0xffff, &save->swd);	__put_user((tsk->thread.fsr>>16) & 0xffff, &save->twd);	__put_user(tsk->thread.fir, &save->fip);	__put_user((tsk->thread.fir>>32) & 0xffff, &save->fcs);	__put_user(tsk->thread.fdr, &save->foo);	__put_user((tsk->thread.fdr>>32) & 0xffff, &save->fos);        /*         *  Stack frames start with 16-bytes of temp space         */        swp = (struct switch_stack *)(tsk->thread.ksp + 16);        ptp = task_pt_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 7;        for (i = 0; i < 8; i++)		put_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);	mxcsr = ((tsk->thread.fcr>>32) & 0xff80) | ((tsk->thread.fsr>>32) & 0x3f);	__put_user(mxcsr & 0xffff, &save->mxcsr);	for (i = 0; i < 8; i++) {		memcpy(&(num128[0]), &(swp->f16) + i*2, sizeof(unsigned long));		memcpy(&(num128[1]), &(swp->f17) + i*2, sizeof(unsigned long));		copy_to_user(&save->xmm_space[0] + 4*i, num128, sizeof(struct _xmmreg_ia32));	}	return 0;}static intrestore_ia32_fpxstate (struct task_struct *tsk, struct ia32_user_fxsr_struct __user *save){	struct switch_stack *swp;	struct pt_regs *ptp;	int i, tos;	unsigned int fsrlo, fsrhi, num32;	int mxcsr;	unsigned long num64;	unsigned long num128[2];	if (!access_ok(VERIFY_READ, save, sizeof(*save)))		return(-EFAULT);	__get_user(num32, (unsigned int __user *)&save->cwd);	tsk->thread.fcr = (tsk->thread.fcr & (~0x1f3f)) | (num32 & 0x1f3f);	__get_user(fsrlo, (unsigned int __user *)&save->swd);	__get_user(fsrhi, (unsigned int __user *)&save->twd);	num32 = (fsrhi << 16) | fsrlo;	tsk->thread.fsr = (tsk->thread.fsr & (~0xffffffff)) | num32;	__get_user(num32, (unsigned int __user *)&save->fip);	tsk->thread.fir = (tsk->thread.fir & (~0xffffffff)) | num32;	__get_user(num32, (unsigned int __user *)&save->foo);	tsk->thread.fdr = (tsk->thread.fdr & (~0xffffffff)) | num32;	/*	 *  Stack frames start with 16-bytes of temp space	 */	swp = (struct switch_stack *)(tsk->thread.ksp + 16);	ptp = task_pt_regs(tsk);	tos = (tsk->thread.fsr >> 11) & 7;	for (i = 0; i < 8; i++)	get_fpreg(i, (struct _fpreg_ia32 __user *)&save->st_space[4*i], ptp, swp, tos);	__get_user(mxcsr, (unsigned int __user *)&save->mxcsr);	num64 = mxcsr & 0xff10;	tsk->thread.fcr = (tsk->thread.fcr & (~0xff1000000000UL)) | (num64<<32);	num64 = mxcsr & 0x3f;	tsk->thread.fsr = (tsk->thread.fsr & (~0x3f00000000UL)) | (num64<<32);	for (i = 0; i < 8; i++) {		copy_from_user(num128, &save->xmm_space[0] + 4*i, sizeof(struct _xmmreg_ia32));		memcpy(&(swp->f16) + i*2, &(num128[0]), sizeof(unsigned long));		memcpy(&(swp->f17) + i*2, &(num128[1]), sizeof(unsigned long));	}	return 0;}asmlinkage longsys32_ptrace (int request, pid_t pid, unsigned int addr, unsigned int data){	struct task_struct *child;	unsigned int value, tmp;	long i, ret;	lock_kernel();	if (request == PTRACE_TRACEME) {		ret = ptrace_traceme();		goto out;	}	child = ptrace_get_task_struct(pid);	if (IS_ERR(child)) {		ret = PTR_ERR(child);		goto out;	}	if (request == PTRACE_ATTACH) {		ret = sys_ptrace(request, pid, addr, data);		goto out_tsk;	}	ret = ptrace_check_attach(child, request == PTRACE_KILL);	if (ret < 0)		goto out_tsk;	switch (request) {	      case PTRACE_PEEKTEXT:	      case PTRACE_PEEKDATA:	/* read word at location addr */		ret = ia32_peek(child, addr, &value);		if (ret == 0)			ret = put_user(value, (unsigned int __user *) compat_ptr(data));		else			ret = -EIO;		goto out_tsk;	      case PTRACE_POKETEXT:	      case PTRACE_POKEDATA:	/* write the word at location addr */		ret = ia32_poke(child, addr, data);		goto out_tsk;	      case PTRACE_PEEKUSR:	/* read word at addr in USER area */		ret = -EIO;		if ((addr & 3) || addr > 17*sizeof(int))			break;		tmp = getreg(child, addr);		if (!put_user(tmp, (unsigned int __user *) compat_ptr(data)))			ret = 0;		break;	      case PTRACE_POKEUSR:	/* write word at addr in USER area */		ret = -EIO;		if ((addr & 3) || addr > 17*sizeof(int))			break;		putreg(child, addr, data);		ret = 0;		break;	      case IA32_PTRACE_GETREGS:		if (!access_ok(VERIFY_WRITE, compat_ptr(data), 17*sizeof(int))) {			ret = -EIO;			break;		}		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {			put_user(getreg(child, i), (unsigned int __user *) compat_ptr(data));			data += sizeof(int);		}		ret = 0;		break;	      case IA32_PTRACE_SETREGS:		if (!access_ok(VERIFY_READ, compat_ptr(data), 17*sizeof(int))) {			ret = -EIO;			break;		}		for (i = 0; i < (int) (17*sizeof(int)); i += sizeof(int) ) {			get_user(tmp, (unsigned int __user *) compat_ptr(data));			putreg(child, i, tmp);			data += sizeof(int);		}		ret = 0;		break;	      case IA32_PTRACE_GETFPREGS:		ret = save_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)					compat_ptr(data));		break;	      case IA32_PTRACE_GETFPXREGS:		ret = save_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)					 compat_ptr(data));		break;	      case IA32_PTRACE_SETFPREGS:		ret = restore_ia32_fpstate(child, (struct ia32_user_i387_struct __user *)					   compat_ptr(data));		break;	      case IA32_PTRACE_SETFPXREGS:		ret = restore_ia32_fpxstate(child, (struct ia32_user_fxsr_struct __user *)					    compat_ptr(data));		break;	      case PTRACE_GETEVENTMSG:   		ret = put_user(child->ptrace_message, (unsigned int __user *) compat_ptr(data));		break;	      case PTRACE_SYSCALL:	/* continue, stop after next syscall */	      case PTRACE_CONT:		/* restart after signal. */	      case PTRACE_KILL:	      case PTRACE_SINGLESTEP:	/* execute chile for one instruction */	      case PTRACE_DETACH:	/* detach a process */		ret = sys_ptrace(request, pid, addr, data);		break;	      default:		ret = ptrace_request(child, request, addr, data);		break;	}  out_tsk:	put_task_struct(child);  out:	unlock_kernel();	return ret;}typedef struct {	unsigned int	ss_sp;	unsigned int	ss_flags;	unsigned int	ss_size;} ia32_stack_t;asmlinkage longsys32_sigaltstack (ia32_stack_t __user *uss32, ia32_stack_t __user *uoss32,		   long arg2, long arg3, long arg4, long arg5, long arg6,		   long arg7, struct pt_regs pt){	stack_t uss, uoss;	ia32_stack_t buf32;	int ret;	mm_segment_t old_fs = get_fs();	if (uss32) {		if (copy_from_user(&buf32, uss32, sizeof(ia32_stack_t)))			return -EFAULT;		uss.ss_sp = (void __user *) (long) buf32.ss_sp;		uss.ss_flags = buf32.ss_flags;		/* MINSIGSTKSZ is different for ia32 vs ia64. We lie here to pass the	           check and set it to the user requested value later */		if ((buf32.ss_flags != SS_DISABLE) && (buf32.ss_size < MINSIGSTKSZ_IA32)) {			ret = -ENOMEM;			goto out;		}		uss.ss_size = MINSIGSTKSZ;	}	set_fs(KERNEL_DS);	ret = do_sigaltstack(uss32 ? (stack_t __user *) &uss : NULL,			     (stack_t __user *) &uoss, pt.r12); 	current->sas_ss_size = buf32.ss_size;	set_fs(old_fs);out:	if (ret < 0)		return(ret);	if (uoss32) {		buf32.ss_sp = (long __user) uoss.ss_sp;		buf32.ss_flags = uoss.ss_flags;		buf32.ss_size = uoss.ss_size;		if (copy_to_user(uoss32, &buf32, sizeof(ia32_stack_t)))			return -EFAULT;	}	return ret;}asmlinkage intsys32_pause (void){	current->state = TASK_INTERRUPTIBLE;	schedule();	return -ERESTARTNOHAND;}asmlinkage intsys32_msync (unsigned int start, unsigned int len, int flags){	unsigned int addr;	if (OFFSET4K(start))		return -EINVAL;	addr = PAGE_START(start);	return sys_msync(addr, len + (start - addr), flags);}struct sysctl32 {	unsigned int	name;	int		nlen;	unsigned int	oldval;	unsigned int	oldlenp;	unsigned int	newval;	unsigned int	newlen;	unsigned int	__unused[4];};#ifdef CONFIG_SYSCTL_SYSCALLasmlinkage longsys32_sysctl (struct sysctl32 __user *args){	struct sysctl32 a32;	mm_segment_t old_fs = get_fs ();	void __user *oldvalp, *newvalp;	size_t oldlen;	int __user *namep;	long ret;	if (copy_from_user(&a32, args, sizeof(a32)))		return -EFAULT;	/*	 * We need to pre-validate these because we have to disable address checking	 * before calling do_sysctl() because of OLDLEN but we can't run the risk of the	 * user specifying bad addresses here.  Well, since we're dealing with 32 bit	 * addresses, we KNOW that access_ok() will always succeed, so this is an	 * expensive NOP, but so what...	 */	namep = (int __user *) compat_ptr(a32.name);	oldvalp = compat_ptr(a32.oldval);	newvalp = compat_ptr(a32.newval);	if ((oldvalp && get_user(oldlen, (int __user *) compat_ptr(a32.oldlenp)))	    || !access_ok(VERIFY_WRITE, namep, 0)	    || !access_ok(VERIFY_WRITE, oldvalp, 0)	    || !access_ok(VERIFY_WRITE, newvalp, 0))		return -EFAULT;	set_fs(KERNEL_DS);	lock_kernel();	ret = do_sysctl(namep, a32.nlen, oldvalp, (size_t __user *) &oldlen,			newvalp, (size_t) a32.newlen);	unlock_kernel();	set_fs(old_fs);	if (oldvalp && put_user (oldlen, (int __user *) compat_ptr(a32.oldlenp)))		return -EFAULT;	return ret;}#endifasmlinkage longsys32_newuname (struct new_utsname __user *name){	int ret = sys_newuname(name);	if (!ret)		if (copy_to_user(name->machine, "i686\0\0\0", 8))			ret = -EFAULT;	return ret;}asmlinkage longsys32_getresuid16 (u16 __user *ruid, u16 __user *euid, u16 __user *suid){	uid_t a, b, c;	int ret;	mm_segment_t old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_getresuid((uid_t __user *) &a, (uid_t __user *) &b, (uid_t __user *) &c);	set_fs(old_fs);	if (put_user(a, ruid) || put_user(b, euid) || put_user(c, suid))		return -EFAULT;	return ret;}asmlinkage longsys32_getresgid16 (u16 __user *rgid, u16 __user *egid, u16 __user *sgid){

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -