Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test_ssl fails after 2038 #101732

Closed
blemouzy opened this issue Feb 9, 2023 · 13 comments
Closed

test_ssl fails after 2038 #101732

blemouzy opened this issue Feb 9, 2023 · 13 comments
Labels
tests Tests in the Lib/test dir topic-SSL type-bug An unexpected behavior, bug, or error

Comments

@blemouzy
Copy link

blemouzy commented Feb 9, 2023

Environment

  • i.MX6 32 bits CPU
  • Yocto Kirkstone (kirkstone-4.0.6)
  • Linux 5.10.109
  • glibc 2.35 (8d125a1f9145ad90c94e438858d6b5b7578686f2)
  • openssl 3.0.7
  • Python 3.10.8
  • RFS built with "-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" flags
  • System date set after 011903142038 (2038 Jan 19 03:14:00)
# openssl version
OpenSSL 3.0.7 1 Nov 2022 (Library: OpenSSL 3.0.7 1 Nov 2022)

# python3 -V
Python 3.10.8

# date
Thu Jan 19 04:04:50 UTC 2040

Description

test_ssl returns the following error on 32 bits board with system date after 2038:

======================================================================
FAIL: test_session (test.test_ssl.ThreadedTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/usr/lib/python3.10/test/test_ssl.py", line 4366, in test_session
    self.assertGreater(session.time, 0)
AssertionError: -2084411619 not greater than 0

----------------------------------------------------------------------

The same test passes with a system date before 2038.

How to reproduce

  • Set enddate to 20421028142316Z in make_ssl_certs.py file
  • Run make_ssl_certs.py to create new certificates
  • Update test_ssl.py and test_asyncio/utils.py according to make_ssl_certs.py output
  • Run the following command:
python3 -m test test_ssl -v

Linked PRs

@blemouzy blemouzy added the type-bug An unexpected behavior, bug, or error label Feb 9, 2023
@arhadthedev arhadthedev added tests Tests in the Lib/test dir topic-SSL labels Feb 9, 2023
@sobolevn
Copy link
Member

sobolevn commented Feb 9, 2023

We have plenty of time to fix this one! (joking, sorry) 😆

@TabLand
Copy link
Contributor

TabLand commented Apr 7, 2023

Hi @blemouzy,

I'm new to cpython and curious in having a look at this. I've managed to build cpython and ssl module on an i686 virtual machine (debian 11, linux kernel 5.10).

Could you clarify the following step a bit further?
RFS built with "-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" flags

I'm not sure if it's just python that needs to be built with these options (in make file CFLAGS or CPPFLAGS?), or both the kernel and user space binaries (i.e everything)? At present, I'm not able to set a system date later than 2038, nor using python datetime module in my 32 bit build:

tabland@debian:/opt/python/cpython$ sudo date --set "7 Apr 2039"
date: invalid date '7 Apr 2039'

tabland@debian:/opt/python/cpython$ ./python
>>> import datetime
>>> datetime.datetime.fromtimestamp(75 * 365 * 24 * 60 * 60)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: timestamp out of range for platform time_t

@blemouzy
Copy link
Author

Hi,

linux kernel 5.10

Linux kernel supports 64 bits time syscalls since 5.1 (https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=48166e6ea47d23984f0b481ca199250e1ce0730a) and is supposed to be fully usable since 5.6. So you have nothing to do with your current version.

user space binaries

You have to use a 64 bits time ready libc (glibc >= 2.35, muslc, ...).
And yes, you have to rebuild all your userspace with "-D_TIME_BITS=64 -D_FILE_OFFSET_BITS=64" flags.

You also have to take care about your filesystem.
For example, with ext4, you need inode size >= 256 bytes.

curious in having a look at this

You can, for example, find more information here: https://sourceware.org/glibc/wiki/Y2038ProofnessDesign

@TabLand
Copy link
Contributor

TabLand commented May 2, 2023

Hello again,

Good news. I've managed to reproduce this issue after building 32-bit Linux From Scratch using the 64-bit time flags you mentioned:

Linux lfs.ijtaba 6.1.11 #1 SMP PREEMPT_DYNAMIC Sun Apr 30 12:53:36 PKT 2023 i686 GNU/Linux
Python 3.12.0a7+
======================================================================
FAIL: test_session (test.test_ssl.ThreadedTests.test_session)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/sources/cpython/Lib/test/test_ssl.py", line 4111, in test_session
    self.assertGreater(session.time, 0)
AssertionError: -2084408147 not greater than 0
----------------------------------------------------------------------

Issues encountered with other projects:

  • binutils-2.40 does not compile with 64-bit time flags
  • p11-kit-0.24.1 build with meson-1.1.0 and python-3.11.2 runs into a "value too large for defined" data type error in mesonbuild/msetup.py

I'll aim to inform relevant project's maintainers on the above 2x

@TabLand
Copy link
Contributor

TabLand commented May 10, 2023

I believe I've found the root cause of the issue here:

cpython/Modules/_ssl.c

Lines 5004 to 5007 in a33ce66

static PyObject *
PySSLSession_get_time(PySSLSession *self, void *closure) {
return PyLong_FromLong(SSL_SESSION_get_time(self->session));
}

Output of ./configure shows that a long is 4 bytes on i686, and 8 bytes on x64. The SSL_SESSION_get_time() function is part of the OpenSSL API, and the datatype is defined as long instead of time_t:

https://www.openssl.org/docs/manmaster/man3/SSL_SESSION_get_time.html

The OpenSSL team are aware of this:
openssl/openssl#16726

I'll try and draft a PR against the OpenSSL project soon and test it against this issue. The cpython fix for this issue will be dependant on the OpenSSL fix. As the fix for this issue will most likely extend their API, I'll probably have to add logic for cpython to fall back to the existing and older non-Y2038 compatible OpenSSL APIs where the extended functions using more appropriate data types are not available.

@TabLand
Copy link
Contributor

TabLand commented Jun 14, 2023

Hi Team,

I've just submitted the following draft PR to openssl:

openssl/openssl#21206

Potentially a slow-burner as the existing commentary in the associated openssl issue (openssl/openssl#16726) suggests that other parts of the library may also be affected by Y2038, which will also need to be discovered and patched (or proven to not be required).

I'll try and draft a better python patch soon, a rudimentary one for Yocto Kirkstone is available here:
TabLand/poky@68e4af2

@kanavin
Copy link
Contributor

kanavin commented Feb 21, 2024

The openssl fix has just landed and will be released in 3.3.0:
openssl/openssl@ffc853b

@kanavin
Copy link
Contributor

kanavin commented Apr 26, 2024

openssl 3.3.0 has been released. So now everything is ready to fix this in python (should be easy, use the new function subject to openssl version being at least 3.3.0).

@novaTopFlex
Copy link

This sounds like an issue on systems that force 32-bit time, where the final second that can be represented in 32 bits falls on January 19, 2038 as the initial second would have been on the beginning of January 1, 1970.

@novaTopFlex
Copy link

I understand that OpenSSL 3.3.0 is now available. However, many distributions of Linux have not yet packaged this new version of the software, so assuming you are on Ubuntu 22.04.1 LTS, you should expect to have OpenSSL version 3.0.2 installed on your system.

@kanavin
Copy link
Contributor

kanavin commented Apr 29, 2024

This sounds like an issue on systems that force 32-bit time, where the final second that can be represented in 32 bits falls on January 19, 2038 as the initial second would have been on the beginning of January 1, 1970.

This is not the case. The issue occurs on 32 bit systems with 64 bit time as well, and was traced to openssl incorrectly using long type for time in one of its public APIs.

@kanavin
Copy link
Contributor

kanavin commented Apr 29, 2024

I understand that OpenSSL 3.3.0 is now available. However, many distributions of Linux have not yet packaged this new version of the software, so assuming you are on Ubuntu 22.04.1 LTS, you should expect to have OpenSSL version 3.0.2 installed on your system.

Which is fine. Any prospective fix would be conditional on the openssl version, and remain compatible with older versions as well. There's a way to check what openssl version is used at build time.

kanavin added a commit to kanavin/cpython that referenced this issue Apr 30, 2024
kanavin added a commit to kanavin/cpython that referenced this issue Apr 30, 2024
kanavin added a commit to kanavin/cpython that referenced this issue Apr 30, 2024
kanavin added a commit to kanavin/cpython that referenced this issue Apr 30, 2024
kanavin added a commit to kanavin/cpython that referenced this issue May 2, 2024
kanavin added a commit to kanavin/cpython that referenced this issue May 2, 2024
kanavin added a commit to kanavin/cpython that referenced this issue May 3, 2024
@encukou
Copy link
Member

encukou commented May 6, 2024

The PR is merged.
The reproducer listed here is too complicated; see #107562 for that.
(You can view #107562 as either a follow-up or a duplicate; either way, this issue should be closed.)

@encukou encukou closed this as completed May 6, 2024
SonicField pushed a commit to SonicField/cpython that referenced this issue May 8, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
tests Tests in the Lib/test dir topic-SSL type-bug An unexpected behavior, bug, or error
Projects
None yet
Development

No branches or pull requests

7 participants