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

📄 sys_ia32.c

📁 上传linux-jx2410的源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
#define ROUND_UP_TIME(x,y) (((x)+(y)-1)/(y))asmlinkage longsys32_select (int n, fd_set *inp, fd_set *outp, fd_set *exp, struct timeval32 *tvp32){	fd_set_bits fds;	char *bits;	long timeout;	int ret, size;	timeout = MAX_SCHEDULE_TIMEOUT;	if (tvp32) {		time_t sec, usec;		ret = -EFAULT;		if (get_user(sec, &tvp32->tv_sec) || get_user(usec, &tvp32->tv_usec))			goto out_nofds;		ret = -EINVAL;		if (sec < 0 || usec < 0)			goto out_nofds;		if ((unsigned long) sec < MAX_SELECT_SECONDS) {			timeout = ROUND_UP_TIME(usec, 1000000/HZ);			timeout += sec * (unsigned long) HZ;		}	}	ret = -EINVAL;	if (n < 0)		goto out_nofds;	if (n > current->files->max_fdset)		n = current->files->max_fdset;	/*	 * We need 6 bitmaps (in/out/ex for both incoming and outgoing),	 * since we used fdset we need to allocate memory in units of	 * long-words.	 */	ret = -ENOMEM;	size = FDS_BYTES(n);	bits = kmalloc(6 * size, GFP_KERNEL);	if (!bits)		goto out_nofds;	fds.in      = (unsigned long *)  bits;	fds.out     = (unsigned long *) (bits +   size);	fds.ex      = (unsigned long *) (bits + 2*size);	fds.res_in  = (unsigned long *) (bits + 3*size);	fds.res_out = (unsigned long *) (bits + 4*size);	fds.res_ex  = (unsigned long *) (bits + 5*size);	if ((ret = get_fd_set(n, inp, fds.in)) ||	    (ret = get_fd_set(n, outp, fds.out)) ||	    (ret = get_fd_set(n, exp, fds.ex)))		goto out;	zero_fd_set(n, fds.res_in);	zero_fd_set(n, fds.res_out);	zero_fd_set(n, fds.res_ex);	ret = do_select(n, &fds, &timeout);	if (tvp32 && !(current->personality & STICKY_TIMEOUTS)) {		time_t sec = 0, usec = 0;		if (timeout) {			sec = timeout / HZ;			usec = timeout % HZ;			usec *= (1000000/HZ);		}		if (put_user(sec, &tvp32->tv_sec) || put_user(usec, &tvp32->tv_usec)) {			ret = -EFAULT;			goto out;		}	}	if (ret < 0)		goto out;	if (!ret) {		ret = -ERESTARTNOHAND;		if (signal_pending(current))			goto out;		ret = 0;	}	set_fd_set(n, inp, fds.res_in);	set_fd_set(n, outp, fds.res_out);	set_fd_set(n, exp, fds.res_ex);out:	kfree(bits);out_nofds:	return ret;}struct sel_arg_struct {	unsigned int n;	unsigned int inp;	unsigned int outp;	unsigned int exp;	unsigned int tvp;};asmlinkage longsys32_old_select (struct sel_arg_struct *arg){	struct sel_arg_struct a;	if (copy_from_user(&a, arg, sizeof(a)))		return -EFAULT;	return sys32_select(a.n, (fd_set *) A(a.inp), (fd_set *) A(a.outp), (fd_set *) A(a.exp),			    (struct timeval32 *) A(a.tvp));}extern asmlinkage long sys_nanosleep (struct timespec *rqtp, struct timespec *rmtp);asmlinkage longsys32_nanosleep (struct timespec32 *rqtp, struct timespec32 *rmtp){	struct timespec t;	int ret;	mm_segment_t old_fs = get_fs();	if (get_user (t.tv_sec, &rqtp->tv_sec) || get_user (t.tv_nsec, &rqtp->tv_nsec))		return -EFAULT;	set_fs(KERNEL_DS);	ret = sys_nanosleep(&t, rmtp ? &t : NULL);	set_fs(old_fs);	if (rmtp && ret == -EINTR) {		if (put_user(t.tv_sec, &rmtp->tv_sec) || put_user(t.tv_nsec, &rmtp->tv_nsec))			return -EFAULT;	}	return ret;}struct iovec32 { unsigned int iov_base; int iov_len; };asmlinkage ssize_t sys_readv (unsigned long,const struct iovec *,unsigned long);asmlinkage ssize_t sys_writev (unsigned long,const struct iovec *,unsigned long);static struct iovec *get_iovec32 (struct iovec32 *iov32, struct iovec *iov_buf, u32 count, int type){	int i;	u32 buf, len;	struct iovec *ivp, *iov;	/* Get the "struct iovec" from user memory */	if (!count)		return 0;	if (verify_area(VERIFY_READ, iov32, sizeof(struct iovec32)*count))		return NULL;	if (count > UIO_MAXIOV)		return NULL;	if (count > UIO_FASTIOV) {		iov = kmalloc(count*sizeof(struct iovec), GFP_KERNEL);		if (!iov)			return NULL;	} else		iov = iov_buf;	ivp = iov;	for (i = 0; i < count; i++) {		if (__get_user(len, &iov32->iov_len) || __get_user(buf, &iov32->iov_base)) {			if (iov != iov_buf)				kfree(iov);			return NULL;		}		if (verify_area(type, (void *)A(buf), len)) {			if (iov != iov_buf)				kfree(iov);			return((struct iovec *)0);		}		ivp->iov_base = (void *)A(buf);		ivp->iov_len = (__kernel_size_t) len;		iov32++;		ivp++;	}	return iov;}asmlinkage longsys32_readv (int fd, struct iovec32 *vector, u32 count){	struct iovec iovstack[UIO_FASTIOV];	struct iovec *iov;	long ret;	mm_segment_t old_fs = get_fs();	iov = get_iovec32(vector, iovstack, count, VERIFY_WRITE);	if (!iov)		return -EFAULT;	set_fs(KERNEL_DS);	ret = sys_readv(fd, iov, count);	set_fs(old_fs);	if (iov != iovstack)		kfree(iov);	return ret;}asmlinkage longsys32_writev (int fd, struct iovec32 *vector, u32 count){	struct iovec iovstack[UIO_FASTIOV];	struct iovec *iov;	long ret;	mm_segment_t old_fs = get_fs();	iov = get_iovec32(vector, iovstack, count, VERIFY_READ);	if (!iov)		return -EFAULT;	set_fs(KERNEL_DS);	ret = sys_writev(fd, iov, count);	set_fs(old_fs);	if (iov != iovstack)		kfree(iov);	return ret;}#define RLIM_INFINITY32	0x7fffffff#define RESOURCE32(x) ((x > RLIM_INFINITY32) ? RLIM_INFINITY32 : x)struct rlimit32 {	int	rlim_cur;	int	rlim_max;};extern asmlinkage long sys_getrlimit (unsigned int resource, struct rlimit *rlim);asmlinkage longsys32_old_getrlimit (unsigned int resource, struct rlimit32 *rlim){	mm_segment_t old_fs = get_fs();	struct rlimit r;	int ret;	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;}asmlinkage longsys32_getrlimit (unsigned int resource, struct rlimit32 *rlim){	mm_segment_t old_fs = get_fs();	struct rlimit r;	int ret;	set_fs(KERNEL_DS);	ret = sys_getrlimit(resource, &r);	set_fs(old_fs);	if (!ret) {		if (r.rlim_cur >= 0xffffffff)			r.rlim_cur = 0xffffffff;		if (r.rlim_max >= 0xffffffff)			r.rlim_max = 0xffffffff;		ret = put_user(r.rlim_cur, &rlim->rlim_cur);		ret |= put_user(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;};struct cmsghdr32 {	__kernel_size_t32 cmsg_len;	int               cmsg_level;	int               cmsg_type;};/* Bleech... */#define __CMSG32_NXTHDR(ctl, len, cmsg, cmsglen) __cmsg32_nxthdr((ctl),(len),(cmsg),(cmsglen))#define CMSG32_NXTHDR(mhdr, cmsg, cmsglen)	cmsg32_nxthdr((mhdr), (cmsg), (cmsglen))#define CMSG32_ALIGN(len) ( ((len)+sizeof(int)-1) & ~(sizeof(int)-1) )#define CMSG32_DATA(cmsg) \	((void *)((char *)(cmsg) + CMSG32_ALIGN(sizeof(struct cmsghdr32))))#define CMSG32_SPACE(len) \	(CMSG32_ALIGN(sizeof(struct cmsghdr32)) + CMSG32_ALIGN(len))#define CMSG32_LEN(len) (CMSG32_ALIGN(sizeof(struct cmsghdr32)) + (len))#define __CMSG32_FIRSTHDR(ctl,len) \	((len) >= sizeof(struct cmsghdr32) ? (struct cmsghdr32 *)(ctl) : (struct cmsghdr32 *)NULL)#define CMSG32_FIRSTHDR(msg)	__CMSG32_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)static inline struct cmsghdr32 *__cmsg32_nxthdr (void *ctl, __kernel_size_t size, struct cmsghdr32 *cmsg, int cmsg_len){	struct cmsghdr32 * ptr;	ptr = (struct cmsghdr32 *)(((unsigned char *) cmsg) + CMSG32_ALIGN(cmsg_len));	if ((unsigned long)((char*)(ptr+1) - (char *) ctl) > size)		return NULL;	return ptr;}static inline struct cmsghdr32 *cmsg32_nxthdr (struct msghdr *msg, struct cmsghdr32 *cmsg, int cmsg_len){	return __cmsg32_nxthdr(msg->msg_control, msg->msg_controllen, cmsg, cmsg_len);}static inline intget_msghdr32 (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;}/* * There is a lot of hair here because the alignment rules (and thus placement) of cmsg * headers and length are different for 32-bit apps.  -DaveM */static intget_cmsghdr32 (struct msghdr *kmsg, unsigned char *stackbuf, struct sock *sk, size_t *bufsize){	struct cmsghdr *kcmsg, *kcmsg_base;	__kernel_size_t kcmlen, tmp;	__kernel_size_t32 ucmlen;	struct cmsghdr32 *ucmsg;	long err;	kcmlen = 0;	kcmsg_base = kcmsg = (struct cmsghdr *)stackbuf;	ucmsg = CMSG32_FIRSTHDR(kmsg);	while (ucmsg != NULL) {		if (get_user(ucmlen, &ucmsg->cmsg_len))			return -EFAULT;		/* Catch bogons. */		if (CMSG32_ALIGN(ucmlen) < CMSG32_ALIGN(sizeof(struct cmsghdr32)))			return -EINVAL;		if ((unsigned long)(((char *)ucmsg - (char *)kmsg->msg_control) + ucmlen)		    > kmsg->msg_controllen)			return -EINVAL;		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +		       CMSG_ALIGN(sizeof(struct cmsghdr)));		kcmlen += tmp;		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);	}	if (kcmlen == 0)		return -EINVAL;	/*	 * The kcmlen holds the 64-bit version of the control length.  It may not be	 * modified as we do not stick it into the kmsg until we have successfully copied	 * over all of the data from the user.	 */	if (kcmlen > *bufsize) {		*bufsize = kcmlen;		kcmsg_base = kcmsg = sock_kmalloc(sk, kcmlen, GFP_KERNEL);	}	if (kcmsg == NULL)		return -ENOBUFS;	/* Now copy them over neatly. */	memset(kcmsg, 0, kcmlen);	ucmsg = CMSG32_FIRSTHDR(kmsg);	while (ucmsg != NULL) {		err = get_user(ucmlen, &ucmsg->cmsg_len);		tmp = ((ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))) +		       CMSG_ALIGN(sizeof(struct cmsghdr)));		kcmsg->cmsg_len = tmp;		err |= get_user(kcmsg->cmsg_level, &ucmsg->cmsg_level);		err |= get_user(kcmsg->cmsg_type, &ucmsg->cmsg_type);		/* Copy over the data. */		err |= copy_from_user(CMSG_DATA(kcmsg), CMSG32_DATA(ucmsg),				      (ucmlen - CMSG32_ALIGN(sizeof(*ucmsg))));		if (err)			goto out_free_efault;		/* Advance. */		kcmsg = (struct cmsghdr *)((char *)kcmsg + CMSG_ALIGN(tmp));		ucmsg = CMSG32_NXTHDR(kmsg, ucmsg, ucmlen);	}	/* Ok, looks like we made it.  Hook it up and return success. */	kmsg->msg_control = kcmsg_base;	kmsg->msg_controllen = kcmlen;	return 0;out_free_efault:	if (kcmsg_base != (struct cmsghdr *)stackbuf)		sock_kfree_s(sk, kcmsg_base, kcmlen);	return -EFAULT;}/* *	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;}static voidput_cmsg32(struct msghdr *kmsg, int level, int type, int len, void *data){	struct cmsghdr32 *cm = (struct cmsghdr32 *) kmsg->msg_control;	struct cmsghdr32 cmhdr;	int cmlen = CMSG32_LEN(len);	if(cm == NULL || kmsg->msg_controllen < sizeof(*cm)) {		kmsg->msg_flags |= MSG_CTRUNC;		return;	}	if(kmsg->msg_controllen < cmlen) {		kmsg->msg_flags |= MSG_CTRUNC;		cmlen = kmsg->msg_controllen;	}	cmhdr.cmsg_level = level;	cmhdr.cmsg_type = type;	cmhdr.cmsg_len = cmlen;

⌨️ 快捷键说明

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