]> git.proxmox.com Git - mirror_ubuntu-eoan-kernel.git/commitdiff
socket: Add SO_TIMESTAMPING_NEW
authorDeepa Dinamani <deepa.kernel@gmail.com>
Sat, 2 Feb 2019 15:34:51 +0000 (07:34 -0800)
committerDavid S. Miller <davem@davemloft.net>
Sun, 3 Feb 2019 19:17:31 +0000 (11:17 -0800)
Add SO_TIMESTAMPING_NEW variant of socket timestamp options.
This is the y2038 safe versions of the SO_TIMESTAMPING_OLD
for all architectures.

Signed-off-by: Deepa Dinamani <deepa.kernel@gmail.com>
Acked-by: Willem de Bruijn <willemb@google.com>
Cc: chris@zankel.net
Cc: fenghua.yu@intel.com
Cc: rth@twiddle.net
Cc: tglx@linutronix.de
Cc: ubraun@linux.ibm.com
Cc: linux-alpha@vger.kernel.org
Cc: linux-arch@vger.kernel.org
Cc: linux-ia64@vger.kernel.org
Cc: linux-mips@linux-mips.org
Cc: linux-s390@vger.kernel.org
Cc: linux-xtensa@linux-xtensa.org
Cc: sparclinux@vger.kernel.org
Signed-off-by: David S. Miller <davem@davemloft.net>
12 files changed:
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/linux/socket.h
include/uapi/asm-generic/socket.h
include/uapi/linux/errqueue.h
net/core/scm.c
net/core/sock.c
net/ipv4/tcp.c
net/smc/af_smc.c
net/socket.c

index aab11eec7c22ef36206591760057e0ded89869c2..934ea6268f1aa94aabe5133f3d6bd281760ce502 100644 (file)
 
 #define SO_TIMESTAMP_NEW        63
 #define SO_TIMESTAMPNS_NEW      64
+#define SO_TIMESTAMPING_NEW     65
 
 #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
 #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)
 #endif
 
-#define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
-
 #define SCM_TIMESTAMP           SO_TIMESTAMP
 #define SCM_TIMESTAMPNS         SO_TIMESTAMPNS
 #define SCM_TIMESTAMPING        SO_TIMESTAMPING
index 11014f684d9fc84560d0077ca3f1d3f5e148c728..110f9506d64f4d84f8626bec822bf2ad6350709a 100644 (file)
 
 #define SO_TIMESTAMP_NEW        63
 #define SO_TIMESTAMPNS_NEW      64
+#define SO_TIMESTAMPING_NEW     65
 
 #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
 #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)
 #endif
 
-#define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
-
 #define SCM_TIMESTAMP           SO_TIMESTAMP
 #define SCM_TIMESTAMPNS         SO_TIMESTAMPNS
 #define SCM_TIMESTAMPING        SO_TIMESTAMPING
index cbc4b89c2fe49758e3dec88f7cb7b02b34b6dca9..bee2a9dde6567b8a0170399d71c1f8e6b0e22ff3 100644 (file)
 
 #define SO_TIMESTAMP_NEW        0x4038
 #define SO_TIMESTAMPNS_NEW      0x4039
+#define SO_TIMESTAMPING_NEW     0x403A
 
 #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
 #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)
 #endif
 
-#define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
-
 #define SCM_TIMESTAMP           SO_TIMESTAMP
 #define SCM_TIMESTAMPNS         SO_TIMESTAMPNS
 #define SCM_TIMESTAMPING        SO_TIMESTAMPING
index 85127425b2948f2e663d962bb219114acb47519e..2b38dda5142675f1e7946eea81e98ef469e6f7fc 100644 (file)
 
 #define SO_TIMESTAMP_NEW         0x0041
 #define SO_TIMESTAMPNS_NEW       0x0042
+#define SO_TIMESTAMPING_NEW      0x0043
 
 #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
 #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)
 #endif
 
-#define SO_TIMESTAMPING        SO_TIMESTAMPING_OLD
-
 #define SCM_TIMESTAMP          SO_TIMESTAMP
 #define SCM_TIMESTAMPNS        SO_TIMESTAMPNS
 #define SCM_TIMESTAMPING       SO_TIMESTAMPING
index ab2041a00e014c87f2bf9b88d93ee65b09464805..6016daeecee41f28511f46c8618fbf05a16aff8a 100644 (file)
@@ -349,9 +349,17 @@ struct ucred {
 extern int move_addr_to_kernel(void __user *uaddr, int ulen, struct sockaddr_storage *kaddr);
 extern int put_cmsg(struct msghdr*, int level, int type, int len, void *data);
 
+struct timespec64;
 struct __kernel_timespec;
 struct old_timespec32;
 
+struct scm_timestamping_internal {
+       struct timespec64 ts[3];
+};
+
+extern void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss);
+extern void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_internal *tss);
+
 /* The __sys_...msg variants allow MSG_CMSG_COMPAT iff
  * forbid_cmsg_compat==false
  */
index f22d3f7162f8a49fd903f4af5244f0e88dbe52d4..2713e0fa68ef7ad07f5d3db5bca125f42a4325a4 100644 (file)
 
 #define SO_TIMESTAMP_NEW        63
 #define SO_TIMESTAMPNS_NEW      64
+#define SO_TIMESTAMPING_NEW     65
 
 #if !defined(__KERNEL__)
 
 /* 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
 #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)
 #endif
 
-#define SO_TIMESTAMPING         SO_TIMESTAMPING_OLD
-
 #define SCM_TIMESTAMP           SO_TIMESTAMP
 #define SCM_TIMESTAMPNS         SO_TIMESTAMPNS
 #define SCM_TIMESTAMPING        SO_TIMESTAMPING
index c0151200f7d1cf65e961a69e3b4fca23a9ff4785..d955b9e32288958528cb5eb7e9f9b84bf5ae2552 100644 (file)
@@ -41,6 +41,10 @@ struct scm_timestamping {
        struct timespec ts[3];
 };
 
+struct scm_timestamping64 {
+       struct __kernel_timespec ts[3];
+};
+
 /* The type of scm_timestamping, passed in sock_extended_err ee_info.
  * This defines the type of ts[0]. For SCM_TSTAMP_SND only, if ts[0]
  * is zero, then this is a hardware timestamp and recorded in ts[2].
index b1ff8a4417489f7c211b4bddd2d07de1caf19cfd..52ef219cf6df1e5f5f3ba0fbcf0822d6e92e4083 100644 (file)
@@ -29,6 +29,7 @@
 #include <linux/pid.h>
 #include <linux/nsproxy.h>
 #include <linux/slab.h>
+#include <linux/errqueue.h>
 
 #include <linux/uaccess.h>
 
@@ -252,6 +253,32 @@ out:
 }
 EXPORT_SYMBOL(put_cmsg);
 
+void put_cmsg_scm_timestamping64(struct msghdr *msg, struct scm_timestamping_internal *tss_internal)
+{
+       struct scm_timestamping64 tss;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tss.ts); i++) {
+               tss.ts[i].tv_sec = tss_internal->ts[i].tv_sec;
+               tss.ts[i].tv_nsec = tss_internal->ts[i].tv_nsec;
+       }
+
+       put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_NEW, sizeof(tss), &tss);
+}
+EXPORT_SYMBOL(put_cmsg_scm_timestamping64);
+
+void put_cmsg_scm_timestamping(struct msghdr *msg, struct scm_timestamping_internal *tss_internal)
+{
+       struct scm_timestamping tss;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(tss.ts); i++)
+               tss.ts[i] = timespec64_to_timespec(tss_internal->ts[i]);
+
+       put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_OLD, sizeof(tss), &tss);
+}
+EXPORT_SYMBOL(put_cmsg_scm_timestamping);
+
 void scm_detach_fds(struct msghdr *msg, struct scm_cookie *scm)
 {
        struct cmsghdr __user *cm
index 14b987eab10c647818b702d248921676b56f849f..a9d1ecce96e5506c91c0d772e6060c5e3910e1e0 100644 (file)
@@ -890,6 +890,8 @@ set_rcvbuf:
                }
                break;
 
+       case SO_TIMESTAMPING_NEW:
+               sock_set_flag(sk, SOCK_TSTAMP_NEW);
        case SO_TIMESTAMPING_OLD:
                if (val & ~SOF_TIMESTAMPING_MASK) {
                        ret = -EINVAL;
@@ -921,9 +923,13 @@ set_rcvbuf:
                if (val & SOF_TIMESTAMPING_RX_SOFTWARE)
                        sock_enable_timestamp(sk,
                                              SOCK_TIMESTAMPING_RX_SOFTWARE);
-               else
+               else {
+                       if (optname == SO_TIMESTAMPING_NEW)
+                               sock_reset_flag(sk, SOCK_TSTAMP_NEW);
+
                        sock_disable_timestamp(sk,
                                               (1UL << SOCK_TIMESTAMPING_RX_SOFTWARE));
+               }
                break;
 
        case SO_RCVLOWAT:
index 4e9388bf104a42cda8d0a203b904a17e5ef419f6..cab6b2f2f61dd30c1052e48d4597d93f9378eb51 100644 (file)
@@ -1844,22 +1844,22 @@ out:
 #endif
 
 static void tcp_update_recv_tstamps(struct sk_buff *skb,
-                                   struct scm_timestamping *tss)
+                                   struct scm_timestamping_internal *tss)
 {
        if (skb->tstamp)
-               tss->ts[0] = ktime_to_timespec(skb->tstamp);
+               tss->ts[0] = ktime_to_timespec64(skb->tstamp);
        else
-               tss->ts[0] = (struct timespec) {0};
+               tss->ts[0] = (struct timespec64) {0};
 
        if (skb_hwtstamps(skb)->hwtstamp)
-               tss->ts[2] = ktime_to_timespec(skb_hwtstamps(skb)->hwtstamp);
+               tss->ts[2] = ktime_to_timespec64(skb_hwtstamps(skb)->hwtstamp);
        else
-               tss->ts[2] = (struct timespec) {0};
+               tss->ts[2] = (struct timespec64) {0};
 }
 
 /* Similar to __sock_recv_timestamp, but does not require an skb */
 static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
-                              struct scm_timestamping *tss)
+                              struct scm_timestamping_internal *tss)
 {
        int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
        bool has_timestamping = false;
@@ -1873,8 +1873,10 @@ static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_NEW,
                                                 sizeof(kts), &kts);
                                } else {
+                                       struct timespec ts_old = timespec64_to_timespec(tss->ts[0]);
+
                                        put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPNS_OLD,
-                                                sizeof(tss->ts[0]), &tss->ts[0]);
+                                                sizeof(ts_old), &ts_old);
                                }
                        } else {
                                if (new_tstamp) {
@@ -1898,20 +1900,22 @@ static void tcp_recv_timestamp(struct msghdr *msg, const struct sock *sk,
                if (sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE)
                        has_timestamping = true;
                else
-                       tss->ts[0] = (struct timespec) {0};
+                       tss->ts[0] = (struct timespec64) {0};
        }
 
        if (tss->ts[2].tv_sec || tss->ts[2].tv_nsec) {
                if (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE)
                        has_timestamping = true;
                else
-                       tss->ts[2] = (struct timespec) {0};
+                       tss->ts[2] = (struct timespec64) {0};
        }
 
        if (has_timestamping) {
-               tss->ts[1] = (struct timespec) {0};
-               put_cmsg(msg, SOL_SOCKET, SO_TIMESTAMPING_OLD,
-                        sizeof(*tss), tss);
+               tss->ts[1] = (struct timespec64) {0};
+               if (sock_flag(sk, SOCK_TSTAMP_NEW))
+                       put_cmsg_scm_timestamping64(msg, tss);
+               else
+                       put_cmsg_scm_timestamping(msg, tss);
        }
 }
 
@@ -1952,7 +1956,7 @@ int tcp_recvmsg(struct sock *sk, struct msghdr *msg, size_t len, int nonblock,
        long timeo;
        struct sk_buff *skb, *last;
        u32 urg_hole = 0;
-       struct scm_timestamping tss;
+       struct scm_timestamping_internal tss;
        bool has_tss = false;
        bool has_cmsg;
 
index c4e56602e0c61476f755e157c35da92a8fbcaaa2..369870b0ef790e2fb26c6f4d906c5f7de71aade1 100644 (file)
@@ -291,7 +291,8 @@ static void smc_copy_sock_settings(struct sock *nsk, struct sock *osk,
                             (1UL << SOCK_RXQ_OVFL) | \
                             (1UL << SOCK_WIFI_STATUS) | \
                             (1UL << SOCK_NOFCS) | \
-                            (1UL << SOCK_FILTER_LOCKED))
+                            (1UL << SOCK_FILTER_LOCKED) | \
+                            (1UL << SOCK_TSTAMP_NEW))
 /* copy only relevant settings and flags of SOL_SOCKET level from smc to
  * clc socket (since smc is not called for these options from net/core)
  */
index 1de96abd78d3e55100100088991dacf876997846..d51930689b9878d0aebc08740680641e6155e7fc 100644 (file)
@@ -706,7 +706,8 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 {
        int need_software_tstamp = sock_flag(sk, SOCK_RCVTSTAMP);
        int new_tstamp = sock_flag(sk, SOCK_TSTAMP_NEW);
-       struct scm_timestamping tss;
+       struct scm_timestamping_internal tss;
+
        int empty = 1, false_tstamp = 0;
        struct skb_shared_hwtstamps *shhwtstamps =
                skb_hwtstamps(skb);
@@ -752,20 +753,22 @@ void __sock_recv_timestamp(struct msghdr *msg, struct sock *sk,
 
        memset(&tss, 0, sizeof(tss));
        if ((sk->sk_tsflags & SOF_TIMESTAMPING_SOFTWARE) &&
-           ktime_to_timespec_cond(skb->tstamp, tss.ts + 0))
+           ktime_to_timespec64_cond(skb->tstamp, tss.ts + 0))
                empty = 0;
        if (shhwtstamps &&
            (sk->sk_tsflags & SOF_TIMESTAMPING_RAW_HARDWARE) &&
            !skb_is_swtx_tstamp(skb, false_tstamp) &&
-           ktime_to_timespec_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
+           ktime_to_timespec64_cond(shhwtstamps->hwtstamp, tss.ts + 2)) {
                empty = 0;
                if ((sk->sk_tsflags & SOF_TIMESTAMPING_OPT_PKTINFO) &&
                    !skb_is_err_queue(skb))
                        put_ts_pktinfo(msg, skb);
        }
        if (!empty) {
-               put_cmsg(msg, SOL_SOCKET,
-                        SO_TIMESTAMPING_OLD, sizeof(tss), &tss);
+               if (sock_flag(sk, SOCK_TSTAMP_NEW))
+                       put_cmsg_scm_timestamping64(msg, &tss);
+               else
+                       put_cmsg_scm_timestamping(msg, &tss);
 
                if (skb_is_err_queue(skb) && skb->len &&
                    SKB_EXT_ERR(skb)->opt_stats)