Commit a743b2c9 authored by Vlad Tsyrklevich's avatar Vlad Tsyrklevich Committed by Commit Bot

[CFI] Make base/once implementation CFI-icall safe

Control Flow Integrity [1] indirect call checking is a compiler-
instrumentation that verifies that function pointers are only used to
call functions whose type signatures matches the type of the function
pointer. The once implementation casts function pointers to different
types--refactor it to pass around a std::function that calls the
provided function pointer with its original type instead.

[1] https://www.chromium.org/developers/testing/control-flow-integrity

Bug=chromium:776905,v8:7164

Change-Id: I26b63973fdcebbc11b1cd7b023a6a6d0724c360c
Reviewed-on: https://chromium-review.googlesource.com/806262Reviewed-by: 's avatarClemens Hammacher <clemensh@chromium.org>
Commit-Queue: Clemens Hammacher <clemensh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#49906}
parent b1e72579
......@@ -15,7 +15,7 @@
namespace v8 {
namespace base {
void CallOnceImpl(OnceType* once, PointerArgFunction init_func, void* arg) {
void CallOnceImpl(OnceType* once, std::function<void()> init_func) {
AtomicWord state = Acquire_Load(once);
// Fast path. The provided function was already executed.
if (state == ONCE_STATE_DONE) {
......@@ -34,7 +34,7 @@ void CallOnceImpl(OnceType* once, PointerArgFunction init_func, void* arg) {
if (state == ONCE_STATE_UNINITIALIZED) {
// We are the first thread to call this function, so we have to call the
// function.
init_func(arg);
init_func();
Release_Store(once, ONCE_STATE_DONE);
} else {
// Another thread has already started executing the function. We need to
......
......@@ -53,6 +53,7 @@
#define V8_BASE_ONCE_H_
#include <stddef.h>
#include <functional>
#include "src/base/atomicops.h"
#include "src/base/base-export.h"
......@@ -80,13 +81,12 @@ struct OneArgFunction {
typedef void (*type)(T);
};
V8_BASE_EXPORT void CallOnceImpl(OnceType* once, PointerArgFunction init_func,
void* arg);
V8_BASE_EXPORT void CallOnceImpl(OnceType* once,
std::function<void()> init_func);
inline void CallOnce(OnceType* once, NoArgFunction init_func) {
if (Acquire_Load(once) != ONCE_STATE_DONE) {
CallOnceImpl(once, reinterpret_cast<PointerArgFunction>(init_func),
nullptr);
CallOnceImpl(once, init_func);
}
}
......@@ -95,8 +95,7 @@ template <typename Arg>
inline void CallOnce(OnceType* once,
typename OneArgFunction<Arg*>::type init_func, Arg* arg) {
if (Acquire_Load(once) != ONCE_STATE_DONE) {
CallOnceImpl(once, reinterpret_cast<PointerArgFunction>(init_func),
static_cast<void*>(arg));
CallOnceImpl(once, [=]() { init_func(arg); });
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment