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

📄 sys_parisc32.c

📁 这个linux源代码是很全面的~基本完整了~使用c编译的~由于时间问题我没有亲自测试~但就算用来做参考资料也是非常好的
💻 C
📖 第 1 页 / 共 5 页
字号:
	unsigned long cmsg_ptr;	int err, total_len, len = 0;	if(msghdr_from_user32_to_kern(&kern_msg, user_msg))		return -EFAULT;	if(kern_msg.msg_iovlen > UIO_MAXIOV)		return -EINVAL;	uaddr = kern_msg.msg_name;	uaddr_len = &user_msg->msg_namelen;	err = verify_iovec32(&kern_msg, iov, addr, VERIFY_WRITE);	if (err < 0)		goto out;	total_len = err;	cmsg_ptr = (unsigned long) kern_msg.msg_control;	kern_msg.msg_flags = 0;	sock = sockfd_lookup(fd, &err);	if (sock != NULL) {		struct scm_cookie scm;		if (sock->file->f_flags & O_NONBLOCK)			user_flags |= MSG_DONTWAIT;		memset(&scm, 0, sizeof(scm));		err = sock->ops->recvmsg(sock, &kern_msg, total_len,					 user_flags, &scm);		if(err >= 0) {			len = err;			if(!kern_msg.msg_control) {				if(sock->passcred || scm.fp)					kern_msg.msg_flags |= MSG_CTRUNC;				if(scm.fp)					__scm_destroy(&scm);			} else {				/* If recvmsg processing itself placed some				 * control messages into user space, it's is				 * using 64-bit CMSG processing, so we need				 * to fix it up before we tack on more stuff.				 */				if((unsigned long) kern_msg.msg_control != cmsg_ptr)					cmsg32_recvmsg_fixup(&kern_msg, cmsg_ptr);				/* Wheee... */				if(sock->passcred)					put_cmsg32(&kern_msg,						   SOL_SOCKET, SCM_CREDENTIALS,						   sizeof(scm.creds), &scm.creds);				if(scm.fp != NULL)					scm_detach_fds32(&kern_msg, &scm);			}		}		sockfd_put(sock);	}	if(uaddr != NULL && err >= 0)		err = move_addr_to_user(addr, kern_msg.msg_namelen, uaddr, uaddr_len);	if(cmsg_ptr != 0 && err >= 0) {		unsigned long ucmsg_ptr = ((unsigned long)kern_msg.msg_control);		__kernel_size_t32 uclen = (__kernel_size_t32) (ucmsg_ptr - cmsg_ptr);		err |= __put_user(uclen, &user_msg->msg_controllen);	}	if(err >= 0)		err = __put_user(kern_msg.msg_flags, &user_msg->msg_flags);	if(kern_msg.msg_iov != iov)		kfree(kern_msg.msg_iov);out:	if(err < 0)		return err;	return len;}extern asmlinkage int sys_setsockopt(int fd, int level, int optname,				     char *optval, int optlen);static int do_set_attach_filter(int fd, int level, int optname,				char *optval, int optlen){	struct sock_fprog32 {		__u16 len;		__u32 filter;	} *fprog32 = (struct sock_fprog32 *)optval;	struct sock_fprog kfprog;	struct sock_filter *kfilter;	unsigned int fsize;	mm_segment_t old_fs;	__u32 uptr;	int ret;	if (get_user(kfprog.len, &fprog32->len) ||	    __get_user(uptr, &fprog32->filter))		return -EFAULT;	kfprog.filter = (struct sock_filter *)A(uptr);	fsize = kfprog.len * sizeof(struct sock_filter);	kfilter = (struct sock_filter *)kmalloc(fsize, GFP_KERNEL);	if (kfilter == NULL)		return -ENOMEM;	if (copy_from_user(kfilter, kfprog.filter, fsize)) {		kfree(kfilter);		return -EFAULT;	}	kfprog.filter = kfilter;	old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_setsockopt(fd, level, optname,			     (char *)&kfprog, sizeof(kfprog));	set_fs(old_fs);	kfree(kfilter);	return ret;}static int do_set_icmpv6_filter(int fd, int level, int optname,				char *optval, int optlen){	struct icmp6_filter kfilter;	mm_segment_t old_fs;	int ret, i;	if (copy_from_user(&kfilter, optval, sizeof(kfilter)))		return -EFAULT;	for (i = 0; i < 8; i += 2) {		u32 tmp = kfilter.data[i];		kfilter.data[i] = kfilter.data[i + 1];		kfilter.data[i + 1] = tmp;	}	old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_setsockopt(fd, level, optname,			     (char *) &kfilter, sizeof(kfilter));	set_fs(old_fs);	return ret;}static int do_ipv4_set_replace(int fd, int level, int optname,				char *optval, int optlen)#if 1/* Fields happen to be padded such that this works.** Don't need to change iptables.h:struct ipt_replace*/{	struct ipt_replace *repl = (struct ipt_replace *) optval;	unsigned long ptr64;	unsigned int ptr32;	int ret;	if (copy_from_user(&ptr32, &repl->counters, sizeof(ptr32)))		return -EFAULT;	ptr64 = (unsigned long) ptr32;	if (copy_to_user(&repl->counters, &ptr64, sizeof(ptr64)))		return -EFAULT;	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);	/* Restore 32-bit ptr */	if (copy_to_user(&repl->counters, &ptr32, sizeof(ptr32)))		return -EFAULT;	return ret;}#else/* This version tries to "do it right". ie allocate kernel buffers for** everything and copy data in/out. Way too complicated.** NOT TESTED for correctness!*/{	struct ipt_replace  *kern_repl;	struct ipt_counters *kern_counters;	unsigned int user_counters;	mm_segment_t old_fs;	int ret = 0;	kern_repl = (struct ipt_replace *) kmalloc(optlen+8, GFP_KERNEL);	if (!kern_repl)		return -ENOMEM;	if (copy_from_user(kern_repl, optval, optlen)) {		ret = -EFAULT;		goto err02;	}	/* 32-bit ptr is in the MSB's */	user_counters = (unsigned int) (((unsigned long) kern_repl->counters) >> 32);	/*	** We are going to set_fs() to kernel space - and thus need	** "relocate" the counters buffer to the kernel space.	*/	kern_counters = (struct ipt_counters *) kmalloc(kern_repl->num_counters * sizeof(struct ipt_counters), GFP_KERNEL);	if (!user_counters) {		ret = -ENOMEM;		goto err02;	}	if (copy_from_user(kern_counters, (char *) user_counters, optlen)) {		ret = -EFAULT;		goto err01;	}	/* We can update the kernel ptr now that we have the data. */	kern_repl->counters = kern_counters;	old_fs = get_fs();	set_fs(KERNEL_DS);	ret = sys_setsockopt(fd, level, optname, (char *) optval, optlen);	set_fs(old_fs);	/* Copy counters back out to user space */	if (copy_to_user((char *) user_counters, kern_counters,			kern_repl->num_counters * sizeof(struct ipt_counters)))	{		ret = -EFAULT;		goto err01;	}	/* restore counters so userspace can consume it */	kern_repl->counters = NULL;	(unsigned int) kern_repl->counters = user_counters;	/* Copy repl back out to user space */	if (copy_to_user(optval, kern_repl, optlen))	{		ret = -EFAULT;	}err01:	kfree(kern_counters);err02:	kfree(kern_repl);	return ret;}#endifasmlinkage int sys32_setsockopt(int fd, int level, int optname,				char *optval, int optlen){	if (optname == SO_ATTACH_FILTER)		return do_set_attach_filter(fd, level, optname, optval, optlen);	if (level == SOL_ICMPV6   && optname == ICMPV6_FILTER)		return do_set_icmpv6_filter(fd, level, optname, optval, optlen);	/*	** Beware:    IPT_SO_SET_REPLACE == IP6T_SO_SET_REPLACE	*/	if (level == IPPROTO_IP   && optname == IPT_SO_SET_REPLACE)		return do_ipv4_set_replace(fd, level, optname, optval, optlen);	if (level == IPPROTO_IPV6 && optname == IP6T_SO_SET_REPLACE)#if 0		/* FIXME: I don't (yet) use IPV6. -ggg */		return do_ipv6_set_replace(fd, level, optname, optval, optlen);#else	{		BUG();		return -ENXIO;	}#endif	return sys_setsockopt(fd, level, optname, optval, optlen);}/*** copied from mips64 ***//* * Ooo, nasty.  We need here to frob 32-bit unsigned longs to * 64-bit unsigned longs. */static inline intget_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset){	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));	if (ufdset) {		unsigned long odd;		if (verify_area(VERIFY_WRITE, ufdset, n*sizeof(u32)))			return -EFAULT;		odd = n & 1UL;		n &= ~1UL;		while (n) {			unsigned long h, l;			__get_user(l, ufdset);			__get_user(h, ufdset+1);			ufdset += 2;			*fdset++ = h << 32 | l;			n -= 2;		}		if (odd)			__get_user(*fdset, ufdset);	} else {		/* Tricky, must clear full unsigned long in the		 * kernel fdset at the end, this makes sure that		 * actually happens.		 */		memset(fdset, 0, ((n + 1) & ~1)*sizeof(u32));	}	return 0;}static inline voidset_fd_set32(unsigned long n, u32 *ufdset, unsigned long *fdset){	unsigned long odd;	n = (n + 8*sizeof(u32) - 1) / (8*sizeof(u32));	if (!ufdset)		return;	odd = n & 1UL;	n &= ~1UL;	while (n) {		unsigned long h, l;		l = *fdset++;		h = l >> 32;		__put_user(l, ufdset);		__put_user(h, ufdset+1);		ufdset += 2;		n -= 2;	}	if (odd)		__put_user(*fdset, ufdset);}/*** This is a virtual copy of sys_select from fs/select.c and probably *** should be compared to it from time to time ***/static inline void *select_bits_alloc(int size){	return kmalloc(6 * size, GFP_KERNEL);}static inline void select_bits_free(void *bits, int size){	kfree(bits);}/* * We can actually return ERESTARTSYS instead of EINTR, but I'd * like to be certain this leads to no problems. So I return * EINTR just for safety. * * Update: ERESTARTSYS breaks at least the xview clock binary, so * I'm trying ERESTARTNOHAND which restart only when you want to. */#define MAX_SELECT_SECONDS \	((unsigned long) (MAX_SCHEDULE_TIMEOUT / HZ)-1)#define DIVIDE_ROUND_UP(x,y) (((x)+(y)-1)/(y))asmlinkage longsys32_select(int n, u32 *inp, u32 *outp, u32 *exp, struct timeval32 *tvp){	fd_set_bits fds;	char *bits;	long timeout;	int ret, size, err;	timeout = MAX_SCHEDULE_TIMEOUT;	if (tvp) {		struct timeval32 tv32;		time_t sec, usec;		if ((ret = copy_from_user(&tv32, tvp, sizeof tv32)))			goto out_nofds;		sec = tv32.tv_sec;		usec = tv32.tv_usec;		ret = -EINVAL;		if (sec < 0 || usec < 0)			goto out_nofds;		if ((unsigned long) sec < MAX_SELECT_SECONDS) {			timeout = DIVIDE_ROUND_UP(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 = select_bits_alloc(size);	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_set32(n, inp, fds.in)) ||	    (ret = get_fd_set32(n, outp, fds.out)) ||	    (ret = get_fd_set32(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 (tvp && !(current->personality & STICKY_TIMEOUTS)) {		time_t sec = 0, usec = 0;		if (timeout) {			sec = timeout / HZ;			usec = timeout % HZ;			usec *= (1000000/HZ);		}		err = put_user(sec, &tvp->tv_sec);		err |= __put_user(usec, &tvp->tv_usec);		if (err)			ret = -EFAULT;	}	if (ret < 0)		goto out;	if (!ret) {		ret = -ERESTARTNOHAND;		if (signal_pending(current))			goto out;		ret = 0;	}	set_fd_set32(n, inp, fds.res_in);	set_fd_set32(n, outp, fds.res_out);	set_fd_set32(n, exp, fds.res_ex);out:	select_bits_free(bits, size);out_nofds:	return ret;}struct msgbuf32 {    int mtype;    char mtext[1];};asmlinkage long sys32_msgsnd(int msqid,				struct msgbuf32 *umsgp32,				size_t msgsz, int msgflg){	struct msgbuf *mb;	struct msgbuf32 mb32;	int err;	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)		return -ENOMEM;	err = get_user(mb32.mtype, &umsgp32->mtype);	mb->mtype = mb32.mtype;	err |= copy_from_user(mb->mtext, &umsgp32->mtext, msgsz);	if (err)		err = -EFAULT;	else		KERNEL_SYSCALL(err, sys_msgsnd, msqid, mb, msgsz, msgflg);	kfree(mb);	return err;}asmlinkage long sys32_msgrcv(int msqid,				struct msgbuf32 *umsgp32,				size_t msgsz, long msgtyp, int msgflg){	struct msgbuf *mb;	struct msgbuf32 mb32;	int err, len;	if ((mb = kmalloc(msgsz + sizeof *mb + 4, GFP_KERNEL)) == NULL)		return -ENOMEM;	KERNEL_SYSCALL(err, sys_msgrcv, msqid, mb, msgsz, msgtyp, msgflg);	if (err >= 0) {		len = err;		mb32.mtype = mb->mtype;		err = put_user(mb32.mtype, &umsgp32->mtype);		err |= copy_to_user(&umsgp32->mtext, mb->mtext, len);		if (err)			err = -EFAULT;		else			err = len;	}	kfree(mb);	return err;}/* LFS */extern asmlinkage long sys_truncate(const char *, loff_t);extern asmlinkage long sys_ftruncate(unsigned int, loff_t);extern asmlinkage long sys_fcntl(unsigned int, unsigned int, unsigned long);extern asmlinkage ssize_t sys_pread(unsigned int, char *, size_t, loff_t);extern asmlinkage ssize_t sys_pwrite(unsigned int, char *, size_t, loff_t);asmlinkage long sys32_truncate64(const char * path, unsigned int high, unsigned int low){	return sys_truncate(path, (loff_t)high << 32 | low);}asmlinkage long sys32_ftruncate64(unsigned int fd, unsigned int high, unsigned int low){	return sys_ftruncate(fd, (loff_t)high << 32 | low);}asmlinkage long sys32_fcntl64(unsigned int fd, unsigned int cmd, unsigned long arg){	switch (cmd) {		case F_GETLK64:			cmd = F_GETLK;			break;		case F_SETLK64:			cmd = F_SETLK;			break;		case F_SETLKW64:			cmd = F_SETLKW;			break;		default:			break;	}	return sys_fcntl(fd, cmd, arg);}asmlinkage int sys32_pread(int fd, void *buf, size

⌨️ 快捷键说明

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