-
Notifications
You must be signed in to change notification settings - Fork 4.9k
Proper fix for compilation issue caused by deprecated API in Mojave #30815
Conversation
…jave by using dlsym to call available API rather than suppressing deprecation warnings. Fixes: #30599
if (!checked) | ||
{ | ||
secCertificateCopyKey = (SecKeyRef (*)(SecCertificateRef))dlsym(RTLD_DEFAULT, "SecCertificateCopyKey"); | ||
secCertificateCopyPublicKey = (OSStatus (*)(SecCertificateRef, SecKeyRef*))dlsym(RTLD_DEFAULT, "SecCertificateCopyPublicKey"); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@janvorli is there a way we could call dlsym only once in this code snippet to improve the diff?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
From @bartonjs on Jul 3, 2018, 8:37 AM PDT
(Or is my static local
-fu weak, and we don't need to do a lazy initializer manually, because static locals guarantee that they only run their initializer once? (and therefore the two dlsym calls should move up to variable initializers))
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkotas will also know for sure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right, this code is wrong. It can be broken even on x64, depending on the compiler optimizations.
The other places in the corefx shims use volatile, double-checked locking and pthread_mutex_lock
(look for pthread_mutex_lock
under src/native for examples). You can use the same pattern.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, I would just use pthread_once
here. It does exactly what you need here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@jkotas, in my case here, I would need to call either of SecCertificateCopyKey
or SecCertificateCopyPublicKey
once, and both have arguments and neither returns void.
While looking at the doc here, it seems that init_routine()
which is the second argument passed to pthread_once
, apparently should have no arguments and returns void.
Please let me know if I misunderstood, but I think because of this observation I don't think I can use pthread_once for my case here.
I just pushed up a commit using the alternative pthread_mutex_lock
pattern you recommended as seen in other places in corefx.
I think it would work just fine. I do not think you need any arguments for the init routine. The init routine would be just:
And you would not need the |
The implementation with mutex is functionally correct, but it is slower than it needs to be. Implementation using |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM otherwise
} | ||
else | ||
{ | ||
assert(secCertificateCopyPublicKey != NULL); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be null when things go wrong. It may be better to return error instead of asserting.
@dotnet-bot test Windows x64 Debug Build please |
@dotnet-bot test Packaging All Configurations x64 Debug Build please |
@dotnet-bot test OSX x64 Debug Build please |
Any other feedback @jkotas? |
} | ||
else | ||
{ | ||
return kErrorBadInput; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is not really capturing the error (there is nothing wrong with the input), but I see we are ignoring the error code on the managed side in release builds anyway, so it does not really matter which error code we are going to return here. It may be worth a comment.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not completely ignored, but anything that isn't 1 or 0 is all a generic CryptographicException.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Here are the other options:
corefx/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_seckey.h
Lines 12 to 19 in 9908dee
// Unless another interpretation is "obvious", pal_seckey functions return 1 on success. | |
// functions which represent a boolean return 0 on "successful false" | |
// otherwise functions will return one of the following return values: | |
static const int32_t kErrorBadInput = -1; | |
static const int32_t kErrorSeeError = -2; | |
static const int32_t kErrorUnknownAlgorithm = -3; | |
static const int32_t kErrorUnknownState = -4; | |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"Unknown state" certainly sounds like what we'd be in if neither method exists.
@dotnet-bot test Packaging All Configurations x64 Debug Build please |
@dotnet-bot test OSX x64 Debug Build please |
This broke a plenty of unit tests on my macOS Mojave DP2 and DP3 machines. I reverted commit 92b4826 and the unit test failures disappeared. I guess we need to revisit this. |
what version macOS Mojave are you using? which tests are failing for you? |
About 8+ tests in System.Security.Cryptography.X509Certificates. It's actually hard to tell because there're some failure that cause assert to be hit before the tests finish:
Basically all the tests that fail either report this assert or that there's invalid handle related to public key. |
macOS Mojave DP2 or DP3, basically any up-to-date developer preview hits it. Reproduced on two separate machines. |
Sounds like Apple is adding support for ECC other than secp256r1, secp384r1, and secp521r1 now. If forward fixing is sensible that's the option I'd prefer (over going back to "ignore deprecation warnings"), but that might turn out to be a somewhat significant change. |
@bartonjs That's probably not the case. Much likely there are some key copy operations that fail and the error is not checked for. Then hell breaks loose later... I am in process of pinning down the issue, but wanted to give a heads up. |
The callstack says this is in a test for ECDSA-224 (secp224r1). https://github.com/dotnet/corefx/blob/master/src/Common/src/System/Security/Cryptography/ECDsaSecurityTransforms.cs#L59-L62 called Then, we made it into corefx/src/Native/Unix/System.Security.Cryptography.Native.Apple/pal_ecc.c Lines 55 to 98 in 9908dee
We know that the pointer isn't NULL, so we skip the first If that shim method is made to allow secp224r1 to flow through then now the caller will still assert (that it got back an answer that wasn't 256, 384, or 521), and then maybe many more places will have similar "we don't know what to do here, because there's no obvious path forward from Apple's current design" guards. If the test passes with this change rolled back, it means that asking for the public key failed, which the test considers acceptable. And that means that Apple has added support for generic ECC (or, at least, "more curves"), but only when using the new function. |
Ok, that sounds like valid reasoning, although it doesn't necessarily explain all the failures I am seeing. Btw, the new values I see in blockSize are 32 (for the stack trace above) and 66. |
@filipnavara I suggest opening a new issue if a follow up change is needed. |
@danmosemsft I will. Just gathering enough details to describe what the issue is... :-) |
|
@bartonjs Eh, or maybe 28... on this machine. And 48 for 384 (TestECDsaPublicKey). And 66 for 521. |
…otnet/corefx#30815) * Proper fix for compilation issue caused by deprecated API in macOS Mojave by using dlsym to call available API rather than suppressing deprecation warnings. Fixes: dotnet/corefx#30599 Commit migrated from dotnet/corefx@92b4826
Proper fix for compilation issue caused by deprecated API in macOS Mojave by
using dlsym to call available API rather than suppressing deprecation warnings.
Fixes: #30599
cc: @janvorli, @bartonjs, @danmosemsft