Commit 0af89151 authored by Tom Anderson's avatar Tom Anderson Committed by Commit Bot

[CFI] Make calls to libunity functions CFI-icall safe

Control Flow Integrity [1] indirect call (cfi-icall) checking can not
verify that dynamically resolved function pointers call their intended
function. Instead we place the function pointer ProtectedMemory, a
wrapper for keeping variables in read-only memory except for when they
are initialized.  After setting the pointer in protected memory we can
use the UnsanitizedCfiCall wrapper to disable cfi-icall checking when
calling it since we know it can not be tampered with.

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

BUG=1014902
R=thestig

Change-Id: Id55510f4d924bf8d4dd73332b7a8b18a9e6bc04c
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1864377
Auto-Submit: Thomas Anderson <thomasanderson@chromium.org>
Commit-Queue: Lei Zhang <thestig@chromium.org>
Reviewed-by: default avatarLei Zhang <thestig@chromium.org>
Cr-Commit-Position: refs/heads/master@{#706822}
parent 70a1b0b3
...@@ -10,6 +10,8 @@ ...@@ -10,6 +10,8 @@
#include <string> #include <string>
#include "base/environment.h" #include "base/environment.h"
#include "base/memory/protected_memory.h"
#include "base/memory/protected_memory_cfi.h"
#include "base/nix/xdg_util.h" #include "base/nix/xdg_util.h"
#include "chrome/common/channel_info.h" #include "chrome/common/channel_info.h"
#include "ui/base/glib/glib_integers.h" #include "ui/base/glib/glib_integers.h"
...@@ -45,12 +47,24 @@ UnityInspector* inspector = nullptr; ...@@ -45,12 +47,24 @@ UnityInspector* inspector = nullptr;
UnityLauncherEntry* chrome_entry = nullptr; UnityLauncherEntry* chrome_entry = nullptr;
// Retrieved functions from libunity. // Retrieved functions from libunity.
unity_inspector_get_unity_running_func get_unity_running = nullptr; PROTECTED_MEMORY_SECTION
unity_launcher_entry_set_count_func entry_set_count = nullptr; base::ProtectedMemory<unity_inspector_get_default_func> inspector_get_default;
unity_launcher_entry_set_count_visible_func entry_set_count_visible = nullptr; PROTECTED_MEMORY_SECTION
unity_launcher_entry_set_progress_func entry_set_progress = nullptr; base::ProtectedMemory<unity_inspector_get_unity_running_func> get_unity_running;
unity_launcher_entry_set_progress_visible_func entry_set_progress_visible = PROTECTED_MEMORY_SECTION
nullptr; base::ProtectedMemory<unity_launcher_entry_get_for_desktop_id_func>
entry_get_for_desktop_id;
PROTECTED_MEMORY_SECTION
base::ProtectedMemory<unity_launcher_entry_set_count_func> entry_set_count;
PROTECTED_MEMORY_SECTION
base::ProtectedMemory<unity_launcher_entry_set_count_visible_func>
entry_set_count_visible;
PROTECTED_MEMORY_SECTION
base::ProtectedMemory<unity_launcher_entry_set_progress_func>
entry_set_progress;
PROTECTED_MEMORY_SECTION
base::ProtectedMemory<unity_launcher_entry_set_progress_visible_func>
entry_set_progress_visible;
void EnsureLibUnityLoaded() { void EnsureLibUnityLoaded() {
using base::nix::GetDesktopEnvironment; using base::nix::GetDesktopEnvironment;
...@@ -77,57 +91,75 @@ void EnsureLibUnityLoaded() { ...@@ -77,57 +91,75 @@ void EnsureLibUnityLoaded() {
if (!unity_lib) if (!unity_lib)
return; return;
unity_inspector_get_default_func inspector_get_default = static base::ProtectedMemory<unity_inspector_get_default_func>::Initializer
reinterpret_cast<unity_inspector_get_default_func>( inspector_get_default_init(
dlsym(unity_lib, "unity_inspector_get_default")); &inspector_get_default,
if (inspector_get_default) { reinterpret_cast<unity_inspector_get_default_func>(
inspector = inspector_get_default(); dlsym(unity_lib, "unity_inspector_get_default")));
if (*inspector_get_default) {
get_unity_running = inspector = UnsanitizedCfiCall(inspector_get_default)();
reinterpret_cast<unity_inspector_get_unity_running_func>(
dlsym(unity_lib, "unity_inspector_get_unity_running")); static base::ProtectedMemory<unity_inspector_get_unity_running_func>::
Initializer get_unity_running_init(
&get_unity_running,
reinterpret_cast<unity_inspector_get_unity_running_func>(
dlsym(unity_lib, "unity_inspector_get_unity_running")));
} }
unity_launcher_entry_get_for_desktop_id_func entry_get_for_desktop_id = static base::ProtectedMemory<unity_launcher_entry_get_for_desktop_id_func>::
reinterpret_cast<unity_launcher_entry_get_for_desktop_id_func>( Initializer entry_get_for_desktop_id_init(
dlsym(unity_lib, "unity_launcher_entry_get_for_desktop_id")); &entry_get_for_desktop_id,
if (entry_get_for_desktop_id) { reinterpret_cast<unity_launcher_entry_get_for_desktop_id_func>(
dlsym(unity_lib, "unity_launcher_entry_get_for_desktop_id")));
if (*entry_get_for_desktop_id) {
std::string desktop_id = chrome::GetDesktopName(env.get()); std::string desktop_id = chrome::GetDesktopName(env.get());
chrome_entry = entry_get_for_desktop_id(desktop_id.c_str()); chrome_entry =
UnsanitizedCfiCall(entry_get_for_desktop_id)(desktop_id.c_str());
entry_set_count = reinterpret_cast<unity_launcher_entry_set_count_func>(
dlsym(unity_lib, "unity_launcher_entry_set_count")); static base::ProtectedMemory<unity_launcher_entry_set_count_func>::
Initializer entry_set_count_init(
entry_set_count_visible = &entry_set_count,
reinterpret_cast<unity_launcher_entry_set_count_visible_func>( reinterpret_cast<unity_launcher_entry_set_count_func>(
dlsym(unity_lib, "unity_launcher_entry_set_count_visible")); dlsym(unity_lib, "unity_launcher_entry_set_count")));
entry_set_progress = static base::ProtectedMemory<unity_launcher_entry_set_count_visible_func>::
reinterpret_cast<unity_launcher_entry_set_progress_func>( Initializer entry_set_count_visible_init(
dlsym(unity_lib, "unity_launcher_entry_set_progress")); &entry_set_count_visible,
reinterpret_cast<unity_launcher_entry_set_count_visible_func>(
entry_set_progress_visible = dlsym(unity_lib, "unity_launcher_entry_set_count_visible")));
reinterpret_cast<unity_launcher_entry_set_progress_visible_func>(
dlsym(unity_lib, "unity_launcher_entry_set_progress_visible")); static base::ProtectedMemory<unity_launcher_entry_set_progress_func>::
Initializer entry_set_progress_init(
&entry_set_progress,
reinterpret_cast<unity_launcher_entry_set_progress_func>(
dlsym(unity_lib, "unity_launcher_entry_set_progress")));
static base::ProtectedMemory<
unity_launcher_entry_set_progress_visible_func>::Initializer
entry_set_progress_visible_init(
&entry_set_progress_visible,
reinterpret_cast<unity_launcher_entry_set_progress_visible_func>(
dlsym(unity_lib, "unity_launcher_entry_set_progress_visible")));
} }
} }
bool IsRunning() { bool IsRunning() {
return inspector && get_unity_running && get_unity_running(inspector); return inspector && *get_unity_running &&
UnsanitizedCfiCall(get_unity_running)(inspector);
} }
void SetDownloadCount(int count) { void SetDownloadCount(int count) {
if (chrome_entry && entry_set_count && entry_set_count_visible) { if (chrome_entry && *entry_set_count && *entry_set_count_visible) {
entry_set_count(chrome_entry, count); UnsanitizedCfiCall(entry_set_count)(chrome_entry, count);
entry_set_count_visible(chrome_entry, count != 0); UnsanitizedCfiCall(entry_set_count_visible)(chrome_entry, count != 0);
} }
} }
void SetProgressFraction(float percentage) { void SetProgressFraction(float percentage) {
if (chrome_entry && entry_set_progress && entry_set_progress_visible) { if (chrome_entry && *entry_set_progress && *entry_set_progress_visible) {
entry_set_progress(chrome_entry, percentage); UnsanitizedCfiCall(entry_set_progress)(chrome_entry, percentage);
entry_set_progress_visible(chrome_entry, UnsanitizedCfiCall(entry_set_progress_visible)(
percentage > 0.0 && percentage < 1.0); chrome_entry, percentage > 0.0 && percentage < 1.0);
} }
} }
......
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