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

📄 sys_ia32.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
		set_fs (KERNEL_DS);	ret = sys_getrlimit(resource, &r);	set_fs (old_fs);	if (!ret) {		ret = put_user (RESOURCE32(r.rlim_cur), &rlim->rlim_cur);		ret |= __put_user (RESOURCE32(r.rlim_max), &rlim->rlim_max);	}	return ret;}extern asmlinkage long sys_setrlimit(unsigned int resource, struct rlimit *rlim);asmlinkage longsys32_setrlimit(unsigned int resource, struct rlimit32 *rlim){	struct rlimit r;	int ret;	mm_segment_t old_fs = get_fs ();	if (resource >= RLIM_NLIMITS) return -EINVAL;		if (get_user (r.rlim_cur, &rlim->rlim_cur) ||	    __get_user (r.rlim_max, &rlim->rlim_max))		return -EFAULT;	if (r.rlim_cur == RLIM_INFINITY32)		r.rlim_cur = RLIM_INFINITY;	if (r.rlim_max == RLIM_INFINITY32)		r.rlim_max = RLIM_INFINITY;	set_fs (KERNEL_DS);	ret = sys_setrlimit(resource, &r);	set_fs (old_fs);	return ret;}/* *  Declare the IA32 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;}/* Argument list sizes for sys_socketcall */#define AL(x) ((x) * sizeof(u32))static unsigned char nas[18]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3),                                AL(3),AL(3),AL(4),AL(4),AL(4),AL(6),                                AL(6),AL(2),AL(5),AL(5),AL(3),AL(3)};#undef ALextern asmlinkage long sys_bind(int fd, struct sockaddr *umyaddr, int addrlen);extern asmlinkage long sys_connect(int fd, struct sockaddr *uservaddr,				  int addrlen);extern asmlinkage long sys_accept(int fd, struct sockaddr *upeer_sockaddr,				 int *upeer_addrlen); extern asmlinkage long sys_getsockname(int fd, struct sockaddr *usockaddr,				      int *usockaddr_len);extern asmlinkage long sys_getpeername(int fd, struct sockaddr *usockaddr,				      int *usockaddr_len);extern asmlinkage long sys_send(int fd, void *buff, size_t len, unsigned flags);extern asmlinkage long sys_sendto(int fd, u32 buff, __kernel_size_t32 len,				   unsigned flags, u32 addr, int addr_len);extern asmlinkage long sys_recv(int fd, void *ubuf, size_t size, unsigned flags);extern asmlinkage long sys_recvfrom(int fd, u32 ubuf, __kernel_size_t32 size,				     unsigned flags, u32 addr, u32 addr_len);extern asmlinkage long sys_setsockopt(int fd, int level, int optname,				     char *optval, int optlen);extern asmlinkage long sys_getsockopt(int fd, int level, int optname,				       u32 optval, u32 optlen);extern asmlinkage long sys_socket(int family, int type, int protocol);extern asmlinkage long sys_socketpair(int family, int type, int protocol,				     int usockvec[2]);extern asmlinkage long sys_shutdown(int fd, int how);extern asmlinkage long sys_listen(int fd, int backlog);asmlinkage long sys32_socketcall(int call, u32 *args){	int ret;	u32 a[6];	u32 a0,a1;				 	if (call<SYS_SOCKET||call>SYS_RECVMSG)		return -EINVAL;	if (copy_from_user(a, args, nas[call]))		return -EFAULT;	a0=a[0];	a1=a[1];		switch(call) 	{		case SYS_SOCKET:			ret = sys_socket(a0, a1, a[2]);			break;		case SYS_BIND:			ret = sys_bind(a0, (struct sockaddr *)A(a1), a[2]);			break;		case SYS_CONNECT:			ret = sys_connect(a0, (struct sockaddr *)A(a1), a[2]);			break;		case SYS_LISTEN:			ret = sys_listen(a0, a1);			break;		case SYS_ACCEPT:			ret = sys_accept(a0, (struct sockaddr *)A(a1),					  (int *)A(a[2]));			break;		case SYS_GETSOCKNAME:			ret = sys_getsockname(a0, (struct sockaddr *)A(a1),					       (int *)A(a[2]));			break;		case SYS_GETPEERNAME:			ret = sys_getpeername(a0, (struct sockaddr *)A(a1),					       (int *)A(a[2]));			break;		case SYS_SOCKETPAIR:			ret = sys_socketpair(a0, a1, a[2], (int *)A(a[3]));			break;		case SYS_SEND:			ret = sys_send(a0, (void *)A(a1), a[2], a[3]);			break;		case SYS_SENDTO:			ret = sys_sendto(a0, a1, a[2], a[3], a[4], a[5]);			break;		case SYS_RECV:			ret = sys_recv(a0, (void *)A(a1), a[2], a[3]);			break;		case SYS_RECVFROM:			ret = sys_recvfrom(a0, a1, a[2], a[3], a[4], a[5]);			break;		case SYS_SHUTDOWN:			ret = sys_shutdown(a0,a1);			break;		case SYS_SETSOCKOPT:			ret = sys_setsockopt(a0, a1, a[2], (char *)A(a[3]),					      a[4]);			break;		case SYS_GETSOCKOPT:			ret = sys_getsockopt(a0, a1, a[2], a[3], a[4]);			break;		case SYS_SENDMSG:			ret = sys32_sendmsg(a0, (struct msghdr32 *)A(a1),					     a[2]);			break;		case SYS_RECVMSG:			ret = sys32_recvmsg(a0, (struct msghdr32 *)A(a1),					     a[2]);			break;		default:			ret = EINVAL;			break;	}	return ret;}/* * sys32_ipc() is the de-multiplexer for the SysV IPC calls in 32bit emulation.. * * This is really horribly ugly. */struct msgbuf32 { s32 mtype; char mtext[1]; };struct ipc_perm32{	key_t    	  key;        __kernel_uid_t32  uid;        __kernel_gid_t32  gid;        __kernel_uid_t32  cuid;        __kernel_gid_t32  cgid;        __kernel_mode_t32 mode;        unsigned short  seq;};struct semid_ds32 {        struct ipc_perm32 sem_perm;               /* permissions .. see ipc.h */        __kernel_time_t32 sem_otime;              /* last semop time */        __kernel_time_t32 sem_ctime;              /* last change time */        u32 sem_base;              /* ptr to first semaphore in array */        u32 sem_pending;          /* pending operations to be processed */        u32 sem_pending_last;    /* last pending operation */        u32 undo;                  /* undo requests on this array */        unsigned short  sem_nsems;              /* no. of semaphores in array */};struct msqid_ds32{        struct ipc_perm32 msg_perm;        u32 msg_first;        u32 msg_last;        __kernel_time_t32 msg_stime;        __kernel_time_t32 msg_rtime;        __kernel_time_t32 msg_ctime;        u32 wwait;        u32 rwait;        unsigned short msg_cbytes;        unsigned short msg_qnum;          unsigned short msg_qbytes;        __kernel_ipc_pid_t32 msg_lspid;        __kernel_ipc_pid_t32 msg_lrpid;};struct shmid_ds32 {        struct ipc_perm32       shm_perm;        int                     shm_segsz;        __kernel_time_t32       shm_atime;        __kernel_time_t32       shm_dtime;        __kernel_time_t32       shm_ctime;        __kernel_ipc_pid_t32    shm_cpid;         __kernel_ipc_pid_t32    shm_lpid;         unsigned short          shm_nattch;};#define IPCOP_MASK(__x)	(1UL << (__x))static intdo_sys32_semctl(int first, int second, int third, void *uptr){	union semun fourth;	u32 pad;	int err, err2;	struct semid64_ds s;	struct semid_ds32 *usp;	mm_segment_t old_fs;	if (!uptr)		return -EINVAL;	err = -EFAULT;	if (get_user (pad, (u32 *)uptr))		return err;	if(third == SETVAL)		fourth.val = (int)pad;	else		fourth.__pad = (void *)A(pad);	switch (third) {	case IPC_INFO:	case IPC_RMID:	case IPC_SET:	case SEM_INFO:	case GETVAL:	case GETPID:	case GETNCNT:	case GETZCNT:	case GETALL:	case SETVAL:	case SETALL:		err = sys_semctl (first, second, third, fourth);		break;	case IPC_STAT:	case SEM_STAT:		usp = (struct semid_ds32 *)A(pad);		fourth.__pad = &s;		old_fs = get_fs ();		set_fs (KERNEL_DS);		err = sys_semctl (first, second, third, fourth);		set_fs (old_fs);		err2 = put_user(s.sem_perm.key, &usp->sem_perm.key);		err2 |= __put_user(s.sem_perm.uid, &usp->sem_perm.uid);		err2 |= __put_user(s.sem_perm.gid, &usp->sem_perm.gid);		err2 |= __put_user(s.sem_perm.cuid,				   &usp->sem_perm.cuid);		err2 |= __put_user (s.sem_perm.cgid,				    &usp->sem_perm.cgid);		err2 |= __put_user (s.sem_perm.mode,				    &usp->sem_perm.mode);		err2 |= __put_user (s.sem_perm.seq, &usp->sem_perm.seq);		err2 |= __put_user (s.sem_otime, &usp->sem_otime);		err2 |= __put_user (s.sem_ctime, &usp->sem_ctime);		err2 |= __put_user (s.sem_nsems, &usp->sem_nsems);		if (err2)			err = -EFAULT;		break;	}	return err;}static intdo_sys32_msgsnd (int first, int second, int third, void *uptr){	struct msgbuf *p = kmalloc (second + sizeof (struct msgbuf)

⌨️ 快捷键说明

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