blob: 88c85606c6fad34a977d0b51206f47338bcda1f0 [file] [log] [blame]
// Copyright 2016 The Fuchsia 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 <inttypes.h>
#include <launchpad/launchpad.h>
#include <launchpad/vmo.h>
#include <zircon/process.h>
#include <zircon/processargs.h>
#include <zircon/syscalls.h>
#include <stdio.h>
#include <stdlib.h>
#include "../private.h"
#define HELPER "/boot/bin/thread-injection-injected"
int main(void) {
zx_handle_t h = zx_get_startup_handle(PA_HND(PA_USER0, 0));
if (h == ZX_HANDLE_INVALID) {
fprintf(stderr, "zx_get_startup_handle: %d\n", h);
return 1;
}
// Read the message from the main test program, so we have
// its process and VMAR handles and know where its bits are.
struct helper_data data;
uint32_t bytes = sizeof(data);
zx_handle_t handles[2];
uint32_t nhandles = countof(handles);
zx_status_t status = zx_channel_read(h, 0, &data, handles, bytes,
nhandles, &bytes, &nhandles);
if (status != ZX_OK) {
fprintf(stderr, "zx_channel_read: %d\n", status);
return 1;
}
if (bytes != sizeof(data)) {
fprintf(stderr, "read %u bytes instead of %zu\n", bytes, sizeof(data));
return 1;
}
if (nhandles != countof(handles)) {
fprintf(stderr, "read %u handles instead of %zu\n", nhandles,
countof(handles));
return 1;
}
const zx_handle_t proc = handles[0];
const zx_handle_t vmar = handles[1];
// Load up the launchpad with the injected program. This works just
// like normal program launching, but it goes into a process that
// already exists (and has another program running in it!).
launchpad_t* lp;
status = launchpad_create_with_process(proc, vmar, &lp);
if (status != ZX_OK) {
fprintf(stderr, "launchpad_create_with_process: %d\n", status);
return 1;
}
zx_handle_t vmo;
status = launchpad_vmo_from_file(HELPER, &vmo);
if (status != ZX_OK) {
fprintf(stderr, "launchpad_vmo_from_file: %d\n", status);
return 1;
}
status = launchpad_elf_load(lp, vmo);
if (status != ZX_OK) {
fprintf(stderr, "launchpad_elf_load: %d\n", status);
return 1;
}
// The injected program gets an argument string telling it an
// address in its own address space (aka the injectee process).
char buf[32];
snprintf(buf, sizeof(buf), "%#" PRIxPTR, (uintptr_t)data.futex_addr);
const char *argv[] = { HELPER, buf };
status = launchpad_set_args(lp, 2, argv);
if (status != ZX_OK) {
fprintf(stderr, "launchpad_arguments: %d\n", status);
return 1;
}
// Launch the injected program with a new thread. It gets as
// its argument the handle number for its end of its bootstrap pipe,
// which the main test program told us in the helper_data message.
// (We're reusing the pipe we got helper_data on as the injected
// program's bootstrap pipe, though the two uses are unrelated.)
// Launchpad will send the bootstrap messages on our end of the pipe.
status = launchpad_start_injected(lp, "injected", h, data.bootstrap);
zx_handle_close(h);
if (status != ZX_OK) {
fprintf(stderr, "launchpad_start_injected: %d\n", status);
return 1;
}
launchpad_destroy(lp);
return 0;
}