mirror of
https://bitbucket.org/chromiumembedded/cef
synced 2025-06-05 21:39:12 +02:00
linux: Fix stack-related sub-process shutdown crashes (fixes #3912)
On Linux systems the stack frame reference canary will be purposely changed when forking sub-processes (see https://crbug.com/40181003). To avoid sub-process shutdown crashes the NO_STACK_PROTECTOR annotation must be added to all functions in the call stack leading to CefExecuteProcess(). Applications that cannot add this annotation must instead pass the `--change-stack-guard-on-fork=disable` command-line flag.
This commit is contained in:
@ -313,6 +313,30 @@
|
||||
#define STACK_UNINITIALIZED
|
||||
#endif
|
||||
|
||||
// Attribute "no_stack_protector" disables -fstack-protector for the specified
|
||||
// function.
|
||||
//
|
||||
// "stack_protector" is enabled on most POSIX builds. The flag adds a canary
|
||||
// to each stack frame, which on function return is checked against a reference
|
||||
// canary. If the canaries do not match, it's likely that a stack buffer
|
||||
// overflow has occurred, so immediately crashing will prevent exploitation in
|
||||
// many cases.
|
||||
//
|
||||
// In some cases it's desirable to remove this, e.g. on hot functions, or if
|
||||
// we have purposely changed the reference canary.
|
||||
//
|
||||
// On Linux systems the reference canary will be purposely changed when forking
|
||||
// sub-processes (see https://crbug.com/40181003). To avoid sub-process shutdown
|
||||
// crashes the NO_STACK_PROTECTOR annotation must be added to all functions in
|
||||
// the call stack leading to CefExecuteProcess(). Applications that cannot add
|
||||
// this annotation must instead pass the `--change-stack-guard-on-fork=disable`
|
||||
// command-line flag.
|
||||
#if defined(COMPILER_GCC) || defined(__clang__)
|
||||
#define NO_STACK_PROTECTOR __attribute__((no_stack_protector))
|
||||
#else
|
||||
#define NO_STACK_PROTECTOR
|
||||
#endif
|
||||
|
||||
// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints
|
||||
// to Clang which control what code paths are statically analyzed,
|
||||
// and is meant to be used in conjunction with assert & assert-like functions.
|
||||
|
@ -59,7 +59,7 @@ class CefApp;
|
||||
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
|
||||
/// (see cef_sandbox_win.h for details).
|
||||
///
|
||||
/*--cef(api_hash_check,optional_param=application,
|
||||
/*--cef(api_hash_check,no_stack_protector,optional_param=application,
|
||||
optional_param=windows_sandbox_info)--*/
|
||||
int CefExecuteProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
|
@ -291,6 +291,7 @@ int RunMainWithPreferredStackSize(FiberState& fiber_state) {
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int CefExecuteProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info) {
|
||||
|
@ -206,6 +206,7 @@ void CefMainRunner::QuitMessageLoop() {
|
||||
}
|
||||
|
||||
// static
|
||||
NO_STACK_PROTECTOR
|
||||
int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
|
||||
CefRefPtr<CefApp> application,
|
||||
void* windows_sandbox_info) {
|
||||
|
@ -48,6 +48,7 @@ void TerminationSignalHandler(int signatl) {
|
||||
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
|
||||
}
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int RunMain(int argc, char* argv[]) {
|
||||
// Create a copy of |argv| on Linux because Chromium mangles the value
|
||||
// internally (see issue #620).
|
||||
@ -158,6 +159,7 @@ int RunMain(int argc, char* argv[]) {
|
||||
} // namespace client
|
||||
|
||||
// Program entry point function.
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
return client::RunMain(argc, argv);
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ int XIOErrorHandlerImpl(Display* display) {
|
||||
#endif // defined(CEF_X11)
|
||||
|
||||
// Entry point function for all processes.
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
// Provide CEF with command-line arguments.
|
||||
CefMainArgs main_args(argc, argv);
|
||||
|
@ -134,6 +134,7 @@ class ScopedPlatformSetup final {
|
||||
|
||||
} // namespace
|
||||
|
||||
NO_STACK_PROTECTOR
|
||||
int main(int argc, char* argv[]) {
|
||||
int exit_code;
|
||||
|
||||
|
@ -522,9 +522,9 @@ def dict_to_str(dict):
|
||||
# Attribute keys allowed in CEF metadata comments.
|
||||
COMMON_ATTRIB_KEYS = ('added', 'removed')
|
||||
CLASS_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('no_debugct_check', 'source')
|
||||
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('api_hash_check', 'capi_name',
|
||||
'count_func', 'default_retval',
|
||||
'index_param', 'optional_param')
|
||||
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + (
|
||||
'api_hash_check', 'capi_name', 'count_func', 'default_retval',
|
||||
'index_param', 'no_stack_protector', 'optional_param')
|
||||
|
||||
# regex for matching comment-formatted attributes
|
||||
_cre_attrib = r'/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/'
|
||||
|
@ -9,10 +9,13 @@ import functools
|
||||
|
||||
|
||||
def make_cpptoc_impl_proto(name, func, parts):
|
||||
proto = ''
|
||||
if func.has_attrib('no_stack_protector'):
|
||||
proto += 'NO_STACK_PROTECTOR '
|
||||
if isinstance(func, obj_function_virtual):
|
||||
proto = parts['retval'] + ' CEF_CALLBACK'
|
||||
proto += parts['retval'] + ' CEF_CALLBACK'
|
||||
else:
|
||||
proto = 'CEF_EXPORT ' + parts['retval']
|
||||
proto += 'CEF_EXPORT ' + parts['retval']
|
||||
|
||||
proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
|
||||
return proto
|
||||
|
@ -11,6 +11,8 @@ def make_ctocpp_impl_proto(clsname, name, func, parts):
|
||||
const = ''
|
||||
|
||||
proto = 'NO_SANITIZE("cfi-icall") '
|
||||
if func.has_attrib('no_stack_protector'):
|
||||
proto += 'NO_STACK_PROTECTOR '
|
||||
if clsname is None:
|
||||
proto += 'CEF_GLOBAL ' + parts['retval'] + ' '
|
||||
else:
|
||||
|
Reference in New Issue
Block a user