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
|
#define STACK_UNINITIALIZED
|
||||||
#endif
|
#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
|
// The ANALYZER_ASSUME_TRUE(bool arg) macro adds compiler-specific hints
|
||||||
// to Clang which control what code paths are statically analyzed,
|
// to Clang which control what code paths are statically analyzed,
|
||||||
// and is meant to be used in conjunction with assert & assert-like functions.
|
// 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
|
/// |windows_sandbox_info| parameter is only used on Windows and may be NULL
|
||||||
/// (see cef_sandbox_win.h for details).
|
/// (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)--*/
|
optional_param=windows_sandbox_info)--*/
|
||||||
int CefExecuteProcess(const CefMainArgs& args,
|
int CefExecuteProcess(const CefMainArgs& args,
|
||||||
CefRefPtr<CefApp> application,
|
CefRefPtr<CefApp> application,
|
||||||
|
@ -291,6 +291,7 @@ int RunMainWithPreferredStackSize(FiberState& fiber_state) {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int CefExecuteProcess(const CefMainArgs& args,
|
int CefExecuteProcess(const CefMainArgs& args,
|
||||||
CefRefPtr<CefApp> application,
|
CefRefPtr<CefApp> application,
|
||||||
void* windows_sandbox_info) {
|
void* windows_sandbox_info) {
|
||||||
|
@ -206,6 +206,7 @@ void CefMainRunner::QuitMessageLoop() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
|
int CefMainRunner::RunAsHelperProcess(const CefMainArgs& args,
|
||||||
CefRefPtr<CefApp> application,
|
CefRefPtr<CefApp> application,
|
||||||
void* windows_sandbox_info) {
|
void* windows_sandbox_info) {
|
||||||
|
@ -48,6 +48,7 @@ void TerminationSignalHandler(int signatl) {
|
|||||||
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
|
MainContext::Get()->GetRootWindowManager()->CloseAllWindows(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int RunMain(int argc, char* argv[]) {
|
int RunMain(int argc, char* argv[]) {
|
||||||
// Create a copy of |argv| on Linux because Chromium mangles the value
|
// Create a copy of |argv| on Linux because Chromium mangles the value
|
||||||
// internally (see issue #620).
|
// internally (see issue #620).
|
||||||
@ -158,6 +159,7 @@ int RunMain(int argc, char* argv[]) {
|
|||||||
} // namespace client
|
} // namespace client
|
||||||
|
|
||||||
// Program entry point function.
|
// Program entry point function.
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
return client::RunMain(argc, argv);
|
return client::RunMain(argc, argv);
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ int XIOErrorHandlerImpl(Display* display) {
|
|||||||
#endif // defined(CEF_X11)
|
#endif // defined(CEF_X11)
|
||||||
|
|
||||||
// Entry point function for all processes.
|
// Entry point function for all processes.
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
// Provide CEF with command-line arguments.
|
// Provide CEF with command-line arguments.
|
||||||
CefMainArgs main_args(argc, argv);
|
CefMainArgs main_args(argc, argv);
|
||||||
|
@ -134,6 +134,7 @@ class ScopedPlatformSetup final {
|
|||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
|
NO_STACK_PROTECTOR
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
int exit_code;
|
int exit_code;
|
||||||
|
|
||||||
|
@ -522,9 +522,9 @@ def dict_to_str(dict):
|
|||||||
# Attribute keys allowed in CEF metadata comments.
|
# Attribute keys allowed in CEF metadata comments.
|
||||||
COMMON_ATTRIB_KEYS = ('added', 'removed')
|
COMMON_ATTRIB_KEYS = ('added', 'removed')
|
||||||
CLASS_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('no_debugct_check', 'source')
|
CLASS_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('no_debugct_check', 'source')
|
||||||
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + ('api_hash_check', 'capi_name',
|
FUNCTION_ATTRIB_KEYS = COMMON_ATTRIB_KEYS + (
|
||||||
'count_func', 'default_retval',
|
'api_hash_check', 'capi_name', 'count_func', 'default_retval',
|
||||||
'index_param', 'optional_param')
|
'index_param', 'no_stack_protector', 'optional_param')
|
||||||
|
|
||||||
# regex for matching comment-formatted attributes
|
# regex for matching comment-formatted attributes
|
||||||
_cre_attrib = r'/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/'
|
_cre_attrib = r'/\*--cef\(([A-Za-z0-9_ ,=:\n]{0,})\)--\*/'
|
||||||
|
@ -9,10 +9,13 @@ import functools
|
|||||||
|
|
||||||
|
|
||||||
def make_cpptoc_impl_proto(name, func, parts):
|
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):
|
if isinstance(func, obj_function_virtual):
|
||||||
proto = parts['retval'] + ' CEF_CALLBACK'
|
proto += parts['retval'] + ' CEF_CALLBACK'
|
||||||
else:
|
else:
|
||||||
proto = 'CEF_EXPORT ' + parts['retval']
|
proto += 'CEF_EXPORT ' + parts['retval']
|
||||||
|
|
||||||
proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
|
proto += ' ' + name + '(' + ', '.join(parts['args']) + ')'
|
||||||
return proto
|
return proto
|
||||||
|
@ -11,6 +11,8 @@ def make_ctocpp_impl_proto(clsname, name, func, parts):
|
|||||||
const = ''
|
const = ''
|
||||||
|
|
||||||
proto = 'NO_SANITIZE("cfi-icall") '
|
proto = 'NO_SANITIZE("cfi-icall") '
|
||||||
|
if func.has_attrib('no_stack_protector'):
|
||||||
|
proto += 'NO_STACK_PROTECTOR '
|
||||||
if clsname is None:
|
if clsname is None:
|
||||||
proto += 'CEF_GLOBAL ' + parts['retval'] + ' '
|
proto += 'CEF_GLOBAL ' + parts['retval'] + ' '
|
||||||
else:
|
else:
|
||||||
|
Reference in New Issue
Block a user