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

📄 linux32.c

📁 该文件是rt_linux
💻 C
📖 第 1 页 / 共 4 页
字号:
	case IPC_INFO:	case IPC_RMID:	case SHM_LOCK:	case SHM_UNLOCK:		err = sys_shmctl (first, second, (struct shmid_ds *)uptr);		break;	case IPC_SET:		err = get_user (s.shm_perm.uid, &up->shm_perm.uid);		err |= __get_user (s.shm_perm.gid, &up->shm_perm.gid);		err |= __get_user (s.shm_perm.mode, &up->shm_perm.mode);		if (err)			break;		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_shmctl (first, second, &s);		set_fs (old_fs);		break;	case IPC_STAT:	case SHM_STAT:		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_shmctl (first, second, (void *) &s64);		set_fs (old_fs);		if (err < 0)			break;		err2 = put_user (s64.shm_perm.key, &up->shm_perm.key);		err2 |= __put_user (s64.shm_perm.uid, &up->shm_perm.uid);		err2 |= __put_user (s64.shm_perm.gid, &up->shm_perm.gid);		err2 |= __put_user (s64.shm_perm.cuid,				    &up->shm_perm.cuid);		err2 |= __put_user (s64.shm_perm.cgid,				    &up->shm_perm.cgid);		err2 |= __put_user (s64.shm_perm.mode,				    &up->shm_perm.mode);		err2 |= __put_user (s64.shm_perm.seq, &up->shm_perm.seq);		err2 |= __put_user (s64.shm_atime, &up->shm_atime);		err2 |= __put_user (s64.shm_dtime, &up->shm_dtime);		err2 |= __put_user (s64.shm_ctime, &up->shm_ctime);		err2 |= __put_user (s64.shm_segsz, &up->shm_segsz);		err2 |= __put_user (s64.shm_nattch, &up->shm_nattch);		err2 |= __put_user (s64.shm_cpid, &up->shm_cpid);		err2 |= __put_user (s64.shm_lpid, &up->shm_lpid);		if (err2)			err = -EFAULT;		break;	case SHM_INFO:		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_shmctl (first, second, (void *)&si);		set_fs (old_fs);		if (err < 0)			break;		err2 = put_user (si.used_ids, &uip->used_ids);		err2 |= __put_user (si.shm_tot, &uip->shm_tot);		err2 |= __put_user (si.shm_rss, &uip->shm_rss);		err2 |= __put_user (si.shm_swp, &uip->shm_swp);		err2 |= __put_user (si.swap_attempts,				    &uip->swap_attempts);		err2 |= __put_user (si.swap_successes,				    &uip->swap_successes);		if (err2)			err = -EFAULT;		break;	}	return err;}asmlinkage longsys32_ipc (u32 call, int first, int second, int third, u32 ptr, u32 fifth){	int version, err;	version = call >> 16; /* hack for backward compatibility */	call &= 0xffff;	switch (call) {	case SEMOP:		/* struct sembuf is the same on 32 and 64bit :)) */		err = sys_semop (first, (struct sembuf *)AA(ptr),				 second);		break;	case SEMGET:		err = sys_semget (first, second, third);		break;	case SEMCTL:		err = do_sys32_semctl (first, second, third,				       (void *)AA(ptr));		break;	case MSGSND:		err = do_sys32_msgsnd (first, second, third,				       (void *)AA(ptr));		break;	case MSGRCV:		err = do_sys32_msgrcv (first, second, fifth, third,				       version, (void *)AA(ptr));		break;	case MSGGET:		err = sys_msgget ((key_t) first, second);		break;	case MSGCTL:		err = do_sys32_msgctl (first, second, (void *)AA(ptr));		break;	case SHMAT:		err = do_sys32_shmat (first, second, third,				      version, (void *)AA(ptr));		break;	case SHMDT:		err = sys_shmdt ((char *)A(ptr));		break;	case SHMGET:		err = sys_shmget (first, second, third);		break;	case SHMCTL:		err = do_sys32_shmctl (first, second, (void *)AA(ptr));		break;	default:		err = -EINVAL;		break;	}	return err;}struct sysctl_args32{	__kernel_caddr_t32 name;	int nlen;	__kernel_caddr_t32 oldval;	__kernel_caddr_t32 oldlenp;	__kernel_caddr_t32 newval;	__kernel_size_t32 newlen;	unsigned int __unused[4];};asmlinkage long sys32_sysctl(struct sysctl_args32 *uargs32){	struct __sysctl_args kargs;	struct sysctl_args32 kargs32;	mm_segment_t old_fs;	int name[CTL_MAXNAME];	size_t oldlen[1];	int err, ret;	ret = -EFAULT;	memset(&kargs, 0, sizeof (kargs));	err = get_user(kargs32.name, &uargs32->name);	err |= __get_user(kargs32.nlen, &uargs32->nlen);	err |= __get_user(kargs32.oldval, &uargs32->oldval);	err |= __get_user(kargs32.oldlenp, &uargs32->oldlenp);	err |= __get_user(kargs32.newval, &uargs32->newval);	err |= __get_user(kargs32.newlen, &uargs32->newlen);	if (err)		goto out;	if (kargs32.nlen == 0 || kargs32.nlen >= CTL_MAXNAME) {		ret = -ENOTDIR;		goto out;	}	kargs.name = name;	kargs.nlen = kargs32.nlen;	if (copy_from_user(kargs.name, (int *)A(kargs32.name),			   kargs32.nlen * sizeof(name) / sizeof(name[0])))		goto out;	if (kargs32.oldval) {		if (!kargs32.oldlenp || get_user(oldlen[0],						 (int *)A(kargs32.oldlenp)))			return -EFAULT;		kargs.oldlenp = oldlen;		kargs.oldval = kmalloc(oldlen[0], GFP_KERNEL);		if (!kargs.oldval) {			ret = -ENOMEM;			goto out;		}	}	if (kargs32.newval && kargs32.newlen) {		kargs.newval = kmalloc(kargs32.newlen, GFP_KERNEL);		if (!kargs.newval) {			ret = -ENOMEM;			goto out;		}		if (copy_from_user(kargs.newval, (int *)A(kargs32.newval),				   kargs32.newlen))			goto out;	}	old_fs = get_fs(); set_fs (KERNEL_DS);	ret = sys_sysctl(&kargs);	set_fs (old_fs);	if (ret)		goto out;	if (kargs.oldval) {		if (put_user(oldlen[0], (int *)A(kargs32.oldlenp)) ||		    copy_to_user((int *)A(kargs32.oldval), kargs.oldval,				 oldlen[0]))			ret = -EFAULT;	}out:	if (kargs.oldval)		kfree(kargs.oldval);	if (kargs.newval)		kfree(kargs.newval);	return ret;}asmlinkage long sys32_newuname(struct new_utsname * name){	int ret = 0;	down_read(&uts_sem);	if (copy_to_user(name,&system_utsname,sizeof *name))		ret = -EFAULT;	up_read(&uts_sem);	if (current->personality == PER_LINUX32 && !ret)		if (copy_to_user(name->machine, "mips\0\0\0", 8))			ret = -EFAULT;	return ret;}extern asmlinkage long sys_personality(unsigned long);asmlinkage int sys32_personality(unsigned long personality){	int ret;	if (current->personality == PER_LINUX32 && personality == PER_LINUX)		personality = PER_LINUX32;	ret = sys_personality(personality);	if (ret == PER_LINUX32)		ret = PER_LINUX;	return ret;}/* Handle adjtimex compatability. */struct timex32 {	u32 modes;	s32 offset, freq, maxerror, esterror;	s32 status, constant, precision, tolerance;	struct timeval32 time;	s32 tick;	s32 ppsfreq, jitter, shift, stabil;	s32 jitcnt, calcnt, errcnt, stbcnt;	s32  :32; s32  :32; s32  :32; s32  :32;	s32  :32; s32  :32; s32  :32; s32  :32;	s32  :32; s32  :32; s32  :32; s32  :32;};extern int do_adjtimex(struct timex *);asmlinkage int sys32_adjtimex(struct timex32 *utp){	struct timex txc;	int ret;	memset(&txc, 0, sizeof(struct timex));	if(get_user(txc.modes, &utp->modes) ||	   __get_user(txc.offset, &utp->offset) ||	   __get_user(txc.freq, &utp->freq) ||	   __get_user(txc.maxerror, &utp->maxerror) ||	   __get_user(txc.esterror, &utp->esterror) ||	   __get_user(txc.status, &utp->status) ||	   __get_user(txc.constant, &utp->constant) ||	   __get_user(txc.precision, &utp->precision) ||	   __get_user(txc.tolerance, &utp->tolerance) ||	   __get_user(txc.time.tv_sec, &utp->time.tv_sec) ||	   __get_user(txc.time.tv_usec, &utp->time.tv_usec) ||	   __get_user(txc.tick, &utp->tick) ||	   __get_user(txc.ppsfreq, &utp->ppsfreq) ||	   __get_user(txc.jitter, &utp->jitter) ||	   __get_user(txc.shift, &utp->shift) ||	   __get_user(txc.stabil, &utp->stabil) ||	   __get_user(txc.jitcnt, &utp->jitcnt) ||	   __get_user(txc.calcnt, &utp->calcnt) ||	   __get_user(txc.errcnt, &utp->errcnt) ||	   __get_user(txc.stbcnt, &utp->stbcnt))		return -EFAULT;	ret = do_adjtimex(&txc);	if(put_user(txc.modes, &utp->modes) ||	   __put_user(txc.offset, &utp->offset) ||	   __put_user(txc.freq, &utp->freq) ||	   __put_user(txc.maxerror, &utp->maxerror) ||	   __put_user(txc.esterror, &utp->esterror) ||	   __put_user(txc.status, &utp->status) ||	   __put_user(txc.constant, &utp->constant) ||	   __put_user(txc.precision, &utp->precision) ||	   __put_user(txc.tolerance, &utp->tolerance) ||	   __put_user(txc.time.tv_sec, &utp->time.tv_sec) ||	   __put_user(txc.time.tv_usec, &utp->time.tv_usec) ||	   __put_user(txc.tick, &utp->tick) ||	   __put_user(txc.ppsfreq, &utp->ppsfreq) ||	   __put_user(txc.jitter, &utp->jitter) ||	   __put_user(txc.shift, &utp->shift) ||	   __put_user(txc.stabil, &utp->stabil) ||	   __put_user(txc.jitcnt, &utp->jitcnt) ||	   __put_user(txc.calcnt, &utp->calcnt) ||	   __put_user(txc.errcnt, &utp->errcnt) ||	   __put_user(txc.stbcnt, &utp->stbcnt))		ret = -EFAULT;	return ret;}/* *  Declare the 32-bit version of the msghdr */struct msghdr32 {	unsigned int    msg_name;	/* Socket name			*/	int		msg_namelen;	/* Length of name		*/	unsigned int    msg_iov;	/* Data blocks			*/	unsigned int	msg_iovlen;	/* Number of blocks		*/	unsigned int    msg_control;	/* Per protocol magic (eg BSD file descriptor passing) */	unsigned int	msg_controllen;	/* Length of cmsg list */	unsigned	msg_flags;};static inline intshape_msg(struct msghdr *mp, struct msghdr32 *mp32){	int ret;	unsigned int i;	if (!access_ok(VERIFY_READ, mp32, sizeof(*mp32)))		return(-EFAULT);	ret = __get_user(i, &mp32->msg_name);	mp->msg_name = (void *)A(i);	ret |= __get_user(mp->msg_namelen, &mp32->msg_namelen);	ret |= __get_user(i, &mp32->msg_iov);	mp->msg_iov = (struct iovec *)A(i);	ret |= __get_user(mp->msg_iovlen, &mp32->msg_iovlen);	ret |= __get_user(i, &mp32->msg_control);	mp->msg_control = (void *)A(i);	ret |= __get_user(mp->msg_controllen, &mp32->msg_controllen);	ret |= __get_user(mp->msg_flags, &mp32->msg_flags);	return(ret ? -EFAULT : 0);}/* *	Verify & re-shape IA32 iovec. The caller must ensure that the *      iovec is big enough to hold the re-shaped message iovec. * *	Save time not doing verify_area. copy_*_user will make this work *	in any case. * *	Don't need to check the total size for overflow (cf net/core/iovec.c), *	32-bit sizes can't overflow a 64-bit count. */static inline intverify_iovec32(struct msghdr *m, struct iovec *iov, char *address, int mode){	int size, err, ct;	struct iovec32 *iov32;	if(m->msg_namelen)	{		if(mode==VERIFY_READ)		{			err=move_addr_to_kernel(m->msg_name, m->msg_namelen, address);			if(err<0)				goto out;		}		m->msg_name = address;	} else		m->msg_name = NULL;	err = -EFAULT;	size = m->msg_iovlen * sizeof(struct iovec32);	if (copy_from_user(iov, m->msg_iov, size))		goto out;	m->msg_iov=iov;	err = 0;	iov32 = (struct iovec32 *)iov;	for (ct = m->msg_iovlen; ct-- > 0; ) {		iov[ct].iov_len = (__kernel_size_t)iov32[ct].iov_len;		iov[ct].iov_base = (void *) A(iov32[ct].iov_base);		err += iov[ct].iov_len;	}out:	return err;}extern __inline__ voidsockfd_put(struct socket *sock){	fput(sock->file);}/* XXX This really belongs in some header file... -DaveM */#define MAX_SOCK_ADDR	128		/* 108 for Unix domain -					   16 for IP, 16 for IPX,					   24 for IPv6,					   about 80 for AX.25 */extern struct socket *sockfd_lookup(int fd, int *err);/* *	BSD sendmsg interface */int sys32_sendmsg(int fd, struct msghdr32 *msg, unsigned flags){	struct socket *sock;	char address[MAX_SOCK_ADDR];	struct iovec iovstack[UIO_FASTIOV], *iov = iovstack;	unsigned char ctl[sizeof(struct cmsghdr) + 20];	/* 20 is size of ipv6_pktinfo */	unsigned char *ctl_buf = ctl;	struct msghdr msg_sys;	int err, ctl_len, iov_size, total_len;	err = -EFAULT;	if (shape_msg(&msg_sys, msg))		goto out;	sock = sockfd_lookup(fd, &err);	if (!sock)		goto out;	/* do not move before msg_sys is valid */	err = -EINVAL;	if (msg_sys.msg_iovlen > UIO_MAXIOV)		goto out_put;	/* Check whether to allocate the iovec area*/	err = -ENOMEM;	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec32);	if (msg_sys.msg_iovlen > UIO_FASTIOV) {		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);		if (!iov)			goto out_put;	}	/* This will also move the address data into kernel space */	err = verify_iovec32(&msg_sys, iov, address, VERIFY_READ);	if (err < 0)		goto out_freeiov;	total_len = err;	err = -ENOBUFS;	if (msg_sys.msg_controllen > INT_MAX)		goto out_freeiov;	ctl_len = msg_sys.msg_controllen;	if (ctl_len)	{		if (ctl_len > sizeof(ctl))		{			err = -ENOBUFS;			ctl_buf = sock_kmalloc(sock->sk, ctl_len, GFP_KERNEL);			if (ctl_buf == NULL)				goto out_freeiov;		}		err = -EFAULT;		if (copy_from_user(ctl_buf, msg_sys.msg_control, ctl_len))			goto out_freectl;		msg_sys.msg_control = ctl_buf;	}	msg_sys.msg_flags = flags;	if (sock->file->f_flags & O_NONBLOCK)		msg_sys.msg_flags |= MSG_DONTWAIT;	err = sock_sendmsg(sock, &msg_sys, total_len);out_freectl:	if (ctl_buf != ctl)		sock_kfree_s(sock->sk, ctl_buf, ctl_len);out_freeiov:	if (iov != iovstack)		sock_kfree_s(sock->sk, iov, iov_size);out_put:	sockfd_put(sock);out:	return err;}/* *	BSD recvmsg interface */intsys32_recvmsg (int fd, struct msghdr32 *msg, unsigned int flags){	struct socket *sock;	struct iovec iovstack[UIO_FASTIOV];	struct iovec *iov=iovstack;	struct msghdr msg_sys;	unsigned long cmsg_ptr;	int err, iov_size, total_len, len;	/* kernel mode address */	char addr[MAX_SOCK_ADDR];	/* user mode address pointers */	struct sockaddr *uaddr;	int *uaddr_len;	err=-EFAULT;	if (shape_msg(&msg_sys, msg))		goto out;	sock = sockfd_lookup(fd, &err);	if (!sock)		goto out;	err = -EINVAL;	if (msg_sys.msg_iovlen > UIO_MAXIOV)		goto out_put;	/* Check whether to allocate the iovec area*/	err = -ENOMEM;	iov_size = msg_sys.msg_iovlen * sizeof(struct iovec);	if (msg_sys.msg_iovlen > UIO_FASTIOV) {		iov = sock_kmalloc(sock->sk, iov_size, GFP_KERNEL);		if (!iov)			goto out_put;	}	/*	 *	Save the user-mode address (verify_iovec will change the	 *	kernel msghdr to use the kernel address space)	 */	uaddr = msg_sys.msg_name;	uaddr_len = &msg->msg_namelen;	err = verify_iovec32(&msg_sys, iov, addr, VERIFY_WRITE);	if (err < 0)		goto out_freeiov;	total_len=err;	cmsg_ptr = (unsigned long)msg_sys.msg_control;	msg_sys.msg_flags = 0;	if (sock->file->f_flags & O_NONBLOCK)		flags |= MSG_DONTWAIT;	err = sock_recvmsg(sock, &msg_sys, total_len, flags);	if (err < 0)		goto out_freeiov;	len = err;	if (uaddr != NULL) {		err = move_addr_to_user(addr, msg_sys.msg_namelen, uaddr, uaddr_len);		if (err < 0)			goto out_freeiov;	}	err = __put_user(msg_sys.msg_flags, &msg->msg_flags);	if (err)		goto out_freeiov;	err = __put_user((unsigned long)msg_sys.msg_control-cmsg_ptr,							 &msg->msg_controllen);	if (err)		goto out_freeiov;	err = len;out_freeiov:	if (iov != iovstack)		sock_kfree_s(sock->sk, iov, iov_size);out_put:	sockfd_put(sock);out:	return err;}asmlinkage ssize_t sys_readahead(int fd, loff_t offset, size_t count);asmlinkage ssize_t sys32_readahead(int fd, u32 pad0, u64 a2, u64 a3,                                   size_t count){	return sys_readahead(fd, merge_64(a2, a3), count);}#ifdef CONFIG_MODULES/* From sparc64 */struct kernel_sym32 {        u32 value;        char name[60];};extern asmlinkage int sys_get_kernel_syms(struct kernel_sym *table);asmlinkage int sys32_get_kernel_syms(struct kernel_sym32 *table){        int len, i;        struct kernel_sym *tbl;        mm_segment_t old_fs;        len = sys_get_kernel_syms(NULL);        if (!table) return len;        tbl = kmalloc (len * sizeof (struct kernel_sym), GFP_KERNEL);        if (!tbl) return -ENOMEM;        old_fs = get_fs();        set_fs (KERNEL_DS);        sys_get_kernel_syms(tbl);        set_fs (old_fs);        for (i = 0; i < len; i++, table++) {                if (put_user (tbl[i].value, &table->value) ||                    copy_to_user (table->name, tbl[i].name, 60))                        break;        }        kfree (tbl);        return i;}#elseasmlinkage longsys32_get_kernel_syms(struct kernel_sym *table){	return -ENOSYS;}#endif

⌨️ 快捷键说明

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