Bug 66035 - SIGSEGV in org.apache.tomcat.jni.SSL::getSessionId - NIO+OpenSSL
Summary: SIGSEGV in org.apache.tomcat.jni.SSL::getSessionId - NIO+OpenSSL
Status: RESOLVED FIXED
Alias: None
Product: Tomcat Native
Classification: Unclassified
Component: Library (show other bugs)
Version: 1.2.30
Hardware: PC Linux
: P2 major (vote)
Target Milestone: ---
Assignee: Tomcat Developers Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-04-27 09:28 UTC by Michal Josifek
Modified: 2022-05-03 16:13 UTC (History)
0 users



Attachments
hs_err_pid (64.83 KB, application/gzip)
2022-04-27 09:28 UTC, Michal Josifek
Details

Note You need to log in before you can comment on or make changes to this bug.
Description Michal Josifek 2022-04-27 09:28:30 UTC
Created attachment 38265 [details]
hs_err_pid

Hello,
we are switching from APR+OpenSSL to NIO(2)+OpenSSL connector configuration and we are facing SIGSEGV error. Tested multiple Java+tomcat-native+OpenSSL combinations, nothing helped.
Tested also with Oracle JDK 11.0.15, openssl 1.1.1n, latest tomcat-native....

fyi. Our APR+OpenSSL configuration is rock solid.

Best Regards
Michal Josifek


#
# A fatal error has been detected by the Java Runtime Environment:
#
#  SIGSEGV (0xb) at pc=0x00007f13f860fbe5, pid=36351, tid=36401
#
# JRE version: OpenJDK Runtime Environment Corretto-11.0.14.9.1 (11.0.14+9) (build 11.0.14+9-LTS)
# Java VM: OpenJDK 64-Bit Server VM Corretto-11.0.14.9.1 (11.0.14+9-LTS, mixed mode, tiered, compressed oops, g1 gc, linux-amd64)
# Problematic frame:
# C  [libssl.so.1.0.0+0x49be5]  SSL_SESSION_get_id+0x5
#
# Core dump will be written. Default location: //core.36351
#
# An error report file with more information is saved as:
# /tmp/hs_err_pid36351.log
Compiled method (nm) 2514776 22100     n 0       org.apache.tomcat.jni.SSL::getSessionId (native)
 total in heap  [0x00007f143d67ef10,0x00007f143d67f350] = 1088
 relocation     [0x00007f143d67f088,0x00007f143d67f0c0] = 56
 main code      [0x00007f143d67f0c0,0x00007f143d67f348] = 648
 oops           [0x00007f143d67f348,0x00007f143d67f350] = 8
Compiled method (nm) 2514781 22100     n 0       org.apache.tomcat.jni.SSL::getSessionId (native)
 total in heap  [0x00007f143d67ef10,0x00007f143d67f350] = 1088
 relocation     [0x00007f143d67f088,0x00007f143d67f0c0] = 56
 main code      [0x00007f143d67f0c0,0x00007f143d67f348] = 648
 oops           [0x00007f143d67f348,0x00007f143d67f350] = 8
#
# If you would like to submit a bug report, please visit:
#   https://github.com/corretto/corretto-11/issues/
# The crash happened outside the Java Virtual Machine in native code.
# See problematic frame for where to report the bug.
#
Comment 1 Remy Maucherat 2022-04-27 10:47:37 UTC
The handshake failed and the session id is accessed through your access logging pattern.

Looking at the Panama code there could be an optimistic use of the SSL_get_session call (it would return NULL if there's no session because handshake failed).

The native code seems to have the same problem, since it does:
    UNREFERENCED(o);
    session = SSL_get_session(ssl_);
    session_id = SSL_SESSION_get_id(session, &len);

While other places do:
    session  = SSL_get_session(ssl_);
    if (session) {
        return SSL_get_time(session);
    } else {
        tcn_ThrowException(e, "ssl session is null");
        return 0;
    }
Comment 2 Christopher Schultz 2022-04-27 20:37:20 UTC
Proposed patch for tcnative:

diff --git a/native/src/ssl.c b/native/src/ssl.c
index d59246ea3..5329a93da 100644
--- a/native/src/ssl.c
+++ b/native/src/ssl.c
@@ -2001,8 +2001,12 @@ TCN_IMPLEMENT_CALL(jbyteArray, SSL, getSessionId)(TCN_STDARGS, jlong ssl)
     }
     UNREFERENCED(o);
     session = SSL_get_session(ssl_);
-    session_id = SSL_SESSION_get_id(session, &len);
+    if (NULL == session) {
+        tcn_ThrowException(e, "ssl session is null");
+        return NULL;
+    }
 
+    session_id = SSL_SESSION_get_id(session, &len);
     if (len == 0 || session_id == NULL) {
         return NULL;
     }
diff --git a/native/src/sslnetwork.c b/native/src/sslnetwork.c
index 6e5960f91..46b253ec8 100644
--- a/native/src/sslnetwork.c
+++ b/native/src/sslnetwork.c
@@ -689,7 +689,7 @@ TCN_IMPLEMENT_CALL(jint, SSLSocket, renegotiate)(TCN_STDARGS,
 
 #if defined(SSL_OP_NO_TLSv1_3)
     session  = SSL_get_session(con->ssl);
-    if (SSL_SESSION_get_protocol_version(session) == TLS1_3_VERSION) {
+    if (NULL != session && SSL_SESSION_get_protocol_version(session) == TLS1_3_VERSION) {
         // TLS 1.3 renegotiation
         retVal = SSL_verify_client_post_handshake(con->ssl);
         if (retVal <= 0) {
Comment 3 Remy Maucherat 2022-04-28 11:27:42 UTC
JF seems to think simply return NULL; is enough (I agree this is not an error). I left the bug open since it has not been addressed. I don't maintain the native code and I am more likely to inadvertently break something.

Also the second check may not be needed, on renegotiate there would be a session I suppose.
Comment 4 jfclere 2022-04-28 16:07:30 UTC
in openssl: ./ssl/ssl_sess.c
{
    if (len)
        *len = (unsigned int)s->session_id_length;
    return s->session_id;
}

So +1 for testing for NULL.

I am curious how you manage to get error, I don't see how the jakarta.servlet.request.ssl_session_id could be read with a failed handshake...
Comment 5 Christopher Schultz 2022-04-29 18:55:56 UTC
(In reply to Remy Maucherat from comment #3)
> JF seems to think simply return NULL; is enough (I agree this is not an
> error).

Aha, so simply return NULL instead of throwing an exception?

> Also the second check may not be needed, on renegotiate there would be a
> session I suppose.

I just figured an extra check is better than a crash... just in case :)
Comment 6 Mark Thomas 2022-05-03 16:13:59 UTC
Thanks all for the report, proposed patch and review.

Variation of patch applied to 1.2.x for 1.2.33 onwards.