aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--darwin-bootstrap/ib-log.h2
-rw-r--r--darwin-bootstrap/posixspawn-hook.c16
-rw-r--r--lib/arm/arch-transform-dis.inc.h6
-rw-r--r--lib/arm/assemble.h3
-rw-r--r--lib/arm/dis-thumb2.inc.h2
-rw-r--r--lib/arm/jump-patch.h13
-rw-r--r--lib/arm64/assemble.h2
-rw-r--r--lib/arm64/jump-patch.h5
-rw-r--r--lib/cbit/vec.c6
-rw-r--r--lib/cbit/vec.h4
-rw-r--r--lib/hook-functions.c17
-rw-r--r--lib/jump-dis.c1
-rw-r--r--lib/x86/arch-transform-dis.inc.h2
-rw-r--r--lib/x86/jump-patch.h1
-rwxr-xr-xscript/gen-deb.sh2
15 files changed, 54 insertions, 28 deletions
diff --git a/darwin-bootstrap/ib-log.h b/darwin-bootstrap/ib-log.h
index c80ae63..536b1a7 100644
--- a/darwin-bootstrap/ib-log.h
+++ b/darwin-bootstrap/ib-log.h
@@ -41,4 +41,4 @@ static inline void ib_log_hex(const void *buf, size_t size) {
free(hex);
}
-#define IB_VERBOSE 1
+#define IB_VERBOSE 0
diff --git a/darwin-bootstrap/posixspawn-hook.c b/darwin-bootstrap/posixspawn-hook.c
index 86c3d01..ee6a1cb 100644
--- a/darwin-bootstrap/posixspawn-hook.c
+++ b/darwin-bootstrap/posixspawn-hook.c
@@ -59,7 +59,8 @@ static bool spawn_unrestrict(pid_t pid, bool should_resume, bool is_exec) {
const char *is_exec_s = is_exec ? "1" : "0";
const char *argv[] = {prog, pid_s, should_resume_s, is_exec_s, NULL};
pid_t prog_pid;
- if (old_posix_spawn(&prog_pid, prog, NULL, NULL, (char **) argv, NULL)) {
+ char *env[] = {"_MSSafeMode=1", NULL};
+ if (old_posix_spawn(&prog_pid, prog, NULL, NULL, (char **) argv, env)) {
ib_log("posixspawn-hook: couldn't start unrestrict - oh well...");
return false;
}
@@ -67,7 +68,8 @@ static bool spawn_unrestrict(pid_t pid, bool should_resume, bool is_exec) {
/* reap intermediate to avoid zombie - if it doesn't work, not a big deal */
if (waitpid(prog_pid, &xstat, 0) == -1)
ib_log("posixspawn-hook: couldn't waitpid");
- ib_log("unrestrict xstat=%x", xstat);
+ if (IB_VERBOSE)
+ ib_log("unrestrict xstat=%x", xstat);
return true;
}
@@ -182,7 +184,14 @@ static int hook_posix_spawn_generic(__typeof__(posix_spawn) *old,
else
goto skip;
} else {
- if (!strcmp(path, "/Library/Substitute/Helpers/substituted"))
+ /* substituted obviously doesn't want to have bundle_loader run in it
+ * and try to contact substituted. I am not sure why notifyd is an
+ * issue. Some libc functions (localtime) synchronously contact it,
+ * which launchd could be calling, but I haven't caught it in the act.
+ * XXX I'd like to be completely sure that notifyd and nothing else is
+ * a problem. */
+ if (!strcmp(path, "/Library/Substitute/Helpers/substituted") ||
+ !strcmp(path, "/usr/sbin/notifyd"))
goto skip;
else
dylib_to_add = bl_dylib;
@@ -442,5 +451,4 @@ static void init() {
end:
if (im)
substitute_close_image(im);
-
}
diff --git a/lib/arm/arch-transform-dis.inc.h b/lib/arm/arch-transform-dis.inc.h
index 8569300..4c44913 100644
--- a/lib/arm/arch-transform-dis.inc.h
+++ b/lib/arm/arch-transform-dis.inc.h
@@ -12,6 +12,7 @@ static struct assemble_ctx tdctx_to_actx(const struct transform_dis_ctx *ctx) {
}
return (struct assemble_ctx) {
ctx->rewritten_ptr_ptr,
+ (uint_tptr) (uintptr_t) ctx->rewritten_ptr_ptr,
ctx->arch.pc_low_bit,
cond
};
@@ -121,7 +122,7 @@ void transform_dis_data(struct transform_dis_ctx *ctx, unsigned o0, unsigned o1,
}
static NOINLINE UNUSED
-void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc,
+void transform_dis_pcrel(struct transform_dis_ctx *ctx, uint_tptr dpc,
struct arch_pcrel_info info) {
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis_pcrel: (0x%llx) dpc=0x%llx reg=%x mode=%d\n",
@@ -149,7 +150,7 @@ void transform_dis_pcrel(struct transform_dis_ctx *ctx, uintptr_t dpc,
}
static NOINLINE UNUSED
-void transform_dis_branch(struct transform_dis_ctx *ctx, uintptr_t dpc, int cc) {
+void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc, int cc) {
#ifdef TRANSFORM_DIS_VERBOSE
printf("transform_dis (0x%llx): branch => 0x%llx\n",
(unsigned long long) ctx->base.pc,
@@ -192,6 +193,7 @@ static void transform_dis_pre_dis(struct transform_dis_ctx *ctx) {
static void transform_dis_post_dis(struct transform_dis_ctx *ctx) {
if (ctx->arch.bccrel_p) {
struct assemble_ctx actx = {&ctx->arch.bccrel_p,
+ (uint_tptr) (uintptr_t) ctx->arch.bccrel_p,
/*thumb*/ true,
ctx->arch.bccrel_bits};
Bccrel(actx, *ctx->rewritten_ptr_ptr - ctx->arch.bccrel_p);
diff --git a/lib/arm/assemble.h b/lib/arm/assemble.h
index c0af020..2303a7a 100644
--- a/lib/arm/assemble.h
+++ b/lib/arm/assemble.h
@@ -3,6 +3,7 @@
struct assemble_ctx {
void **codep;
+ uint_tptr pc;
bool thumb;
int cond;
};
@@ -100,6 +101,8 @@ static inline void Bccrel(struct assemble_ctx ctx, int offset) {
}
static inline void LDR_PC(struct assemble_ctx ctx, uint32_t dpc) {
+ if (ctx.pc & 2)
+ op16(ctx.codep, 0xbf00);
if (ctx.thumb)
op32(ctx.codep, 0xf000f8df);
else
diff --git a/lib/arm/dis-thumb2.inc.h b/lib/arm/dis-thumb2.inc.h
index 0a4c12c..b8082f3 100644
--- a/lib/arm/dis-thumb2.inc.h
+++ b/lib/arm/dis-thumb2.inc.h
@@ -197,7 +197,7 @@ static INLINE void P(thumb2_do_it)(tdis_ctx ctx) {
static INLINE void P(dis_thumb2)(tdis_ctx ctx) {
ctx->base.op = unaligned_r32(ctx->base.ptr);
- ctx->base.op_size = ctx->base.newop_size = 2;
+ ctx->base.op_size = ctx->base.newop_size = 4;
/* LLVM likes to think about Thumb2 instructions the way the ARM manual
* does - 15..0 15..0 rather than 31..0 as actually laid out in memory... */
ctx->base.op = flip16(ctx->base.op);
diff --git a/lib/arm/jump-patch.h b/lib/arm/jump-patch.h
index b65a97d..8787070 100644
--- a/lib/arm/jump-patch.h
+++ b/lib/arm/jump-patch.h
@@ -2,17 +2,18 @@
#include "dis.h"
#include "arm/assemble.h"
#define MAX_JUMP_PATCH_SIZE 8
+#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14)
-static inline int jump_patch_size(UNUSED uintptr_t pc,
- UNUSED uintptr_t dpc,
+static inline int jump_patch_size(uint_tptr pc,
+ UNUSED uint_tptr dpc,
UNUSED struct arch_dis_ctx arch,
UNUSED bool force) {
- return 8;
+ return (pc & 2) ? 10 : 8;
}
-static inline void make_jump_patch(void **codep, UNUSED uintptr_t pc,
- uintptr_t dpc,
+static inline void make_jump_patch(void **codep, uint_tptr pc,
+ uint_tptr dpc,
struct arch_dis_ctx arch) {
- struct assemble_ctx actx = {codep, arch.pc_low_bit, 0xe};
+ struct assemble_ctx actx = {codep, pc, arch.pc_low_bit, 0xe};
LDR_PC(actx, dpc);
}
diff --git a/lib/arm64/assemble.h b/lib/arm64/assemble.h
index 42c0f0c..c4fb487 100644
--- a/lib/arm64/assemble.h
+++ b/lib/arm64/assemble.h
@@ -46,7 +46,7 @@ static inline void LDRxi(void **codep, int Rt, int Rn, uint32_t off,
}
static inline void ADRP_ADD(void **codep, int reg, uint64_t pc, uint64_t dpc) {
- uintptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff);
+ uint64_t diff = (dpc & ~0xfff) - (pc & ~0xfff);
/* ADRP reg, dpc */
op32(codep, 0x90000000 | reg | (diff & 0x3000) << 17 | (diff & 0x1ffffc000) >> 9);
uint32_t lo = dpc & 0xfff;
diff --git a/lib/arm64/jump-patch.h b/lib/arm64/jump-patch.h
index 5a44174..fe36d14 100644
--- a/lib/arm64/jump-patch.h
+++ b/lib/arm64/jump-patch.h
@@ -1,8 +1,9 @@
#pragma once
#include "arm64/assemble.h"
#define MAX_JUMP_PATCH_SIZE 20
+#define MAX_EXTENDED_PATCH_SIZE MAX_JUMP_PATCH_SIZE
-static inline int jump_patch_size(uintptr_t pc, uintptr_t dpc,
+static inline int jump_patch_size(uint_tptr pc, uint_tptr dpc,
UNUSED struct arch_dis_ctx arch,
bool force) {
intptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff);
@@ -14,7 +15,7 @@ static inline int jump_patch_size(uintptr_t pc, uintptr_t dpc,
return 12;
}
-static inline void make_jump_patch(void **codep, uintptr_t pc, uintptr_t dpc,
+static inline void make_jump_patch(void **codep, uint_tptr pc, uint_tptr dpc,
struct arch_dis_ctx arch) {
int reg = arm64_get_unwritten_temp_reg(&arch);
intptr_t diff = (dpc & ~0xfff) - (pc & ~0xfff);
diff --git a/lib/cbit/vec.c b/lib/cbit/vec.c
index 21038a2..2f875ff 100644
--- a/lib/cbit/vec.c
+++ b/lib/cbit/vec.c
@@ -1,12 +1,16 @@
#include "cbit/vec.h"
#include <stdio.h>
+#include <stdlib.h>
void vec_realloc_internal(struct vec_internal *vi, size_t new_capacity,
size_t esize) {
+ if (new_capacity == 0)
+ abort();
size_t new_size = safe_mul(new_capacity, esize);
if (vi->els == vi->storage) {
void *new = malloc(new_size);
- memcpy(new, vi->els, vi->capacity * esize);
+ size_t min_cap = new_capacity < vi->capacity ? new_capacity : vi->capacity;
+ memcpy(new, vi->els, min_cap * esize);
vi->els = new;
} else {
vi->els = realloc(vi->els, new_size);
diff --git a/lib/cbit/vec.h b/lib/cbit/vec.h
index 2889ac1..eddee6a 100644
--- a/lib/cbit/vec.h
+++ b/lib/cbit/vec.h
@@ -73,8 +73,8 @@ void vec_realloc_internal_as_necessary(struct vec_internal *vi,
VEC_TY(name) vec_pop_##name(struct vec_##name *v) { \
size_t i = v->length - 1; \
VEC_TY(name) ret = v->els[i]; \
- if (i - 1 < v->capacity / 3) \
- vec_realloc_internal_as_necessary(&v->vi, i - 1, sizeof(v->els[0])); \
+ if (v->els != v->storage && i < v->capacity / 3) \
+ vec_realloc_internal_as_necessary(&v->vi, i, sizeof(v->els[0])); \
v->length = i; \
return ret; \
} \
diff --git a/lib/hook-functions.c b/lib/hook-functions.c
index 2a8d618..673d6d9 100644
--- a/lib/hook-functions.c
+++ b/lib/hook-functions.c
@@ -8,7 +8,7 @@
#include <pthread.h>
struct hook_internal {
- int offset_by_pcdiff[MAX_JUMP_PATCH_SIZE + 1];
+ int offset_by_pcdiff[MAX_EXTENDED_PATCH_SIZE + 1];
uint8_t jump_patch[MAX_JUMP_PATCH_SIZE];
size_t jump_patch_size;
void *code;
@@ -139,7 +139,7 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
struct execmem_foreign_write *fws;
struct hook_internal *his = malloc(nhooks * sizeof(*his) +
- nhooks + sizeof(*fws));
+ nhooks * sizeof(*fws));
if (!his)
return SUBSTITUTE_ERR_OOM;
fws = (void *) (his + nhooks);
@@ -202,7 +202,12 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
hi->trampoline_page = trampoline_ptr;
}
- hi->outro_trampoline = trampoline_ptr;
+ void *outro_trampoline_real = trampoline_ptr;
+ hi->outro_trampoline = outro_trampoline_real;
+#ifdef __arm__
+ if (arch.pc_low_bit)
+ hi->outro_trampoline++;
+#endif
if (hook->old_ptr)
*(void **) hook->old_ptr = hi->outro_trampoline;
@@ -218,10 +223,8 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
uintptr_t dpc = pc_patch_end;
#ifdef __arm__
- if (arch.pc_low_bit) {
- hi->outro_trampoline++;
+ if (arch.pc_low_bit)
dpc++;
- }
#endif
/* Now that transform_dis_main has given us the final pc_patch_end,
@@ -233,7 +236,7 @@ int substitute_hook_functions(const struct substitute_function_hook *hooks,
make_jump_patch(&trampoline_ptr, (uintptr_t) trampoline_ptr, dpc, arch);
trampoline_ptr += -(uintptr_t) trampoline_ptr % ARCH_MAX_CODE_ALIGNMENT;
trampoline_size_left -= (uint8_t *) trampoline_ptr
- - (uint8_t *) hi->outro_trampoline;
+ - (uint8_t *) outro_trampoline_real;
}
/* Now commit. */
diff --git a/lib/jump-dis.c b/lib/jump-dis.c
index aa562a6..13845f5 100644
--- a/lib/jump-dis.c
+++ b/lib/jump-dis.c
@@ -131,6 +131,7 @@ bool jump_dis_main(void *code_ptr, uint_tptr pc_patch_start, uint_tptr pc_patch_
ctx.pc_ret = -1;
ctx.base.pc = pc_patch_end;
ctx.arch = initial_dis_ctx;
+ VEC_STORAGE_INIT(&ctx.queue, uint_tptr);
while (1) {
ctx.bad_insn = false;
ctx.continue_after_this_insn = true;
diff --git a/lib/x86/arch-transform-dis.inc.h b/lib/x86/arch-transform-dis.inc.h
index a4be424..454423b 100644
--- a/lib/x86/arch-transform-dis.inc.h
+++ b/lib/x86/arch-transform-dis.inc.h
@@ -89,7 +89,7 @@ static void transform_dis_branch(struct transform_dis_ctx *ctx, uint_tptr dpc,
ctx->write_newop_here = code;
code += ctx->base.op_size;
- uintptr_t source = ctx->pc_trampoline + ctx->base.op_size + 2;
+ uint_tptr source = ctx->pc_trampoline + ctx->base.op_size + 2;
int size = jump_patch_size(source, dpc, arch, true);
/* If not taken, jmp past the big jump - this is a bit suboptimal but not
diff --git a/lib/x86/jump-patch.h b/lib/x86/jump-patch.h
index 09554d1..c09cb1c 100644
--- a/lib/x86/jump-patch.h
+++ b/lib/x86/jump-patch.h
@@ -1,5 +1,6 @@
#pragma once
#define MAX_JUMP_PATCH_SIZE 14
+#define MAX_EXTENDED_PATCH_SIZE (MAX_JUMP_PATCH_SIZE+14)
#include "dis.h"
static inline int jump_patch_size(uint_tptr pc, uint_tptr dpc,
diff --git a/script/gen-deb.sh b/script/gen-deb.sh
index cd3298e..1848a93 100755
--- a/script/gen-deb.sh
+++ b/script/gen-deb.sh
@@ -16,6 +16,8 @@ cp substrate/substrate.h $debroot/usr/include/substitute/
mkdir -p $debroot/Library/Substitute/DynamicLibraries
mkdir -p $debroot/Library/Substitute/Helpers
cp out/{posixspawn-hook.dylib,bundle-loader.dylib,unrestrict,inject-into-launchd,substituted} $debroot/Library/Substitute/Helpers/
+mkdir -p $debroot/etc/rc.d
+ln -s /Library/Substitute/Helpers/inject-into-launchd $debroot/etc/rc.d/substitute
mkdir -p $debroot/Library/LaunchDaemons
cp darwin-bootstrap/com.ex.substituted.plist $debroot/Library/LaunchDaemons/
cp -a DEBIAN $debroot/