diff options
Diffstat (limited to 'net/compat.c')
| -rw-r--r-- | net/compat.c | 40 | 
1 files changed, 34 insertions, 6 deletions
diff --git a/net/compat.c b/net/compat.c index a407c3addbae..e1a56ade803b 100644 --- a/net/compat.c +++ b/net/compat.c @@ -390,9 +390,6 @@ asmlinkage long compat_sys_setsockopt(int fd, int level, int optname,  	int err;  	struct socket *sock; -	if (optlen < 0) -		return -EINVAL; -  	if ((sock = sockfd_lookup(fd, &err))!=NULL)  	{  		err = security_socket_setsockopt(sock,level,optname); @@ -727,10 +724,10 @@ EXPORT_SYMBOL(compat_mc_getsockopt);  /* Argument list sizes for compat_sys_socketcall */  #define AL(x) ((x) * sizeof(u32)) -static unsigned char nas[19]={AL(0),AL(3),AL(3),AL(3),AL(2),AL(3), +static unsigned char nas[20]={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), -				AL(4)}; +				AL(4),AL(5)};  #undef AL  asmlinkage long compat_sys_sendmsg(int fd, struct compat_msghdr __user *msg, unsigned flags) @@ -755,13 +752,40 @@ asmlinkage long compat_sys_recvfrom(int fd, void __user *buf, size_t len,  	return sys_recvfrom(fd, buf, len, flags | MSG_CMSG_COMPAT, addr, addrlen);  } +asmlinkage long compat_sys_recvmmsg(int fd, struct compat_mmsghdr __user *mmsg, +				    unsigned vlen, unsigned int flags, +				    struct timespec __user *timeout) +{ +	int datagrams; +	struct timespec ktspec; +	struct compat_timespec __user *utspec; + +	if (timeout == NULL) +		return __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, +				      flags | MSG_CMSG_COMPAT, NULL); + +	utspec = (struct compat_timespec __user *)timeout; +	if (get_user(ktspec.tv_sec, &utspec->tv_sec) || +	    get_user(ktspec.tv_nsec, &utspec->tv_nsec)) +		return -EFAULT; + +	datagrams = __sys_recvmmsg(fd, (struct mmsghdr __user *)mmsg, vlen, +				   flags | MSG_CMSG_COMPAT, &ktspec); +	if (datagrams > 0 && +	    (put_user(ktspec.tv_sec, &utspec->tv_sec) || +	     put_user(ktspec.tv_nsec, &utspec->tv_nsec))) +		datagrams = -EFAULT; + +	return datagrams; +} +  asmlinkage long compat_sys_socketcall(int call, u32 __user *args)  {  	int ret;  	u32 a[6];  	u32 a0, a1; -	if (call < SYS_SOCKET || call > SYS_ACCEPT4) +	if (call < SYS_SOCKET || call > SYS_RECVMMSG)  		return -EINVAL;  	if (copy_from_user(a, args, nas[call]))  		return -EFAULT; @@ -823,6 +847,10 @@ asmlinkage long compat_sys_socketcall(int call, u32 __user *args)  	case SYS_RECVMSG:  		ret = compat_sys_recvmsg(a0, compat_ptr(a1), a[2]);  		break; +	case SYS_RECVMMSG: +		ret = compat_sys_recvmmsg(a0, compat_ptr(a1), a[2], a[3], +					  compat_ptr(a[4])); +		break;  	case SYS_ACCEPT4:  		ret = sys_accept4(a0, compat_ptr(a1), compat_ptr(a[2]), a[3]);  		break;  | 
