Return int from platform mutex_init #439
No reviewers
Labels
No labels
api-break
approved
bug
component-docs
component-platform
component-test
dependencies
deprecation
DO-NOT-MERGE
enhancement
good first issue
help wanted
needs-adoption
needs-backports
needs-ci
needs-design-approval
needs-info
needs-preceding-pr
needs-review
needs-reviewer
needs-work
priority-high
priority-low
priority-medium
priority-scheduled
priority-very-high
resolved-after-1.1
single-reviewer
size-l
size-m
size-optimisation
size-s
size-xs
No milestone
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
gh-Mbed-TLS/TF-PSA-Crypto!439
Loading…
Reference in a new issue
No description provided.
Delete branch "threading-1.0-mutex-init-crypto"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Change the platform
mutex_initfunction to return an error code. This allows us to keep track of whether a mutex has been initialized, and thus to react safely if mutex initialization failed. This isn't an issue in pthread, but it is one with many other threading implementations. With this change, we don't have to hope that the platform functions are doing this for us.If I was designing the interface from scratch, I'd make the API function
mbedtls_mutex_initalso return the error code. But I'm not sure there's a way to do that in the limited amount of time that we have, even if we keep ignoring the return value in our own code for now.Thus, as far as I'm concerned, this resolves https://github.com/Mbed-TLS/mbedtls/issues/8455.
This is part of a chain, due to how
metatest.cis stored in the framework, impacts crypto, and is built in mbedtls.PR checklist
Note that this isn't ready for review yet. I'm still trying to figure out what makes it not as simple as was thinking yesterday.
Looks pretty good to me. A few minor nits, but also some thoughts on the design: we have no idea what the value of
initializedis beforemutex_init()has been called. I think that's OK for the limited goal we have here, but we should be aware of the limitations.Partially pre-existing, I was on the fence about it when reviewing the previous PR already: we might want to split this into "Requirement changes" (condition variables) and "API changes" (the rest).
@ -158,21 +153,32 @@ int (*mbedtls_mutex_unlock_ptr)(mbedtls_platform_mutex_t *) = threading_mutex_faThat seems completely unsafe: assume I create a variable of type
mbedtls_threading_mutext_ton the stack. Then the initial value of itsinitializedmember will be whatever was on in this stack location previously, and in particular it might be 1. Then inactual initialization of the underlying platform mutex would be skipped.
Actually this seems like a larger concern with the
initializedfield: we have no idea what its value is before we callinit. In particular it might happen to be 1 by accident.Well (thinking while writing) this is only an issue before
mutext_inithas been called. After that, the field has a well-defined value. And I don't think we mean to catch the kind of misuse where people forget to cal init - we only mean to cover the case where people do callmutex_init(), but internallyplatform_init()fails and this can't be reported back to the caller.So I think it's fine as long as we don't try reading the
initializedfield beforemutex_init()has been called - in particular we shouldn't do things like this line, which fortunately is removed in a later commit.@ -66,4 +61,4 @@* \note The library will always unlock a mutex from the same* thread that locked it, and will never lock a mutex* in a thread that has already locked it.*Just checking: it's implicit that the behaviour is undefined if the function is called concurrently from multiple threads, because that's covered by the fact that double-init is undefined, right?
Minor: "and has not been destroyed" (like for
mutex_init)?Typo: the the
Minor: I'm not sure that "if A or B are not both" is entirely correct syntax, but I think it's clear enough in practice.
@ -81,0 +94,4 @@* if a thread is waiting on it, or if this function* is called concurrently from multiple threads.* \param cond_signal The condition variable signal implementation. <br>* The behavior is undefined if the condition variableQuestion: why do we mention "if called concurrently from multiple threads" here but not for
init? Here too "called from multiple threads" seems to be covered by "already destroyed" I think?@ -31,6 +31,35 @@ exit:}Note: this is a double free, but we're not in the test function about double free. Should we switch to a single free here for the sake of orthogonality?
I wouldn't consider platform interfaces to be an API (A stands for “application”, after all), but that does seem to be our historical practice, so I'll split it.
@ -81,0 +94,4 @@* if a thread is waiting on it, or if this function* is called concurrently from multiple threads.* \param cond_signal The condition variable signal implementation. <br>* The behavior is undefined if the condition variableI was just inconsistent. I'll err on the side of explicitness.
@ -158,21 +153,32 @@ int (*mbedtls_mutex_unlock_ptr)(mbedtls_platform_mutex_t *) = threading_mutex_faOh, right, this was fundamentally flawed. The init function just can't read anything from the object.
Right. I think we're using "API changes" with the more general meaning of "you'll need to change your own code when upgrading", whether "you" is a normal application writer or an integrator. I'm not sure if there's a well recognised term for that.
I rebased to get the merge of the framework PR. I also fixed the typo Manuel found. The previous version is in https://github.com/gilles-peskine-arm/TF-PSA-Crypto/tree/threading-1.0-mutex-init-crypto-3
LGTM, thanks!