diff --git a/catalog/catalog.py b/catalog/catalog.py index c7ec809..632776c 100644 --- a/catalog/catalog.py +++ b/catalog/catalog.py @@ -52,7 +52,13 @@ def dbg_result(): sysent = dmini.cur.find('- 00 10 86 00') + 4 code_addr = 0x80000400 -weirdfile = dmini.Connection(kcode, rw=True).relocate(dmini.cur, code_addr).nth_segment(0).data()[:-8] +def my_ls(binary, sym): + if sym == '_chgproccnt': + # I'm lazy, make this strref later + result = dmini.cur.find('+ f0 b5 03 af 2d e9 00 0d .. .. .. .. 05 46 8a 46 4f f0 00 08') + print hex(result) + return result +weirdfile = dmini.Connection(kcode, rw=True).relocate(dmini.cur, code_addr, my_ls).nth_segment(0).data()[:-8] count = 0 stuff = '' while True: @@ -122,7 +128,7 @@ def seek_kernel_ldm(reg): set_fwd('PC', code_addr) -kstuff = finalize(None, must_be_simple=False, should_heapdump=True); +kstuff = finalize(None, must_be_simple=False, should_heapdump=False) kstuff.append('\0'*1024) def set_cache(cachefile): @@ -313,6 +319,6 @@ def do_main_thing(): init_sp = 0x10031000 address = 0x8000 - final = finalize(address, should_heapdump=True) + final = finalize(address, should_heapdump=False) 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 91eb45c..aee1f05 100644 --- a/catalog/kcode.S +++ b/catalog/kcode.S @@ -102,6 +102,10 @@ syscall_0: ldr r0, [r0, #c(0x6c, 0x80)] cmp r0, #0 strne r1, [r0, #8] + # I don't care about mobile staying alive, but I do care about the reference count dropping + #mov r0, #0 + #mov r1, #1 + #bl _chgproccnt #endif ldr r0, sysent ldr r1, [r0, #0xc4] diff --git a/common/common.h b/common/common.h index 309923d..0f25177 100644 --- a/common/common.h +++ b/common/common.h @@ -13,10 +13,17 @@ #ifndef _log #define _log(args...) fprintf(stderr, args) #endif +#ifndef _fail +#define _fail(name) exit(1) +#endif + +#define LINENO lineno1(__FILE__, __LINE__) +#define lineno1(f, l) lineno2(f, l) +#define lineno2(f, l) f ":" #l -#define _assert(expr, arg...) ((expr) ?: (_assert_helper(#expr, arg + 0), (typeof(expr)) 0)) +#define _assert(expr, arg...) ((expr) ?: (_assert_helper(#expr, LINENO, arg + 0), (typeof(expr)) 0)) #define _assert_zero(expr, arg...) do { typeof(expr) _value = (expr); \ - if(_value) _assert_zero_helper(#expr, arg + 0, (unsigned int) _value); \ + if(_value) _assert_zero_helper(#expr, LINENO, arg + 0, (unsigned int) _value); \ } while(0) #ifdef NO_ASSERT_MESSAGES #define _assert_helper(...) abort() @@ -24,15 +31,15 @@ #else __attribute__((noreturn)) -static void _assert_helper(const char name[], const char *arg) { - _log("assertion failed: %s%s%s%s (errno=%s)\n", name, arg ? "[" : "", arg ? arg : "", arg ? "]" : "", strerror(errno)); - exit(1); +static void _assert_helper(const char name[], const char lineno[], const char *arg) { + _log("assertion failed (%s): %s%s%s%s (errno=%s)\n", lineno, name, arg ? "[" : "", arg ? arg : "", arg ? "]" : "", strerror(errno)); + _fail(name); } __attribute__((noreturn)) -static void _assert_zero_helper(const char name[], const char *arg, unsigned int value) { - _log("assertion failed: %s%s%s%s (value=0x%x, errno=%s)\n", name, arg ? "[" : "", arg ? arg : "", arg ? "]" : "", value, strerror(errno)); - exit(1); +static void _assert_zero_helper(const char name[], const char lineno[], const char *arg, unsigned int value) { + _log("assertion failed (%s): %s%s%s%s (value=0x%x, errno=%s)\n", lineno, name, arg ? "[" : "", arg ? arg : "", arg ? "]" : "", value, strerror(errno)); + _fail(name); } #endif diff --git a/data b/data index be67f52..121f784 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit be67f52507d9607e4353d1d91d379eec1a8ea347 +Subproject commit 121f784fb89cc31ef51b1d1ed69f38ecdfa77c1c diff --git a/fs/fs.h b/fs/fs.h index d8464b8..766fb8f 100644 --- a/fs/fs.h +++ b/fs/fs.h @@ -1,5 +1,6 @@ // whether to spam the syslog/dmesg with printfs #define DEBUG_PRINTF 0 +#define LOCKSPAM 0 #define IS_64BIT_PROCESS(x) 0 #include @@ -26,8 +27,7 @@ asm("$strref_22_76_6e_6f_64_65_5f_63_72_65_61_74_65_3a_20_75_6e_6b_6e_6f_77_6e_2 // '"vnode_create: unknown vtype %d' #define vn_create x_vn_create -#if 0 - +#if LOCKSPAM static void x_lck_mtx_lock(lck_mtx_t *lck) { printf("About to lock %p\n", lck); lck_mtx_lock(lck); diff --git a/fs/union/splice.c b/fs/union/splice.c new file mode 100644 index 0000000..6bdff06 --- /dev/null +++ b/fs/union/splice.c @@ -0,0 +1,130 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "union.h" +#include +#include +#include +#include + +#define CMD_ITERATE(hdr, cmd) for(struct load_command *cmd = (struct load_command *)((hdr) + 1), *end = (struct load_command *)((char *)(hdr + 1) + (hdr)->sizeofcmds); cmd < end; cmd = (struct load_command *)((char *)cmd + cmd->cmdsize)) + +extern struct { + int maxvfsconf; + struct vfstable *vfsconf; +} stuff + +#ifdef IPAD2 +// this stuff was modified prior to the dump, it's not a real difference +asm("$in___DATA__11_00_00_00_03_00_00_00_C_15_00_00_00"); +#else +asm("$in___DATA__11_00_00_00_00_00_00_00_C_11_00_00_00"); +#endif + +extern int union_lookup(struct vnop_lookup_args *ap); +extern lck_mtx_t * union_mtxp; +extern LIST_HEAD(unhead, union_node) *unhead; +extern int *unvplock; +extern int (**union_vnodeop_p)(void *); + +static void *sym(void *ptr, const char *find) { + union { + uintptr_t addr; + struct mach_header *mh; + } u; + u.addr = ((uintptr_t) ptr) & ~0xfff; + // search for the header + while(!(u.mh->magic == MH_MAGIC && u.mh->cputype == CPU_TYPE_ARM && u.mh->cpusubtype == CPU_SUBTYPE_ARM_V7)) { + u.addr -= 0x1000; + } + uint32_t le_begin = 0, le_end = 0; + void *le_ptr = NULL; + struct nlist *syms; + const char *strs; + uint32_t nsyms; + uint32_t slide = 0; + + CMD_ITERATE(u.mh, cmd) { + if(cmd->cmd == LC_SEGMENT) { + struct segment_command *sc = (void *) cmd; + if(!slide) slide = sc->vmaddr; + if(!strncmp(sc->segname, "__LINKEDIT", 16)) { + le_begin = sc->fileoff; + le_end = le_begin + sc->filesize; + le_ptr = (void *) sc->vmaddr; + } + } else if(cmd->cmd == LC_SYMTAB) { + struct symtab_command *sc = (void *) cmd; + if(le_ptr && sc->symoff >= le_begin && sc->symoff < le_end && sc->stroff >= le_begin && sc->stroff < le_end) { + syms = le_ptr + (sc->symoff - le_begin); + strs = le_ptr + (sc->stroff - le_begin); + nsyms = sc->nsyms; + goto ok; + } + } + } + IOLog("couldn't find syms\n"); + return 0; + ok:; + size_t findlen = strlen(find); + for(uint32_t i = 0; i < nsyms; i++) { + const char *name = strs + syms[i].n_un.n_strx; + if(!strncmp(name, find, findlen) && (name[findlen] == 0 || name[findlen] == '.')) { + return (void *) syms[i].n_value + slide; + } + } + return NULL; +} + +bool splice() { + int real_maxvfsconf = 0; + struct vfstable *union_tbl = NULL; + for(struct vfstable *tbl = stuff.vfsconf; tbl; tbl = tbl->vfc_next) { + if(tbl->vfc_typenum >= real_maxvfsconf) real_maxvfsconf = tbl->vfc_typenum; + if(!strncmp(tbl->vfc_name, "unionfs", MFSNAMELEN)) union_tbl = tbl; + } + stuff.maxvfsconf = real_maxvfsconf + 1; + + if(!union_tbl) return false; + + IOLog("Replacing union_lookup...\n"); + + struct nameidata nd; + NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, (user_addr_t) "/Applications", vfs_context_current()); + int error; + if(error = namei(&nd)) { + IOLog("couldn't look up /Applications\n"); + return true; + } + nameidone(&nd); + if(nd.ni_vp->v_mount->mnt_vtable != union_tbl) { + IOLog("/Applications is not unionfs\n"); + goto end; + } + void **lookup = (void **) &nd.ni_vp->v_op[vnop_lookup_desc.vdesc_offset]; + + void *old = *lookup; + union_mtxp = *(void **)sym(*lookup, "_union_mtxp"); + unhead = sym(*lookup, "_unhead_storage") ?: sym(*lookup, "_unhead"); + unvplock = sym(*lookup, "_unvplock_storage") ?: sym(*lookup, "_unvplock"); + union_vnodeop_p = *(void **)sym(*lookup, "_union_vnodeop_p"); + + IOLog("union_mtxp = %p head=%p vplock=%p ul=%p\n", union_mtxp, unhead, unvplock, union_lookup); + *lookup = &union_lookup; + end: + vnode_put(nd.ni_vp); + + return true; +} diff --git a/fs/union/union_subr.c b/fs/union/union_subr.c index 999690e..67f803e 100644 --- a/fs/union/union_subr.c +++ b/fs/union/union_subr.c @@ -95,7 +95,6 @@ #include #endif - static int union_vn_close(struct vnode *vp, int fmode, vfs_context_t ctx); /* must be power of two, otherwise change UNION_HASH() */ @@ -105,13 +104,13 @@ static int union_vn_close(struct vnode *vp, int fmode, vfs_context_t ctx); #define UNION_HASH(u, l) \ (((((uintptr_t) (u)) + ((uintptr_t) l)) >> 8) & (NHASH-1)) -static LIST_HEAD(unhead, union_node) unhead[NHASH]; -static int unvplock[NHASH]; +LIST_HEAD(unhead, union_node) unhead_storage[NHASH], *unhead = unhead_storage; +int unvplock_storage[NHASH], *unvplock = unvplock_storage; static lck_grp_t * union_lck_grp; static lck_grp_attr_t * union_lck_grp_attr; static lck_attr_t * union_lck_attr; -static lck_mtx_t * union_mtxp; +lck_mtx_t * union_mtxp; static int union_dircheck(struct vnode **, struct fileproc *, vfs_context_t ctx); static void union_newlower(struct union_node *, struct vnode *); diff --git a/fs/union/union_vfsops.c b/fs/union/union_vfsops.c index 8d0ffdb..8d5e6e4 100644 --- a/fs/union/union_vfsops.c +++ b/fs/union/union_vfsops.c @@ -82,6 +82,8 @@ #include #include #include +#include +#include #include "union.h" static int union_itercallback(vnode_t, void *); @@ -574,15 +576,18 @@ struct vfs_fsentry fe = { descs, 15, "unionfs", - VFS_TBLTHREADSAFE, + VFS_TBLTHREADSAFE | VFS_TBLNOTYPENUM, {NULL, NULL} }; extern void init_vnodeop_entries(); +extern bool splice(); + vfstable_t ft; __attribute__((constructor)) static void init() { + if(splice()) return; init_vnodeop_entries(); printf("vfs_fsadd: %d\n", vfs_fsadd(&fe, &ft)); printf("whiteout: %p\n", &vnop_whiteout_desc); @@ -594,3 +599,4 @@ static void fini() { printf("vfs_fsremove: %d\n", vfs_fsremove(ft)); union_dircheckp = NULL; } + diff --git a/fs/union/union_vnops.c b/fs/union/union_vnops.c index 4844acc..5d397de 100644 --- a/fs/union/union_vnops.c +++ b/fs/union/union_vnops.c @@ -188,9 +188,9 @@ union_lookup1(struct vnode *udvp, struct vnode **dvpp, struct vnode **vpp, return (0); } -#define CHUD(thr) ((uint32_t *) ((char *) (thr) + 0x4ac)) +#define CHUD(thr) ((uint32_t *) ((char *) (thr) + (VERSION >= 0x040300 ? 0x478 : 0x444))) -static int +int union_lookup(struct vnop_lookup_args *ap) /* struct vnop_lookup_args { @@ -215,7 +215,12 @@ union_lookup(struct vnop_lookup_args *ap) kauth_cred_t saved_cred; struct vnode_attr va; int retry_count = 0; - int old_flags = cnp->cn_flags & (LOCKPARENT | WANTPARENT); + int old_flags = cnp->cn_flags; + char mode = 2; + uint32_t *chud = CHUD(current_thread()); + + /*uint32_t crap; chud = &crap; + if(cnp->cn_nameiop == CREATE || cnp->cn_nameiop == RENAME) return EROFS;*/ *ap->a_vpp = NULLVP; @@ -229,17 +234,19 @@ union_lookup(struct vnop_lookup_args *ap) lowerdvp = dun->un_lowervp; 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); + //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; - - 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 + + if(DEBUG_PRINTF) { + 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); } - 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(); @@ -260,6 +267,7 @@ union_lookup(struct vnop_lookup_args *ap) if(cnp->cn_consume != 0 || (!uerror && !vnode_isdir(uppervp))) { vnode_get(*ap->a_vpp = uppervp); + mode = 3; error = uerror; goto out; } @@ -286,6 +294,7 @@ union_lookup(struct vnop_lookup_args *ap) if(cnp->cn_consume != 0 || (!lerror && !vnode_isdir(lowervp))) { vnode_get(*ap->a_vpp = lowervp); + mode = 4; error = lerror; goto out; } @@ -379,26 +388,32 @@ union_lookup(struct vnop_lookup_args *ap) vnode_put(lowerdvp); // XXX lockparent? - cnp->cn_flags = (cnp->cn_flags & ~(LOCKPARENT | WANTPARENT)) | old_flags; - - if(cnp->cn_nameiop == DELETE) { - *CHUD(current_thread()) = *ap->a_vpp != NULLVP && !vnode_isdir(*ap->a_vpp); - } - + cnp->cn_flags = old_flags; + // sigh if(!slash && ((error == EJUSTRETURN && cnp->cn_nameiop == RENAME) ? - *CHUD(current_thread()) : + *chud : !((uppervp != NULLVP && vnode_isdir(uppervp)) || (lowervp != NULLVP && vnode_isdir(lowervp)))) && (cnp->cn_nameiop == CREATE || 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])); + printf("mega hack %p %p %p chud=%x\n", ap->a_vpp[1], upper(ap->a_vpp[1]), lower(ap->a_vpp[1]), *chud); vnode_t ovp = ap->a_vpp[1]; if(ovp != NULLVP) { - vnode_t newvp = upper_or_lower(ovp); + vnode_t newvp; + if((cnp->cn_flags & ~(FSNODELOCKHELD | HASBUF | CN_VOLFSPATH | MAKEENTRY | ISSYMLINK | ISLASTCN)) == (LOCKPARENT | AUDITVNPATH2 | CN_NBMOUNTLOOK)) { // link() + switch(*chud) { + case 3: newvp = upper(ovp); break; + case 4: newvp = lower(ovp); break; + default: newvp = upper_or_lower(ovp); break; + } + if(newvp == NULLVP) goto nvm; + } else { + newvp = upper_or_lower(ovp); + } if(newvp != ovp) { // did we lock it? char locked = (void *) ovp->v_lock.opaque[0] == current_thread(); @@ -415,12 +430,18 @@ union_lookup(struct vnop_lookup_args *ap) } } + if(cnp->cn_nameiop == DELETE) { + *chud = (*ap->a_vpp != NULLVP && !vnode_isdir(*ap->a_vpp)); + } else if(cnp->cn_nameiop == LOOKUP) { + *chud = mode; + } + nvm: - printf("out: %p RC=%d / %d error=%d isdir=%d\n", dun->un_uppervp, dun->un_uppervp ? dun->un_uppervp->v_iocount : -1, uppervp ? uppervp->v_iocount : -1, error, *ap->a_vpp ? vnode_isdir(*ap->a_vpp) : -1); + //printf("out: %p RC=%d / %d error=%d isdir=%d\n", dun->un_uppervp, dun->un_uppervp ? dun->un_uppervp->v_iocount : -1, uppervp ? uppervp->v_iocount : -1, error, *ap->a_vpp ? vnode_isdir(*ap->a_vpp) : -1); return (error); } -static int +int union_create(struct vnop_create_args *ap) /* struct vnop_create_args { @@ -473,7 +494,7 @@ union_create(struct vnop_create_args *ap) STUB(union_whiteout, struct vnop_whiteout_args *, a_dvp) /* mknod can do fifos, chr, blk or whiteout entries */ -static int +int union_mknod(struct vnop_mknod_args *ap) /* struct vnop_mknod_args { @@ -515,7 +536,7 @@ union_mknod(struct vnop_mknod_args *ap) return (EROFS); } -static int +int union_open(struct vnop_open_args *ap) { stub("union_open", ap->a_vp); @@ -527,7 +548,7 @@ union_open(struct vnop_open_args *ap) return EROFS; } -static int +int union_close(struct vnop_close_args *ap) /* struct vnop_close_args { @@ -563,7 +584,7 @@ union_close(struct vnop_close_args *ap) * file permissions are given away simply because * the user caused an implicit file copy. */ -static int +int union_access(struct vnop_access_args *ap) /* struct vnop_access_args { @@ -604,7 +625,7 @@ union_access(struct vnop_access_args *ap) * We handle getattr only to change the fsid and * track object sizes */ -static int +int union_getattr(struct vnop_getattr_args *ap) /* struct vnop_getattr_args { @@ -681,7 +702,7 @@ union_getattr(struct vnop_getattr_args *ap) return (0); } -static int +int union_setattr(struct vnop_setattr_args *ap) /* struct vnop_setattr_args { @@ -732,7 +753,7 @@ union_setattr(struct vnop_setattr_args *ap) STUB(union_read, struct vnop_read_args *, a_vp) STUB(union_write, struct vnop_read_args *, a_vp) -static int +int union_ioctl(struct vnop_ioctl_args *ap) /* struct vnop_ioctl_args { @@ -750,7 +771,7 @@ union_ioctl(struct vnop_ioctl_args *ap) return (VCALL(ovp, VOFFSET(vnop_ioctl), ap)); } -static int +int union_select(struct vnop_select_args *ap) /* struct vnop_select_args { @@ -768,7 +789,7 @@ union_select(struct vnop_select_args *ap) return (VCALL(ovp, VOFFSET(vnop_select), ap)); } -static int +int union_revoke(struct vnop_revoke_args *ap) /* struct vnop_revoke_args { @@ -792,7 +813,7 @@ union_revoke(struct vnop_revoke_args *ap) STUB(union_mmap, struct vnop_mmap_args *, a_vp) STUB(union_mnomap, struct vnop_mnomap_args *, a_vp) -static int +int union_fsync(struct vnop_fsync_args *ap) /* struct vnop_fsync_args { @@ -821,7 +842,7 @@ union_fsync(struct vnop_fsync_args *ap) return (error); } -static int +int union_remove(struct vnop_remove_args *ap) /* struct vnop_remove_args { @@ -851,7 +872,7 @@ union_remove(struct vnop_remove_args *ap) } } -static int +int union_link(struct vnop_link_args *ap) /* struct vnop_link_args { @@ -874,7 +895,7 @@ union_link(struct vnop_link_args *ap) return EROFS; } -static int +int union_rename(struct vnop_rename_args *ap) /* struct vnop_rename_args { @@ -924,7 +945,7 @@ union_rename(struct vnop_rename_args *ap) return error; } -static int +int union_mkdir(struct vnop_mkdir_args *ap) /* struct vnop_mkdir_args { @@ -964,7 +985,7 @@ union_mkdir(struct vnop_mkdir_args *ap) return (EROFS); } -static int +int union_rmdir(struct vnop_rmdir_args *ap) /* struct vnop_rmdir_args { @@ -1008,7 +1029,7 @@ union_rmdir(struct vnop_rmdir_args *ap) return uerror == ENOENT ? lerror : uerror; } -static int +int union_symlink(struct vnop_symlink_args *ap) /* struct vnop_symlink_args { @@ -1043,7 +1064,7 @@ union_symlink(struct vnop_symlink_args *ap) * down the union stack. readdir(3) is responsible for * eliminating duplicate names from the returned data stream. */ -static int +int union_readdir(struct vnop_readdir_args *ap) /* struct vnop_readdir_args { @@ -1083,7 +1104,7 @@ union_readdir(struct vnop_readdir_args *ap) STUB(union_readlink, struct vnop_readlink_args *, a_vp) -static int +int union_inactive(struct vnop_inactive_args *ap) /* struct vnop_inactive_args { @@ -1128,7 +1149,7 @@ union_inactive(struct vnop_inactive_args *ap) return (0); } -static int +int union_reclaim(struct vnop_reclaim_args *ap) /* struct vnop_reclaim_args { @@ -1145,7 +1166,7 @@ union_reclaim(struct vnop_reclaim_args *ap) return (0); } -static int +int union_blockmap(struct vnop_blockmap_args *ap) /* struct vnop_blockmap_args { @@ -1168,7 +1189,7 @@ union_blockmap(struct vnop_blockmap_args *ap) return (error); } -static int +int union_pathconf(struct vnop_pathconf_args *ap) /* struct vnop_pathconf_args { @@ -1188,7 +1209,7 @@ union_pathconf(struct vnop_pathconf_args *ap) return (error); } -static int +int union_advlock(struct vnop_advlock_args *ap) /* struct vnop_advlock_args { @@ -1213,7 +1234,7 @@ union_advlock(struct vnop_advlock_args *ap) * vnode in its arguments. * This goes away with a merged VM/buffer cache. */ -static int +int union_strategy(struct vnop_strategy_args *ap) /* struct vnop_strategy_args { diff --git a/install/install.m b/install/install.m index 6ad9c6d..b6bd7e7 100644 --- a/install/install.m +++ b/install/install.m @@ -1,4 +1,6 @@ #define _log(fmt, args...) NSLog(@fmt, ##args) +#define _fail generic_fail +__attribute__((noreturn)) static void generic_fail(const char *lineno); #import #include #include @@ -24,8 +26,13 @@ static size_t written_bytes; static void (*set_progress)(float); +__attribute__((noreturn)) static void (*fatal)(NSString *); static NSMutableArray *to_load; +static void generic_fail(const char *lineno) { + fatal([NSString stringWithFormat:@"Internal error at %s", lineno]); +} + static void wrote_bytes(ssize_t bytes) { static size_t last = 0; written_bytes += bytes; @@ -39,12 +46,6 @@ static void wrote_bytes(ssize_t bytes) { } } -ssize_t my_write(int fd, const void *buf, size_t len) { - ssize_t ret = write(fd, buf, len); - if(ret > 0) wrote_bytes(ret); - return ret; -} - static void remove_files(const char *path) { if(access(path, F_OK)) return; char *argv[2], *path_; @@ -94,20 +95,7 @@ static int run(char **argv, char **envp) { return WEXITSTATUS(stat); } - - -unsigned int config_vnode_patch; - -static void qstat(const char *path) { - struct stat st; - if(lstat(path, &st)) { - _log("Could not lstat %s: %s\n", path, strerror(errno)); - } else { - _log("%s: size %d uid %d gid %d mode %04o flags %d\n", path, (int) st.st_size, (int) st.st_uid, (int) st.st_gid, (int) st.st_mode, (int) st.st_flags); - _log("again, mode is %d", (int) st.st_mode); - _log("access is %d", R_OK | W_OK | F_OK | X_OK); - } -} +static int crap; static int lzmaopen(const char *path, int oflag, int foo) { int realfd = open(path, O_RDONLY); @@ -140,6 +128,7 @@ static ssize_t lzmaread(int fd, void *buf, size_t len) { } size_t br = len - strm->avail_out; + wrote_bytes(br); return br; } @@ -154,7 +143,7 @@ static void extract(const char *fn) { _log("could not open %s: %s", fn, strerror(errno)); exit(3); } - while(!th_read(tar)) { + while(errno = 0, !th_read(tar)) { char *pathname = th_get_pathname(tar); while(*pathname == '.' || *pathname == '/') pathname++; if(USE_NULL && ( @@ -173,13 +162,20 @@ static void extract(const char *fn) { } else { chdir("/"); } - if(!access(pathname, F_OK)) { - _log("skipping %s", pathname); + if(TH_ISDIR(tar) && !access(pathname, F_OK)) { + //_log("skipping %s", pathname); continue; } - tar_extract_file(tar, pathname); + errno = 0; + //_log("extracting %s", pathname); + if(tar_extract_file(tar, pathname) && errno != EEXIST) { + _log("error extracting %s: %s", pathname, strerror(errno)); + fatal([NSString stringWithFormat:@"Error extracting bootstrap (jailbreak cancelled): %s", strerror(errno)]); + } + } + if(errno) { + fatal(@"Error extracting bootstrap (jailbreak cancelled)"); } - tar_close(tar); } @@ -290,19 +286,41 @@ static void install_starstuff() { _assert_zero(run((char *[]) {USE_NULL ? "/private/var/null/usr/bin/dpkg" : "/usr/bin/dpkg", "-i", "/tmp/saffron-jailbreak.deb", NULL}, (char *[]) {"DYLD_LIBRARY_PATH=/private/var/null/usr/lib", "PATH=/private/var/null/usr/bin:/private/var/null/usr/sbin:/usr/bin:/usr/sbin:/bin:/sbin", NULL})); } +static void maybe_mkdir(const char *dir) { + errno = 0; + if(mkdir(dir, 0755)) _assert(errno == EEXIST); +} + static void make_nulls() { - mkdir("/private/var/null", 0755); - mkdir("/private/var/null/Applications", 0755); - mkdir("/private/var/null/Library", 0755); - mkdir("/private/var/null/System", 0755); - mkdir("/private/var/null/usr", 0755); - mkdir("/private/var/null/private", 0755); - mkdir("/private/var/null/private/etc", 0755); + struct stat root, applications; + _assert_zero(stat("/", &root)); + _assert_zero(stat("/Applications/", &applications)); + // don't rename if already mounted + if(root.st_dev == applications.st_dev) { + char dest[MAXPATHLEN]; + for(int i = 0; i < 1024; i++) { + snprintf(dest, sizeof(dest), "/private/var/null.%d", i); + if(!rename("/private/var/null", dest) || errno == ENOENT) goto ok; + if(errno != EEXIST && errno != ENOTEMPTY) _assert(0); + } + _assert(0); + } + ok: + maybe_mkdir("/private/var/null"); + maybe_mkdir("/private/var/null/Applications"); + maybe_mkdir("/private/var/null/Library"); + maybe_mkdir("/private/var/null/System"); + maybe_mkdir("/private/var/null/usr"); + maybe_mkdir("/private/var/null/private"); + maybe_mkdir("/private/var/null/private/etc"); } -void do_install(void (*set_progress_)(float)) { +void do_install(void *_set_progress, void *_fatal) { + fatal = _fatal; + set_progress = _set_progress; + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - set_progress = set_progress_; + to_load = [NSMutableArray array]; chdir("/"); diff --git a/install/libtar.a b/install/libtar.a index 7ea6489..5dd4e65 100644 Binary files a/install/libtar.a and b/install/libtar.a differ diff --git a/locutus/locutus.c b/locutus/locutus.c index 49afb44..b0e11e5 100644 --- a/locutus/locutus.c +++ b/locutus/locutus.c @@ -18,15 +18,10 @@ #include #include #include +#include static const float download_share = 0.50; -// and SB freezing or hanging on black -// blinking alertview of doom -// if Cydia was not actually created *or locutus crashes*, don't sit on installing forever (so we should use a socket - that would also handle the locking issue) -// but when it /doesn't/ crash, Cydia disappears -// Safari is respawning and reloading it - I think this can be avoided by having JavaScript load the pdf - //#define TINY #ifdef TINY @@ -52,6 +47,7 @@ static struct request { CFStringRef url; const char *output; CFStringRef content_type; + uint32_t adler; union { struct {}; struct { @@ -60,18 +56,19 @@ static struct request { size_t content_length; bool finished; bool got_headers; + uLong actual_adler; }; }; } requests[] = { #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"), {}}, + {CFSTR("http://www.jailbreakme.com/saffron/_/saffron-jailbreak-%s-%s-" PACKAGE_VERSION ".deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), 0, {}}, + {CFSTR("http://www.jailbreakme.com/saffron/_/freeze.tar.xz"), "/tmp/freeze.tar.xz", CFSTR("application/octet-stream"), 0, {}}, + {CFSTR("http://www.jailbreakme.com/saffron/_/install-" INSTALLER_VERSION ".dylib"), "/tmp/install.dylib", CFSTR("application/octet-stream"), INSTALL_ADLER, {}}, #else - {CFSTR("http://a.qoid.us/omgleak/_/saffron-jailbreak-%s-%s.deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), {}}, + {CFSTR("http://a.qoid.us/saffron/saffron-jailbreak-%s-%s-" PACKAGE_VERSION ".deb"), "/tmp/saffron-jailbreak.deb", CFSTR("application/x-debian-package"), 0, {}}, //{CFSTR("http://test.saurik.com/dhowett/Cydia-4.1b1-Srk.txz"), "/tmp/freeze.tar.xz", 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"), {}}, + {CFSTR("http://a.qoid.us/saffron/freeze.tar.xz"), "/tmp/freeze.tar.xz", CFSTR("application/x-tar"), 0, {}}, + {CFSTR("http://a.qoid.us/saffron/install-" INSTALLER_VERSION ".dylib"), "/tmp/install.dylib", CFSTR("text/plain"), 0, {}}, #endif }, *const requests_end = requests + sizeof(requests)/sizeof(*requests); @@ -107,6 +104,8 @@ static void pause_it(CFStringRef err) { // handle an error or completion static void handle_error(struct request *r, CFStringRef err) { + downloaded_bytes -= lseek(r->out_fd, 0, SEEK_CUR); + NSLog(CFSTR("at the moment, we closed %s with %d"), r->output, (int) lseek(r->out_fd, 0, SEEK_CUR)); close(r->out_fd); r->out_fd = 0; if(err) { @@ -141,9 +140,12 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ case kCFStreamEventEndEncountered: { size_t actual_length = lseek(r->out_fd, 0, SEEK_CUR); - NSLog(CFSTR("[%@] %p, %p, %zd, %zd"), r->url, stream, r->read_stream, actual_length, r->content_length); + //NSLog(CFSTR("[%@] %p, %p, %zd, %zd"), r->url, stream, r->read_stream, actual_length, r->content_length); if(actual_length != r->content_length) { handle_error(r, CFSTR("Truncated")); + } else if(r->adler && r->adler != (uint32_t) r->actual_adler) { + NSLog(CFSTR("[%@] Got adler32 %x but expected %x"), r->url, r->actual_adler, r->adler); + handle_error(r, CFSTR("Invalid checksum")); } else { handle_error(r, NULL); } @@ -198,7 +200,7 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ if(!content_type || kCFCompareEqualTo != CFStringCompare(content_type, r->content_type, kCFCompareCaseInsensitive)) { 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?"))); + handle_error(r, CFStringCreateWithFormat(NULL, NULL, CFSTR("Wrong Content-Type- are you on a fail Wi-Fi network?"))); break; } } @@ -206,8 +208,8 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ // actually read size_t written = 0; while(CFReadStreamHasBytesAvailable(r->read_stream)) { - static char compressed[8192], uncompressed[16384]; - CFIndex idx = CFReadStreamRead(r->read_stream, (void *) compressed, sizeof(compressed)); + static char buf[8192]; + CFIndex idx = CFReadStreamRead(r->read_stream, (void *) buf, sizeof(buf)); if(idx == -1) { handle_error(r, CFSTR("Huh?")); goto end; @@ -215,7 +217,9 @@ static void request_callback(CFReadStreamRef stream, CFStreamEventType event_typ written += (size_t) idx; - _assert((CFIndex) write(r->out_fd, compressed, idx) == idx); + r->actual_adler = adler32(r->actual_adler, (void *) buf, idx); + + _assert((CFIndex) write(r->out_fd, buf, idx) == idx); } end: did_download(written); @@ -239,10 +243,10 @@ static void init_requests() { NSLog(CFSTR("[%@] sending range %@"), r->url, range); CFHTTPMessageSetHeaderFieldValue(message, CFSTR("Range"), range); CFRelease(range); - } else { - nvm: + } else if(!r->out_fd) { r->out_fd = open(/*basename*/((char *) r->output), O_WRONLY | O_CREAT | O_TRUNC, 0644); _assert(r->out_fd != -1); + r->actual_adler = adler32(0L, Z_NULL, 0); } // creating the read stream should succeed, but there might be an error later @@ -266,13 +270,18 @@ static void set_progress(float progress_) { update_state("INSTALLING_ICON_LABEL", NULL); } +static void fatal(CFStringRef err) { + update_state("INSTALLING_ICON_LABEL", err); + exit(1); +} + static void run_install() { NSLog(CFSTR("running install")); signal(SIGUSR1, SIG_IGN); set_progress(0.0); void *install = dlopen("/tmp/install.dylib", RTLD_LAZY); - void (*do_install)(void (*set_progress)(float)) = dlsym(install, "do_install"); - do_install(set_progress); + void (*do_install)(void *set_progress, void *fatal) = dlsym(install, "do_install"); + do_install(set_progress, fatal); update_state("`", NULL); exit(0); } diff --git a/locutus/locutus_server.m b/locutus/locutus_server.m index 9f3cf74..d22e302 100644 --- a/locutus/locutus_server.m +++ b/locutus/locutus_server.m @@ -10,6 +10,8 @@ #include #include #include +#include +#include static NSString *bundle_identifier; static id existing_icon; @@ -26,6 +28,7 @@ // Cancel Retry // quit pause static UIAlertView *alert_view; +static bool dont_hide_alert; static NSString *display_name, *old_display_key; static bool is_installing; static int sock; @@ -100,7 +103,8 @@ static void do_alert(NSString *title, NSString *message, NSString *cancel, NSStr } static void (^sk)() = ^{ - [alert_view dismissWithClickedButtonIndex:0 animated:YES]; + if(!dont_hide_alert) [alert_view dismissWithClickedButtonIndex:0 animated:YES]; + [alert_view setDelegate:nil]; [icon remove]; [icon release]; icon = nil; @@ -118,8 +122,7 @@ static void (^sk)() = ^{ } static void MyIcon_launch(id self, SEL sel) { - NSLog(@"%d", write(sock, "p", 1)); - NSLog(@"%s", strerror(errno)); + write(sock, "p", 1); } static BOOL MyIcon_allowsUninstall(id self, SEL sel) { @@ -170,14 +173,12 @@ static void installed() { static void *read_state(void *fp_) { FILE *fp = fp_; while(1) { - struct { - char state[128], errs[128]; - } s; float progress; - + // in a struct for block's benefit + struct { char state[128], errs[256]; } s; char buf[1024]; if(!fgets(buf, sizeof(buf), fp) || - sscanf(buf, "%128s\t%f\t%128[^;]", s.state, &progress, s.errs) != 3) { + sscanf(buf, "%128s\t%f\t%256[^\t]", s.state, &progress, s.errs) != 3) { dispatch_async(dispatch_get_main_queue(), (dispatch_block_t) sk); return NULL; } @@ -192,7 +193,14 @@ static void installed() { } if(s.errs[0] != '`') { - do_alert(@"There was a problem downloading the jailbreak files.", [NSString stringWithUTF8String:s.errs], _(@"DATA_PLAN_FAILED_TRY_LATER"), _(@"DATA_PLAN_FAILED_TRY_AGAIN")); + NSString *err = [NSString stringWithUTF8String:s.errs]; + if(!strcmp(s.state, "INSTALLING_ICON_LABEL")) { + do_alert(@"There was a problem installing the jailbreak.", err, _(@"OK"), nil); + dont_hide_alert = true; + sk(); + } else { + do_alert(@"There was a problem downloading the jailbreak files.", err, _(@"DATA_PLAN_FAILED_TRY_LATER"), _(@"DATA_PLAN_FAILED_TRY_AGAIN")); + } } NSString *display_key = [NSString stringWithCString:s.state encoding:NSUTF8StringEncoding]; @@ -271,6 +279,14 @@ static void init() { [icon_model addIcon:icon]; [icon_controller addNewIconToDesignatedLocation:icon animate:NO scrollToList:NO saveIconState:YES]; [icon_controller setIconToReveal:icon]; + + struct statfs sfs; + if(!statfs("/private/var", &sfs) && sfs.f_bavail < 20*1024*1024/sfs.f_bsize) { + do_alert(@"Can't jailbreak.", @"There is not enough free disk space. Please delete some photos or videos.", _(@"OK"), nil); + dont_hide_alert = true; + sk(); + return; + } if(existing_icon) { write(sock, "p", 1); diff --git a/make.py b/make.py index 1f29f75..94ea3f8 100755 --- a/make.py +++ b/make.py @@ -9,10 +9,13 @@ def hybrid_hasher(filename): return None fabricate.default_builder.hasher = hybrid_hasher fabricate.default_builder.deps # do this before we chdir -import sys, os, re, glob, traceback, shutil, tempfile +import sys, os, re, glob, traceback, shutil, tempfile, zlib ROOT = os.path.realpath(os.path.dirname(sys.argv[0])) +installer_version = '3' +package_version = '3' + use_null = True # configgy @@ -41,8 +44,10 @@ def set_firmware(firmware=None, lndir=False): GCC_BIN = BIN + '/gcc-4.2' GCC_BASE = [GCC_BIN, GCC_FLAGS, '-isysroot', SDK, '-F'+SDK+'/System/Library/Frameworks', '-F'+SDK+'/System/Library/PrivateFrameworks', '-I', ROOT, '-fblocks', '-mapcs-frame', '-fomit-frame-pointer'] GCC = [GCC_BASE, '-arch', ('armv7' if is_armv7 else 'armv6'), '-mthumb', '-DVERSION=0x%x' % iversion] + if 'iPad2' in device: GCC.append('-DIPAD2=1') GCC_UNIVERSAL = [GCC_BASE, '-arch', 'armv6', '-arch', 'armv7', '-mthumb'] - GCC_ARMV6 = [GCC_BASE, '-arch', 'armv6', '-mthumb'] + #GCC_ARMV6 = [GCC_BASE, '-arch', 'armv6', '-mthumb'] + GCC_ARMV6 = [GCC_BASE, '-arch', 'armv7', '-mthumb'] GCC_NATIVE = ['gcc', '-arch', 'i386', '-arch', 'x86_64', GCC_FLAGS] HEADERS = ROOT + '/headers' @@ -66,14 +71,16 @@ def chext(f, ext): def install(): goto('install') - compile_stuff(['install.m'], tmp('install.dylib'), gcc=GCC_ARMV6, cflags=['-I../headers', '-fblocks', '-DUSE_NULL=%d' % use_null], ldflags=['-framework', 'Foundation', '-framework', 'GraphicsServices', '-framework', 'MobileCoreServices', '-L.', '-ltar', '-llzma', '-dynamiclib']) + compile_stuff(['install.m'], 'install-%s.dylib' % installer_version, gcc=GCC_ARMV6, cflags=['-I../headers', '-fblocks', '-DUSE_NULL=%d' % use_null], ldflags=['-framework', 'Foundation', '-framework', 'GraphicsServices', '-framework', 'MobileCoreServices', '-L.', '-ltar', '-llzma', '-dynamiclib']) def locutus(): + install() + adler = zlib.adler32(open('install-%s.dylib' % installer_version).read()) & 0xffffffff goto('locutus') - cflags = ['-DFNO_ASSERT_MESSAGES', '-fblocks', '-Oz', '-Wno-parentheses', '-miphoneos-version-min=4.0', '-Wno-deprecated-declarations'] + cflags = ['-DFNO_ASSERT_MESSAGES', '-DPACKAGE_VERSION="%s"' % package_version, '-DINSTALLER_VERSION="%s"' % installer_version, '-fblocks', '-Oz', '-Wno-parentheses', '-miphoneos-version-min=4.0', '-Wno-deprecated-declarations'] compile_stuff(['locutus_server.m'], tmp('locutus_server.dylib'), gcc=GCC, cflags=cflags, ldflags=['-dynamiclib', '-framework', 'Foundation', '-framework', 'UIKit', '-install_name', 'X'*32]+cflags, ldid=False) run('sh', '-c', 'xxd -i "%s" | sed "s/[l_].*dylib/dylib/g" > "%s"' % (tmp('locutus_server.dylib'), tmp('locutus_server_.c'))) - compile_stuff(['locutus.c', 'inject.c', 'baton.S', tmp('locutus_server_.c')], tmp('locutus'), gcc=GCC_ARMV6, cflags=cflags, ldflags=['-lbz2', '-framework', 'CoreFoundation', '-framework', 'CFNetwork', '-framework', 'Foundation']+cflags, ldid=True, ent='ent.plist') + compile_stuff(['locutus.c', 'inject.c', 'baton.S', tmp('locutus_server_.c')], tmp('locutus'), gcc=GCC_ARMV6, cflags=cflags+['-DINSTALL_ADLER=%u' % adler], ldflags=['-lz', '-framework', 'CoreFoundation', '-framework', 'CFNetwork', '-framework', 'Foundation']+cflags, ldid=True, ent='ent.plist') build = locutus @@ -104,7 +111,7 @@ def pdf(files=None): goto('pdf') run('python', 'mkpdf.py', tmp('../dejavu/dejavu.pfb'), tmp('out.pdf')) -def compile_stuff(files, output, ent='', cflags=[], ldflags=[], strip=True, gcc=None, ldid=True, combine=False, use_tmp=True): +def compile_stuff(files, output, ent='', cflags=[], ldflags=[], strip=True, gcc=None, ldid=True, combine=False): if gcc is None: gcc = GCC objs = [] output_ = (output + '_' if strip or ldid else output) @@ -113,7 +120,7 @@ def compile_stuff(files, output, ent='', cflags=[], ldflags=[], strip=True, gcc= else: for inp in files: obj = chext(os.path.basename(inp), '.o') - if use_tmp: obj = tmp(obj) + if BUILD_ROOT in output: obj = tmp(obj) objs.append(obj) if obj == inp: continue run(gcc, '-c', '-o', obj, inp, cflags) @@ -143,7 +150,7 @@ def fs(): goto('fs') crap = [GCC, '-dynamiclib', '-g3', '-fwhole-program', '-combine', '-nostdinc', '-nodefaultlibs', '-lgcc', '-Wno-error', '-Wno-parentheses', '-Wno-format', '-I.', '-Ixnu', '-Ixnu/bsd', '-Ixnu/libkern', '-Ixnu/osfmk', '-Ixnu/bsd/i386', '-Ixnu/bsd/sys', '-Ixnu/EXTERNAL_HEADERS', '-Ixnu/osfmk/libsa', '-D__i386__', '-DKERNEL', '-DKERNEL_PRIVATE', '-DBSD_KERNEL_PRIVATE', '-D__APPLE_API_PRIVATE', '-DXNU_KERNEL_PRIVATE', '-flat_namespace', '-undefined', 'dynamic_lookup', '-fno-builtin-printf', '-fno-builtin-log', '-DNULLFS_DIAGNOSTIC', '-dead_strip'] #run(*(crap + ['-o', tmp('nullfs.dylib'), 'kpi_vfs.c', 'null/null_subr.c', 'null/null_vfsops.c', 'null/null_vnops.c'])) - run(*(crap + ['-o', tmp('union.dylib'), 'kpi_vfs.c', 'union/union_subr.c', 'union/union_vfsops.c', 'union/union_vnops.c'])) + run(*(crap + ['-o', tmp('union.dylib'), 'kpi_vfs.c', 'union/union_subr.c', 'union/union_vfsops.c', 'union/union_vnops.c', 'union/splice.c'])) def mroib(): goto('mroib') @@ -163,22 +170,35 @@ def dejavu(files=None): def white(): make('data', 'universal') make('white', 'universal', 'universal', 'universal/white_loader') - make('data', 'armv6') + #make('data', 'armv6') + make('data', 'armv7') goto('white') - run_multiple([GCC_ARMV6, '-o', 'white_loader', 'white_loader.c', '../data/armv6/libdata.a', '-DMINIMAL', '-Wno-parentheses'], + run_multiple([GCC_ARMV6, '-o', 'white_loader', 'white_loader.c', '../data/armv7/libdata.a', '-DMINIMAL', '-Wno-parentheses'], ['strip', '-ur', 'white_loader'], ['ldid', '-Sent.plist', 'white_loader']) +#def humanify_device(device): +# return { +# 'iPhone1,1': 'iPhone', +# 'iPhone1,2': 'iPhone 3G', +# 'iPhone2,1': 'iPhone 3GS', +# 'iPhone3,1': 'iPhone 4 GSM', +# 'iPhone3,3': 'iPhone 4 CDMA', +# 'iPod1,1 +# }[device] + def starstuff(): fs() white() untether() goto('starstuff') - compile_stuff(['mount_nulls.c'], 'mount_nulls', ldid=True, gcc=GCC_ARMV6, use_tmp=False, cflags='-DUSE_NULL=%d' % use_null) + compile_stuff(['mount_nulls.c'], 'mount_nulls', ldid=True, gcc=GCC_ARMV6, 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')) package = 'saffron-jailbreak-%s-%s' % (device, build_num) - run('bash', 'build-archive.sh', tmp('.'), package, package.replace(',', '.').lower(), '%d' % use_null) + package_name = '%s %s JailbreakMe 3.0' % (build_num, device) + run('bash', 'build-archive.sh', tmp('.'), package, package.replace(',', '.').lower(), '%d' % use_null, package_version, package_name) + 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'] @@ -195,7 +215,7 @@ def stage(string=None): firmwares = glob.glob(basetype + '*_' + version) eligible = [] - outpdf = '%s/pdf/%s.pdf' % (ROOT, string) + outpdf = '%s/pdf/%s-%s.pdf' % (ROOT, string, installer_version) for firmware in firmwares: device = firmware[:firmware.find('_')] if device in all_devices: diff --git a/starstuff/build-archive.sh b/starstuff/build-archive.sh index f3285df..1fa0a33 100644 --- a/starstuff/build-archive.sh +++ b/starstuff/build-archive.sh @@ -1,7 +1,7 @@ #!/bin/sh set -xe root="$1/root" -mkdir -p "$root"/{DEBIAN,boot,private/var/null} +mkdir -p "$root"/{DEBIAN,boot,private/var/null{,/Applications,/Library,/System,/usr,/private/etc}} if [ "$4" = "1" ]; then cp -a "$1"/union_prelink.dylib "$root"/boot/union_prelink.dylib fi @@ -10,19 +10,27 @@ cp -a ../white/white_loader "$root"/boot/white_loader cp -a mount_nulls "$root"/boot/mount_nulls cat >"$root"/DEBIAN/control << EOF Package: $3 -Essential: yes +Name: $6 Priority: required Maintainer: comex Section: System Architecture: iphoneos-arm -Version: 1 -Description: Untether and other files +Version: $5 +Tag: role::cydia +Description: support files for JailbreakMe 3.0 +Depiction: http://cydia.saurik.com/info/saffron-jailbreak/ EOF # note that the below script may be running with stuff only in union mounts... cat >"$root"/DEBIAN/extrainst_ << EOF #!/bin/sh -ln -ns /boot/untether /usr/libexec/dirhelper 2>/dev/null -exec /boot/mount_nulls +if [ "\$1" = install -o "\$1" = upgrade ]; then + if [ ! -e /usr/libexec/dirhelper ]; then + ln -ns /boot/untether /usr/libexec/dirhelper || exit 1 + fi + /boot/mount_nulls >&/dev/null +fi +sync; sync +exit 0 EOF chmod 755 "$root"/DEBIAN/extrainst_ -./fauxsu.sh dpkg-deb -b -z9 "$root" "$2".deb +./fauxsu.sh dpkg-deb -b -z9 "$root" "$2"-"$5".deb