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:
Родитель
1ab839281c
Коммит
c7cbdbf29f
|
@ -161,6 +161,8 @@ struct proto_ops {
|
|||
int (*compat_ioctl) (struct socket *sock, unsigned int cmd,
|
||||
unsigned long arg);
|
||||
#endif
|
||||
int (*gettstamp) (struct socket *sock, void __user *userstamp,
|
||||
bool timeval, bool time32);
|
||||
int (*listen) (struct socket *sock, int len);
|
||||
int (*shutdown) (struct socket *sock, int flags);
|
||||
int (*setsockopt)(struct socket *sock, int level,
|
||||
|
|
|
@ -30,9 +30,6 @@ struct compat_cmsghdr {
|
|||
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) */
|
||||
/*
|
||||
* 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,
|
||||
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,
|
||||
int noblock, int *errcode);
|
||||
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);
|
||||
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 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);
|
||||
break;
|
||||
}
|
||||
case SIOCGSTAMP:
|
||||
rc = sock_get_timestamp(sk, argp);
|
||||
break;
|
||||
case SIOCGSTAMPNS:
|
||||
rc = sock_get_timestampns(sk, argp);
|
||||
break;
|
||||
/* Routing */
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
|
@ -1871,6 +1865,7 @@ static const struct proto_ops atalk_dgram_ops = {
|
|||
.getname = atalk_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = atalk_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = atalk_compat_ioctl,
|
||||
#endif
|
||||
|
|
|
@ -81,22 +81,6 @@ static int do_vcc_ioctl(struct socket *sock, unsigned int cmd,
|
|||
(int __user *)argp) ? -EFAULT : 0;
|
||||
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:
|
||||
net_warn_ratelimited("ATM_SETSC is obsolete; used by %s:%d\n",
|
||||
current->comm, task_pid_nr(current));
|
||||
|
|
|
@ -118,6 +118,7 @@ static const struct proto_ops pvc_proto_ops = {
|
|||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = vcc_compat_ioctl,
|
||||
#endif
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = pvc_shutdown,
|
||||
.setsockopt = pvc_setsockopt,
|
||||
|
|
|
@ -641,6 +641,7 @@ static const struct proto_ops svc_proto_ops = {
|
|||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = svc_compat_ioctl,
|
||||
#endif
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = svc_listen,
|
||||
.shutdown = svc_shutdown,
|
||||
.setsockopt = svc_setsockopt,
|
||||
|
|
|
@ -1714,14 +1714,6 @@ static int ax25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
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 SIOCAX25DELUID: /* Delete a uid from the uid/call map table */
|
||||
case SIOCAX25GETUID: {
|
||||
|
@ -1950,6 +1942,7 @@ static const struct proto_ops ax25_proto_ops = {
|
|||
.getname = ax25_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = ax25_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = ax25_listen,
|
||||
.shutdown = ax25_shutdown,
|
||||
.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);
|
||||
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:
|
||||
err = -ENOIOCTLCMD;
|
||||
break;
|
||||
|
|
|
@ -1655,6 +1655,7 @@ static const struct proto_ops l2cap_sock_ops = {
|
|||
.recvmsg = l2cap_sock_recvmsg,
|
||||
.poll = bt_sock_poll,
|
||||
.ioctl = bt_sock_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.mmap = sock_no_mmap,
|
||||
.socketpair = sock_no_socketpair,
|
||||
.shutdown = l2cap_sock_shutdown,
|
||||
|
|
|
@ -1039,6 +1039,7 @@ static const struct proto_ops rfcomm_sock_ops = {
|
|||
.setsockopt = rfcomm_sock_setsockopt,
|
||||
.getsockopt = rfcomm_sock_getsockopt,
|
||||
.ioctl = rfcomm_sock_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.poll = bt_sock_poll,
|
||||
.socketpair = sock_no_socketpair,
|
||||
.mmap = sock_no_mmap
|
||||
|
|
|
@ -1190,6 +1190,7 @@ static const struct proto_ops sco_sock_ops = {
|
|||
.recvmsg = sco_sock_recvmsg,
|
||||
.poll = bt_sock_poll,
|
||||
.ioctl = bt_sock_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.mmap = sock_no_mmap,
|
||||
.socketpair = sock_no_socketpair,
|
||||
.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)
|
||||
{
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
switch (cmd) {
|
||||
|
||||
case SIOCGSTAMP:
|
||||
return sock_get_timestamp(sk, (struct timeval __user *)arg);
|
||||
|
||||
default:
|
||||
return -ENOIOCTLCMD;
|
||||
}
|
||||
|
|
|
@ -1689,6 +1689,7 @@ static const struct proto_ops bcm_ops = {
|
|||
.getname = sock_no_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = sock_no_setsockopt,
|
||||
|
|
|
@ -846,6 +846,7 @@ static const struct proto_ops raw_ops = {
|
|||
.getname = raw_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = can_ioctl, /* use can_ioctl() from af_can.c */
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.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);
|
||||
}
|
||||
|
||||
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,
|
||||
char __user *optval,
|
||||
int __user *optlen)
|
||||
|
|
|
@ -2977,39 +2977,44 @@ bool lock_sock_fast(struct sock *sk)
|
|||
}
|
||||
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);
|
||||
tv = ktime_to_timeval(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));
|
||||
ts = ktime_to_timespec64(sock_read_timestamp(sk));
|
||||
if (ts.tv_sec == -1)
|
||||
return -ENOENT;
|
||||
if (ts.tv_sec == 0) {
|
||||
ktime_t kt = ktime_get_real();
|
||||
sock_write_timestamp(sk, kt);
|
||||
ts = ktime_to_timespec(sk->sk_stamp);
|
||||
sock_write_timestamp(sk, kt);;
|
||||
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;
|
||||
}
|
||||
#endif
|
||||
return put_timespec64(&ts, userstamp);
|
||||
}
|
||||
EXPORT_SYMBOL(sock_get_timestampns);
|
||||
EXPORT_SYMBOL(sock_gettstamp);
|
||||
|
||||
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 */
|
||||
.poll = dccp_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
/* FIXME: work on inet_listen to rename it to sock_common_listen */
|
||||
.listen = inet_dccp_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
|
|
|
@ -1075,6 +1075,7 @@ static const struct proto_ops inet6_dccp_ops = {
|
|||
.getname = inet6_getname,
|
||||
.poll = dccp_poll,
|
||||
.ioctl = inet6_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = inet_dccp_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
|
|
@ -164,10 +164,6 @@ static int ieee802154_sock_ioctl(struct socket *sock, unsigned int cmd,
|
|||
struct sock *sk = sock->sk;
|
||||
|
||||
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 SIOCSIFADDR:
|
||||
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,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = ieee802154_sock_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
@ -988,6 +985,7 @@ static const struct proto_ops ieee802154_dgram_ops = {
|
|||
.getname = sock_no_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = ieee802154_sock_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
|
|
@ -915,12 +915,6 @@ int inet_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
struct rtentry rt;
|
||||
|
||||
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 SIOCDELRT:
|
||||
if (copy_from_user(&rt, p, sizeof(struct rtentry)))
|
||||
|
@ -992,6 +986,7 @@ const struct proto_ops inet_stream_ops = {
|
|||
.getname = inet_getname,
|
||||
.poll = tcp_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = inet_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
@ -1027,6 +1022,7 @@ const struct proto_ops inet_dgram_ops = {
|
|||
.getname = inet_getname,
|
||||
.poll = udp_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
@ -1059,6 +1055,7 @@ static const struct proto_ops inet_sockraw_ops = {
|
|||
.getname = inet_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.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);
|
||||
|
||||
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 SIOCDELRT:
|
||||
|
||||
|
@ -585,6 +579,7 @@ const struct proto_ops inet6_stream_ops = {
|
|||
.getname = inet6_getname,
|
||||
.poll = tcp_poll, /* ok */
|
||||
.ioctl = inet6_ioctl, /* must change */
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = inet_listen, /* ok */
|
||||
.shutdown = inet_shutdown, /* ok */
|
||||
.setsockopt = sock_common_setsockopt, /* ok */
|
||||
|
@ -618,6 +613,7 @@ const struct proto_ops inet6_dgram_ops = {
|
|||
.getname = inet6_getname,
|
||||
.poll = udp_poll, /* ok */
|
||||
.ioctl = inet6_ioctl, /* must change */
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen, /* ok */
|
||||
.shutdown = inet_shutdown, /* ok */
|
||||
.setsockopt = sock_common_setsockopt, /* ok */
|
||||
|
|
|
@ -1356,6 +1356,7 @@ const struct proto_ops inet6_sockraw_ops = {
|
|||
.getname = inet6_getname,
|
||||
.poll = datagram_poll, /* ok */
|
||||
.ioctl = inet6_ioctl, /* must change */
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen, /* ok */
|
||||
.shutdown = inet_shutdown, /* ok */
|
||||
.setsockopt = sock_common_setsockopt, /* ok */
|
||||
|
|
|
@ -618,6 +618,7 @@ static const struct proto_ops l2tp_ip_ops = {
|
|||
.getname = l2tp_ip_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
|
|
@ -752,6 +752,7 @@ static const struct proto_ops l2tp_ip6_ops = {
|
|||
.getname = l2tp_ip6_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = inet6_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.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;
|
||||
void __user *argp = (void __user *)arg;
|
||||
int ret;
|
||||
|
||||
switch (cmd) {
|
||||
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);
|
||||
}
|
||||
|
||||
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 SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
|
@ -1362,6 +1349,7 @@ static const struct proto_ops nr_proto_ops = {
|
|||
.getname = nr_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = nr_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = nr_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.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);
|
||||
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
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
|
@ -4455,6 +4450,7 @@ static const struct proto_ops packet_ops_spkt = {
|
|||
.getname = packet_getname_spkt,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = packet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = sock_no_setsockopt,
|
||||
|
@ -4476,6 +4472,7 @@ static const struct proto_ops packet_ops = {
|
|||
.getname = packet_getname,
|
||||
.poll = packet_poll,
|
||||
.ioctl = packet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sock_no_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = packet_setsockopt,
|
||||
|
|
|
@ -968,9 +968,6 @@ static int qrtr_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case SIOCGSTAMP:
|
||||
rc = sock_get_timestamp(sk, argp);
|
||||
break;
|
||||
case SIOCADDRT:
|
||||
case SIOCDELRT:
|
||||
case SIOCSIFADDR:
|
||||
|
@ -1033,6 +1030,7 @@ static const struct proto_ops qrtr_proto_ops = {
|
|||
.recvmsg = qrtr_recvmsg,
|
||||
.getname = qrtr_getname,
|
||||
.ioctl = qrtr_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.poll = datagram_poll,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.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);
|
||||
}
|
||||
|
||||
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 SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
|
@ -1474,6 +1468,7 @@ static const struct proto_ops rose_proto_ops = {
|
|||
.getname = rose_getname,
|
||||
.poll = datagram_poll,
|
||||
.ioctl = rose_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = rose_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = rose_setsockopt,
|
||||
|
|
|
@ -1030,6 +1030,7 @@ static const struct proto_ops inet6_seqpacket_ops = {
|
|||
.getname = sctp_getname,
|
||||
.poll = sctp_poll,
|
||||
.ioctl = inet6_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sctp_inet_listen,
|
||||
.shutdown = inet_shutdown,
|
||||
.setsockopt = sock_common_setsockopt,
|
||||
|
|
|
@ -1026,6 +1026,7 @@ static const struct proto_ops inet_seqpacket_ops = {
|
|||
.getname = inet_getname, /* Semantics are different. */
|
||||
.poll = sctp_poll,
|
||||
.ioctl = inet_ioctl,
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = sctp_inet_listen,
|
||||
.shutdown = inet_shutdown, /* Looks harmless. */
|
||||
.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);
|
||||
break;
|
||||
case SIOCGSTAMP:
|
||||
case SIOCGSTAMPNS:
|
||||
if (!sock->ops->gettstamp) {
|
||||
err = -ENOIOCTLCMD;
|
||||
break;
|
||||
}
|
||||
err = sock->ops->gettstamp(sock, argp,
|
||||
cmd == SIOCGSTAMP, false);
|
||||
break;
|
||||
default:
|
||||
err = sock_do_ioctl(net, sock, cmd, arg);
|
||||
break;
|
||||
|
@ -2916,38 +2925,6 @@ void socket_seq_show(struct seq_file *seq)
|
|||
#endif /* CONFIG_PROC_FS */
|
||||
|
||||
#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)
|
||||
{
|
||||
struct compat_ifconf ifc32;
|
||||
|
@ -3348,9 +3325,12 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
|
|||
case SIOCDELRT:
|
||||
return routing_ioctl(net, sock, cmd, argp);
|
||||
case SIOCGSTAMP:
|
||||
return do_siocgstamp(net, sock, cmd, argp);
|
||||
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 SIOCBONDINFOQUERY:
|
||||
case SIOCSHWTSTAMP:
|
||||
|
|
|
@ -1398,18 +1398,6 @@ static int x25_ioctl(struct socket *sock, unsigned int cmd, unsigned long arg)
|
|||
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 SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
|
@ -1681,8 +1669,6 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
|
|||
unsigned long arg)
|
||||
{
|
||||
void __user *argp = compat_ptr(arg);
|
||||
struct sock *sk = sock->sk;
|
||||
|
||||
int rc = -ENOIOCTLCMD;
|
||||
|
||||
switch(cmd) {
|
||||
|
@ -1690,18 +1676,6 @@ static int compat_x25_ioctl(struct socket *sock, unsigned int cmd,
|
|||
case TIOCINQ:
|
||||
rc = x25_ioctl(sock, cmd, (unsigned long)argp);
|
||||
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 SIOCSIFADDR:
|
||||
case SIOCGIFDSTADDR:
|
||||
|
@ -1765,6 +1739,7 @@ static const struct proto_ops x25_proto_ops = {
|
|||
#ifdef CONFIG_COMPAT
|
||||
.compat_ioctl = compat_x25_ioctl,
|
||||
#endif
|
||||
.gettstamp = sock_gettstamp,
|
||||
.listen = x25_listen,
|
||||
.shutdown = sock_no_shutdown,
|
||||
.setsockopt = x25_setsockopt,
|
||||
|
|
Загрузка…
Ссылка в новой задаче