Date: Thu, 28 Feb 2019 00:21:53 +1100 (EST) From: Bruce Evans <brde@optusnet.com.au> To: everton.win32@gmail.com Cc: bugs@freebsd.org Subject: Re: [Bug 236065] TimeStamp Overflow 2106 year Message-ID: <20190227223837.D2208@besplex.bde.org> In-Reply-To: <bug-236065-227@https.bugs.freebsd.org/bugzilla/> References: <bug-236065-227@https.bugs.freebsd.org/bugzilla/>
next in thread | previous in thread | raw e-mail | index | archive | help
On Tue, 26 Feb 2019 bugzilla-noreply@freebsd.org wrote: > https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=236065 > I work doing tests, and I found one possible in a decentralized system that is > used worldwide. > I want to simulate a specific date in the 22nd century; > however when I define the system with the date: 01/01/2106 00:00; > > the system reports an error. This is not supported. On x86 systems, the hardware clock only has a trustable range of 100 years. This range currently defaults to 1970-2069 for all arches whose clocks have a range of 100 years. Old versions that had to work before Y2K did the same thing in driver code on at least x86. This regressed to to blindly adding 2000 in driver code in FreeBSD7-[7-8] (perhaps the same in FreeBSD-6 and late FreeBSD-5). This gave the different range of 2000-2099. This advanced towards the previous version by changing the range to 1980-2079 in FreeBSD-[9-10]. Advancing the range by 10 or 30 years 50 years before a change is needed mainly breaks testing past dates for young people's birthdays and takes longer mail to describe. 1970 is a much better start for a 100-year range since it is the POSIX Epoch and covers a few more birthdays. 1980 is politically incorrect since msdosfs uses it. This was finally improved relative to what old versions did in FreeBSD-[11-current] by removing the adjustments in driver code so that the better machine-independent code is used. The machine-independent code also adjusts for years 70-199. This will start supporting clocks with a single bit for the century in 2070. Dates before 1970 are disallowed in the MI code even for clocks that support them. x86 clocks actually have a century register, so can do better than clocks with a century bit, but FreeBSD doesn't trust this register. You can try it using the unsupported option USE_RTC_CENTURY. Expect bugs using this option. The bugs are hard to test, and are especially likely in testing where you set the year to anything except the 21st century. The BIOS might reset the century to 20. The FreeBSD clock code is not very robust, except on i386 where it limits the year to 1970-2037. Know bugs in this include not being able to represent local time for the Epoch in some timezones. Then for the Epoch time of 0 representing the start of 1970, the local time is 1969 in some timezones. Writing this 1969 to x86 clocks truncates it to 69, which means 2069 in local time on the next boot. But it means 2070 in UTC on the next boot. 2070 is outside of the supported range, and it is unclear what happens. At best it gets converted back to 1970. 2106 is a good date to warm up with. It is when 32-bit unsigned time_t overflows. There is too much broken clock code which assumes that time_t is signed to easily extend the range if 32-bit signed time_t by changing it to unsigned. > if I enter another date, for exemple: 01/01/2105 00:00 > the freebsd allows it to be changed. > > but after the reboot. it sets to: 01/01/2005 00:00; You just found a bug after in the non-robust MI clock code. i386 doesn't have this bug, since it doesn't allow setting times after 2037, since 32-bit singed time_t can't represent times a little later in 2038 and stopping at the end of 2037 gives a safety margin. On amd64, the kernel allows setting times that the driver or hardware clock can't handle. It asks the driver to write 2105, but the driver only writes 05. Then on the next boot, this means 2005. Don't worry about this for tests. Just set the time early in the boot, and also set it back to the the current time before rebooting in case the BIOS or other OSes don't like it being later. I don't know of anything that immediately breaks similar testing in 2106 or even at the end of 64-bit time_t in 292 billion years. Set the time early in the boot using date(1) or similar, and don't let ntpdate or anything else on the network see this time. This write garbage to the x86 clock, but the x86 clock is write-only until the next boot. > I found some information on: > > https://en.wikipedia.org/wiki/Year_2038_problem 2038 is just the special limit for 32-bit signed time_t which only some systems use. > there is a possibility that I compile the system to use the size uint64? > > according to the wikipedia topic: > > FreeBSD uses 64-bit time_t for all 32-bit and 64-bit architectures except > 32-bit i386[11]. You must already be using 64-bit time_t to reach 2105, > if the field actually has 64 bits, it can even be used after 2107 (which is the > date I need); For another 292 billion years. If there really is a 2106 limit on amd64, then it must be from using 32-bit unsigned seconds counts somewhere. I haven't looked at what user library code does with this lately. I did a quick check on amd64, in single user mode with no disks mounted rw (to prevent clobbering file times). Setting the date to 2106 just works, at least with a very old userland. Setting the date to the last second in 9999 works too. date(1) doesn't support setting centuries after the 99th, but it works for displaying them after the time advances from the end of 9999 to 10000. Bruce
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?20190227223837.D2208>