OSDN Git Service

sock: Add SO_RCVTIMEO_NEW and SO_SNDTIMEO_NEW
authorDeepa Dinamani <deepa.kernel@gmail.com>
Sat, 2 Feb 2019 15:34:54 +0000 (07:34 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Feb 2019 19:17:31 +0000 (11:17 -0800)
Add new socket timeout options that are y2038 safe.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Cc: ccaulfie@redhat.com
Cc: davem@davemloft.net
Cc: deller@gmx.de
Cc: paulus@samba.org
Cc: ralf@linux-mips.org
Cc: rth@twiddle.net
Cc: cluster-devel@redhat.com
Cc: linuxppc-dev@lists.ozlabs.org
Cc: linux-alpha@vger.kernel.org
Cc: linux-arch@vger.kernel.org
Cc: linux-mips@vger.kernel.org
Cc: linux-parisc@vger.kernel.org
Cc: sparclinux@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
arch/alpha/include/uapi/asm/socket.h
arch/mips/include/uapi/asm/socket.h
arch/parisc/include/uapi/asm/socket.h
arch/sparc/include/uapi/asm/socket.h
include/uapi/asm-generic/socket.h
net/core/sock.c

index 9826d1d..0d0fddb 100644 (file)
 #define SO_TIMESTAMPNS_NEW      64
 #define SO_TIMESTAMPING_NEW     65
 
-#if !defined(__KERNEL__)
+#define SO_RCVTIMEO_NEW         66
+#define SO_SNDTIMEO_NEW         67
 
-#define        SO_RCVTIMEO SO_RCVTIMEO_OLD
-#define        SO_SNDTIMEO SO_SNDTIMEO_OLD
+#if !defined(__KERNEL__)
 
 #if __BITS_PER_LONG == 64
 #define SO_TIMESTAMP           SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS         SO_TIMESTAMPNS_OLD
 #define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
+
+#define SO_RCVTIMEO            SO_RCVTIMEO_OLD
+#define SO_SNDTIMEO            SO_SNDTIMEO_OLD
 #else
 #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
 #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
 #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
+
+#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
+#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
 #endif
 
 #define SCM_TIMESTAMP           SO_TIMESTAMP
index 96cc0e9..eb9f33f 100644 (file)
 #define SO_TIMESTAMPNS_NEW      64
 #define SO_TIMESTAMPING_NEW     65
 
+#define SO_RCVTIMEO_NEW         66
+#define SO_SNDTIMEO_NEW         67
+
 #if !defined(__KERNEL__)
 
-#define        SO_RCVTIMEO SO_RCVTIMEO_OLD
-#define        SO_SNDTIMEO SO_SNDTIMEO_OLD
 #if __BITS_PER_LONG == 64
 #define SO_TIMESTAMP           SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS         SO_TIMESTAMPNS_OLD
 #define SO_TIMESTAMPING                SO_TIMESTAMPING_OLD
+
+#define SO_RCVTIMEO             SO_RCVTIMEO_OLD
+#define SO_SNDTIMEO             SO_SNDTIMEO_OLD
 #else
 #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
 #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
 #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
+
+#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
+#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
 #endif
 
 #define SCM_TIMESTAMP           SO_TIMESTAMP
index 046f0cd..16e428f 100644 (file)
 #define SO_TIMESTAMPNS_NEW      0x4039
 #define SO_TIMESTAMPING_NEW     0x403A
 
+#define SO_RCVTIMEO_NEW         0x4040
+#define SO_SNDTIMEO_NEW         0x4041
+
 #if !defined(__KERNEL__)
 
-#define        SO_RCVTIMEO SO_RCVTIMEO_OLD
-#define        SO_SNDTIMEO SO_SNDTIMEO_OLD
 #if __BITS_PER_LONG == 64
 #define SO_TIMESTAMP           SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS         SO_TIMESTAMPNS_OLD
 #define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
+#define SO_RCVTIMEO            SO_RCVTIMEO_OLD
+#define SO_SNDTIMEO            SO_SNDTIMEO_OLD
 #else
 #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
 #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
 #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
+
+#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
+#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
 #endif
 
 #define SCM_TIMESTAMP           SO_TIMESTAMP
index 342ffdc..8c9f74a 100644 (file)
 #define SO_TIMESTAMPNS_NEW       0x0042
 #define SO_TIMESTAMPING_NEW      0x0043
 
+#define SO_RCVTIMEO_NEW          0x0044
+#define SO_SNDTIMEO_NEW          0x0045
+
 #if !defined(__KERNEL__)
 
-#define SO_RCVTIMEO              SO_RCVTIMEO_OLD
-#define SO_SNDTIMEO              SO_SNDTIMEO_OLD
 
 #if __BITS_PER_LONG == 64
 #define SO_TIMESTAMP           SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS         SO_TIMESTAMPNS_OLD
 #define SO_TIMESTAMPING                SO_TIMESTAMPING_OLD
+
+#define SO_RCVTIMEO            SO_RCVTIMEO_OLD
+#define SO_SNDTIMEO            SO_SNDTIMEO_OLD
 #else
 #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
 #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
 #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
+
+#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
+#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
 #endif
 
 #define SCM_TIMESTAMP          SO_TIMESTAMP
index c56b8b4..c8b430c 100644 (file)
 #define SO_TIMESTAMPNS_NEW      64
 #define SO_TIMESTAMPING_NEW     65
 
+#define SO_RCVTIMEO_NEW         66
+#define SO_SNDTIMEO_NEW         67
+
 #if !defined(__KERNEL__)
 
-#define        SO_RCVTIMEO SO_RCVTIMEO_OLD
-#define        SO_SNDTIMEO SO_SNDTIMEO_OLD
 #if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
 /* on 64-bit and x32, avoid the ?: operator */
 #define SO_TIMESTAMP           SO_TIMESTAMP_OLD
 #define SO_TIMESTAMPNS         SO_TIMESTAMPNS_OLD
 #define SO_TIMESTAMPING                SO_TIMESTAMPING_OLD
+
+#define SO_RCVTIMEO            SO_RCVTIMEO_OLD
+#define SO_SNDTIMEO            SO_SNDTIMEO_OLD
 #else
 #define SO_TIMESTAMP (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMP_OLD : SO_TIMESTAMP_NEW)
 #define SO_TIMESTAMPNS (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPNS_OLD : SO_TIMESTAMPNS_NEW)
 #define SO_TIMESTAMPING (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_TIMESTAMPING_OLD : SO_TIMESTAMPING_NEW)
+
+#define SO_RCVTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_RCVTIMEO_OLD : SO_RCVTIMEO_NEW)
+#define SO_SNDTIMEO (sizeof(time_t) == sizeof(__kernel_long_t) ? SO_SNDTIMEO_OLD : SO_SNDTIMEO_NEW)
 #endif
 
 #define SCM_TIMESTAMP           SO_TIMESTAMP
index 27b4000..a8904ae 100644 (file)
@@ -335,9 +335,10 @@ int __sk_backlog_rcv(struct sock *sk, struct sk_buff *skb)
 }
 EXPORT_SYMBOL(__sk_backlog_rcv);
 
-static int sock_get_timeout(long timeo, void *optval)
+static int sock_get_timeout(long timeo, void *optval, bool old_timeval)
 {
-       struct __kernel_old_timeval tv;
+       struct __kernel_sock_timeval tv;
+       int size;
 
        if (timeo == MAX_SCHEDULE_TIMEOUT) {
                tv.tv_sec = 0;
@@ -353,13 +354,23 @@ static int sock_get_timeout(long timeo, void *optval)
                return sizeof(tv32);
        }
 
-       *(struct __kernel_old_timeval *)optval = tv;
-       return sizeof(tv);
+       if (old_timeval) {
+               struct __kernel_old_timeval old_tv;
+               old_tv.tv_sec = tv.tv_sec;
+               old_tv.tv_usec = tv.tv_usec;
+               *(struct __kernel_old_timeval *)optval = old_tv;
+               size = sizeof(old_tv);
+       } else {
+               *(struct __kernel_sock_timeval *)optval = tv;
+               size = sizeof(tv);
+       }
+
+       return size;
 }
 
-static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
+static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen, bool old_timeval)
 {
-       struct __kernel_old_timeval tv;
+       struct __kernel_sock_timeval tv;
 
        if (in_compat_syscall() && !COMPAT_USE_64BIT_TIME) {
                struct old_timeval32 tv32;
@@ -371,6 +382,15 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
                        return -EFAULT;
                tv.tv_sec = tv32.tv_sec;
                tv.tv_usec = tv32.tv_usec;
+       } else if (old_timeval) {
+               struct __kernel_old_timeval old_tv;
+
+               if (optlen < sizeof(old_tv))
+                       return -EINVAL;
+               if (copy_from_user(&old_tv, optval, sizeof(old_tv)))
+                       return -EFAULT;
+               tv.tv_sec = old_tv.tv_sec;
+               tv.tv_usec = old_tv.tv_usec;
        } else {
                if (optlen < sizeof(tv))
                        return -EINVAL;
@@ -394,8 +414,8 @@ static int sock_set_timeout(long *timeo_p, char __user *optval, int optlen)
        *timeo_p = MAX_SCHEDULE_TIMEOUT;
        if (tv.tv_sec == 0 && tv.tv_usec == 0)
                return 0;
-       if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT/HZ - 1))
-               *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP(tv.tv_usec, USEC_PER_SEC / HZ);
+       if (tv.tv_sec < (MAX_SCHEDULE_TIMEOUT / HZ - 1))
+               *timeo_p = tv.tv_sec * HZ + DIV_ROUND_UP((unsigned long)tv.tv_usec, USEC_PER_SEC / HZ);
        return 0;
 }
 
@@ -942,11 +962,13 @@ set_rcvbuf:
                break;
 
        case SO_RCVTIMEO_OLD:
-               ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen);
+       case SO_RCVTIMEO_NEW:
+               ret = sock_set_timeout(&sk->sk_rcvtimeo, optval, optlen, optname == SO_RCVTIMEO_OLD);
                break;
 
        case SO_SNDTIMEO_OLD:
-               ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen);
+       case SO_SNDTIMEO_NEW:
+               ret = sock_set_timeout(&sk->sk_sndtimeo, optval, optlen, optname == SO_SNDTIMEO_OLD);
                break;
 
        case SO_ATTACH_FILTER:
@@ -1171,6 +1193,7 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                struct linger ling;
                struct old_timeval32 tm32;
                struct __kernel_old_timeval tm;
+               struct  __kernel_sock_timeval stm;
                struct sock_txtime txtime;
        } v;
 
@@ -1279,12 +1302,14 @@ int sock_getsockopt(struct socket *sock, int level, int optname,
                v.val = sk->sk_tsflags;
                break;
 
-       case SO_RCVTIMEO:
-               lv = sock_get_timeout(sk->sk_rcvtimeo, &v);
+       case SO_RCVTIMEO_OLD:
+       case SO_RCVTIMEO_NEW:
+               lv = sock_get_timeout(sk->sk_rcvtimeo, &v, SO_RCVTIMEO_OLD == optname);
                break;
 
-       case SO_SNDTIMEO:
-               lv = sock_get_timeout(sk->sk_sndtimeo, &v);
+       case SO_SNDTIMEO_OLD:
+       case SO_SNDTIMEO_NEW:
+               lv = sock_get_timeout(sk->sk_sndtimeo, &v, SO_SNDTIMEO_OLD == optname);
                break;
 
        case SO_RCVLOWAT: