forked from mirrors/linux
		
	net: rework SIOCGSTAMP ioctl handling
The SIOCGSTAMP/SIOCGSTAMPNS ioctl commands are implemented by many socket protocol handlers, and all of those end up calling the same sock_get_timestamp()/sock_get_timestampns() helper functions, which results in a lot of duplicate code. With the introduction of 64-bit time_t on 32-bit architectures, this gets worse, as we then need four different ioctl commands in each socket protocol implementation. To simplify that, let's add a new .gettstamp() operation in struct proto_ops, and move ioctl implementation into the common sock_ioctl()/compat_sock_ioctl_trans() functions that these all go through. We can reuse the sock_get_timestamp() implementation, but generalize it so it can deal with both native and compat mode, as well as timeval and timespec structures. Acked-by: Stefan Schmidt <stefan@datenfreihafen.org> Acked-by: Neil Horman <nhorman@tuxdriver.com> Acked-by: Marc Kleine-Budde <mkl@pengutronix.de> Link: https://lore.kernel.org/lkml/CAK8P3a038aDQQotzua_QtKGhq8O9n+rdiz2=WDCp82ys8eUT+A@mail.gmail.com/ Signed-off-by: Arnd Bergmann <arnd@arndb.de> Acked-by: Willem de Bruijn <willemb@google.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
		
							parent
							
								
									1ab839281c
								
							
						
					
					
						commit
						c7cbdbf29f
					
				
					 33 changed files with 76 additions and 233 deletions
				
			
		|  | @ -161,6 +161,8 @@ struct proto_ops { | ||||||
| 	int	 	(*compat_ioctl) (struct socket *sock, unsigned int cmd, | 	int	 	(*compat_ioctl) (struct socket *sock, unsigned int cmd, | ||||||
| 				      unsigned long arg); | 				      unsigned long arg); | ||||||
| #endif | #endif | ||||||
|  | 	int		(*gettstamp) (struct socket *sock, void __user *userstamp, | ||||||
|  | 				      bool timeval, bool time32); | ||||||
| 	int		(*listen)    (struct socket *sock, int len); | 	int		(*listen)    (struct socket *sock, int len); | ||||||
| 	int		(*shutdown)  (struct socket *sock, int flags); | 	int		(*shutdown)  (struct socket *sock, int flags); | ||||||
| 	int		(*setsockopt)(struct socket *sock, int level, | 	int		(*setsockopt)(struct socket *sock, int level, | ||||||
|  |  | ||||||
|  | @ -30,9 +30,6 @@ struct compat_cmsghdr { | ||||||
| 	compat_int_t	cmsg_type; | 	compat_int_t	cmsg_type; | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| int compat_sock_get_timestamp(struct sock *, struct timeval __user *); |  | ||||||
| int compat_sock_get_timestampns(struct sock *, struct timespec __user *); |  | ||||||
| 
 |  | ||||||
| #else /* defined(CONFIG_COMPAT) */ | #else /* defined(CONFIG_COMPAT) */ | ||||||
| /*
 | /*
 | ||||||
|  * To avoid compiler warnings: |  * To avoid compiler warnings: | ||||||
|  |  | ||||||
|  | @ -1614,6 +1614,8 @@ int sock_setsockopt(struct socket *sock, int level, int op, | ||||||
| 
 | 
 | ||||||
| int sock_getsockopt(struct socket *sock, int level, int op, | int sock_getsockopt(struct socket *sock, int level, int op, | ||||||
| 		    char __user *optval, int __user *optlen); | 		    char __user *optval, int __user *optlen); | ||||||
|  | int sock_gettstamp(struct socket *sock, void __user *userstamp, | ||||||
|  | 		   bool timeval, bool time32); | ||||||
| struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | struct sk_buff *sock_alloc_send_skb(struct sock *sk, unsigned long size, | ||||||
| 				    int noblock, int *errcode); | 				    int noblock, int *errcode); | ||||||
| struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | struct sk_buff *sock_alloc_send_pskb(struct sock *sk, unsigned long header_len, | ||||||
|  | @ -2503,8 +2505,6 @@ static inline bool sk_listener(const struct sock *sk) | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| void sock_enable_timestamp(struct sock *sk, int flag); | void sock_enable_timestamp(struct sock *sk, int flag); | ||||||
| int sock_get_timestamp(struct sock *, struct timeval __user *); |  | ||||||
| int sock_get_timestampns(struct sock *, struct timespec __user *); |  | ||||||
| int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level, | int sock_recv_errqueue(struct sock *sk, struct msghdr *msg, int len, int level, | ||||||
| 		       int type); | 		       int type); | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1806,12 +1806,6 @@ static int atalk_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		rc = put_user(amount, (int __user *)argp); | 		rc = put_user(amount, (int __user *)argp); | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		rc = sock_get_timestamp(sk, argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		rc = sock_get_timestampns(sk, argp); |  | ||||||
| 		break; |  | ||||||
| 	/* Routing */ | 	/* Routing */ | ||||||
| 	case SIOCADDRT: | 	case SIOCADDRT: | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
|  | @ -1871,6 +1865,7 @@ static const struct proto_ops atalk_dgram_ops = { | ||||||
| 	.getname	= atalk_getname, | 	.getname	= atalk_getname, | ||||||
| 	.poll		= datagram_poll, | 	.poll		= datagram_poll, | ||||||
| 	.ioctl		= atalk_ioctl, | 	.ioctl		= atalk_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| #ifdef CONFIG_COMPAT | #ifdef CONFIG_COMPAT | ||||||
| 	.compat_ioctl	= atalk_compat_ioctl, | 	.compat_ioctl	= atalk_compat_ioctl, | ||||||
| #endif | #endif | ||||||
|  |  | ||||||
|  | @ -81,22 +81,6 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd, | ||||||
| 				 (int __user *)argp) ? -EFAULT : 0; | 				 (int __user *)argp) ? -EFAULT : 0; | ||||||
| 		goto done; | 		goto done; | ||||||
| 	} | 	} | ||||||
| 	case SIOCGSTAMP: /* borrowed from IP */ |  | ||||||
| #ifdef CONFIG_COMPAT |  | ||||||
| 		if (compat) |  | ||||||
| 			error = compat_sock_get_timestamp(sk, argp); |  | ||||||
| 		else |  | ||||||
| #endif |  | ||||||
| 			error = sock_get_timestamp(sk, argp); |  | ||||||
| 		goto done; |  | ||||||
| 	case SIOCGSTAMPNS: /* borrowed from IP */ |  | ||||||
| #ifdef CONFIG_COMPAT |  | ||||||
| 		if (compat) |  | ||||||
| 			error = compat_sock_get_timestampns(sk, argp); |  | ||||||
| 		else |  | ||||||
| #endif |  | ||||||
| 			error = sock_get_timestampns(sk, argp); |  | ||||||
| 		goto done; |  | ||||||
| 	case ATM_SETSC: | 	case ATM_SETSC: | ||||||
| 		net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n", | 		net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n", | ||||||
| 				     current->comm, task_pid_nr(current)); | 				     current->comm, task_pid_nr(current)); | ||||||
|  |  | ||||||
|  | @ -118,6 +118,7 @@ static const struct proto_ops pvc_proto_ops = { | ||||||
| #ifdef CONFIG_COMPAT | #ifdef CONFIG_COMPAT | ||||||
| 	.compat_ioctl = vcc_compat_ioctl, | 	.compat_ioctl = vcc_compat_ioctl, | ||||||
| #endif | #endif | ||||||
|  | 	.gettstamp =	sock_gettstamp, | ||||||
| 	.listen =	sock_no_listen, | 	.listen =	sock_no_listen, | ||||||
| 	.shutdown =	pvc_shutdown, | 	.shutdown =	pvc_shutdown, | ||||||
| 	.setsockopt =	pvc_setsockopt, | 	.setsockopt =	pvc_setsockopt, | ||||||
|  |  | ||||||
|  | @ -641,6 +641,7 @@ static const struct proto_ops svc_proto_ops = { | ||||||
| #ifdef CONFIG_COMPAT | #ifdef CONFIG_COMPAT | ||||||
| 	.compat_ioctl =	svc_compat_ioctl, | 	.compat_ioctl =	svc_compat_ioctl, | ||||||
| #endif | #endif | ||||||
|  | 	.gettstamp =	sock_gettstamp, | ||||||
| 	.listen =	svc_listen, | 	.listen =	svc_listen, | ||||||
| 	.shutdown =	svc_shutdown, | 	.shutdown =	svc_shutdown, | ||||||
| 	.setsockopt =	svc_setsockopt, | 	.setsockopt =	svc_setsockopt, | ||||||
|  |  | ||||||
|  | @ -1714,14 +1714,6 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		res = sock_get_timestamp(sk, argp); |  | ||||||
| 		break; |  | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		res = sock_get_timestampns(sk, argp); |  | ||||||
| 		break; |  | ||||||
| 
 |  | ||||||
| 	case SIOCAX25ADDUID:	/* Add a uid to the uid/call map table */ | 	case SIOCAX25ADDUID:	/* Add a uid to the uid/call map table */ | ||||||
| 	case SIOCAX25DELUID:	/* Delete a uid from the uid/call map table */ | 	case SIOCAX25DELUID:	/* Delete a uid from the uid/call map table */ | ||||||
| 	case SIOCAX25GETUID: { | 	case SIOCAX25GETUID: { | ||||||
|  | @ -1950,6 +1942,7 @@ static const struct proto_ops ax25_proto_ops = { | ||||||
| 	.getname	= ax25_getname, | 	.getname	= ax25_getname, | ||||||
| 	.poll		= datagram_poll, | 	.poll		= datagram_poll, | ||||||
| 	.ioctl		= ax25_ioctl, | 	.ioctl		= ax25_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| 	.listen		= ax25_listen, | 	.listen		= ax25_listen, | ||||||
| 	.shutdown	= ax25_shutdown, | 	.shutdown	= ax25_shutdown, | ||||||
| 	.setsockopt	= ax25_setsockopt, | 	.setsockopt	= ax25_setsockopt, | ||||||
|  |  | ||||||
|  | @ -521,14 +521,6 @@ int bt_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		err = put_user(amount, (int __user *) arg); | 		err = put_user(amount, (int __user *) arg); | ||||||
| 		break; | 		break; | ||||||
| 
 | 
 | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		err = sock_get_timestamp(sk, (struct timeval __user *) arg); |  | ||||||
| 		break; |  | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		err = sock_get_timestampns(sk, (struct timespec __user *) arg); |  | ||||||
| 		break; |  | ||||||
| 
 |  | ||||||
| 	default: | 	default: | ||||||
| 		err = -ENOIOCTLCMD; | 		err = -ENOIOCTLCMD; | ||||||
| 		break; | 		break; | ||||||
|  |  | ||||||
|  | @ -1655,6 +1655,7 @@ static const struct proto_ops l2cap_sock_ops = { | ||||||
| 	.recvmsg	= l2cap_sock_recvmsg, | 	.recvmsg	= l2cap_sock_recvmsg, | ||||||
| 	.poll		= bt_sock_poll, | 	.poll		= bt_sock_poll, | ||||||
| 	.ioctl		= bt_sock_ioctl, | 	.ioctl		= bt_sock_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| 	.mmap		= sock_no_mmap, | 	.mmap		= sock_no_mmap, | ||||||
| 	.socketpair	= sock_no_socketpair, | 	.socketpair	= sock_no_socketpair, | ||||||
| 	.shutdown	= l2cap_sock_shutdown, | 	.shutdown	= l2cap_sock_shutdown, | ||||||
|  |  | ||||||
|  | @ -1039,6 +1039,7 @@ static const struct proto_ops rfcomm_sock_ops = { | ||||||
| 	.setsockopt	= rfcomm_sock_setsockopt, | 	.setsockopt	= rfcomm_sock_setsockopt, | ||||||
| 	.getsockopt	= rfcomm_sock_getsockopt, | 	.getsockopt	= rfcomm_sock_getsockopt, | ||||||
| 	.ioctl		= rfcomm_sock_ioctl, | 	.ioctl		= rfcomm_sock_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| 	.poll		= bt_sock_poll, | 	.poll		= bt_sock_poll, | ||||||
| 	.socketpair	= sock_no_socketpair, | 	.socketpair	= sock_no_socketpair, | ||||||
| 	.mmap		= sock_no_mmap | 	.mmap		= sock_no_mmap | ||||||
|  |  | ||||||
|  | @ -1190,6 +1190,7 @@ static const struct proto_ops sco_sock_ops = { | ||||||
| 	.recvmsg	= sco_sock_recvmsg, | 	.recvmsg	= sco_sock_recvmsg, | ||||||
| 	.poll		= bt_sock_poll, | 	.poll		= bt_sock_poll, | ||||||
| 	.ioctl		= bt_sock_ioctl, | 	.ioctl		= bt_sock_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| 	.mmap		= sock_no_mmap, | 	.mmap		= sock_no_mmap, | ||||||
| 	.socketpair	= sock_no_socketpair, | 	.socketpair	= sock_no_socketpair, | ||||||
| 	.shutdown	= sco_sock_shutdown, | 	.shutdown	= sco_sock_shutdown, | ||||||
|  |  | ||||||
|  | @ -89,13 +89,7 @@ static atomic_t skbcounter = ATOMIC_INIT(0); | ||||||
| 
 | 
 | ||||||
| int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | int can_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; |  | ||||||
| 
 |  | ||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		return sock_get_timestamp(sk, (struct timeval __user *)arg); |  | ||||||
| 
 |  | ||||||
| 	default: | 	default: | ||||||
| 		return -ENOIOCTLCMD; | 		return -ENOIOCTLCMD; | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | @ -1689,6 +1689,7 @@ static const struct proto_ops bcm_ops = { | ||||||
| 	.getname       = sock_no_getname, | 	.getname       = sock_no_getname, | ||||||
| 	.poll          = datagram_poll, | 	.poll          = datagram_poll, | ||||||
| 	.ioctl         = can_ioctl,	/* use can_ioctl() from af_can.c */ | 	.ioctl         = can_ioctl,	/* use can_ioctl() from af_can.c */ | ||||||
|  | 	.gettstamp     = sock_gettstamp, | ||||||
| 	.listen        = sock_no_listen, | 	.listen        = sock_no_listen, | ||||||
| 	.shutdown      = sock_no_shutdown, | 	.shutdown      = sock_no_shutdown, | ||||||
| 	.setsockopt    = sock_no_setsockopt, | 	.setsockopt    = sock_no_setsockopt, | ||||||
|  |  | ||||||
|  | @ -846,6 +846,7 @@ static const struct proto_ops raw_ops = { | ||||||
| 	.getname       = raw_getname, | 	.getname       = raw_getname, | ||||||
| 	.poll          = datagram_poll, | 	.poll          = datagram_poll, | ||||||
| 	.ioctl         = can_ioctl,	/* use can_ioctl() from af_can.c */ | 	.ioctl         = can_ioctl,	/* use can_ioctl() from af_can.c */ | ||||||
|  | 	.gettstamp     = sock_gettstamp, | ||||||
| 	.listen        = sock_no_listen, | 	.listen        = sock_no_listen, | ||||||
| 	.shutdown      = sock_no_shutdown, | 	.shutdown      = sock_no_shutdown, | ||||||
| 	.setsockopt    = raw_setsockopt, | 	.setsockopt    = raw_setsockopt, | ||||||
|  |  | ||||||
							
								
								
									
										57
									
								
								net/compat.c
									
									
									
									
									
								
							
							
						
						
									
										57
									
								
								net/compat.c
									
									
									
									
									
								
							|  | @ -395,63 +395,6 @@ COMPAT_SYSCALL_DEFINE5(setsockopt, int, fd, int, level, int, optname, | ||||||
| 	return __compat_sys_setsockopt(fd, level, optname, optval, optlen); | 	return __compat_sys_setsockopt(fd, level, optname, optval, optlen); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| int compat_sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) |  | ||||||
| { |  | ||||||
| 	struct compat_timeval __user *ctv; |  | ||||||
| 	int err; |  | ||||||
| 	struct timeval tv; |  | ||||||
| 
 |  | ||||||
| 	if (COMPAT_USE_64BIT_TIME) |  | ||||||
| 		return sock_get_timestamp(sk, userstamp); |  | ||||||
| 
 |  | ||||||
| 	ctv = (struct compat_timeval __user *) userstamp; |  | ||||||
| 	err = -ENOENT; |  | ||||||
| 	sock_enable_timestamp(sk, SOCK_TIMESTAMP); |  | ||||||
| 	tv = ktime_to_timeval(sock_read_timestamp(sk)); |  | ||||||
| 
 |  | ||||||
| 	if (tv.tv_sec == -1) |  | ||||||
| 		return err; |  | ||||||
| 	if (tv.tv_sec == 0) { |  | ||||||
| 		ktime_t kt = ktime_get_real(); |  | ||||||
| 		sock_write_timestamp(sk, kt); |  | ||||||
| 		tv = ktime_to_timeval(kt); |  | ||||||
| 	} |  | ||||||
| 	err = 0; |  | ||||||
| 	if (put_user(tv.tv_sec, &ctv->tv_sec) || |  | ||||||
| 			put_user(tv.tv_usec, &ctv->tv_usec)) |  | ||||||
| 		err = -EFAULT; |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| EXPORT_SYMBOL(compat_sock_get_timestamp); |  | ||||||
| 
 |  | ||||||
| int compat_sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) |  | ||||||
| { |  | ||||||
| 	struct compat_timespec __user *ctv; |  | ||||||
| 	int err; |  | ||||||
| 	struct timespec ts; |  | ||||||
| 
 |  | ||||||
| 	if (COMPAT_USE_64BIT_TIME) |  | ||||||
| 		return sock_get_timestampns (sk, userstamp); |  | ||||||
| 
 |  | ||||||
| 	ctv = (struct compat_timespec __user *) userstamp; |  | ||||||
| 	err = -ENOENT; |  | ||||||
| 	sock_enable_timestamp(sk, SOCK_TIMESTAMP); |  | ||||||
| 	ts = ktime_to_timespec(sock_read_timestamp(sk)); |  | ||||||
| 	if (ts.tv_sec == -1) |  | ||||||
| 		return err; |  | ||||||
| 	if (ts.tv_sec == 0) { |  | ||||||
| 		ktime_t kt = ktime_get_real(); |  | ||||||
| 		sock_write_timestamp(sk, kt); |  | ||||||
| 		ts = ktime_to_timespec(kt); |  | ||||||
| 	} |  | ||||||
| 	err = 0; |  | ||||||
| 	if (put_user(ts.tv_sec, &ctv->tv_sec) || |  | ||||||
| 			put_user(ts.tv_nsec, &ctv->tv_nsec)) |  | ||||||
| 		err = -EFAULT; |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| EXPORT_SYMBOL(compat_sock_get_timestampns); |  | ||||||
| 
 |  | ||||||
| static int __compat_sys_getsockopt(int fd, int level, int optname, | static int __compat_sys_getsockopt(int fd, int level, int optname, | ||||||
| 				   char __user *optval, | 				   char __user *optval, | ||||||
| 				   int __user *optlen) | 				   int __user *optlen) | ||||||
|  |  | ||||||
|  | @ -2977,39 +2977,44 @@ bool lock_sock_fast(struct sock *sk) | ||||||
| } | } | ||||||
| EXPORT_SYMBOL(lock_sock_fast); | EXPORT_SYMBOL(lock_sock_fast); | ||||||
| 
 | 
 | ||||||
| int sock_get_timestamp(struct sock *sk, struct timeval __user *userstamp) | int sock_gettstamp(struct socket *sock, void __user *userstamp, | ||||||
|  | 		   bool timeval, bool time32) | ||||||
| { | { | ||||||
| 	struct timeval tv; | 	struct sock *sk = sock->sk; | ||||||
|  | 	struct timespec64 ts; | ||||||
| 
 | 
 | ||||||
| 	sock_enable_timestamp(sk, SOCK_TIMESTAMP); | 	sock_enable_timestamp(sk, SOCK_TIMESTAMP); | ||||||
| 	tv = ktime_to_timeval(sock_read_timestamp(sk)); | 	ts = ktime_to_timespec64(sock_read_timestamp(sk)); | ||||||
| 	if (tv.tv_sec == -1) |  | ||||||
| 		return -ENOENT; |  | ||||||
| 	if (tv.tv_sec == 0) { |  | ||||||
| 		ktime_t kt = ktime_get_real(); |  | ||||||
| 		sock_write_timestamp(sk, kt); |  | ||||||
| 		tv = ktime_to_timeval(kt); |  | ||||||
| 	} |  | ||||||
| 	return copy_to_user(userstamp, &tv, sizeof(tv)) ? -EFAULT : 0; |  | ||||||
| } |  | ||||||
| EXPORT_SYMBOL(sock_get_timestamp); |  | ||||||
| 
 |  | ||||||
| int sock_get_timestampns(struct sock *sk, struct timespec __user *userstamp) |  | ||||||
| { |  | ||||||
| 	struct timespec ts; |  | ||||||
| 
 |  | ||||||
| 	sock_enable_timestamp(sk, SOCK_TIMESTAMP); |  | ||||||
| 	ts = ktime_to_timespec(sock_read_timestamp(sk)); |  | ||||||
| 	if (ts.tv_sec == -1) | 	if (ts.tv_sec == -1) | ||||||
| 		return -ENOENT; | 		return -ENOENT; | ||||||
| 	if (ts.tv_sec == 0) { | 	if (ts.tv_sec == 0) { | ||||||
| 		ktime_t kt = ktime_get_real(); | 		ktime_t kt = ktime_get_real(); | ||||||
| 		sock_write_timestamp(sk, kt); | 		sock_write_timestamp(sk, kt);; | ||||||
| 		ts = ktime_to_timespec(sk->sk_stamp); | 		ts = ktime_to_timespec64(kt); | ||||||
| 	} | 	} | ||||||
| 	return copy_to_user(userstamp, &ts, sizeof(ts)) ? -EFAULT : 0; | 
 | ||||||
|  | 	if (timeval) | ||||||
|  | 		ts.tv_nsec /= 1000; | ||||||
|  | 
 | ||||||
|  | #ifdef CONFIG_COMPAT_32BIT_TIME | ||||||
|  | 	if (time32) | ||||||
|  | 		return put_old_timespec32(&ts, userstamp); | ||||||
|  | #endif | ||||||
|  | #ifdef CONFIG_SPARC64 | ||||||
|  | 	/* beware of padding in sparc64 timeval */ | ||||||
|  | 	if (timeval && !in_compat_syscall()) { | ||||||
|  | 		struct __kernel_old_timeval __user tv = { | ||||||
|  | 			.tv_sec = ts.tv_sec; | ||||||
|  | 			.tv_usec = ts.tv_nsec; | ||||||
|  | 		}; | ||||||
|  | 		if (copy_to_user(userstamp, &tv, sizeof(tv)) | ||||||
|  | 			return -EFAULT; | ||||||
|  | 		return 0; | ||||||
| 	} | 	} | ||||||
| EXPORT_SYMBOL(sock_get_timestampns); | #endif | ||||||
|  | 	return put_timespec64(&ts, userstamp); | ||||||
|  | } | ||||||
|  | EXPORT_SYMBOL(sock_gettstamp); | ||||||
| 
 | 
 | ||||||
| void sock_enable_timestamp(struct sock *sk, int flag) | void sock_enable_timestamp(struct sock *sk, int flag) | ||||||
| { | { | ||||||
|  |  | ||||||
|  | @ -991,6 +991,7 @@ static const struct proto_ops inet_dccp_ops = { | ||||||
| 	/* FIXME: work on tcp_poll to rename it to inet_csk_poll */ | 	/* FIXME: work on tcp_poll to rename it to inet_csk_poll */ | ||||||
| 	.poll		   = dccp_poll, | 	.poll		   = dccp_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	/* FIXME: work on inet_listen to rename it to sock_common_listen */ | 	/* FIXME: work on inet_listen to rename it to sock_common_listen */ | ||||||
| 	.listen		   = inet_dccp_listen, | 	.listen		   = inet_dccp_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
|  |  | ||||||
|  | @ -1075,6 +1075,7 @@ static const struct proto_ops inet6_dccp_ops = { | ||||||
| 	.getname	   = inet6_getname, | 	.getname	   = inet6_getname, | ||||||
| 	.poll		   = dccp_poll, | 	.poll		   = dccp_poll, | ||||||
| 	.ioctl		   = inet6_ioctl, | 	.ioctl		   = inet6_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = inet_dccp_listen, | 	.listen		   = inet_dccp_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -164,10 +164,6 @@ static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd, | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 
 | 
 | ||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		return sock_get_timestamp(sk, (struct timeval __user *)arg); |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		return sock_get_timestampns(sk, (struct timespec __user *)arg); |  | ||||||
| 	case SIOCGIFADDR: | 	case SIOCGIFADDR: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
| 		return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, | 		return ieee802154_dev_ioctl(sk, (struct ifreq __user *)arg, | ||||||
|  | @ -426,6 +422,7 @@ static const struct proto_ops ieee802154_raw_ops = { | ||||||
| 	.getname	   = sock_no_getname, | 	.getname	   = sock_no_getname, | ||||||
| 	.poll		   = datagram_poll, | 	.poll		   = datagram_poll, | ||||||
| 	.ioctl		   = ieee802154_sock_ioctl, | 	.ioctl		   = ieee802154_sock_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = sock_no_shutdown, | 	.shutdown	   = sock_no_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  | @ -988,6 +985,7 @@ static const struct proto_ops ieee802154_dgram_ops = { | ||||||
| 	.getname	   = sock_no_getname, | 	.getname	   = sock_no_getname, | ||||||
| 	.poll		   = datagram_poll, | 	.poll		   = datagram_poll, | ||||||
| 	.ioctl		   = ieee802154_sock_ioctl, | 	.ioctl		   = ieee802154_sock_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = sock_no_shutdown, | 	.shutdown	   = sock_no_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -915,12 +915,6 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 	struct rtentry rt; | 	struct rtentry rt; | ||||||
| 
 | 
 | ||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		err = sock_get_timestamp(sk, (struct timeval __user *)arg); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		err = sock_get_timestampns(sk, (struct timespec __user *)arg); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCADDRT: | 	case SIOCADDRT: | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
| 		if (copy_from_user(&rt, p, sizeof(struct rtentry))) | 		if (copy_from_user(&rt, p, sizeof(struct rtentry))) | ||||||
|  | @ -992,6 +986,7 @@ const struct proto_ops inet_stream_ops = { | ||||||
| 	.getname	   = inet_getname, | 	.getname	   = inet_getname, | ||||||
| 	.poll		   = tcp_poll, | 	.poll		   = tcp_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = inet_listen, | 	.listen		   = inet_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  | @ -1027,6 +1022,7 @@ const struct proto_ops inet_dgram_ops = { | ||||||
| 	.getname	   = inet_getname, | 	.getname	   = inet_getname, | ||||||
| 	.poll		   = udp_poll, | 	.poll		   = udp_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  | @ -1059,6 +1055,7 @@ static const struct proto_ops inet_sockraw_ops = { | ||||||
| 	.getname	   = inet_getname, | 	.getname	   = inet_getname, | ||||||
| 	.poll		   = datagram_poll, | 	.poll		   = datagram_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -547,12 +547,6 @@ int inet6_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 	struct net *net = sock_net(sk); | 	struct net *net = sock_net(sk); | ||||||
| 
 | 
 | ||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		return sock_get_timestamp(sk, (struct timeval __user *)arg); |  | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		return sock_get_timestampns(sk, (struct timespec __user *)arg); |  | ||||||
| 
 |  | ||||||
| 	case SIOCADDRT: | 	case SIOCADDRT: | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
| 
 | 
 | ||||||
|  | @ -585,6 +579,7 @@ const struct proto_ops inet6_stream_ops = { | ||||||
| 	.getname	   = inet6_getname, | 	.getname	   = inet6_getname, | ||||||
| 	.poll		   = tcp_poll,			/* ok		*/ | 	.poll		   = tcp_poll,			/* ok		*/ | ||||||
| 	.ioctl		   = inet6_ioctl,		/* must change  */ | 	.ioctl		   = inet6_ioctl,		/* must change  */ | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = inet_listen,		/* ok		*/ | 	.listen		   = inet_listen,		/* ok		*/ | ||||||
| 	.shutdown	   = inet_shutdown,		/* ok		*/ | 	.shutdown	   = inet_shutdown,		/* ok		*/ | ||||||
| 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | ||||||
|  | @ -618,6 +613,7 @@ const struct proto_ops inet6_dgram_ops = { | ||||||
| 	.getname	   = inet6_getname, | 	.getname	   = inet6_getname, | ||||||
| 	.poll		   = udp_poll,			/* ok		*/ | 	.poll		   = udp_poll,			/* ok		*/ | ||||||
| 	.ioctl		   = inet6_ioctl,		/* must change  */ | 	.ioctl		   = inet6_ioctl,		/* must change  */ | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen,		/* ok		*/ | 	.listen		   = sock_no_listen,		/* ok		*/ | ||||||
| 	.shutdown	   = inet_shutdown,		/* ok		*/ | 	.shutdown	   = inet_shutdown,		/* ok		*/ | ||||||
| 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | ||||||
|  |  | ||||||
|  | @ -1356,6 +1356,7 @@ const struct proto_ops inet6_sockraw_ops = { | ||||||
| 	.getname	   = inet6_getname, | 	.getname	   = inet6_getname, | ||||||
| 	.poll		   = datagram_poll,		/* ok		*/ | 	.poll		   = datagram_poll,		/* ok		*/ | ||||||
| 	.ioctl		   = inet6_ioctl,		/* must change  */ | 	.ioctl		   = inet6_ioctl,		/* must change  */ | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen,		/* ok		*/ | 	.listen		   = sock_no_listen,		/* ok		*/ | ||||||
| 	.shutdown	   = inet_shutdown,		/* ok		*/ | 	.shutdown	   = inet_shutdown,		/* ok		*/ | ||||||
| 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | 	.setsockopt	   = sock_common_setsockopt,	/* ok		*/ | ||||||
|  |  | ||||||
|  | @ -618,6 +618,7 @@ static const struct proto_ops l2tp_ip_ops = { | ||||||
| 	.getname	   = l2tp_ip_getname, | 	.getname	   = l2tp_ip_getname, | ||||||
| 	.poll		   = datagram_poll, | 	.poll		   = datagram_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -752,6 +752,7 @@ static const struct proto_ops l2tp_ip6_ops = { | ||||||
| 	.getname	   = l2tp_ip6_getname, | 	.getname	   = l2tp_ip6_getname, | ||||||
| 	.poll		   = datagram_poll, | 	.poll		   = datagram_poll, | ||||||
| 	.ioctl		   = inet6_ioctl, | 	.ioctl		   = inet6_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sock_no_listen, | 	.listen		   = sock_no_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -1199,7 +1199,6 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| { | { | ||||||
| 	struct sock *sk = sock->sk; | 	struct sock *sk = sock->sk; | ||||||
| 	void __user *argp = (void __user *)arg; | 	void __user *argp = (void __user *)arg; | ||||||
| 	int ret; |  | ||||||
| 
 | 
 | ||||||
| 	switch (cmd) { | 	switch (cmd) { | ||||||
| 	case TIOCOUTQ: { | 	case TIOCOUTQ: { | ||||||
|  | @ -1225,18 +1224,6 @@ static int nr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		return put_user(amount, (int __user *)argp); | 		return put_user(amount, (int __user *)argp); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		lock_sock(sk); |  | ||||||
| 		ret = sock_get_timestamp(sk, argp); |  | ||||||
| 		release_sock(sk); |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		lock_sock(sk); |  | ||||||
| 		ret = sock_get_timestampns(sk, argp); |  | ||||||
| 		release_sock(sk); |  | ||||||
| 		return ret; |  | ||||||
| 
 |  | ||||||
| 	case SIOCGIFADDR: | 	case SIOCGIFADDR: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
| 	case SIOCGIFDSTADDR: | 	case SIOCGIFDSTADDR: | ||||||
|  | @ -1362,6 +1349,7 @@ static const struct proto_ops nr_proto_ops = { | ||||||
| 	.getname	=	nr_getname, | 	.getname	=	nr_getname, | ||||||
| 	.poll		=	datagram_poll, | 	.poll		=	datagram_poll, | ||||||
| 	.ioctl		=	nr_ioctl, | 	.ioctl		=	nr_ioctl, | ||||||
|  | 	.gettstamp	=	sock_gettstamp, | ||||||
| 	.listen		=	nr_listen, | 	.listen		=	nr_listen, | ||||||
| 	.shutdown	=	sock_no_shutdown, | 	.shutdown	=	sock_no_shutdown, | ||||||
| 	.setsockopt	=	nr_setsockopt, | 	.setsockopt	=	nr_setsockopt, | ||||||
|  |  | ||||||
|  | @ -4075,11 +4075,6 @@ static int packet_ioctl(struct socket *sock, unsigned int cmd, | ||||||
| 		spin_unlock_bh(&sk->sk_receive_queue.lock); | 		spin_unlock_bh(&sk->sk_receive_queue.lock); | ||||||
| 		return put_user(amount, (int __user *)arg); | 		return put_user(amount, (int __user *)arg); | ||||||
| 	} | 	} | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		return sock_get_timestamp(sk, (struct timeval __user *)arg); |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		return sock_get_timestampns(sk, (struct timespec __user *)arg); |  | ||||||
| 
 |  | ||||||
| #ifdef CONFIG_INET | #ifdef CONFIG_INET | ||||||
| 	case SIOCADDRT: | 	case SIOCADDRT: | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
|  | @ -4455,6 +4450,7 @@ static const struct proto_ops packet_ops_spkt = { | ||||||
| 	.getname =	packet_getname_spkt, | 	.getname =	packet_getname_spkt, | ||||||
| 	.poll =		datagram_poll, | 	.poll =		datagram_poll, | ||||||
| 	.ioctl =	packet_ioctl, | 	.ioctl =	packet_ioctl, | ||||||
|  | 	.gettstamp =	sock_gettstamp, | ||||||
| 	.listen =	sock_no_listen, | 	.listen =	sock_no_listen, | ||||||
| 	.shutdown =	sock_no_shutdown, | 	.shutdown =	sock_no_shutdown, | ||||||
| 	.setsockopt =	sock_no_setsockopt, | 	.setsockopt =	sock_no_setsockopt, | ||||||
|  | @ -4476,6 +4472,7 @@ static const struct proto_ops packet_ops = { | ||||||
| 	.getname =	packet_getname, | 	.getname =	packet_getname, | ||||||
| 	.poll =		packet_poll, | 	.poll =		packet_poll, | ||||||
| 	.ioctl =	packet_ioctl, | 	.ioctl =	packet_ioctl, | ||||||
|  | 	.gettstamp =	sock_gettstamp, | ||||||
| 	.listen =	sock_no_listen, | 	.listen =	sock_no_listen, | ||||||
| 	.shutdown =	sock_no_shutdown, | 	.shutdown =	sock_no_shutdown, | ||||||
| 	.setsockopt =	packet_setsockopt, | 	.setsockopt =	packet_setsockopt, | ||||||
|  |  | ||||||
|  | @ -968,9 +968,6 @@ static int qrtr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 			break; | 			break; | ||||||
| 		} | 		} | ||||||
| 		break; | 		break; | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		rc = sock_get_timestamp(sk, argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCADDRT: | 	case SIOCADDRT: | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
|  | @ -1033,6 +1030,7 @@ static const struct proto_ops qrtr_proto_ops = { | ||||||
| 	.recvmsg	= qrtr_recvmsg, | 	.recvmsg	= qrtr_recvmsg, | ||||||
| 	.getname	= qrtr_getname, | 	.getname	= qrtr_getname, | ||||||
| 	.ioctl		= qrtr_ioctl, | 	.ioctl		= qrtr_ioctl, | ||||||
|  | 	.gettstamp	= sock_gettstamp, | ||||||
| 	.poll		= datagram_poll, | 	.poll		= datagram_poll, | ||||||
| 	.shutdown	= sock_no_shutdown, | 	.shutdown	= sock_no_shutdown, | ||||||
| 	.setsockopt	= sock_no_setsockopt, | 	.setsockopt	= sock_no_setsockopt, | ||||||
|  |  | ||||||
|  | @ -1301,12 +1301,6 @@ static int rose_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		return put_user(amount, (unsigned int __user *) argp); | 		return put_user(amount, (unsigned int __user *) argp); | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		return sock_get_timestamp(sk, (struct timeval __user *) argp); |  | ||||||
| 
 |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		return sock_get_timestampns(sk, (struct timespec __user *) argp); |  | ||||||
| 
 |  | ||||||
| 	case SIOCGIFADDR: | 	case SIOCGIFADDR: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
| 	case SIOCGIFDSTADDR: | 	case SIOCGIFDSTADDR: | ||||||
|  | @ -1474,6 +1468,7 @@ static const struct proto_ops rose_proto_ops = { | ||||||
| 	.getname	=	rose_getname, | 	.getname	=	rose_getname, | ||||||
| 	.poll		=	datagram_poll, | 	.poll		=	datagram_poll, | ||||||
| 	.ioctl		=	rose_ioctl, | 	.ioctl		=	rose_ioctl, | ||||||
|  | 	.gettstamp	=	sock_gettstamp, | ||||||
| 	.listen		=	rose_listen, | 	.listen		=	rose_listen, | ||||||
| 	.shutdown	=	sock_no_shutdown, | 	.shutdown	=	sock_no_shutdown, | ||||||
| 	.setsockopt	=	rose_setsockopt, | 	.setsockopt	=	rose_setsockopt, | ||||||
|  |  | ||||||
|  | @ -1030,6 +1030,7 @@ static const struct proto_ops inet6_seqpacket_ops = { | ||||||
| 	.getname	   = sctp_getname, | 	.getname	   = sctp_getname, | ||||||
| 	.poll		   = sctp_poll, | 	.poll		   = sctp_poll, | ||||||
| 	.ioctl		   = inet6_ioctl, | 	.ioctl		   = inet6_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sctp_inet_listen, | 	.listen		   = sctp_inet_listen, | ||||||
| 	.shutdown	   = inet_shutdown, | 	.shutdown	   = inet_shutdown, | ||||||
| 	.setsockopt	   = sock_common_setsockopt, | 	.setsockopt	   = sock_common_setsockopt, | ||||||
|  |  | ||||||
|  | @ -1026,6 +1026,7 @@ static const struct proto_ops inet_seqpacket_ops = { | ||||||
| 	.getname	   = inet_getname,	/* Semantics are different.  */ | 	.getname	   = inet_getname,	/* Semantics are different.  */ | ||||||
| 	.poll		   = sctp_poll, | 	.poll		   = sctp_poll, | ||||||
| 	.ioctl		   = inet_ioctl, | 	.ioctl		   = inet_ioctl, | ||||||
|  | 	.gettstamp	   = sock_gettstamp, | ||||||
| 	.listen		   = sctp_inet_listen, | 	.listen		   = sctp_inet_listen, | ||||||
| 	.shutdown	   = inet_shutdown,	/* Looks harmless.  */ | 	.shutdown	   = inet_shutdown,	/* Looks harmless.  */ | ||||||
| 	.setsockopt	   = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */ | 	.setsockopt	   = sock_common_setsockopt, /* IP_SOL IP_OPTION is a problem */ | ||||||
|  |  | ||||||
							
								
								
									
										48
									
								
								net/socket.c
									
									
									
									
									
								
							
							
						
						
									
										48
									
								
								net/socket.c
									
									
									
									
									
								
							|  | @ -1164,6 +1164,15 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg) | ||||||
| 
 | 
 | ||||||
| 			err = open_related_ns(&net->ns, get_net_ns); | 			err = open_related_ns(&net->ns, get_net_ns); | ||||||
| 			break; | 			break; | ||||||
|  | 		case SIOCGSTAMP: | ||||||
|  | 		case SIOCGSTAMPNS: | ||||||
|  | 			if (!sock->ops->gettstamp) { | ||||||
|  | 				err = -ENOIOCTLCMD; | ||||||
|  | 				break; | ||||||
|  | 			} | ||||||
|  | 			err = sock->ops->gettstamp(sock, argp, | ||||||
|  | 						   cmd == SIOCGSTAMP, false); | ||||||
|  | 			break; | ||||||
| 		default: | 		default: | ||||||
| 			err = sock_do_ioctl(net, sock, cmd, arg); | 			err = sock_do_ioctl(net, sock, cmd, arg); | ||||||
| 			break; | 			break; | ||||||
|  | @ -2916,38 +2925,6 @@ void socket_seq_show(struct seq_file *seq) | ||||||
| #endif				/* CONFIG_PROC_FS */ | #endif				/* CONFIG_PROC_FS */ | ||||||
| 
 | 
 | ||||||
| #ifdef CONFIG_COMPAT | #ifdef CONFIG_COMPAT | ||||||
| static int do_siocgstamp(struct net *net, struct socket *sock, |  | ||||||
| 			 unsigned int cmd, void __user *up) |  | ||||||
| { |  | ||||||
| 	mm_segment_t old_fs = get_fs(); |  | ||||||
| 	struct timeval ktv; |  | ||||||
| 	int err; |  | ||||||
| 
 |  | ||||||
| 	set_fs(KERNEL_DS); |  | ||||||
| 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv); |  | ||||||
| 	set_fs(old_fs); |  | ||||||
| 	if (!err) |  | ||||||
| 		err = compat_put_timeval(&ktv, up); |  | ||||||
| 
 |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int do_siocgstampns(struct net *net, struct socket *sock, |  | ||||||
| 			   unsigned int cmd, void __user *up) |  | ||||||
| { |  | ||||||
| 	mm_segment_t old_fs = get_fs(); |  | ||||||
| 	struct timespec kts; |  | ||||||
| 	int err; |  | ||||||
| 
 |  | ||||||
| 	set_fs(KERNEL_DS); |  | ||||||
| 	err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts); |  | ||||||
| 	set_fs(old_fs); |  | ||||||
| 	if (!err) |  | ||||||
| 		err = compat_put_timespec(&kts, up); |  | ||||||
| 
 |  | ||||||
| 	return err; |  | ||||||
| } |  | ||||||
| 
 |  | ||||||
| static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | static int compat_dev_ifconf(struct net *net, struct compat_ifconf __user *uifc32) | ||||||
| { | { | ||||||
| 	struct compat_ifconf ifc32; | 	struct compat_ifconf ifc32; | ||||||
|  | @ -3348,9 +3325,12 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock, | ||||||
| 	case SIOCDELRT: | 	case SIOCDELRT: | ||||||
| 		return routing_ioctl(net, sock, cmd, argp); | 		return routing_ioctl(net, sock, cmd, argp); | ||||||
| 	case SIOCGSTAMP: | 	case SIOCGSTAMP: | ||||||
| 		return do_siocgstamp(net, sock, cmd, argp); |  | ||||||
| 	case SIOCGSTAMPNS: | 	case SIOCGSTAMPNS: | ||||||
| 		return do_siocgstampns(net, sock, cmd, argp); | 		if (!sock->ops->gettstamp) | ||||||
|  | 			return -ENOIOCTLCMD; | ||||||
|  | 		return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP, | ||||||
|  | 					    !COMPAT_USE_64BIT_TIME); | ||||||
|  | 
 | ||||||
| 	case SIOCBONDSLAVEINFOQUERY: | 	case SIOCBONDSLAVEINFOQUERY: | ||||||
| 	case SIOCBONDINFOQUERY: | 	case SIOCBONDINFOQUERY: | ||||||
| 	case SIOCSHWTSTAMP: | 	case SIOCSHWTSTAMP: | ||||||
|  |  | ||||||
|  | @ -1398,18 +1398,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg) | ||||||
| 		break; | 		break; | ||||||
| 	} | 	} | ||||||
| 
 | 
 | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		rc = -EINVAL; |  | ||||||
| 		if (sk) |  | ||||||
| 			rc = sock_get_timestamp(sk, |  | ||||||
| 						(struct timeval __user *)argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		rc = -EINVAL; |  | ||||||
| 		if (sk) |  | ||||||
| 			rc = sock_get_timestampns(sk, |  | ||||||
| 					(struct timespec __user *)argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGIFADDR: | 	case SIOCGIFADDR: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
| 	case SIOCGIFDSTADDR: | 	case SIOCGIFDSTADDR: | ||||||
|  | @ -1681,8 +1669,6 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | ||||||
| 				unsigned long arg) | 				unsigned long arg) | ||||||
| { | { | ||||||
| 	void __user *argp = compat_ptr(arg); | 	void __user *argp = compat_ptr(arg); | ||||||
| 	struct sock *sk = sock->sk; |  | ||||||
| 
 |  | ||||||
| 	int rc = -ENOIOCTLCMD; | 	int rc = -ENOIOCTLCMD; | ||||||
| 
 | 
 | ||||||
| 	switch(cmd) { | 	switch(cmd) { | ||||||
|  | @ -1690,18 +1676,6 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd, | ||||||
| 	case TIOCINQ: | 	case TIOCINQ: | ||||||
| 		rc = x25_ioctl(sock, cmd, (unsigned long)argp); | 		rc = x25_ioctl(sock, cmd, (unsigned long)argp); | ||||||
| 		break; | 		break; | ||||||
| 	case SIOCGSTAMP: |  | ||||||
| 		rc = -EINVAL; |  | ||||||
| 		if (sk) |  | ||||||
| 			rc = compat_sock_get_timestamp(sk, |  | ||||||
| 					(struct timeval __user*)argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGSTAMPNS: |  | ||||||
| 		rc = -EINVAL; |  | ||||||
| 		if (sk) |  | ||||||
| 			rc = compat_sock_get_timestampns(sk, |  | ||||||
| 					(struct timespec __user*)argp); |  | ||||||
| 		break; |  | ||||||
| 	case SIOCGIFADDR: | 	case SIOCGIFADDR: | ||||||
| 	case SIOCSIFADDR: | 	case SIOCSIFADDR: | ||||||
| 	case SIOCGIFDSTADDR: | 	case SIOCGIFDSTADDR: | ||||||
|  | @ -1765,6 +1739,7 @@ static const struct proto_ops x25_proto_ops = { | ||||||
| #ifdef CONFIG_COMPAT | #ifdef CONFIG_COMPAT | ||||||
| 	.compat_ioctl = compat_x25_ioctl, | 	.compat_ioctl = compat_x25_ioctl, | ||||||
| #endif | #endif | ||||||
|  | 	.gettstamp =	sock_gettstamp, | ||||||
| 	.listen =	x25_listen, | 	.listen =	x25_listen, | ||||||
| 	.shutdown =	sock_no_shutdown, | 	.shutdown =	sock_no_shutdown, | ||||||
| 	.setsockopt =	x25_setsockopt, | 	.setsockopt =	x25_setsockopt, | ||||||
|  |  | ||||||
		Loading…
	
		Reference in a new issue
	
	 Arnd Bergmann
						Arnd Bergmann