1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-08-08 17:42:12 +03:00

nptl: Move legacy unwinding implementation into libc

It is still used internally.  Since unwinding is now available
unconditionally, avoid indirect calls through function pointers loaded
from the stack by inlining the non-cancellation cleanup code.  This
avoids a regression in security hardening.

The out-of-line  __libc_cleanup_routine implementation is no longer
needed because the inline definition is now static __always_inline.

Reviewed-by: Adhemerval Zanella  <adhemerval.zanella@linaro.org>
This commit is contained in:
Florian Weimer
2021-04-21 19:49:50 +02:00
parent 5715c29e91
commit f79f206581
7 changed files with 98 additions and 117 deletions

View File

@@ -143,39 +143,40 @@ typedef struct __libc_lock_recursive_opaque__ __libc_lock_recursive_t;
__libc_maybe_call (__pthread_mutex_unlock, (&(NAME).mutex), 0)
#endif
/* Note that for I/O cleanup handling we are using the old-style
cancel handling. It does not have to be integrated with C++ since
no C++ code is called in the middle. The old-style handling is
faster and the support is not going away. */
extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
void (*routine) (void *), void *arg);
extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
int execute);
/* Put the unwind buffer BUFFER on the per-thread callback stack. The
caller must fill BUFFER->__routine and BUFFER->__arg before calling
this function. */
void __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer);
libc_hidden_proto (__libc_cleanup_push_defer)
/* Remove BUFFER from the unwind callback stack. The caller must invoke
the callback if desired. */
void __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer);
libc_hidden_proto (__libc_cleanup_pop_restore)
/* Start critical region with cleanup. */
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
{ struct _pthread_cleanup_buffer _buffer; \
int _avail; \
if (DOIT) { \
_avail = PTFAVAIL (_pthread_cleanup_push_defer); \
if (_avail) { \
__libc_ptf_call_always (_pthread_cleanup_push_defer, (&_buffer, FCT, \
ARG)); \
} else { \
_buffer.__routine = (FCT); \
_buffer.__arg = (ARG); \
} \
} else { \
_avail = 0; \
}
#define __libc_cleanup_region_start(DOIT, FCT, ARG) \
{ bool _cleanup_start_doit; \
struct _pthread_cleanup_buffer _buffer; \
/* Non-addressable copy of FCT, so that we avoid indirect calls on \
the non-unwinding path. */ \
void (*_cleanup_routine) (void *) = (FCT); \
_buffer.__arg = (ARG); \
if (DOIT) \
{ \
_cleanup_start_doit = true; \
_buffer.__routine = _cleanup_routine; \
__libc_cleanup_push_defer (&_buffer); \
} \
else \
_cleanup_start_doit = false;
/* End critical region with cleanup. */
#define __libc_cleanup_region_end(DOIT) \
if (_avail) { \
__libc_ptf_call_always (_pthread_cleanup_pop_restore, (&_buffer, DOIT));\
} else if (DOIT) \
_buffer.__routine (_buffer.__arg); \
}
#define __libc_cleanup_region_end(DOIT) \
if (_cleanup_start_doit) \
__libc_cleanup_pop_restore (&_buffer); \
if (DOIT) \
_cleanup_routine (_buffer.__arg); \
} /* matches __libc_cleanup_region_start */
/* Hide the definitions which are only supposed to be used inside libc in