ERR: Make CRYPTO_malloc() and friends report ERR_R_MALLOC_FAILURE#14833
ERR: Make CRYPTO_malloc() and friends report ERR_R_MALLOC_FAILURE#14833DDvO wants to merge 9 commits intoopenssl:masterfrom
Conversation
|
You'd have to clean up all the calls where ERR_R_MALLOC_FAILURE is raised otherwise there would be double error reporting wouldn't it? |
Yes, but I'd spend this major effort only if/when the core solution is firmly accepted. Marking this PR as WIP for now, and post-3.0.0. |
40e0bcd to
1a8143c
Compare
|
My goodness. Then, for instance Raising the limit to 5300000 still causes while for 5400000 only the above two fuzz tests fail. |
|
Suppose |
That's what the following code is for: |
|
And you're sure all of the other possible "init" functions can't cause a loop? I guess not since they'll end up falling through to that err code. okay. thanks. |
|
Conditioning based on the name of the file seems rather fragile. If This also isn't quite how you check for malloc failure. Some malloc implementations return NULL on zero, so you need to check both values. |
|
somebody has to be at the bottom; either malloc or error-stuff. making them interdependent, which this PR (as of this writing) does is like David said, fragile. It's a pain to report malloc failures all over the place. This fix seems wrong. |
|
I had a closer look at what is potentially called through and it's a whole mess of stuff, where as @richsalz wrote one cannot really be sure that this does not include any indirect memory allocation calls. |
|
I'm now considering options to use a pre-allocated place that is reserved per thread When a malloc failure is encountered and this place is available and not (yet) occupied, it is used, Does anyone see a problem with this approach? |
In my experience, most of the time when |
Well, in such a case, memory is corrupted anyway,
Good point. This brings me to an improvement of the sketched new approach: |
No it's per-thread. If that's not a typo, then I have to wonder if you really read the err.c code. Quietly making "malloc failed" a global error, unlike all other errors, is not something to be just tossed into a PR but should be discussed by the OTC. I am going to not comment any more until after 3.0 is out. |
Argh, I should stop working after 12 hours. Apparently I had too many context switches today.
In the light of the above clarification, reverting my proposal to an extra space per thread. |
|
Finally, I took the time to continue working in on this, taking into account the review comments above. @t8m, as discussed above, I'm going to clean up all the calls where ERR_R_MALLOC_FAILURE is raised |
1a8143c to
5802ad1
Compare
5802ad1 to
25ab843
Compare
OTC wanted to resolve them based on the context. If the ERR_raise() call is in the same function where the OPENSSL_*alloc() is done and is done solely as the result of the malloc failure, it should NOT be kept. For the rest, the replacement as you suggest would be OK. |
t8m
left a comment
There was a problem hiding this comment.
LGTM apart from placing the docs into a different .pod file.
…loc() and friends report ERR_R_MALLOC_FAILURE
crypto/err/err.c
Outdated
| void *CRYPTO_malloc_with_err(void *(*fn)(size_t, const char *, int), size_t num, | ||
| const char *file, int line, const char *func) | ||
| { | ||
| void *ptr = (*fn)(num, file, line); |
There was a problem hiding this comment.
I'm not a fan of an indirect call here. We already do one to get to malloc et al and this makes it two. Moreover, this one won't be predicted at all well because so many functions are funneling through here.
The alternative would be having each of the allocation functions separately defined which is ugly but won't hit performance.
There was a problem hiding this comment.
Sigh, a smart compiler might flatten this out, but likely we cannot hope for that.
Would be so nice to use just a macro for CRYPTO_malloc_with_err et al., but this is made impossible by the non-linear use of the num argument.
There was a problem hiding this comment.
Anyway, I do not really see the very slight decrease in performance using the function pointer as an issue here.
Memory allocation is in itself a pretty expensive operation, so an extra function pointer dereference should not make any noticeable difference.
Moreover, memory allocation is very unusual in tight loops.
There was a problem hiding this comment.
Could we make the functions static inline? Not sure if that doesn't open another can of worms though.
There was a problem hiding this comment.
I'm uncertain if it is possible to declare CRYPTO_malloc_with_err et al. static because they need to be declared in a public header (crypto.h) for use with public macros such as OPENSSL_malloc().
I was also considering making CRYPTO_malloc_with_err et al. inline, but as there is s pretty large number of calls to OPENSSL_malloc() et al., this would likely add quite a bit to the code size, while the performance gain would be tiny.
So also in this direction I see no point trying to optimize on performance.
There was a problem hiding this comment.
It has a spurious state to s change, that's not a big deal.
It adds new xxx_with_err functions that might not be needed if the decision is to use backtrace or its equivalent. (And if those functions are only for internal use, why are they in public header files and documentation?) It does no work to change the source base to use those with_err functions.
This seems like a partial change, no promise of future work to complete it and a known pending open issue about the direction in which to go.
There was a problem hiding this comment.
@richsalz occasionally it feels like you wanna re-enter the OpenSSL project?
There was a problem hiding this comment.
malloc shouldn't be a huge expense most of the time. Modern libc's implement it pretty well. A branch misprediction takes hundreds of cycles which represents quite an expense.
The other concern is about what we make public. Once public, forever public (almost). Do we want CRYPTO_malloc_with_err() as a public API?
There was a problem hiding this comment.
Thinking a little more about all this, I found a solution that does not use function pointers and the like and
avoids using and adding (actually internal) aux functions to public headers. It even does not change header files at all.
It reports malloc errors once and for all in CRYPTO_malloc()
while making sure to prevent mem alloc error loops simply as follows:
ossl_err_get_state_int() in err.c uses the special call CRYPTO_zalloc(num, NULL, 0) for ERR_STATE allocation,
and CRYPTO_*alloc() do not report an malloc failure in this special case (i.e., file == NULL && line == 0).
All other OPENSSL_*malloc() and CRYPTO_*alloc() calls lead to file != NULL || line != 0 and thus do report any malloc error.
…PTO_malloc() and friends report ERR_R_MALLOC_FAILURE
|
@t8m:
I disagree with this, especially with the latest changes |
Well, with the latest changes keeping the original ERR_raises makes some sense. I'd still change them to ERR_R_CRYPTO_LIB. @DDvO given this should be now a simple sed command, could you please create a PR to do this based on top of this PR? |
|
Could you please test that if CRYPTO_*alloc() returns always NULL we do not get an infinite recursion on OPENSSL_init_crypto() call? |
I just made all |
|
Merged - thanks a lot @t8m, @paulidale, @levitte, and @richsalz for the discussion and the approvals. |
|
24 hours has passed since 'approval: done' was set, but as this PR has been updated in that time the label 'approval: ready to merge' is not being automatically set. Please review the updates and set the label manually. |
|
Very unfortunate that the malloc error reporting was not handled in a good way right from the beginning. Also finding, discussing, and trying out solutions was a considerable amount of work. |
Fixes openssl#6251 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from openssl#14833)
Fixes openssl#6251 Reviewed-by: Tomas Mraz <tomas@openssl.org> Reviewed-by: Paul Dale <pauli@openssl.org> Reviewed-by: David von Oheimb <david.von.oheimb@siemens.com> (Merged from openssl#14833)
This proposes a simple fix of #6251. Maybe this is already sufficient?
It also takes into account thoughts given in #5781 and #6217.