Compare commits

...
7 Commits
Author SHA1 Message Date
Ole André Vadla Ravnås f2e071ed78 subprojects: Prepare for release 2024-06-04 13:41:11 +02:00
Ole André Vadla Ravnås bc7f73b492 subprojects: Bump outdated 2024-06-04 13:38:40 +02:00
f91a3c92fe darwin: Avoid thread_set_state() during injection (#530)
So we don't get killed by the system on e.g. macOS >= 14.5.

We can create the thread in running state. There is no need to keep it
suspended until we have created the dispatch source.

Co-authored-by: Håvard Sørbø <[email protected]>
Co-authored-by: Ole André Vadla Ravnås <[email protected]>
2024-06-04 13:36:31 +02:00
Ole André Vadla RavnåsandHåvard Sørbø 6eacc889cd fruity: Perform RSDCheckin on services that need it
In this way we retain backwards-compatibility for open_channel() of
lockdown services when a CoreDevice tunnel is available.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-06-04 12:27:57 +02:00
Ole André Vadla RavnåsandHåvard Sørbø d21ba21aea fruity: Stop caching the LockdownClient
To avoid issues with multiple consumers.

Co-authored-by: Håvard Sørbø <[email protected]>
2024-06-04 11:34:55 +02:00
Ole André Vadla Ravnås cfcdc26d29 subprojects: Prepare for release 2024-05-31 22:52:22 +02:00
Ole André Vadla Ravnås 69555bbbb6 subprojects: Bump outdated 2024-05-31 22:50:47 +02:00
3 changed files with 96 additions and 64 deletions

No files matched your search

+60 -7
View File
@@ -428,6 +428,8 @@ static void frida_agent_context_emit_mach_stub_code (FridaAgentContext * self, g
static void frida_agent_context_emit_pthread_stub_code (FridaAgentContext * self, guint8 * code, GumDarwinModuleResolver * resolver,
GumDarwinMapper * mapper);
static gboolean frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count, GError ** error);
static mach_port_t frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id);
static kern_return_t frida_get_thread_state (mach_port_t thread, thread_state_flavor_t flavor, gpointer state,
mach_msg_type_number_t * count);
@@ -2583,16 +2585,24 @@ static gboolean
frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
{
gboolean success = FALSE;
thread_state_t thread_state;
mach_msg_type_number_t thread_state_count;
kern_return_t kr;
const gchar * failed_operation;
FridaHelperContext * ctx = self->backend->context;
dispatch_source_t source;
kr = thread_create (self->task, &self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
thread_state = g_alloca (self->thread_state_count * sizeof (natural_t));
thread_state_count = self->thread_state_count;
kr = frida_set_thread_state (self->thread, self->thread_state_flavor, self->thread_state_data, self->thread_state_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "set_thread_state");
if (!frida_convert_thread_state_for_task (self->task, self->thread_state_flavor, self->thread_state_data, self->thread_state_count,
thread_state, &thread_state_count, error))
{
return FALSE;
}
kr = thread_create_running (self->task, self->thread_state_flavor, thread_state, thread_state_count, &self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_create");
source = dispatch_source_create (DISPATCH_SOURCE_TYPE_MACH_SEND, self->thread, DISPATCH_MACH_SEND_DEAD, ctx->dispatch_queue);
self->thread_monitor_source = source;
@@ -2601,9 +2611,6 @@ frida_inject_instance_start_thread (FridaInjectInstance * self, GError ** error)
dispatch_source_set_event_handler_f (source, frida_inject_instance_on_mach_thread_dead);
dispatch_resume (source);
kr = thread_resume (self->thread);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_resume");
success = TRUE;
goto beach;
@@ -5072,6 +5079,52 @@ frida_agent_context_emit_arm64_pthread_stub_body (FridaAgentContext * self, Frid
#endif
static gboolean
frida_convert_thread_state_for_task (mach_port_t task, thread_state_flavor_t flavor, gconstpointer in_state,
mach_msg_type_number_t in_state_count, gpointer out_state, mach_msg_type_number_t * out_state_count,
GError ** error)
{
gboolean success = FALSE;
kern_return_t kr;
const gchar * failed_operation;
thread_act_array_t threads = NULL;
mach_msg_type_number_t thread_count = 0;
kr = task_threads (task, &threads, &thread_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "task_threads");
kr = frida_convert_thread_state (threads[0], FRIDA_CONVERT_THREAD_STATE_OUT, flavor, in_state, in_state_count,
out_state, out_state_count);
CHECK_MACH_RESULT (kr, ==, KERN_SUCCESS, "thread_convert_thread_state");
success = TRUE;
goto beach;
mach_failure:
{
g_set_error (error,
FRIDA_ERROR,
FRIDA_ERROR_NOT_SUPPORTED,
"Unexpected error while converting thread state for task (%s returned '%s')",
failed_operation, mach_error_string (kr));
goto beach;
}
beach:
{
mach_msg_type_number_t i;
if (threads != NULL)
{
for (i = 0; i != thread_count; i++)
mach_port_deallocate (mach_task_self (), threads[i]);
vm_deallocate (mach_task_self (), (vm_address_t) threads, thread_count * sizeof (thread_t));
}
return success;
}
}
static mach_port_t
frida_obtain_thread_port_for_thread_id (mach_port_t task, uint64_t thread_id)
{
+35 -56
View File
@@ -244,11 +244,7 @@ namespace Frida {
}
private FruityHostSession? host_session;
private Promise<Fruity.LockdownClient>? lockdown_client_request;
private Promise<Fruity.Tunnel?>? tunnel_request;
private Timer? lockdown_client_timer;
private const double MAX_LOCKDOWN_CLIENT_AGE = 30.0;
public FruityHostSessionProvider (string name, Variant? icon, Fruity.DeviceDetails details) {
Object (
@@ -271,19 +267,6 @@ namespace Frida {
if (tunnel != null)
yield tunnel.close (cancellable);
}
if (lockdown_client_request != null) {
Fruity.LockdownClient? lockdown = null;
try {
lockdown = yield get_lockdown_client (cancellable);
} catch (Error e) {
}
if (lockdown != null) {
on_lockdown_client_closed (lockdown);
yield lockdown.close (cancellable);
}
}
}
public async HostSession create (HostSessionOptions? options, Cancellable? cancellable) throws Error, IOError {
@@ -392,15 +375,46 @@ namespace Frida {
var tunnel = yield find_tunnel (cancellable);
if (tunnel != null) {
Fruity.ServiceInfo? service_info = null;
bool needs_checkin = false;
try {
service_info = tunnel.discovery.get_service (service_name);
} catch (Error e) {
if (!(e is Error.NOT_SUPPORTED))
throw e;
}
if (service_info == null)
if (service_info == null) {
service_info = tunnel.discovery.get_service (service_name + ".shim.remote");
return yield tunnel.open_tcp_connection (service_info.port, cancellable);
needs_checkin = true;
}
var stream = yield tunnel.open_tcp_connection (service_info.port, cancellable);
if (needs_checkin) {
var service = new Fruity.PlistServiceClient (stream);
var checkin = new Fruity.Plist ();
checkin.set_string ("Request", "RSDCheckin");
checkin.set_string ("Label", "Xcode");
checkin.set_string ("ProtocolVersion", "2");
try {
yield service.query (checkin, cancellable);
var result = yield service.read_message (cancellable);
if (result.has ("Error")) {
var error_type = result.get_string ("Error");
if (error_type == "ServiceProhibited")
throw new Error.PERMISSION_DENIED ("Service prohibited");
throw new Error.NOT_SUPPORTED ("%s", error_type);
}
} catch (Fruity.PlistServiceError e) {
throw new Error.PROTOCOL ("%s", e.message);
} catch (Frida.Fruity.PlistError e) {
throw new Error.PROTOCOL ("%s", e.message);
}
}
return stream;
}
try {
@@ -445,50 +459,15 @@ namespace Frida {
}
private async Fruity.LockdownClient get_lockdown_client (Cancellable? cancellable) throws Error, IOError {
if (lockdown_client_timer != null) {
if (lockdown_client_timer.elapsed () > MAX_LOCKDOWN_CLIENT_AGE)
on_lockdown_client_closed (lockdown_client_request.future.value);
else
lockdown_client_timer.start ();
}
while (lockdown_client_request != null) {
try {
return yield lockdown_client_request.future.wait_async (cancellable);
} catch (Error e) {
throw e;
} catch (IOError e) {
cancellable.set_error_if_cancelled ();
}
}
lockdown_client_request = new Promise<Fruity.LockdownClient> ();
try {
var client = yield Fruity.LockdownClient.open (device_details, cancellable);
yield client.start_session (cancellable);
client.closed.connect (on_lockdown_client_closed);
lockdown_client_request.resolve (client);
lockdown_client_timer = new Timer ();
return client;
} catch (GLib.Error e) {
var api_error = new Error.NOT_SUPPORTED ("%s", e.message);
lockdown_client_request.reject (api_error);
lockdown_client_request = null;
lockdown_client_timer = null;
throw_api_error (api_error);
} catch (Frida.Fruity.LockdownError e) {
throw new Error.NOT_SUPPORTED ("%s", e.message);
}
}
private void on_lockdown_client_closed (Fruity.LockdownClient client) {
client.closed.disconnect (on_lockdown_client_closed);
lockdown_client_request = null;
lockdown_client_timer = null;
}
private async Fruity.Tunnel? find_tunnel (Cancellable? cancellable) throws Error, IOError {
while (tunnel_request != null) {
try {
+1 -1
View File
@@ -1,6 +1,6 @@
[wrap-git]
url = https://github.com/frida/frida-gum.git
revision = 16.3.0
revision = 16.3.2
depth = 1
[provide]