Skip to content

Commit 6673934

Browse files
dom96narimiran
authored andcommitted
Fixes issues with dynamic loading OpenSSL. Fixes #13903. (#13919) [backport]
This fixes at least a couple of issues: * Procs loaded from the DLL being used even when the pointer is nil. * The actual issue (#13903) which appeared to cause stack corruption on Android 7.1.1 with OpenSSL 1.1.1f. The change that fixed this was the move to loading the procs in `sslSym`. (cherry picked from commit 350ee03)
1 parent 8a8fddc commit 6673934

File tree

1 file changed

+39
-19
lines changed

1 file changed

+39
-19
lines changed

lib/wrappers/openssl.nim

Lines changed: 39 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ proc TLSv1_method*(): PSSL_METHOD{.cdecl, dynlib: DLLSSLName, importc.}
240240
# and support SSLv3, TLSv1, TLSv1.1 and TLSv1.2
241241
# SSLv23_method(), SSLv23_server_method(), SSLv23_client_method() are removed in 1.1.0
242242

243-
when compileOption("dynlibOverride", "ssl"):
243+
when compileOption("dynlibOverride", "ssl") or defined(noOpenSSLHacks):
244244
# Static linking
245245

246246
when defined(openssl10):
@@ -281,40 +281,59 @@ else:
281281
proc thisModule(): LibHandle {.inline.} =
282282
var thisMod {.global.}: LibHandle
283283
if thisMod.isNil: thisMod = loadLib()
284+
284285
result = thisMod
285286

286287
proc sslModule(): LibHandle {.inline.} =
287288
var sslMod {.global.}: LibHandle
288289
if sslMod.isNil: sslMod = loadLibPattern(DLLSSLName)
290+
289291
result = sslMod
290292

291-
proc sslSym(name: string): pointer =
292-
var dl = thisModule()
293-
if not dl.isNil:
294-
result = symAddr(dl, name)
293+
proc sslSymNullable(name: string, alternativeName = ""): pointer =
294+
# Load from DLL.
295+
var sslDynlib = sslModule()
296+
if not sslDynlib.isNil:
297+
result = symAddr(sslDynlib, name)
298+
if result.isNil and alternativeName.len > 0:
299+
result = symAddr(sslDynlib, alternativeName)
300+
301+
# Attempt to load from current exe.
295302
if result.isNil:
296-
dl = sslModule()
297-
if not dl.isNil:
298-
result = symAddr(dl, name)
303+
let thisDynlib = thisModule()
304+
if thisDynlib.isNil: return nil
305+
result = symAddr(thisDynlib, name)
306+
if result.isNil and alternativeName.len > 0:
307+
result = symAddr(sslDynlib, alternativeName)
308+
309+
proc sslSymThrows(name: string, alternativeName = ""): pointer =
310+
result = sslSymNullable(name, alternativeName)
311+
if result.isNil: raiseInvalidLibrary(name)
299312

300313
proc loadPSSLMethod(method1, method2: string): PSSL_METHOD =
301314
## Load <method1> from OpenSSL if available, otherwise <method2>
302-
let m1 = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method1))
303-
if not m1.isNil:
304-
return m1()
305-
cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](sslSym(method2))()
315+
##
316+
let methodSym = sslSymNullable(method1, method2)
317+
if methodSym.isNil:
318+
raise newException(LibraryError, "Could not load " & method1 & " nor " & method2)
319+
320+
let method2Proc = cast[proc(): PSSL_METHOD {.cdecl, gcsafe.}](methodSym)
321+
return method2Proc()
306322

307323
proc SSL_library_init*(): cint {.discardable.} =
308324
## Initialize SSL using OPENSSL_init_ssl for OpenSSL >= 1.1.0 otherwise
309325
## SSL_library_init
310-
let theProc = cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](sslSym("OPENSSL_init_ssl"))
311-
if not theProc.isNil:
312-
return theProc(0, 0)
313-
let olderProc = cast[proc(): cint {.cdecl.}](sslSym("SSL_library_init"))
326+
let newInitSym = sslSymNullable("OPENSSL_init_ssl")
327+
if not newInitSym.isNil:
328+
let newInitProc =
329+
cast[proc(opts: uint64, settings: uint8): cint {.cdecl.}](newInitSym)
330+
return newInitProc(0, 0)
331+
let olderProc = cast[proc(): cint {.cdecl.}](sslSymThrows("SSL_library_init"))
314332
if not olderProc.isNil: result = olderProc()
315333

316334
proc SSL_load_error_strings*() =
317-
let theProc = cast[proc() {.cdecl.}](sslSym("SSL_load_error_strings"))
335+
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
336+
let theProc = cast[proc() {.cdecl.}](sslSymNullable("SSL_load_error_strings"))
318337
if not theProc.isNil: theProc()
319338

320339
proc SSLv23_client_method*(): PSSL_METHOD =
@@ -339,12 +358,13 @@ else:
339358
loadPSSLMethod("TLS_server_method", "SSLv23_server_method")
340359

341360
proc OpenSSL_add_all_algorithms*() =
342-
let theProc = cast[proc() {.cdecl.}](sslSym("OPENSSL_add_all_algorithms_conf"))
361+
# TODO: Are we ignoring this on purpose? SSL GitHub CI fails otherwise.
362+
let theProc = cast[proc() {.cdecl.}](sslSymNullable("OPENSSL_add_all_algorithms_conf"))
343363
if not theProc.isNil: theProc()
344364

345365
proc getOpenSSLVersion*(): culong =
346366
## Return OpenSSL version as unsigned long or 0 if not available
347-
let theProc = cast[proc(): culong {.cdecl.}](sslSym("OpenSSL_version_num"))
367+
let theProc = cast[proc(): culong {.cdecl.}](sslSymNullable("OpenSSL_version_num"))
348368
result =
349369
if theProc.isNil: 0.culong
350370
else: theProc()

0 commit comments

Comments
 (0)