diff options
author | comex | 2015-02-28 21:18:20 -0500 |
---|---|---|
committer | comex | 2015-02-28 21:18:20 -0500 |
commit | bfce3bf03e7bc285bc5bbf3df561a6f4e9169899 (patch) | |
tree | 115e02d7a4d44ca6e0a13c4a02a335dffe9b54e2 /darwin-bootstrap/substituted.c | |
parent | Rename ios-bootstrap to darwin-bootstrap; cleanup posixspawn-hook and unrestr... (diff) | |
download | substitute-bfce3bf03e7bc285bc5bbf3df561a6f4e9169899.tar.gz |
Add substituted and fix things up to use it. Still untested.
Diffstat (limited to '')
-rw-r--r-- | darwin-bootstrap/substituted.c | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/darwin-bootstrap/substituted.c b/darwin-bootstrap/substituted.c new file mode 100644 index 0000000..7eade8b --- /dev/null +++ b/darwin-bootstrap/substituted.c @@ -0,0 +1,127 @@ +/* This is a daemon contacted by all processes which can load extensions. It + * currently does the work of reading the plists in + * /Library/Substitute/DynamicLibraries in order to avoid loading objc/CF + * libraries into the target binary (unless actually required by loaded + * libraries). By itself this would not merit the overhead of a separate + * daemon, but in the future this will also coordinate hot loading and + * unloading, for which purpose I think a daemon would be a cleaner solution + * than task_for_pid'ing everything in sight. */ + +#define IB_LOG_NAME "substituted" +#include "darwin/mach-decls.h" +#include "ib-log.h" +#include "substituted-messages.h" +#include "substituted-plist-loader.h" +#include <mach/mach.h> +#include <stddef.h> +//#include <sys/types.h> + +/* libbsm.h */ +struct au_tid; +void audit_token_to_au32(audit_token_t, uid_t *, uid_t *, gid_t *, uid_t *, + gid_t *, pid_t *, pid_t *, struct au_tid *); + +struct msgbuf { + mach_msg_header_t hdr; + union { + struct substituted_msg_body_hello hello; + } u; + mach_msg_audit_trailer_t trail_space; +}; + +static void handle_hello(struct msgbuf *buf, pid_t pid) { + if (buf->hdr.msgh_size < offsetof(struct msgbuf, u.hello.argv0)) { + ib_log("mesage too short"); + return; + } + ((char *) buf)[buf->hdr.msgh_size] = '\0'; /* overwrite trailer or whatever */ + const char *name = buf->u.hello.argv0; + if (IB_VERBOSE) + ib_log("got hello from pid %d [%s]", pid, name); + int error = 0; + const void *bundle_list = NULL; + size_t bundle_list_size = 0; + if (buf->u.hello.proto_version != SUBSTITUTED_PROTO_VERSION) { + error = 1; + } else { + get_bundle_list(name, &bundle_list, &bundle_list_size); + } + struct { + mach_msg_header_t hdr; + struct substituted_msg_body_hello_resp b; + } resp; + resp.hdr.msgh_bits = MACH_MSGH_BITS(MACH_MSG_TYPE_MOVE_SEND_ONCE, 0) | + MACH_MSGH_BITS_COMPLEX; + resp.hdr.msgh_size = sizeof(resp); + resp.hdr.msgh_remote_port = buf->hdr.msgh_remote_port; + resp.hdr.msgh_local_port = MACH_PORT_NULL; + resp.hdr.msgh_reserved = 0; + resp.hdr.msgh_id = SUBSTITUTED_MSG_HELLO_RESP; + resp.b.body.msgh_descriptor_count = 1; + mach_msg_ool_descriptor_t *ool = &resp.b.bundle_list_ool; + ool->pad1 = 0; + ool->type = MACH_MSG_OOL_DESCRIPTOR; + ool->deallocate = 0; + ool->copy = MACH_MSG_PHYSICAL_COPY; + ool->address = (void *) bundle_list; + ool->size = (mach_msg_size_t) bundle_list_size; + resp.b.error = error; + + kern_return_t kr = mach_msg(&resp.hdr, MACH_SEND_MSG, sizeof(resp), 0, + MACH_PORT_NULL, MACH_MSG_TIMEOUT_NONE, + MACH_PORT_NULL); + if (kr) + ib_log("mach_msg(hello resp) -> %x", kr); + else /* don't re-destroy the moved right */ + buf->hdr.msgh_remote_port = MACH_PORT_NULL; +} + +int main() { + mach_port_t service; + kern_return_t kr = bootstrap_check_in(bootstrap_port, + "com.ex.substituted", + &service); + while (1) { + struct msgbuf buf; + mach_msg_option_t option = + MACH_RCV_MSG | + MACH_RCV_TRAILER_TYPE(MACH_RCV_TRAILER_AUDIT) | + MACH_RCV_TRAILER_ELEMENTS(MACH_RCV_TRAILER_AUDIT); + + kr = mach_msg(&buf.hdr, option, 0, sizeof(buf), service, + MACH_MSG_TIMEOUT_NONE, MACH_PORT_NULL); + switch (kr) { + case MACH_MSG_SUCCESS: + break; + case MACH_RCV_BODY_ERROR: + mach_msg_destroy(&buf.hdr); + /* fallthrough */ + case MACH_RCV_TOO_LARGE: + case MACH_RCV_HEADER_ERROR: + case MACH_RCV_SCATTER_SMALL: + ib_log("mach_msg(rcv) -> %x", kr); + continue; + default: + ib_log("mach_msg(rcv) -> %x (fatal)", kr); + return 1; + } + + mach_msg_audit_trailer_t *real_trail = (void *) &buf.hdr + + round_msg(buf.hdr.msgh_size); + + pid_t pid; + audit_token_to_au32(real_trail->msgh_audit, NULL, NULL, NULL, NULL, + NULL, &pid, NULL, NULL); + + switch (buf.hdr.msgh_id) { + case SUBSTITUTED_MSG_HELLO: + handle_hello(&buf, pid); + break; + default: + ib_log("unknown message %d", buf.hdr.msgh_id); + break; + } + + mach_msg_destroy(&buf.hdr); + } +} |