Skip to content

crypto/init.c: use destructor_key even as guard in OPENSSL_thread_stop.#6752

Closed
dot-asm wants to merge 11 commits intoopenssl:masterfrom
dot-asm:windows-init
Closed

crypto/init.c: use destructor_key even as guard in OPENSSL_thread_stop.#6752
dot-asm wants to merge 11 commits intoopenssl:masterfrom
dot-asm:windows-init

Conversation

@dot-asm
Copy link
Copy Markdown
Contributor

@dot-asm dot-asm commented Jul 20, 2018

Problem was that Windows threads that were terminating before libcrypto
was initialized were referencing uninitialized or possibly even
unrelated thread local storage index.

Request covers even couple of other issues related to dllmain. This is alternative to #6627 and #6711.

1.0.2 and 1.1.0 labels are speculative in sense that not everything should be back-ported and those commits that should be won't necessarily cherry-pick.

Andy Polyakov added 4 commits July 20, 2018 13:30
@dot-asm dot-asm added branch: master Applies to master branch branch: 1.0.2 Applies to OpenSSL_1_0_2-stable branch (EOL) 1.1.0 branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL) labels Jul 20, 2018
@mattcaswell mattcaswell added this to the Assessed milestone Jul 20, 2018
else if (ossl_isxdigit(ossl_tolower(c)))
return c - 'a' + 10;

return 16;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why 16?

Copy link
Copy Markdown
Contributor Author

@dot-asm dot-asm Jul 21, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's largest possible base value, that will make caller terminate to the loop. Added commentary.

crypto/init.c Outdated
static void ossl_init_thread_stop(struct thread_local_inits_st *locals);
/*
* Since per-thread-specific-data destructors are not universally
* available, i.e. not on *cough*-dows, only below CRYPTO_THREAD_LOCAL
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you write that as Windows?

* agnostic" means that they work with either wide or 8-bit characters,
* exploiting the fact that first 127 characters can be simply casted
* between the sets, while the rest would be simply rejected by ossl_is*
* subroutines.
Copy link
Copy Markdown
Member

@kroeckx kroeckx Jul 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure how this is supposed to work. You get a char *. Every 2 characters will be a '\0' if it's UTF-16

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I must have somehow missed the ossl_char

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about renaming ossl_char to variant_char? Hopefully it would be harder to miss then...

static WCHAR value[48];
DWORD len = GetEnvironmentVariableW(L"OPENSSL_ia32cap", value, 48);

return (len > 0 && len <= 48) ? value : NULL;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand, you can never get 48 back. But I would expect the check to be < 48.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh! I thought that it returns value that accounts even for trailing null. But it does so only when buffer is not large enough. Thanks for spotting this!

*/
# ifdef _WIN32
typedef WCHAR ossl_char;
static ossl_char *ossl_getenv(const char *name)
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name parameter is unused ...

Copy link
Copy Markdown
Contributor Author

@dot-asm dot-asm Jul 22, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correct. Basically there are two alternatives to this. a) Make conversion from char to WCHAR with MutliByteToWideChar in this subroutine. b) Arrange preprocessor directives so that "OPENSSL_ia32cap" literal is passed to ossl_getenv as L"OPENSSL_ia32cap" on Windows. Chosen approach (of ignoring the argument and resorting to hard-coded L-literal that works with specifically here) is least-typing one. Would a commentary be sufficient of should I switch to alternative?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A comment is good for me.


CRYPTO_THREAD_cleanup_local(&threadstopkey);
key = destructor_key;
destructor_key = (CRYPTO_THREAD_LOCAL)-1;
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does it get set to -1?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To denote the fact that it's no longer valid. Since libcrypto leaks descriptor to itself (not fan of it by the way), it won't go away from memory, so that Windows will keep invoking DLL_THREAD_DETACH and OPENSSL_thread_stop even after OPENSSL_cleanup. So that destructor_key has to go back to "impossible" value.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've mentioned post-cleanup case in commentary to destructor_key.

@dot-asm
Copy link
Copy Markdown
Contributor Author

dot-asm commented Jul 22, 2018

Feedback is addressed.

@dot-asm
Copy link
Copy Markdown
Contributor Author

dot-asm commented Jul 22, 2018

Spotted bug in todigit!

@kroeckx kroeckx added the approval: done This pull request has the required number of approvals label Jul 22, 2018
@dot-asm
Copy link
Copy Markdown
Contributor Author

dot-asm commented Jul 22, 2018

I've spotted typo in commentary, MSCVRT vs. MSVCRT, which fixed in first post-approval commit. Since it's commentary-only change I claim that it doesn't invalidate approval status (unless somebody claims otherwise). But on top of that I did ossl_char -> variant_char rename, which certainly invalidates approval status. However! I leave lack of re-approval as option. In sense that [if] request is not re-approved with variant_char, then I intend to merge commits up to this last one.

@kroeckx
Copy link
Copy Markdown
Member

kroeckx commented Jul 22, 2018

I don't really care how you name that type, so consider this +1.
But I wonder why you call it "variant"

@dot-asm
Copy link
Copy Markdown
Contributor Author

dot-asm commented Jul 22, 2018

But I wonder why you call it "variant"

There might be better options. "variant" can be used as adjective and does describe something that can change depending on situation. In this case depending on whether or not code is compiled for Windows.

levitte pushed a commit that referenced this pull request Jul 25, 2018
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from #6752)
levitte pushed a commit that referenced this pull request Jul 25, 2018
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from #6752)
levitte pushed a commit that referenced this pull request Jul 25, 2018
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from #6752)
levitte pushed a commit that referenced this pull request Jul 25, 2018
Problem was that Windows threads that were terminating before libcrypto
was initialized were referencing uninitialized or possibly even
unrelated thread local storage index.

Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from #6752)
levitte pushed a commit that referenced this pull request Jul 25, 2018
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from #6752)

(cherry picked from commit 9e4a1c3)
@dot-asm
Copy link
Copy Markdown
Contributor Author

dot-asm commented Jul 25, 2018

9e4a1c3 was the only that cherry-picked to 1.1.0. So that will be branch-specific requests...

@dot-asm dot-asm closed this Jul 25, 2018
dot-asm pushed a commit to dot-asm/openssl that referenced this pull request Jul 27, 2018
Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from openssl#6752)

(cherry picked from commit b86d57b)

Resolved conflicts:
	crypto/cryptlib.c
dot-asm pushed a commit to dot-asm/openssl that referenced this pull request Jul 27, 2018
Problem was that Windows threads that were terminating before libcrypto
was initialized were referencing uninitialized or possibly even
unrelated thread local storage index.

Reviewed-by: Kurt Roeckx <kurt@roeckx.be>
(Merged from openssl#6752)

(cherry picked from commit 80ae728)

Resolved conflicts:
	crypto/init.c
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

approval: done This pull request has the required number of approvals branch: master Applies to master branch branch: 1.0.2 Applies to OpenSSL_1_0_2-stable branch (EOL) branch: 1.1.1 Applies to OpenSSL_1_1_1-stable branch (EOL)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants