Improve post-2038 compatibility of time_t usage#17778
Improve post-2038 compatibility of time_t usage#17778kaduk wants to merge 1 commit intoopenssl:masterfrom
Conversation
The Unix epoch will overflow a signed 32-bit integer in the year 2038, and many systems are updating time_t to be 64-bits or to treat the time as an unsigned integer as a result. To protect openssl against such issues: - update s_time's internal logic to consistently use time_t for tracking timeouts - update BIO_SSL to use a time_t to track the last renegotiation time, rather than the ad hoc 'unsigned long'. The structure is private to bio_ssl.c and so there is no external ABI breakage
|
Alternative to #17701 |
| } | ||
| totalTime += tm_Time_F(STOP); /* Add the time for this iteration */ | ||
|
|
||
| i = (int)((long)time(NULL) - finishtime + maxtime); |
There was a problem hiding this comment.
I couldn't find anywhere that this value was used.
It seems plausible that at one point it was used in the printf call a couple lines later, but that the expression got duplicated as part of a cleanup change; I did not look into the history to try to confirm that.
|
I'll also note that I only looked at places that #17701 was already touching, and did not do an independent survey of other |
|
This version seems clearer to me. |
|
Some systems are keeping time_t as 32-bit and moving to time64_t. I know of three. This is not a permanent fix, however (permanent being a relative term). I think having an OpenSSL-specific time type may be the only rational way to go - OpenSSL_time_t and have the platform implement whatever it must to deal with 2038. Given how fast people are moving off of 1.0.1m (really, it's still in production), this is somewhat urgent. |
| tm = (unsigned long)time(NULL); | ||
| if (tm > sb->last_time + sb->renegotiate_timeout) { | ||
| tm = time(NULL); | ||
| if (tm - sb->last_time > (time_t)sb->renegotiate_timeout) { |
There was a problem hiding this comment.
my approach had the nice added value that it is robust if the system time is set back,
that's why I rewrote the condition to tm - bs->last_time > bs->renegotiate_timeout
I thought that's obvious.
|
Alternative proposal: #17786 (it's a WIP, and could subsume this work). |
|
|
||
| bytes_read = 0; | ||
| finishtime = (long)time(NULL) + maxtime; | ||
| finishtime = time(NULL) + maxtime; |
There was a problem hiding this comment.
Overflow for 32-bit time_t systems in 2038.
There was a problem hiding this comment.
#8687 includes timeoutcmp() for SSL_SESSION structures, that looks at overflow... It basically gives an extra bit of time (so on 32-bit systems, it's an extra 68 years...) Does that kick the can down the road? Yes, will 32-bit systems still exists after 2038? Probably? Will they have been updated with a 64-bit time_t? Who knows.
| totalTime = 0.0; | ||
|
|
||
| finishtime = (long)time(NULL) + maxtime; | ||
| finishtime = time(NULL) + maxtime; |
There was a problem hiding this comment.
Again overflow.
In general, I believe that finishtimes should no longer be used. Better to subtract the timeout value from "now", and compare to the starttime. In other words, keep two values around (start and duration) rather than finishtime.
There was a problem hiding this comment.
I agree with this as a better approach
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
|
Where are we with this particular PR? |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 92 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 123 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 154 days ago |
|
We have OSSL_TIME nowadays. That might otherwise be useful here. |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
I think any solution will have to take into account that there is no consistency between 32-bit and 64-bit time implementations on different platforms. It is consistent in gcc and some 64-bit builds, but not universal. The |
|
@rsbeckerca ok, thats reasonable, but thats not what this PR does. My goal here was to motivate movement on this issue in some way, given that it has been idle for a year, be that to make arguments for its inclusion, or its rejection (either in favor of something else, or to close it entirely if there is not current interest to pursue it). So I suppose in my mind the first question is to @kaduk - do you want to address the comments made in this PR and continue to pursue its inclusion, or should we close this, and address the problem in a future issue? |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 92 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 123 days ago |
The discussion of what we want to do "in this space" (itself a vaguely defined matter) got split across quite a few PRs but after a brief survey it does seem like I should pick this one up again and we can get some small incremental improvements in even if we end up wanting to do a bigger cleanup pass later. |
|
ack, assigning to you, @openssl/committers can we pick up reviewing this please |
|
Please note that we explicitly added new public APIs with time_t arguments as the type for holding time values instead of long. I do not think we are going to fix issues on platforms where time_t cannot hold time after 2038. |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
|
There are some unresolved comments from @tmshort and @bernd-edlinger . @kaduk could you please respond to them? |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 30 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 61 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 92 days ago |
|
This PR is in a state where it requires action by @openssl/committers but the last update was 123 days ago |
|
This PR is waiting for the creator to make requested changes but it has not been updated for 30 days. If you have made changes or commented to the reviewer please make sure you re-request a review (see icon in the 'reviewers' section). |
|
This PR is waiting for the creator to make requested changes but it has not been updated for 61 days. If you have made changes or commented to the reviewer please make sure you re-request a review (see icon in the 'reviewers' section). |
|
This PR has been closed. It was waiting for the creator to make requested changes but it has not been updated for 90 days. |
The Unix epoch will overflow a signed 32-bit integer in the year 2038,
and many systems are updating time_t to be 64-bits or to treat the time
as an unsigned integer as a result. To protect openssl against such
issues:
update s_time's internal logic to consistently use time_t for tracking
timeouts
update BIO_SSL to use a time_t to track the last renegotiation time,
rather than the ad hoc 'unsigned long'. The structure is private to
bio_ssl.c and so there is no external ABI breakage