Skip to content

Commit

Permalink
net: socket: implement 64-bit timestamps
Browse files Browse the repository at this point in the history
The 'timeval' and 'timespec' data structures used for socket timestamps
are going to be redefined in user space based on 64-bit time_t in future
versions of the C library to deal with the y2038 overflow problem,
which breaks the ABI definition.

Unlike many modern ioctl commands, SIOCGSTAMP and SIOCGSTAMPNS do not
use the _IOR() macro to encode the size of the transferred data, so it
remains ambiguous whether the application uses the old or new layout.

The best workaround I could find is rather ugly: we redefine the command
code based on the size of the respective data structure with a ternary
operator. This lets it get evaluated as late as possible, hopefully after
that structure is visible to the caller. We cannot use an #ifdef here,
because inux/sockios.h might have been included before any libc header
that could determine the size of time_t.

The ioctl implementation now interprets the new command codes as always
referring to the 64-bit structure on all architectures, while the old
architecture specific command code still refers to the old architecture
specific layout. The new command number is only used when they are
actually different.

Signed-off-by: Arnd Bergmann <arnd@arndb.de>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
arndb authored and davem330 committed Apr 19, 2019
1 parent 5ce5d8a commit 0768e17
Show file tree
Hide file tree
Showing 7 changed files with 50 additions and 16 deletions.
4 changes: 2 additions & 2 deletions arch/alpha/include/uapi/asm/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)

#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#define SIOCGSTAMP_OLD 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS_OLD 0x8907 /* Get stamp (timespec) */

#endif /* _ASM_ALPHA_SOCKIOS_H */
4 changes: 2 additions & 2 deletions arch/mips/include/uapi/asm/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)

#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#define SIOCGSTAMP_OLD 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS_OLD 0x8907 /* Get stamp (timespec) */

#endif /* _ASM_SOCKIOS_H */
5 changes: 3 additions & 2 deletions arch/sh/include/uapi/asm/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)

#define SIOCGSTAMP _IOR('s', 100, struct timeval) /* Get stamp (timeval) */
#define SIOCGSTAMPNS _IOR('s', 101, struct timespec) /* Get stamp (timespec) */
#define SIOCGSTAMP_OLD _IOR('s', 100, struct timeval) /* Get stamp (timeval) */
#define SIOCGSTAMPNS_OLD _IOR('s', 101, struct timespec) /* Get stamp (timespec) */

#endif /* __ASM_SH_SOCKIOS_H */
4 changes: 2 additions & 2 deletions arch/xtensa/include/uapi/asm/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
#define SIOCSPGRP _IOW('s', 8, pid_t)
#define SIOCGPGRP _IOR('s', 9, pid_t)

#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#define SIOCGSTAMP_OLD 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS_OLD 0x8907 /* Get stamp (timespec) */

#endif /* _XTENSA_SOCKIOS_H */
4 changes: 2 additions & 2 deletions include/uapi/asm-generic/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define FIOGETOWN 0x8903
#define SIOCGPGRP 0x8904
#define SIOCATMARK 0x8905
#define SIOCGSTAMP 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS 0x8907 /* Get stamp (timespec) */
#define SIOCGSTAMP_OLD 0x8906 /* Get stamp (timeval) */
#define SIOCGSTAMPNS_OLD 0x8907 /* Get stamp (timespec) */

#endif /* __ASM_GENERIC_SOCKIOS_H */
21 changes: 21 additions & 0 deletions include/uapi/linux/sockios.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#ifndef _LINUX_SOCKIOS_H
#define _LINUX_SOCKIOS_H

#include <asm/bitsperlong.h>
#include <asm/sockios.h>

/* Linux-specific socket ioctls */
Expand All @@ -27,6 +28,26 @@

#define SOCK_IOC_TYPE 0x89

/*
* the timeval/timespec data structure layout is defined by libc,
* so we need to cover both possible versions on 32-bit.
*/
/* Get stamp (timeval) */
#define SIOCGSTAMP_NEW _IOR(SOCK_IOC_TYPE, 0x06, long long[2])
/* Get stamp (timespec) */
#define SIOCGSTAMPNS_NEW _IOR(SOCK_IOC_TYPE, 0x07, long long[2])

#if __BITS_PER_LONG == 64 || (defined(__x86_64__) && defined(__ILP32__))
/* on 64-bit and x32, avoid the ?: operator */
#define SIOCGSTAMP SIOCGSTAMP_OLD
#define SIOCGSTAMPNS SIOCGSTAMPNS_OLD
#else
#define SIOCGSTAMP ((sizeof(struct timeval)) == 8 ? \
SIOCGSTAMP_OLD : SIOCGSTAMP_NEW)
#define SIOCGSTAMPNS ((sizeof(struct timespec)) == 8 ? \
SIOCGSTAMPNS_OLD : SIOCGSTAMPNS_NEW)
#endif

/* Routing table calls. */
#define SIOCADDRT 0x890B /* add routing table entry */
#define SIOCDELRT 0x890C /* delete routing table entry */
Expand Down
24 changes: 18 additions & 6 deletions net/socket.c
Original file line number Diff line number Diff line change
Expand Up @@ -1164,14 +1164,24 @@ 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:
case SIOCGSTAMP_OLD:
case SIOCGSTAMPNS_OLD:
if (!sock->ops->gettstamp) {
err = -ENOIOCTLCMD;
break;
}
err = sock->ops->gettstamp(sock, argp,
cmd == SIOCGSTAMP, false);
cmd == SIOCGSTAMP_OLD,
!IS_ENABLED(CONFIG_64BIT));
case SIOCGSTAMP_NEW:
case SIOCGSTAMPNS_NEW:
if (!sock->ops->gettstamp) {
err = -ENOIOCTLCMD;
break;
}
err = sock->ops->gettstamp(sock, argp,
cmd == SIOCGSTAMP_NEW,
false);
break;
default:
err = sock_do_ioctl(net, sock, cmd, arg);
Expand Down Expand Up @@ -3324,11 +3334,11 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCADDRT:
case SIOCDELRT:
return routing_ioctl(net, sock, cmd, argp);
case SIOCGSTAMP:
case SIOCGSTAMPNS:
case SIOCGSTAMP_OLD:
case SIOCGSTAMPNS_OLD:
if (!sock->ops->gettstamp)
return -ENOIOCTLCMD;
return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP,
return sock->ops->gettstamp(sock, argp, cmd == SIOCGSTAMP_OLD,
!COMPAT_USE_64BIT_TIME);

case SIOCBONDSLAVEINFOQUERY:
Expand All @@ -3348,6 +3358,8 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
case SIOCADDDLCI:
case SIOCDELDLCI:
case SIOCGSKNS:
case SIOCGSTAMP_NEW:
case SIOCGSTAMPNS_NEW:
return sock_ioctl(file, cmd, arg);

case SIOCGIFFLAGS:
Expand Down

0 comments on commit 0768e17

Please sign in to comment.