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

📄 sys_ia32.c

📁 linux 内核源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * sys_ia32.c: Conversion between 32bit and 64bit native syscalls. Based on *             sys_sparc32  * * Copyright (C) 2000		VA Linux Co * Copyright (C) 2000		Don Dugger <n0ano@valinux.com> * Copyright (C) 1999 		Arun Sharma <arun.sharma@intel.com> * Copyright (C) 1997,1998 	Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1997 		David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 2000		Hewlett-Packard Co. * Copyright (C) 2000		David Mosberger-Tang <davidm@hpl.hp.com> * Copyright (C) 2000,2001,2002	Andi Kleen, SuSE Labs (x86-64 port)  * * These routines maintain argument size conversion between 32bit and 64bit * environment. In 2.5 most of this should be moved to a generic directory.  * * This file assumes that there is a hole at the end of user address space. *  * Some of the functions are LE specific currently. These are hopefully all marked. * This should be fixed. */#include <linux/kernel.h>#include <linux/sched.h>#include <linux/fs.h> #include <linux/file.h> #include <linux/signal.h>#include <linux/syscalls.h>#include <linux/resource.h>#include <linux/times.h>#include <linux/utsname.h>#include <linux/smp.h>#include <linux/smp_lock.h>#include <linux/sem.h>#include <linux/msg.h>#include <linux/mm.h>#include <linux/shm.h>#include <linux/slab.h>#include <linux/uio.h>#include <linux/nfs_fs.h>#include <linux/quota.h>#include <linux/module.h>#include <linux/sunrpc/svc.h>#include <linux/nfsd/nfsd.h>#include <linux/nfsd/cache.h>#include <linux/nfsd/xdr.h>#include <linux/nfsd/syscall.h>#include <linux/poll.h>#include <linux/personality.h>#include <linux/stat.h>#include <linux/ipc.h>#include <linux/rwsem.h>#include <linux/binfmts.h>#include <linux/init.h>#include <linux/aio_abi.h>#include <linux/aio.h>#include <linux/compat.h>#include <linux/vfs.h>#include <linux/ptrace.h>#include <linux/highuid.h>#include <linux/vmalloc.h>#include <linux/fsnotify.h>#include <linux/sysctl.h>#include <asm/mman.h>#include <asm/types.h>#include <asm/uaccess.h>#include <asm/semaphore.h>#include <asm/atomic.h>#include <asm/ldt.h>#include <net/scm.h>#include <net/sock.h>#include <asm/ia32.h>#define AA(__x)		((unsigned long)(__x))int cp_compat_stat(struct kstat *kbuf, struct compat_stat __user *ubuf){	compat_ino_t ino;	typeof(ubuf->st_uid) uid = 0;	typeof(ubuf->st_gid) gid = 0;	SET_UID(uid, kbuf->uid);	SET_GID(gid, kbuf->gid);	if (!old_valid_dev(kbuf->dev) || !old_valid_dev(kbuf->rdev))		return -EOVERFLOW;	if (kbuf->size >= 0x7fffffff)		return -EOVERFLOW;	ino = kbuf->ino;	if (sizeof(ino) < sizeof(kbuf->ino) && ino != kbuf->ino)		return -EOVERFLOW;	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct compat_stat)) ||	    __put_user (old_encode_dev(kbuf->dev), &ubuf->st_dev) ||	    __put_user (ino, &ubuf->st_ino) ||	    __put_user (kbuf->mode, &ubuf->st_mode) ||	    __put_user (kbuf->nlink, &ubuf->st_nlink) ||	    __put_user (uid, &ubuf->st_uid) ||	    __put_user (gid, &ubuf->st_gid) ||	    __put_user (old_encode_dev(kbuf->rdev), &ubuf->st_rdev) ||	    __put_user (kbuf->size, &ubuf->st_size) ||	    __put_user (kbuf->atime.tv_sec, &ubuf->st_atime) ||	    __put_user (kbuf->atime.tv_nsec, &ubuf->st_atime_nsec) ||	    __put_user (kbuf->mtime.tv_sec, &ubuf->st_mtime) ||	    __put_user (kbuf->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||	    __put_user (kbuf->ctime.tv_sec, &ubuf->st_ctime) ||	    __put_user (kbuf->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||	    __put_user (kbuf->blksize, &ubuf->st_blksize) ||	    __put_user (kbuf->blocks, &ubuf->st_blocks))		return -EFAULT;	return 0;}asmlinkage longsys32_truncate64(char __user * filename, unsigned long offset_low, unsigned long offset_high){       return sys_truncate(filename, ((loff_t) offset_high << 32) | offset_low);}asmlinkage longsys32_ftruncate64(unsigned int fd, unsigned long offset_low, unsigned long offset_high){       return sys_ftruncate(fd, ((loff_t) offset_high << 32) | offset_low);}/* Another set for IA32/LFS -- x86_64 struct stat is different due to    support for 64bit inode numbers. */static intcp_stat64(struct stat64 __user *ubuf, struct kstat *stat){	typeof(ubuf->st_uid) uid = 0;	typeof(ubuf->st_gid) gid = 0;	SET_UID(uid, stat->uid);	SET_GID(gid, stat->gid);	if (!access_ok(VERIFY_WRITE, ubuf, sizeof(struct stat64)) ||	    __put_user(huge_encode_dev(stat->dev), &ubuf->st_dev) ||	    __put_user (stat->ino, &ubuf->__st_ino) ||	    __put_user (stat->ino, &ubuf->st_ino) ||	    __put_user (stat->mode, &ubuf->st_mode) ||	    __put_user (stat->nlink, &ubuf->st_nlink) ||	    __put_user (uid, &ubuf->st_uid) ||	    __put_user (gid, &ubuf->st_gid) ||	    __put_user (huge_encode_dev(stat->rdev), &ubuf->st_rdev) ||	    __put_user (stat->size, &ubuf->st_size) ||	    __put_user (stat->atime.tv_sec, &ubuf->st_atime) ||	    __put_user (stat->atime.tv_nsec, &ubuf->st_atime_nsec) ||	    __put_user (stat->mtime.tv_sec, &ubuf->st_mtime) ||	    __put_user (stat->mtime.tv_nsec, &ubuf->st_mtime_nsec) ||	    __put_user (stat->ctime.tv_sec, &ubuf->st_ctime) ||	    __put_user (stat->ctime.tv_nsec, &ubuf->st_ctime_nsec) ||	    __put_user (stat->blksize, &ubuf->st_blksize) ||	    __put_user (stat->blocks, &ubuf->st_blocks))		return -EFAULT;	return 0;}asmlinkage longsys32_stat64(char __user * filename, struct stat64 __user *statbuf){	struct kstat stat;	int ret = vfs_stat(filename, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}asmlinkage longsys32_lstat64(char __user * filename, struct stat64 __user *statbuf){	struct kstat stat;	int ret = vfs_lstat(filename, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}asmlinkage longsys32_fstat64(unsigned int fd, struct stat64 __user *statbuf){	struct kstat stat;	int ret = vfs_fstat(fd, &stat);	if (!ret)		ret = cp_stat64(statbuf, &stat);	return ret;}asmlinkage longsys32_fstatat(unsigned int dfd, char __user *filename,	      struct stat64 __user* statbuf, int flag){	struct kstat stat;	int error = -EINVAL;	if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0)		goto out;	if (flag & AT_SYMLINK_NOFOLLOW)		error = vfs_lstat_fd(dfd, filename, &stat);	else		error = vfs_stat_fd(dfd, filename, &stat);	if (!error)		error = cp_stat64(statbuf, &stat);out:	return error;}/* * Linux/i386 didn't use to be able to handle more than * 4 system call parameters, so these system calls used a memory * block for parameter passing.. */struct mmap_arg_struct {	unsigned int addr;	unsigned int len;	unsigned int prot;	unsigned int flags;	unsigned int fd;	unsigned int offset;};asmlinkage longsys32_mmap(struct mmap_arg_struct __user *arg){	struct mmap_arg_struct a;	struct file *file = NULL;	unsigned long retval;	struct mm_struct *mm ;	if (copy_from_user(&a, arg, sizeof(a)))		return -EFAULT;	if (a.offset & ~PAGE_MASK)		return -EINVAL; 	if (!(a.flags & MAP_ANONYMOUS)) {		file = fget(a.fd);		if (!file)			return -EBADF;	}		mm = current->mm; 	down_write(&mm->mmap_sem); 	retval = do_mmap_pgoff(file, a.addr, a.len, a.prot, a.flags, a.offset>>PAGE_SHIFT);	if (file)		fput(file);	up_write(&mm->mmap_sem); 	return retval;}asmlinkage long sys32_mprotect(unsigned long start, size_t len, unsigned long prot){	return sys_mprotect(start,len,prot); }asmlinkage longsys32_pipe(int __user *fd){	int retval;	int fds[2];	retval = do_pipe(fds);	if (retval)		goto out;	if (copy_to_user(fd, fds, sizeof(fds)))		retval = -EFAULT;  out:	return retval;}asmlinkage longsys32_rt_sigaction(int sig, struct sigaction32 __user *act,		   struct sigaction32 __user *oact,  unsigned int sigsetsize){	struct k_sigaction new_ka, old_ka;	int ret;	compat_sigset_t set32;	/* XXX: Don't preclude handling different sized sigset_t's.  */	if (sigsetsize != sizeof(compat_sigset_t))		return -EINVAL;	if (act) {		compat_uptr_t handler, restorer;		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||		    __get_user(handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||		    __get_user(restorer, &act->sa_restorer)||		    __copy_from_user(&set32, &act->sa_mask, sizeof(compat_sigset_t)))			return -EFAULT;		new_ka.sa.sa_handler = compat_ptr(handler);		new_ka.sa.sa_restorer = compat_ptr(restorer);		/* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */		switch (_NSIG_WORDS) {		case 4: new_ka.sa.sa_mask.sig[3] = set32.sig[6]				| (((long)set32.sig[7]) << 32);		case 3: new_ka.sa.sa_mask.sig[2] = set32.sig[4]				| (((long)set32.sig[5]) << 32);		case 2: new_ka.sa.sa_mask.sig[1] = set32.sig[2]				| (((long)set32.sig[3]) << 32);		case 1: new_ka.sa.sa_mask.sig[0] = set32.sig[0]				| (((long)set32.sig[1]) << 32);		}	}	ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		/* FIXME: here we rely on _COMPAT_NSIG_WORS to be >= than _NSIG_WORDS << 1 */		switch (_NSIG_WORDS) {		case 4:			set32.sig[7] = (old_ka.sa.sa_mask.sig[3] >> 32);			set32.sig[6] = old_ka.sa.sa_mask.sig[3];		case 3:			set32.sig[5] = (old_ka.sa.sa_mask.sig[2] >> 32);			set32.sig[4] = old_ka.sa.sa_mask.sig[2];		case 2:			set32.sig[3] = (old_ka.sa.sa_mask.sig[1] >> 32);			set32.sig[2] = old_ka.sa.sa_mask.sig[1];		case 1:			set32.sig[1] = (old_ka.sa.sa_mask.sig[0] >> 32);			set32.sig[0] = old_ka.sa.sa_mask.sig[0];		}		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||		    __copy_to_user(&oact->sa_mask, &set32, sizeof(compat_sigset_t)))			return -EFAULT;	}	return ret;}asmlinkage longsys32_sigaction (int sig, struct old_sigaction32 __user *act, struct old_sigaction32 __user *oact){        struct k_sigaction new_ka, old_ka;        int ret;        if (act) {		compat_old_sigset_t mask;		compat_uptr_t handler, restorer;		if (!access_ok(VERIFY_READ, act, sizeof(*act)) ||		    __get_user(handler, &act->sa_handler) ||		    __get_user(new_ka.sa.sa_flags, &act->sa_flags) ||		    __get_user(restorer, &act->sa_restorer) ||		    __get_user(mask, &act->sa_mask))			return -EFAULT;		new_ka.sa.sa_handler = compat_ptr(handler);		new_ka.sa.sa_restorer = compat_ptr(restorer);		siginitset(&new_ka.sa.sa_mask, mask);        }        ret = do_sigaction(sig, act ? &new_ka : NULL, oact ? &old_ka : NULL);	if (!ret && oact) {		if (!access_ok(VERIFY_WRITE, oact, sizeof(*oact)) ||		    __put_user(ptr_to_compat(old_ka.sa.sa_handler), &oact->sa_handler) ||		    __put_user(ptr_to_compat(old_ka.sa.sa_restorer), &oact->sa_restorer) ||		    __put_user(old_ka.sa.sa_flags, &oact->sa_flags) ||		    __put_user(old_ka.sa.sa_mask.sig[0], &oact->sa_mask))			return -EFAULT;        }	return ret;}asmlinkage longsys32_rt_sigprocmask(int how, compat_sigset_t __user *set,			compat_sigset_t __user *oset, unsigned int sigsetsize){	sigset_t s;	compat_sigset_t s32;	int ret;	mm_segment_t old_fs = get_fs();		if (set) {		if (copy_from_user (&s32, set, sizeof(compat_sigset_t)))			return -EFAULT;		switch (_NSIG_WORDS) {		case 4: s.sig[3] = s32.sig[6] | (((long)s32.sig[7]) << 32);		case 3: s.sig[2] = s32.sig[4] | (((long)s32.sig[5]) << 32);		case 2: s.sig[1] = s32.sig[2] | (((long)s32.sig[3]) << 32);		case 1: s.sig[0] = s32.sig[0] | (((long)s32.sig[1]) << 32);		}	}	set_fs (KERNEL_DS);	ret = sys_rt_sigprocmask(how,				 set ? (sigset_t __user *)&s : NULL,				 oset ? (sigset_t __user *)&s : NULL,				 sigsetsize); 	set_fs (old_fs);	if (ret) return ret;	if (oset) {		switch (_NSIG_WORDS) {		case 4: s32.sig[7] = (s.sig[3] >> 32); s32.sig[6] = s.sig[3];		case 3: s32.sig[5] = (s.sig[2] >> 32); s32.sig[4] = s.sig[2];		case 2: s32.sig[3] = (s.sig[1] >> 32); s32.sig[2] = s.sig[1];		case 1: s32.sig[1] = (s.sig[0] >> 32); s32.sig[0] = s.sig[0];		}		if (copy_to_user (oset, &s32, sizeof(compat_sigset_t)))			return -EFAULT;	}	return 0;}static inline longget_tv32(struct timeval *o, struct compat_timeval __user *i){	int err = -EFAULT; 	if (access_ok(VERIFY_READ, i, sizeof(*i))) { 		err = __get_user(o->tv_sec, &i->tv_sec);		err |= __get_user(o->tv_usec, &i->tv_usec);	}	return err; }static inline longput_tv32(struct compat_timeval __user *o, struct timeval *i){	int err = -EFAULT;	if (access_ok(VERIFY_WRITE, o, sizeof(*o))) { 		err = __put_user(i->tv_sec, &o->tv_sec);		err |= __put_user(i->tv_usec, &o->tv_usec);	} 	return err; }extern unsigned int alarm_setitimer(unsigned int seconds);asmlinkage longsys32_alarm(unsigned int seconds){	return alarm_setitimer(seconds);}

⌨️ 快捷键说明

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