My ignorance was Re: ✘64-bit time_t on glibc 2.34 and up
James Browning
jamesb192 at jamesb192.com
Fri Jan 13 16:49:34 UTC 2023
> On 01/12/2023 5:10 PM PST Gary E. Miller <gem at rellim.com> wrote:
>
>
> Yo All!
>
> Cross-posted to gpsd-dev and devel at ntpsec.org
>
> Recent glibc (2.34 and up) and recent Linux kernels, allow 64 bit
> time_t on 32-bit Linux without much work.
>
> But...
>
> How to get that 2038 compatible time to ntpd and chronyd? That is a
> much bigger problem.
>
> Extracted from include/ntpshm.h:
>
> struct shmTime
> {
> int mode;
> volatile int count;
> time_t clockTimeStampSec;
> int clockTimeStampUSec;
> time_t receiveTimeStampSec;
> int receiveTimeStampUSec;
> int leap; // not leapsecond offset, a notification code
> int precision; // log(2) of source jitter
> int nsamples; // not used
> volatile int valid;
> unsigned clockTimeStampNSec; // Unsigned ns timestamps
> unsigned receiveTimeStampNSec; // Unsigned ns timestamps
> int dummy[8];
> };
>
> Note the struct size depends on the size of an int, and the size of time_t.
>
> This is no problem for newer musl on 32-bits. An int is 32-bits and
> time_t is 64. Assuming all clients use the same version musl.
>
> This is a problem for glibc on 32 bits. And int is 32-bits, but time_t
> is a compile time option (32 or 64 bits).
>
> How does ntpd know what size time_t to use? And thus know the size of
> shmTime? How do we know portably, preserving backwards and forwards
> compatibility?
>
> In hindsight, maybe shmTime should have started with a 1 char version
> field,or magic field. But, no such luck.
>
> Options (for 32-bit only):
>
> 1. Do nothing, stick with 32-bit time_t. Fail in 2038.
>
> 2. Allow 64-bit time_t and let incompatible ntpd fail.
>
> 3. Add run time options to gpsd and ntpd to specify time_t size.
>
> 4. gpsd and ntpd always use 64-bit time_t going forward. Admin needs
> to mix and match.
>
> 5. 1st process to open SHM(0) wins, the other process checks the size
> to know the contents.
>
> 6. Create a new way to pass time from gpsd to ntpd and chronyd.
>
> Also note, chrony sockets have a similar problem:
>
> #define SOCK_MAGIC 0x534f434b
> struct sock_sample {
> struct timeval tv;
> double offset;
> int pulse;
> int leap; // notify that a leap second is upcoming
> int _pad;
> int magic; // must be SOCK_MAGIC
> };
>
> Where timeval is:
>
> struct timeval {
> time_t tv_sec;
> suseconds_t tv_usec;
> };
> ```
>
> Since the sample has a magic value, maybe that can be used to detect versions.
>
> This makes my head hurt...
IIRC there are a few users of those interfaces; linuxptp, gpsd,
classic NTP, NTPsec, and chrony. I would jokingly suggest
something like the following as a replacement. Purely based on
the misassumption that SHM internally works on page-sized blocks
and probably via POSIX shared memory which would allow names.
Also, the mode should be 640, and the root user should not be
remotely involved.
```c
typedef struct {
uint32_t left_book;
uint32_t mode; // modes 4-7 match this
uint32_t half_epoch; /* number of 2^31 seconds since
1900-01-01T00:00:00Z */
uint32_t c_seconds; /* coarse time from string mangling
probably */
uint32_t c_nseconds;
uint32_t f_seconds; /* fine time probably from a pulse
per second */
uint32_t f_nseconds;
signed int32_t leap;
signed int32_t precision;
uint32_t padding[1013]; // I think it should be 1014
uint32_t right_book;
} pshm_t;
```
The low two bits of mode could be the validity of coarse and
fine time, respectively. Anyone needing microsecond or NTP
partial seconds can math it.
Posted to gpsd issue #152 earlier, gpsd-dev, and NTPsec devel.
- JamesB192
I'm supposed to put a signature here...
More information about the devel
mailing list