Skip to content

Commit

Permalink
Do some hardening in XPCServiceEventHandler()
Browse files Browse the repository at this point in the history
https://bugs.webkit.org/show_bug.cgi?id=226860
<rdar://66837596>

Reviewed by Geoffrey Garen.

Do some hardening in XPCServiceEventHandler() to deal with unexpected values and add
some more logging as well.

* Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceMain.mm:
(WebKit::XPCServiceEventHandler):
* WebProcess/cocoa/HandleXPCEndpointMessages.h:
* WebProcess/cocoa/HandleXPCEndpointMessages.mm:
(WebKit::handleXPCEndpointMessages):


Canonical link: https://commits.webkit.org/238684@main
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@278716 268f45cc-cd09-0410-ab3c-d52691b4dbfc
  • Loading branch information
cdumez committed Jun 10, 2021
1 parent 48b3154 commit 985de70
Show file tree
Hide file tree
Showing 5 changed files with 92 additions and 63 deletions.
1 change: 1 addition & 0 deletions Source/WTF/wtf/spi/darwin/XPCSPI.h
Expand Up @@ -154,6 +154,7 @@ void xpc_dictionary_set_string(xpc_object_t, const char* key, const char* string
void xpc_dictionary_set_uint64(xpc_object_t, const char* key, uint64_t value);
void xpc_dictionary_set_value(xpc_object_t, const char* key, xpc_object_t value);
xpc_type_t xpc_get_type(xpc_object_t);
const char* xpc_type_get_name(xpc_type_t);
void xpc_main(xpc_connection_handler_t);
const char* xpc_string_get_string_ptr(xpc_object_t);
os_transaction_t os_transaction_create(const char *description);
Expand Down
17 changes: 17 additions & 0 deletions Source/WebKit/ChangeLog
@@ -1,3 +1,20 @@
2021-06-10 Chris Dumez <cdumez@apple.com>

Do some hardening in XPCServiceEventHandler()
https://bugs.webkit.org/show_bug.cgi?id=226860
<rdar://66837596>

Reviewed by Geoffrey Garen.

Do some hardening in XPCServiceEventHandler() to deal with unexpected values and add
some more logging as well.

* Shared/EntryPointUtilities/Cocoa/XPCService/XPCServiceMain.mm:
(WebKit::XPCServiceEventHandler):
* WebProcess/cocoa/HandleXPCEndpointMessages.h:
* WebProcess/cocoa/HandleXPCEndpointMessages.mm:
(WebKit::handleXPCEndpointMessages):

2021-06-10 Chris Dumez <cdumez@apple.com>

Enable WebPage's release logging in ephemeral sessions
Expand Down
Expand Up @@ -69,73 +69,88 @@ static void XPCServiceEventHandler(xpc_connection_t peer)
xpc_connection_set_target_queue(peer, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
xpc_connection_set_event_handler(peer, ^(xpc_object_t event) {
xpc_type_t type = xpc_get_type(event);
if (type == XPC_TYPE_ERROR) {
if (event == XPC_ERROR_CONNECTION_INVALID || event == XPC_ERROR_TERMINATION_IMMINENT) {
RELEASE_LOG_FAULT(IPC, "Exiting: Received XPC event type: %s", event == XPC_ERROR_CONNECTION_INVALID ? "XPC_ERROR_CONNECTION_INVALID" : "XPC_ERROR_TERMINATION_IMMINENT");
// FIXME: Handle this case more gracefully.
[[NSRunLoop mainRunLoop] performBlock:^{
exit(EXIT_FAILURE);
}];
}
} else {
assert(type == XPC_TYPE_DICTIONARY);

if (!strcmp(xpc_dictionary_get_string(event, "message-name"), "bootstrap")) {
CFBundleRef webKitBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit"));

const char* serviceName = xpc_dictionary_get_string(event, "service-name");
CFStringRef entryPointFunctionName = nullptr;
if (strstr(serviceName, "com.apple.WebKit.WebContent") == serviceName)
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(WEBCONTENT_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.Networking"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(NETWORK_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.Plugin.64"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(PLUGIN_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.GPU"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(GPU_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.WebAuthn"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(WEBAUTHN_SERVICE_INITIALIZER));
else
RELEASE_ASSERT_NOT_REACHED();

typedef void (*InitializerFunction)(xpc_connection_t, xpc_object_t, xpc_object_t);
InitializerFunction initializerFunctionPtr = reinterpret_cast<InitializerFunction>(CFBundleGetFunctionPointerForName(webKitBundle, entryPointFunctionName));
if (!initializerFunctionPtr) {
RELEASE_LOG_FAULT(IPC, "Exiting: Unable to find entry point in WebKit.framework with name: %s", [(__bridge NSString *)entryPointFunctionName UTF8String]);
if (type != XPC_TYPE_DICTIONARY) {
RELEASE_LOG_ERROR(IPC, "XPCServiceEventHandler: Received unexpected XPC event type: %{public}s", xpc_type_get_name(type));
if (type == XPC_TYPE_ERROR) {
if (event == XPC_ERROR_CONNECTION_INVALID || event == XPC_ERROR_TERMINATION_IMMINENT) {
RELEASE_LOG_ERROR(IPC, "Exiting: Received XPC event type: %{public}s", event == XPC_ERROR_CONNECTION_INVALID ? "XPC_ERROR_CONNECTION_INVALID" : "XPC_ERROR_TERMINATION_IMMINENT");
// FIXME: Handle this case more gracefully.
[[NSRunLoop mainRunLoop] performBlock:^{
exit(EXIT_FAILURE);
}];
}
}
return;
}

auto reply = adoptOSObject(xpc_dictionary_create_reply(event));
xpc_dictionary_set_string(reply.get(), "message-name", "process-finished-launching");
xpc_connection_send_message(xpc_dictionary_get_remote_connection(event), reply.get());
auto* messageName = xpc_dictionary_get_string(event, "message-name");
if (!messageName) {
RELEASE_LOG_ERROR(IPC, "XPCServiceEventHandler: 'message-name' is not present in the XPC dictionary");
return;
}
if (!strcmp(messageName, "bootstrap")) {
const char* serviceName = xpc_dictionary_get_string(event, "service-name");
if (!serviceName) {
RELEASE_LOG_ERROR(IPC, "XPCServiceEventHandler: 'service-name' is not present in the XPC dictionary");
return;
}
CFStringRef entryPointFunctionName = nullptr;
if (!strncmp(serviceName, "com.apple.WebKit.WebContent", strlen("com.apple.WebKit.WebContent")))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(WEBCONTENT_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.Networking"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(NETWORK_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.Plugin.64"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(PLUGIN_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.GPU"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(GPU_SERVICE_INITIALIZER));
else if (!strcmp(serviceName, "com.apple.WebKit.WebAuthn"))
entryPointFunctionName = CFSTR(STRINGIZE_VALUE_OF(WEBAUTHN_SERVICE_INITIALIZER));
else {
RELEASE_LOG_ERROR(IPC, "XPCServiceEventHandler: Unexpected 'service-name': %{public}s", serviceName);
return;
}

int fd = xpc_dictionary_dup_fd(event, "stdout");
if (fd != -1)
dup2(fd, STDOUT_FILENO);
CFBundleRef webKitBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit"));
typedef void (*InitializerFunction)(xpc_connection_t, xpc_object_t, xpc_object_t);
InitializerFunction initializerFunctionPtr = reinterpret_cast<InitializerFunction>(CFBundleGetFunctionPointerForName(webKitBundle, entryPointFunctionName));
if (!initializerFunctionPtr) {
RELEASE_LOG_FAULT(IPC, "Exiting: Unable to find entry point in WebKit.framework with name: %s", [(__bridge NSString *)entryPointFunctionName UTF8String]);
[[NSRunLoop mainRunLoop] performBlock:^{
exit(EXIT_FAILURE);
}];
return;
}

fd = xpc_dictionary_dup_fd(event, "stderr");
if (fd != -1)
dup2(fd, STDERR_FILENO);
auto reply = adoptOSObject(xpc_dictionary_create_reply(event));
xpc_dictionary_set_string(reply.get(), "message-name", "process-finished-launching");
xpc_connection_send_message(xpc_dictionary_get_remote_connection(event), reply.get());

WorkQueue::main().dispatchSync([initializerFunctionPtr, event = OSObjectPtr<xpc_object_t>(event), retainedPeerConnection] {
initializerFunctionPtr(retainedPeerConnection.get(), event.get(), priorityBoostMessage.get().get());
int fd = xpc_dictionary_dup_fd(event, "stdout");
if (fd != -1)
dup2(fd, STDOUT_FILENO);

setAppleLanguagesPreference();
});
fd = xpc_dictionary_dup_fd(event, "stderr");
if (fd != -1)
dup2(fd, STDERR_FILENO);

priorityBoostMessage.get() = nullptr;
}
WorkQueue::main().dispatchSync([initializerFunctionPtr, event = OSObjectPtr<xpc_object_t>(event), retainedPeerConnection] {
initializerFunctionPtr(retainedPeerConnection.get(), event.get(), priorityBoostMessage.get().get());

// Leak a boost onto the NetworkProcess.
if (!strcmp(xpc_dictionary_get_string(event, "message-name"), "pre-bootstrap")) {
assert(!priorityBoostMessage.get());
priorityBoostMessage.get() = event;
}
setAppleLanguagesPreference();
});

handleXPCEndpointMessages(event);
priorityBoostMessage.get() = nullptr;
return;
}

// Leak a boost onto the NetworkProcess.
if (!strcmp(messageName, "pre-bootstrap")) {
assert(!priorityBoostMessage.get());
priorityBoostMessage.get() = event;
return;
}

handleXPCEndpointMessages(event, messageName);
});

xpc_connection_resume(peer);
Expand Down
2 changes: 1 addition & 1 deletion Source/WebKit/WebProcess/cocoa/HandleXPCEndpointMessages.h
Expand Up @@ -29,6 +29,6 @@

namespace WebKit {

void handleXPCEndpointMessages(xpc_object_t event);
void handleXPCEndpointMessages(xpc_object_t event, const char* messageName);

}
12 changes: 4 additions & 8 deletions Source/WebKit/WebProcess/cocoa/HandleXPCEndpointMessages.mm
Expand Up @@ -34,17 +34,13 @@

namespace WebKit {

void handleXPCEndpointMessages(xpc_object_t event)
void handleXPCEndpointMessages(xpc_object_t event, const char* messageName)
{
if (xpc_get_type(event) != XPC_TYPE_DICTIONARY)
return;
ASSERT_UNUSED(event, xpc_get_type(event) == XPC_TYPE_DICTIONARY);
ASSERT_UNUSED(messageName, messageName);

#if HAVE(LSDATABASECONTEXT)
String messageName = xpc_dictionary_get_string(event, XPCEndpoint::xpcMessageNameKey);
if (messageName.isEmpty())
return;

if (messageName == LaunchServicesDatabaseXPCConstants::xpcLaunchServicesDatabaseXPCEndpointMessageName) {
if (!strcmp(messageName, LaunchServicesDatabaseXPCConstants::xpcLaunchServicesDatabaseXPCEndpointMessageName)) {
auto xpcEndPoint = xpc_dictionary_get_value(event, LaunchServicesDatabaseXPCConstants::xpcLaunchServicesDatabaseXPCEndpointNameKey);
if (!xpcEndPoint || xpc_get_type(xpcEndPoint) != XPC_TYPE_ENDPOINT)
return;
Expand Down

0 comments on commit 985de70

Please sign in to comment.