Skip to content

Commit

Permalink
[Mojo] Add SetDefaultProcessErrorHandler ABI
Browse files Browse the repository at this point in the history
This adds SetDefaultProcessErrorHandler to the public C ABI for Mojo
Core to replace the only remaining non-public, non-Init, non-test-only
API in the mojo::core namespace.

Setting a default process error handler is something the Network Service
uses as part of its own application logic in order to generate useful
crash reports when bad IPCs are received. This suggests that the feature
belongs in the public API, and indeed it must be exposed there in order
to support Chrome loading Mojo Core dynamically in some runtime
environments.

A follow-up CL will transition call sites from the static mojo::core API
to this new public one.

helper in mojo/public/cpp/test_support, which is migrated to the public
API by this CL.

Bug: 1082473
Test: Several content_unittests tests rely on the BadMessageObserver
Change-Id: I77378467afde722b8173df56538221fcaf82a4eb
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2227866
Commit-Queue: Ken Rockot <rockot@google.com>
Reviewed-by: Oksana Zhuravlova <oksamyt@chromium.org>
Cr-Commit-Position: refs/heads/master@{#774869}
  • Loading branch information
krockot authored and Commit Bot committed Jun 3, 2020
1 parent 349207a commit f6a4207
Show file tree
Hide file tree
Showing 12 changed files with 152 additions and 6 deletions.
23 changes: 23 additions & 0 deletions mojo/core/core.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1477,6 +1477,29 @@ MojoResult Core::QueryQuota(MojoHandle handle,
return dispatcher->QueryQuota(type, limit, usage);
}

MojoResult Core::SetDefaultProcessErrorHandler(
MojoDefaultProcessErrorHandler handler,
const MojoSetDefaultProcessErrorHandlerOptions* options) {
if (default_process_error_callback_ && handler)
return MOJO_RESULT_ALREADY_EXISTS;

if (!handler) {
default_process_error_callback_.Reset();
return MOJO_RESULT_OK;
}

default_process_error_callback_ = base::BindRepeating(
[](MojoDefaultProcessErrorHandler handler, const std::string& error) {
MojoProcessErrorDetails details = {0};
details.struct_size = sizeof(details);
details.error_message_length = static_cast<uint32_t>(error.size());
details.error_message = error.c_str();
handler(&details);
},
handler);
return MOJO_RESULT_OK;
}

void Core::GetActiveHandlesForTest(std::vector<MojoHandle>* handles) {
base::AutoLock lock(handles_->GetLock());
handles_->GetActiveHandlesForTest(handles);
Expand Down
4 changes: 4 additions & 0 deletions mojo/core/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -325,6 +325,10 @@ class MOJO_SYSTEM_IMPL_EXPORT Core {
uint64_t* limit,
uint64_t* usage);

MojoResult SetDefaultProcessErrorHandler(
MojoDefaultProcessErrorHandler handler,
const MojoSetDefaultProcessErrorHandlerOptions* options);

void GetActiveHandlesForTest(std::vector<MojoHandle>* handles);

private:
Expand Down
9 changes: 8 additions & 1 deletion mojo/core/entrypoints.cc
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,12 @@ MojoResult MojoShutdownImpl(const MojoShutdownOptions* options) {
return MOJO_RESULT_UNIMPLEMENTED;
}

MojoResult MojoSetDefaultProcessErrorHandlerImpl(
MojoDefaultProcessErrorHandler handler,
const MojoSetDefaultProcessErrorHandlerOptions* options) {
return g_core->SetDefaultProcessErrorHandler(handler, options);
}

} // extern "C"

MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks),
Expand Down Expand Up @@ -396,7 +402,8 @@ MojoSystemThunks g_thunks = {sizeof(MojoSystemThunks),
MojoAcceptInvitationImpl,
MojoSetQuotaImpl,
MojoQueryQuotaImpl,
MojoShutdownImpl};
MojoShutdownImpl,
MojoSetDefaultProcessErrorHandlerImpl};

} // namespace

Expand Down
1 change: 1 addition & 0 deletions mojo/public/c/system/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
#include <stddef.h>
#include <stdint.h>

#include "mojo/public/c/system/invitation.h"
#include "mojo/public/c/system/system_export.h"
#include "mojo/public/c/system/types.h"

Expand Down
50 changes: 50 additions & 0 deletions mojo/public/c/system/invitation.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,6 +251,25 @@ struct MOJO_ALIGNAS(8) MojoAcceptInvitationOptions {
MOJO_STATIC_ASSERT(sizeof(struct MojoAcceptInvitationOptions) == 8,
"MojoAcceptInvitationOptions has wrong size");

// Flags passed to |MojoSetDefaultProcessErrorHandler()| via
// |MojoSetDefaultProcessErrorHandlerOptions|.
typedef uint32_t MojoSetDefaultProcessErrorHandlerFlags;

// No flags. Default behavior.
#define MOJO_SET_DEFAULT_PROCESS_ERROR_HANDLER_FLAG_NONE \
((MojoSetDefaultProcessErrorHandlerFlags)0)

// Options passed to |MojoSetDefaultProcessErrorHandler()|.
struct MOJO_ALIGNAS(8) MojoSetDefaultProcessErrorHandlerOptions {
// The size of this structure, used for versioning.
uint32_t struct_size;

// See |MojoSetDefaultProcessErrorHandlerFlags|.
MojoSetDefaultProcessErrorHandlerFlags flags;
};
MOJO_STATIC_ASSERT(sizeof(struct MojoSetDefaultProcessErrorHandlerOptions) == 8,
"MojoSetDefaultProcessErrorHandlerOptions has wrong size");

#ifdef __cplusplus
extern "C" {
#endif
Expand All @@ -266,6 +285,12 @@ typedef void (*MojoProcessErrorHandler)(
uintptr_t context,
const struct MojoProcessErrorDetails* details);

// Similar to above, but registered globally via
// |MojoSetDefaultProcessErrorHandler()| and invoked only for communication
// errors regarding processes NOT invited by the calling process.
typedef void (*MojoDefaultProcessErrorHandler)(
const struct MojoProcessErrorDetails* details);

// Creates a new invitation to be sent to another process.
//
// An invitation is used to invite another process to join this process's
Expand Down Expand Up @@ -474,6 +499,31 @@ MOJO_SYSTEM_EXPORT MojoResult MojoAcceptInvitation(
const struct MojoAcceptInvitationOptions* options,
MojoHandle* invitation_handle);

// Registers a process-wide handler to be invoked when an error is raised on a
// connection to a peer process. Such errors can be raised if the peer process
// sends malformed data to this process.
//
// Note that this handler is only invoked for connections to processes NOT
// explicitly invited by this process. To handle errors concerning processes
// invited by this process, see the MojoProcessErrorHandler argument to
// |MojoSendInvitation()|.
//
// The general use case for this API is to be able to log or report instances of
// bad IPCs received by a client process which no real ability or authority to
// identify the source.
//
// Returns:
// |MOJO_RESULT_OK| if |handler| is successfully registered as the global
// default process error handler within the calling process. If |handler|
// is null, any registered default process error handler is removed.
// |MOJO_RESULT_ALREADY_EXISTS| if |handler| is non-null and there is already
// a registered error handler. Callers wishing to replace an existing
// handler must first call |MojoSetDefaultProcessErrorHandler()| with null
// in order to do so.
MOJO_SYSTEM_EXPORT MojoResult MojoSetDefaultProcessErrorHandler(
MojoDefaultProcessErrorHandler handler,
const struct MojoSetDefaultProcessErrorHandlerOptions* options);

#ifdef __cplusplus
} // extern "C"
#endif
Expand Down
6 changes: 6 additions & 0 deletions mojo/public/c/system/thunks.cc
Original file line number Diff line number Diff line change
Expand Up @@ -476,6 +476,12 @@ MojoResult MojoShutdown(const MojoShutdownOptions* options) {
return INVOKE_THUNK(Shutdown, options);
}

MojoResult MojoSetDefaultProcessErrorHandler(
MojoDefaultProcessErrorHandler handler,
const struct MojoSetDefaultProcessErrorHandlerOptions* options) {
return INVOKE_THUNK(SetDefaultProcessErrorHandler, handler, options);
}

} // extern "C"

void MojoEmbedderSetSystemThunks(const MojoSystemThunks* thunks) {
Expand Down
5 changes: 5 additions & 0 deletions mojo/public/c/system/thunks.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,11 @@ struct MojoSystemThunks {
// Core ABI version 2 additions begin here.

MojoResult (*Shutdown)(const struct MojoShutdownOptions* options);

// Core ABI version 3 additions begin here.
MojoResult (*SetDefaultProcessErrorHandler)(
MojoDefaultProcessErrorHandler handler,
const struct MojoSetDefaultProcessErrorHandlerOptions* options);
};
#pragma pack(pop)

Expand Down
1 change: 1 addition & 0 deletions mojo/public/cpp/system/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ component("system") {
"file_data_source.h",
"filtered_data_source.cc",
"filtered_data_source.h",
"functions.cc",
"functions.h",
"handle.h",
"handle_signal_tracker.cc",
Expand Down
36 changes: 36 additions & 0 deletions mojo/public/cpp/system/functions.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Copyright 2020 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "mojo/public/cpp/system/functions.h"

#include "base/callback.h"
#include "base/no_destructor.h"

namespace mojo {

namespace {

DefaultProcessErrorHandler& GetDefaultProcessErrorHandler() {
static base::NoDestructor<DefaultProcessErrorHandler> handler;
return *handler;
}

void HandleError(const MojoProcessErrorDetails* details) {
const DefaultProcessErrorHandler& handler = GetDefaultProcessErrorHandler();
handler.Run(
std::string(details->error_message, details->error_message_length));
}

} // namespace

void SetDefaultProcessErrorHandler(DefaultProcessErrorHandler handler) {
// Ensure any previously set handler is wiped out.
MojoSetDefaultProcessErrorHandler(nullptr, nullptr);
auto& global_handler = GetDefaultProcessErrorHandler();
global_handler = std::move(handler);
if (global_handler)
MojoSetDefaultProcessErrorHandler(&HandleError, nullptr);
}

} // namespace mojo
15 changes: 15 additions & 0 deletions mojo/public/cpp/system/functions.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,11 @@
#ifndef MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_
#define MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_

#include <string>

#include "base/callback_forward.h"
#include "mojo/public/c/system/functions.h"
#include "mojo/public/cpp/system/system_export.h"

namespace mojo {

Expand All @@ -21,6 +25,17 @@ inline MojoTimeTicks GetTimeTicksNow() {
return MojoGetTimeTicksNow();
}

// Sets a callback to handle communication errors regarding peer processes whose
// identity is not explicitly known by this process, i.e. processes that are
// part of the same Mojo process network but which were not invited by this
// process.
//
// This can be used to globally listen for reports of bad incoming IPCs.
using DefaultProcessErrorHandler =
base::RepeatingCallback<void(const std::string& error)>;
void MOJO_CPP_SYSTEM_EXPORT
SetDefaultProcessErrorHandler(DefaultProcessErrorHandler handler);

} // namespace mojo

#endif // MOJO_PUBLIC_CPP_SYSTEM_FUNCTIONS_H_
1 change: 0 additions & 1 deletion mojo/public/cpp/test_support/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,6 @@ static_library("test_utils") {
]

deps = [
"//mojo/core/embedder",
"//mojo/public/c/test_support",
"//mojo/public/cpp/bindings",
"//mojo/public/cpp/system",
Expand Down
7 changes: 3 additions & 4 deletions mojo/public/cpp/test_support/lib/test_utils.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
#include <vector>

#include "base/bind.h"
#include "mojo/core/embedder/embedder.h"
#include "base/bind_helpers.h"
#include "mojo/public/cpp/system/core.h"
#include "mojo/public/cpp/system/wait.h"
#include "mojo/public/cpp/test_support/test_support.h"
Expand Down Expand Up @@ -80,13 +80,12 @@ void IterateAndReportPerf(const char* test_name,
}

BadMessageObserver::BadMessageObserver() : got_bad_message_(false) {
mojo::core::SetDefaultProcessErrorCallback(base::BindRepeating(
mojo::SetDefaultProcessErrorHandler(base::BindRepeating(
&BadMessageObserver::OnReportBadMessage, base::Unretained(this)));
}

BadMessageObserver::~BadMessageObserver() {
mojo::core::SetDefaultProcessErrorCallback(
mojo::core::ProcessErrorCallback());
mojo::SetDefaultProcessErrorHandler(base::NullCallback());
}

std::string BadMessageObserver::WaitForBadMessage() {
Expand Down

0 comments on commit f6a4207

Please sign in to comment.