From 755d4c9cd048e6f9226a46c68d791f11fb415bcf Mon Sep 17 00:00:00 2001 From: comex Date: Tue, 21 Jun 2011 16:50:03 -0400 Subject: [PATCH] bullshit --- catalog/kcode.S | 1 + fs/fs.h | 7 +- fs/union/union_vfsops.c | 2 +- fs/union/union_vnops.c | 111 +++-- install/install.m | 98 +++-- installui/crc32.h | 51 --- installui/dddata.h | 11 - installui/dddata.m | 48 --- installui/installui.m | 379 ------------------ installui/mkUIKit.sh | 9 - locutus/locutus.c | 2 +- locutus/locutus_server.m | 5 +- make.py | 17 +- starstuff/build-archive.sh | 28 ++ starstuff/fauxsu.dylib | Bin 0 -> 137240 bytes starstuff/fauxsu.sh | 7 + starstuff/lunchd | 18 - starstuff/mount_nulls.c | 8 +- starstuff/root/boot/union_prelink.dylib | Bin 25 -> 38872 bytes starstuff/root/boot/untether | Bin 25 -> 8192 bytes starstuff/root/boot/white_loader | Bin 27 -> 34944 bytes .../private/var/null/Applications/.ignore | 0 .../root/private/var/null/Library/.ignore | 0 .../root/private/var/null/System/.ignore | 0 starstuff/root/private/var/null/bin/.ignore | 0 .../root/private/var/null/private/etc/.ignore | 0 starstuff/root/private/var/null/sbin/.ignore | 0 starstuff/root/private/var/null/usr/.ignore | 0 28 files changed, 201 insertions(+), 601 deletions(-) delete mode 100644 installui/crc32.h delete mode 100644 installui/dddata.h delete mode 100644 installui/dddata.m delete mode 100644 installui/installui.m delete mode 100755 installui/mkUIKit.sh create mode 100644 starstuff/build-archive.sh create mode 100755 starstuff/fauxsu.dylib create mode 100755 starstuff/fauxsu.sh delete mode 100644 starstuff/lunchd mode change 120000 => 100644 starstuff/root/boot/union_prelink.dylib mode change 120000 => 100755 starstuff/root/boot/untether mode change 120000 => 100755 starstuff/root/boot/white_loader delete mode 100644 starstuff/root/private/var/null/Applications/.ignore delete mode 100644 starstuff/root/private/var/null/Library/.ignore delete mode 100644 starstuff/root/private/var/null/System/.ignore delete mode 100644 starstuff/root/private/var/null/bin/.ignore delete mode 100644 starstuff/root/private/var/null/private/etc/.ignore delete mode 100644 starstuff/root/private/var/null/sbin/.ignore delete mode 100644 starstuff/root/private/var/null/usr/.ignore diff --git a/catalog/kcode.S b/catalog/kcode.S index 02c2dad..d24b4b2 100644 --- a/catalog/kcode.S +++ b/catalog/kcode.S @@ -78,6 +78,7 @@ syscall_0: bl _proc_ucred mov r1, #0 str r1, [r0, #0xc] + str r1, [r0, #0x10] ldr r0, [r0, #0x6c] cmp r0, #0 strne r1, [r0, #8] diff --git a/fs/fs.h b/fs/fs.h index f846049..07e67ec 100644 --- a/fs/fs.h +++ b/fs/fs.h @@ -1,8 +1,5 @@ #define IS_64BIT_PROCESS(x) 0 #include -//extern void IOLog(const char *fmt, ...) __attribute__((format (printf, 1, 2))); -//#define printf(args...) IOLog(args) -//#define printf(args...) (void) (args) int x_namei(struct nameidata *ndp) asm("$bl1__vnode_lookup"); void x_nameidone(struct nameidata *) @@ -46,3 +43,7 @@ inline void buf_setvnode(buf_t bp, vnode_t vp) { #define bcopy(a, b, c) memcpy(b, a, c) + +extern void IOLog(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +#define printf(args...) ((void) (args)) + diff --git a/fs/union/union_vfsops.c b/fs/union/union_vfsops.c index 4d5eae1..2122d4c 100644 --- a/fs/union/union_vfsops.c +++ b/fs/union/union_vfsops.c @@ -577,7 +577,7 @@ struct vfs_fsentry fe = { vfstable_t ft; __attribute__((constructor)) static void init() { - vfs_fsadd(&fe, &ft); + printf("vfs_fsadd: %d\n", vfs_fsadd(&fe, &ft)); } __attribute__((destructor)) diff --git a/fs/union/union_vnops.c b/fs/union/union_vnops.c index e64bf8f..6486268 100644 --- a/fs/union/union_vnops.c +++ b/fs/union/union_vnops.c @@ -87,6 +87,33 @@ #include #include +static int stub(const char *name, vnode_t vp) { + char buf[512] = "[???]"; + int len = 511; + vn_getpath(vp, buf, &len); + buf[len] = 0; + printf("Stub for %s: %s\n", name, buf); + return ENXIO; +} +#define STUB(func, typ, field) static int func(typ ap) { return stub(#func, ap->field); } + +__attribute__((const)) +static char is_union(vnode_t vp) { + return vp != NULLVP && vp->v_op == union_vnodeop_p; +} + +__attribute__((const)) +static vnode_t upper(vnode_t vp) { + if(!is_union(vp)) return vp; + return VTOUNION(vp)->un_uppervp; +} + +__attribute__((const)) +static vnode_t lower(vnode_t vp) { + if(!is_union(vp)) return vp; + return VTOUNION(vp)->un_lowervp; +} + /* called with no union lock held */ static int union_lookup1(struct vnode *udvp, struct vnode **dvpp, struct vnode **vpp, @@ -181,6 +208,8 @@ union_lookup(struct vnop_lookup_args *ap) int retry_count = 0; *ap->a_vpp = NULLVP; + + printf("looking up %s\n", cnp->cn_nameptr); retry: union_lock(); @@ -228,6 +257,7 @@ union_lookup(struct vnop_lookup_args *ap) goto out; } } else { + printf("lookup: dir = %d\n", vnode_isdir(uppervp)); if(!vnode_isdir(uppervp)) { vnode_get(*ap->a_vpp = uppervp); goto out; @@ -292,6 +322,8 @@ union_lookup(struct vnop_lookup_args *ap) * vnode referencing whatever the new top layer and * whatever the bottom layer returned. */ + + printf("lookup: uerror=%d lerror=%d\n", uerror, lerror); /* case 1. */ if ((uerror != 0) && (lerror != 0)) { @@ -313,6 +345,10 @@ union_lookup(struct vnop_lookup_args *ap) goto out; } + printf("lookup: okay we are allocvp'ing\n"); + + // I don't get this weird reference counting it so I'll just do this + vnode_get(uppervp); vnode_get(lowervp); union_lock(); error = union_allocvp(ap->a_vpp, dvp->v_mount, dvp, upperdvp, cnp, uppervp, lowervp, 1); @@ -378,9 +414,7 @@ union_create(struct vnop_create_args *ap) return (EROFS); } -static int -union_whiteout(struct vnop_whiteout_args *ap) -{ return ENXIO; } +STUB(union_whiteout, struct vnop_whiteout_args *, a_dvp) /* mknod can do fifos, chr, blk or whiteout entries */ static int @@ -427,7 +461,15 @@ union_mknod(struct vnop_mknod_args *ap) static int union_open(struct vnop_open_args *ap) -{ return ENXIO; } +{ + stub("union_open", ap->a_vp); + struct union_node *un = VTOUNION(ap->a_vp); + printf("upper=%p lower=%p\n", un->un_uppervp, un->un_lowervp); + if(un->un_uppervp != NULLVP) return VNOP_OPEN(un->un_uppervp, ap->a_mode, ap->a_context); + un->un_openl++; + if(un->un_lowervp != NULLVP) return VNOP_OPEN(un->un_lowervp, ap->a_mode, ap->a_context); + return ENOMSG; +} static int union_close(struct vnop_close_args *ap) @@ -838,19 +880,28 @@ union_remove(struct vnop_remove_args *ap) */ { int error, flags; - struct union_node *dun = VTOUNION(ap->a_dvp); - struct union_node *un = VTOUNION(ap->a_vp); + vnode_t dvp = ap->a_dvp; + vnode_t vp = ap->a_vp; + //IOLog("%d %p %p %d %p %p\n", is_union(ap->a_dvp), dun->un_uppervp, dun->un_lowervp, is_union(ap->a_vp), un->un_uppervp, un->un_lowervp); + //return ENXIO; struct componentname *cnp = ap->a_cnp; int busydel = 0; + if(!vnode_isdir(ap->a_vp)) { + int error = ENXIO; + if(upper(dvp) != NULLVP && upper(vp) != NULLVP) if(error = VNOP_REMOVE(upper(dvp), upper(vp), ap->a_cnp, ap->a_flags, ap->a_context)) return error; + if(lower(dvp) != NULLVP && lower(vp) != NULLVP) if(error = VNOP_REMOVE(lower(dvp), lower(vp), ap->a_cnp, ap->a_flags, ap->a_context)) return error; + return error; + } + + if(!is_union(dvp) || !is_union(dvp)) return ENXIO; + + struct union_node *dun = VTOUNION(ap->a_dvp); + struct union_node *un = VTOUNION(ap->a_vp); + if (dun->un_uppervp == NULLVP) panic("union remove: null upper vnode"); - if (UNNODE_FAULTIN(dun) && ((ap->a_vp != NULLVP) && - ((vnode_isreg(ap->a_vp) != 0) || (vnode_islnk(ap->a_vp) != 0)))) { - return(VNOP_REMOVE(dun->un_uppervp, ap->a_vp, ap->a_cnp, ap->a_flags, ap->a_context)); - } - if (un->un_uppervp != NULLVP) { struct vnode *dvp = dun->un_uppervp; struct vnode *vp = un->un_uppervp; @@ -971,23 +1022,31 @@ union_rename(struct vnop_rename_args *ap) struct union_node *dun = VTOUNION(fdvp); struct union_node *un = VTOUNION(fvp); + IOLog("vps: %p, %p, %p, %p\n", fdvp, fvp, tdvp, tvp); + IOLog("upper:%p, %p, %p, %p\n", dun->un_uppervp, un->un_uppervp, upper(tdvp), upper(tvp)); + IOLog("lower:%p, %p, %p, %p\n", dun->un_lowervp, un->un_lowervp, lower(tdvp), lower(tvp)); + return ENXIO; + + if(un->un_uppervp != NULLVP) { if(dun->un_uppervp == NULLVP) panic("wat (upper)"); - if(error = VNOP_RENAME(dun->un_uppervp, un->un_uppervp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp, ap->a_context)) { + if(error = VNOP_RENAME(dun->un_uppervp, un->un_uppervp, ap->a_fcnp, upper(tdvp), upper(tvp), ap->a_tcnp, ap->a_context)) { + printf("got an error from upper: %d\n", error); return error; } } - if(un->un_lowervp != NULLVP) { if(dun->un_lowervp == NULLVP) panic("wat (lower)"); - if(error = VNOP_RENAME(dun->un_lowervp, un->un_lowervp, ap->a_fcnp, tdvp, tvp, ap->a_tcnp, ap->a_context)) { + if(error = VNOP_RENAME(dun->un_lowervp, un->un_lowervp, ap->a_fcnp, lower(tdvp), lower(tvp), ap->a_tcnp, ap->a_context)) { if(un->un_uppervp != NULLVP) { - printf("bad bad bad - the first rename succeeded but the second one failed; trying to rename it back\n"); + printf("bad bad bad - the first rename succeeded but the second one failed (%d); trying to rename it back\n", error); + /* int error2; - if(error2 = VNOP_RENAME(dun->un_uppervp, un->un_uppervp, ap->a_fcnp, tdvp, tvp, ap->a_fcnp, ap->a_context)) { + if(error2 = VNOP_RENAME(dun->un_uppervp, un->un_uppervp, ap->a_fcnp, upper(fdvp), NULLVP, ap->a_fcnp, ap->a_context)) { printf("that failed too: %d\n", error2); } + */ } return error; } @@ -1152,9 +1211,7 @@ union_readdir(struct vnop_readdir_args *ap) return (VCALL(uvp, VOFFSET(vnop_readdir), ap)); } -static int -union_readlink(struct vnop_readlink_args *ap) -{ return ENXIO; } +STUB(union_readlink, struct vnop_readlink_args *, a_vp) static int union_inactive(struct vnop_inactive_args *ap) @@ -1316,24 +1373,16 @@ union_strategy(struct vnop_strategy_args *ap) } /* Pagein */ -static int -union_pagein(struct vnop_pagein_args *ap) -{ return ENXIO; } +STUB(union_pagein, struct vnop_pagein_args *, a_vp) /* Pageout */ -static int -union_pageout(struct vnop_pageout_args *ap) -{ return ENXIO; } +STUB(union_pageout, struct vnop_pageout_args *, a_vp) /* Blktooff derives file offset for the given logical block number */ -static int -union_blktooff(struct vnop_blktooff_args *ap) -{ return ENXIO; } +STUB(union_blktooff, struct vnop_blktooff_args *, a_vp) /* offtoblk derives file offset for the given logical block number */ -static int -union_offtoblk(struct vnop_offtoblk_args *ap) -{ return ENXIO; } +STUB(union_offtoblk, struct vnop_offtoblk_args *, a_vp) #define VOPFUNC int (*)(void *) diff --git a/install/install.m b/install/install.m index cc89ae3..e47708d 100644 --- a/install/install.m +++ b/install/install.m @@ -1,4 +1,5 @@ -#define _log(fmt, args...) fprintf(stderr, fmt "\n", ##args) +#define _log(fmt, args...) NSLog(@fmt, ##args) +#import #include #include #include @@ -19,13 +20,6 @@ #include #include #include -#import - -bool GSSystemHasCapability(NSString *capability); - -extern void do_copy(char *, char *, ssize_t (*)(int, const void *, size_t)); -extern void init(); -extern void finish(); static size_t written_bytes; static void (*set_progress)(float); @@ -83,16 +77,16 @@ static void remove_files(const char *path) { free(path_); } -static int run(char **args) { +static int run(char **argv, char **envp) { fprintf(stderr, "run:"); - for(char **p = args; *p; p++) { + for(char **p = argv; *p; p++) { fprintf(stderr, " %s", *p); } fprintf(stderr, "\n"); pid_t pid; int stat; - if(posix_spawn(&pid, args[0], NULL, NULL, args, NULL)) return 255; + if(posix_spawn(&pid, argv[0], NULL, NULL, argv, envp)) return 255; if(pid != waitpid(pid, &stat, 0)) return 254; if(!WIFEXITED(stat)) return 253; return WEXITSTATUS(stat); @@ -163,13 +157,13 @@ static void extract(const char *fn, bool use_null) { while(*pathname == '.' || *pathname == '/') pathname++; if(use_null && ( #define O(x) !memcmp(pathname, x, strlen(x)) - //O("Applications") || - //O("Library") || - //O("System") || + O("Applications") || + O("Library") || + O("System") || //O("bin") || //O("sbin") || - //O("usr") || - //O("private/etc") || + O("usr") || + O("private/etc") || 0 #undef O )) { @@ -189,7 +183,7 @@ static void extract(const char *fn, bool use_null) { static void remount() { _log("remount..."); - _assert_zero(run((char *[]) {"/sbin/mount", "-u", "-o", "rw,suid,dev", "/", NULL})); + _assert_zero(run((char *[]) {"/sbin/mount", "-u", "-o", "rw,suid,dev", "/", NULL}, NULL)); NSString *string = _assert([NSString stringWithContentsOfFile:@"/etc/fstab" encoding:NSUTF8StringEncoding error:NULL]); string = [string stringByReplacingOccurrencesOfString:@",nosuid,nodev" withString:@""]; @@ -200,7 +194,10 @@ static void remount() { // returns whether the plist existed static bool modify_plist(NSString *filename, void (^func)(id)) { NSData *data = [NSData dataWithContentsOfFile:filename]; - if(!data) return false; + if(!data) { + _log("did not modify %@", filename); + return false; + } NSPropertyListFormat format; NSError *error; id plist = [NSPropertyListSerialization propertyListWithData:data options:NSPropertyListMutableContainersAndLeaves format:&format error:&error]; @@ -213,6 +210,7 @@ static bool modify_plist(NSString *filename, void (^func)(id)) { _assert([new_data writeToFile:filename atomically:YES]); + _log("modified %@", filename); return true; } @@ -222,17 +220,15 @@ static void dok48() { _assert_zero(sysctlbyname("hw.model", model, &model_size, NULL, 0)); NSString *filename = [NSString stringWithFormat:@"/System/Library/CoreServices/SpringBoard.app/%s.plist", model]; - if(modify_plist(filename, ^(id plist) { + modify_plist(filename, ^(id plist) { [[plist objectForKey:@"capabilities"] setObject:[NSNumber numberWithBool:false] forKey:@"hide-non-default-apps"]; - })) { - _log("%s.plist modified", model); - } + }); } static void add_afc2() { _assert(modify_plist(@"/System/Library/Lockdown/Services.plist", ^(id services) { NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys: - [NSArray arrayWithObjects:@"/usr/lib/afcd", + [NSArray arrayWithObjects:@"/usr/libexec/afcd", @"--lockdown", @"-d", @"/", @@ -245,13 +241,57 @@ static void add_afc2() { } static void finish_up() { - int ret = symlink("/boot/untether", "/usr/libexec/dirhelper"); - if(errno != EEXIST) _assert_zero(ret); - TIME(_assert_zero(run((char *[]) {"/boot/mount_nulls", NULL}))); for(NSData *pathname in to_load) { chdir("/"); - run((char *[]) {"/bin/launchctl", "load", (char *) [pathname bytes], NULL}); + run((char *[]) {"/bin/launchctl", "load", (char *) [pathname bytes], NULL}, NULL); + } +} + +@interface LSApplicationWorkspace { +} ++(LSApplicationWorkspace *)defaultWorkspace; +-(BOOL)registerApplication:(id)application; +-(BOOL)unregisterApplication:(id)application; +@end + + +static void uicache() { + // I am not using uicache because I want loc_s to do the reloading + + // probably not safe: + NSMutableDictionary *cache = [NSMutableDictionary dictionaryWithContentsOfFile:@"/var/mobile/Library/Caches/com.apple.mobile.installation.plist"]; + if(cache) { + NSMutableDictionary *cydia = _assert([NSMutableDictionary dictionaryWithContentsOfFile:@"/Applications/Cydia.app/Info.plist"]); + [cydia setObject:@"/Applications/Cydia.app" forKey:@"Path"]; + [cydia setObject:@"System" forKey:@"ApplicationType"]; + id system = [cache objectForKey:@"System"]; + if([system respondsToSelector:@selector(addObject:)]) + [system addObject:cydia]; + else + [system setObject:cydia forKey:@"com.saurik.Cydia"]; + [cache writeToFile:@"/var/mobile/Library/Caches/com.apple.mobile.installation.plist" atomically:YES]; } + + NSURL *url = [NSURL fileURLWithPath:@"/Applications/Cydia.app/Info.plist"]; + LSApplicationWorkspace *workspace = [LSApplicationWorkspace defaultWorkspace]; + [workspace unregisterApplication:url]; + [workspace registerApplication:url]; + + run((char *[]) {"/usr/bin/killall", "installd", NULL}, NULL); +} + +static void install_starstuff() { + _assert_zero(run((char *[]) {"/private/var/null/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 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); } void do_install(void (*set_progress_)(float)) { @@ -264,9 +304,11 @@ void do_install(void (*set_progress_)(float)) { TIME(remount()); TIME(dok48()); TIME(add_afc2()); - TIME(extract("/tmp/starstuff.tar.xz", false)); + TIME(make_nulls()); TIME(extract("/tmp/freeze.tar.xz", true)); + TIME(install_starstuff()); TIME(finish_up()); + TIME(uicache()); TIME(sync()); _log("final written_bytes = %zd", written_bytes); } diff --git a/installui/crc32.h b/installui/crc32.h deleted file mode 100644 index a356f14..0000000 --- a/installui/crc32.h +++ /dev/null @@ -1,51 +0,0 @@ -static unsigned int crc32(const void *buf, size_t bufLen) { - static const unsigned int crcTable[256] = { - 0x00000000,0x77073096,0xEE0E612C,0x990951BA,0x076DC419,0x706AF48F,0xE963A535, - 0x9E6495A3,0x0EDB8832,0x79DCB8A4,0xE0D5E91E,0x97D2D988,0x09B64C2B,0x7EB17CBD, - 0xE7B82D07,0x90BF1D91,0x1DB71064,0x6AB020F2,0xF3B97148,0x84BE41DE,0x1ADAD47D, - 0x6DDDE4EB,0xF4D4B551,0x83D385C7,0x136C9856,0x646BA8C0,0xFD62F97A,0x8A65C9EC, - 0x14015C4F,0x63066CD9,0xFA0F3D63,0x8D080DF5,0x3B6E20C8,0x4C69105E,0xD56041E4, - 0xA2677172,0x3C03E4D1,0x4B04D447,0xD20D85FD,0xA50AB56B,0x35B5A8FA,0x42B2986C, - 0xDBBBC9D6,0xACBCF940,0x32D86CE3,0x45DF5C75,0xDCD60DCF,0xABD13D59,0x26D930AC, - 0x51DE003A,0xC8D75180,0xBFD06116,0x21B4F4B5,0x56B3C423,0xCFBA9599,0xB8BDA50F, - 0x2802B89E,0x5F058808,0xC60CD9B2,0xB10BE924,0x2F6F7C87,0x58684C11,0xC1611DAB, - 0xB6662D3D,0x76DC4190,0x01DB7106,0x98D220BC,0xEFD5102A,0x71B18589,0x06B6B51F, - 0x9FBFE4A5,0xE8B8D433,0x7807C9A2,0x0F00F934,0x9609A88E,0xE10E9818,0x7F6A0DBB, - 0x086D3D2D,0x91646C97,0xE6635C01,0x6B6B51F4,0x1C6C6162,0x856530D8,0xF262004E, - 0x6C0695ED,0x1B01A57B,0x8208F4C1,0xF50FC457,0x65B0D9C6,0x12B7E950,0x8BBEB8EA, - 0xFCB9887C,0x62DD1DDF,0x15DA2D49,0x8CD37CF3,0xFBD44C65,0x4DB26158,0x3AB551CE, - 0xA3BC0074,0xD4BB30E2,0x4ADFA541,0x3DD895D7,0xA4D1C46D,0xD3D6F4FB,0x4369E96A, - 0x346ED9FC,0xAD678846,0xDA60B8D0,0x44042D73,0x33031DE5,0xAA0A4C5F,0xDD0D7CC9, - 0x5005713C,0x270241AA,0xBE0B1010,0xC90C2086,0x5768B525,0x206F85B3,0xB966D409, - 0xCE61E49F,0x5EDEF90E,0x29D9C998,0xB0D09822,0xC7D7A8B4,0x59B33D17,0x2EB40D81, - 0xB7BD5C3B,0xC0BA6CAD,0xEDB88320,0x9ABFB3B6,0x03B6E20C,0x74B1D29A,0xEAD54739, - 0x9DD277AF,0x04DB2615,0x73DC1683,0xE3630B12,0x94643B84,0x0D6D6A3E,0x7A6A5AA8, - 0xE40ECF0B,0x9309FF9D,0x0A00AE27,0x7D079EB1,0xF00F9344,0x8708A3D2,0x1E01F268, - 0x6906C2FE,0xF762575D,0x806567CB,0x196C3671,0x6E6B06E7,0xFED41B76,0x89D32BE0, - 0x10DA7A5A,0x67DD4ACC,0xF9B9DF6F,0x8EBEEFF9,0x17B7BE43,0x60B08ED5,0xD6D6A3E8, - 0xA1D1937E,0x38D8C2C4,0x4FDFF252,0xD1BB67F1,0xA6BC5767,0x3FB506DD,0x48B2364B, - 0xD80D2BDA,0xAF0A1B4C,0x36034AF6,0x41047A60,0xDF60EFC3,0xA867DF55,0x316E8EEF, - 0x4669BE79,0xCB61B38C,0xBC66831A,0x256FD2A0,0x5268E236,0xCC0C7795,0xBB0B4703, - 0x220216B9,0x5505262F,0xC5BA3BBE,0xB2BD0B28,0x2BB45A92,0x5CB36A04,0xC2D7FFA7, - 0xB5D0CF31,0x2CD99E8B,0x5BDEAE1D,0x9B64C2B0,0xEC63F226,0x756AA39C,0x026D930A, - 0x9C0906A9,0xEB0E363F,0x72076785,0x05005713,0x95BF4A82,0xE2B87A14,0x7BB12BAE, - 0x0CB61B38,0x92D28E9B,0xE5D5BE0D,0x7CDCEFB7,0x0BDBDF21,0x86D3D2D4,0xF1D4E242, - 0x68DDB3F8,0x1FDA836E,0x81BE16CD,0xF6B9265B,0x6FB077E1,0x18B74777,0x88085AE6, - 0xFF0F6A70,0x66063BCA,0x11010B5C,0x8F659EFF,0xF862AE69,0x616BFFD3,0x166CCF45, - 0xA00AE278,0xD70DD2EE,0x4E048354,0x3903B3C2,0xA7672661,0xD06016F7,0x4969474D, - 0x3E6E77DB,0xAED16A4A,0xD9D65ADC,0x40DF0B66,0x37D83BF0,0xA9BCAE53,0xDEBB9EC5, - 0x47B2CF7F,0x30B5FFE9,0xBDBDF21C,0xCABAC28A,0x53B39330,0x24B4A3A6,0xBAD03605, - 0xCDD70693,0x54DE5729,0x23D967BF,0xB3667A2E,0xC4614AB8,0x5D681B02,0x2A6F2B94, - 0xB40BBE37,0xC30C8EA1,0x5A05DF1B,0x2D02EF8D }; - unsigned int crc32; - unsigned char *byteBuf; - size_t i; - - /** accumulate crc32 for buffer **/ - crc32 = 0xffffffff; - byteBuf = (unsigned char*) buf; - for (i=0; i < bufLen; i++) { - crc32 = (crc32 >> 8) ^ crcTable[ (crc32 ^ byteBuf[i]) & 0xFF ]; - } - return( crc32 ^ 0xFFFFFFFF ); -} diff --git a/installui/dddata.h b/installui/dddata.h deleted file mode 100644 index 01f2007..0000000 --- a/installui/dddata.h +++ /dev/null @@ -1,11 +0,0 @@ -// http://deusty.blogspot.com/2007/07/gzip-compressiondecompression.html -// Thanks! - -@interface NSData (DDData) - -- (NSData *)inflatedData; - -@end - - - diff --git a/installui/dddata.m b/installui/dddata.m deleted file mode 100644 index 26de5b2..0000000 --- a/installui/dddata.m +++ /dev/null @@ -1,48 +0,0 @@ -#include -#import - -@implementation NSData (DDData) -- (NSData *)inflatedData { - - if ([self length] == 0) return self; - - unsigned full_length = [self length]; - unsigned half_length = [self length] / 2; - - NSMutableData *decompressed = [NSMutableData dataWithLength: full_length + half_length]; - BOOL done = NO; - int status; - - z_stream strm; - strm.next_in = (Bytef *)[self bytes]; - strm.avail_in = [self length]; - strm.total_out = 0; - strm.zalloc = Z_NULL; - strm.zfree = Z_NULL; - - if (inflateInit2(&strm, (15+32)) != Z_OK) return nil; - while (!done) - { - // Make sure we have enough room and reset the lengths. - if (strm.total_out >= [decompressed length]) - [decompressed increaseLengthBy: half_length]; - strm.next_out = [decompressed mutableBytes] + strm.total_out; - strm.avail_out = [decompressed length] - strm.total_out; - - // Inflate another chunk. - status = inflate (&strm, Z_SYNC_FLUSH); - if (status == Z_STREAM_END) done = YES; - else if (status != Z_OK) break; - } - if (inflateEnd (&strm) != Z_OK) return nil; - - // Set real length. - if (done) - { - [decompressed setLength: strm.total_out]; - return decompressed;//[NSData dataWithData: decompressed]; - } - else return nil; -} - -@end diff --git a/installui/installui.m b/installui/installui.m deleted file mode 100644 index f6f27f1..0000000 --- a/installui/installui.m +++ /dev/null @@ -1,379 +0,0 @@ -#include -#include -#import -#import -#import -#import -#import -#import -#import -#import -#include -#include -#include -#include -#include -#include -#include -#include -#include "dddata.h" -#include -#include -//#include "crc32.h" - -#define TESTING 0 -#define SLEEP 0 -//#define WAD_URL @"http://a.qoid.us/wad.bin" -//#define EXPECTED_DOMAIN @"a.qoid.us" -#define WAD_URL @"http://jailbreakme.com/wad.bin" -#define EXPECTED_DOMAIN @"jailbreakme.com" -//#define WAD_URL @"http://pudor.local/wad.bin" -//#define EXPECTED_DOMAIN @"pudor.local" -@interface NSObject (ShutUpGcc) -+ (id)sharedBrowserController; -- (id)tabController; -- (id)activeTabDocument; --(void)loadURL:(id)url userDriven:(BOOL)driven; -@end - -@interface Dude : NSObject { - UIAlertView *progressAlertView; - UIAlertView *choiceAlertView; - UIAlertView *doneAlertView; - UIProgressView *progressBar; - NSMutableData *wad; - long long expectedLength; - const char *freeze; - int freeze_len; - unsigned char *one; - unsigned int one_len; - NSURLConnection *connection; -} -@end - -static Dude *dude; -static BOOL is_hung; - -@implementation Dude - -- (id)initWithOne:(unsigned char *)one_ oneLen:(int)one_len_ { - if(self = [super init]) { - one = one_; - one_len = one_len_; - //[self showPurple]; - } - return self; -} - -static void unpatch() { - int fd = open("/dev/kmem", O_RDWR); - if(fd <= 0) goto fail; - unsigned int things[2] = {1, 2}; // original values of staticmax, maxindex - if(pwrite(fd, &things, sizeof(things), CONFIG_MAC_POLICY_LIST + 8) != sizeof(things)) goto fail; - close(fd); - setuid(501); - return; -fail: - NSLog(@"Unpatch failed!"); -} - -#if CONFIG_KILL_SB -static BOOL my_suspendForEventsOnly(id self, SEL sel, BOOL whatever) { - system("killall SpringBoard"); - exit(1); -} - -static void allow_quit() { - Class cls = objc_getClass("Application"); // MobileSafari specific, thanks phoenix3200 - Method m; - m = class_getInstanceMethod(cls, @selector(_suspendForEventsOnly:)); - method_setImplementation(m, (IMP) my_suspendForEventsOnly); -} -#endif - -static void set_progress(float progress) { - [dude performSelectorOnMainThread:@selector(setProgress:) withObject:[NSNumber numberWithFloat:progress] waitUntilDone:NO]; -} - -- (void)setProgress:(NSNumber *)progress { - [progressBar setProgress:[progress floatValue]]; -} - -- (void)setProgressCookie:(unsigned int)progress { - NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:[NSDictionary dictionaryWithObjectsAndKeys: - @"progress", NSHTTPCookieName, - [NSString stringWithFormat:@"%u_%f", progress, [[NSDate date] timeIntervalSince1970]], NSHTTPCookieValue, - @"jailbreakme.com", NSHTTPCookieDomain, - @"/", NSHTTPCookiePath, - @"Sat, 01 Feb 2020 05:00:00 GMT", NSHTTPCookieExpires, - nil]]; - [[NSHTTPCookieStorage sharedHTTPCookieStorage] setCookie:cookie]; -} - -- (void)doStuff { - NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; - void *handle = dlopen("/tmp/install.dylib", RTLD_LAZY); - if(!handle) abort(); - void (*do_install)(const char *, int, void (*)(float), unsigned int, unsigned char *, unsigned int) = dlsym(handle, "do_install"); - -#if !SLEEP - do_install(freeze, freeze_len, set_progress, CONFIG_VNODE_PATCH, one, one_len); -#else - for(int i = 0; i < 10; i++) { set_progress(0.1 * i); usleep(250000); } -#endif - - NSLog(@"Um, I guess it worked."); - unpatch(); - - [progressAlertView dismissWithClickedButtonIndex:1 animated:YES]; - [progressAlertView release]; - progressAlertView = nil; - -#if CONFIG_KILL_SB - allow_quit(); -#endif - doneAlertView = [[UIAlertView alloc] initWithTitle:@"Cydia has been added to the home screen." message:@"Have fun!" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [doneAlertView show]; - - [self setProgressCookie:2]; -} - -- (void)bored { - if([progressAlertView.message isEqualToString:@"This might take a while."]) { - progressAlertView.message = @"(*yawn*)"; - } -} - -- (void)bored2 { - if([progressAlertView.message isEqualToString:@"(*yawn*)"]) { - if(!memcmp(CONFIG_PLATFORM, "iPhone3,1", 9)) { - progressAlertView.message = @"(Let go of the black strip on the left. ;)"; - } else { - progressAlertView.message = @"(Come on, it's only a few megs!)"; - } - } -} - -- (void)connection:(NSURLConnection *)connection_ didReceiveResponse:(NSURLResponse *)response { - expectedLength = [response expectedContentLength]; -} - -- (void)connection:(NSURLConnection *)connection_ didReceiveData:(NSData *)data { - [wad appendData:data]; - [progressBar setProgress:((float)[wad length])/expectedLength]; -} - -struct wad { - unsigned int magic; - unsigned int full_size; - unsigned int first_part_size; - unsigned char data[]; -}; - -- (void)connectionDidFinishLoading:(NSURLConnection *)connection_ { - [connection release]; - connection = nil; - NSString *message; - const struct wad *sw = [wad bytes]; - if([wad length] < sizeof(struct wad)) { - message = @"File received was truncated."; - goto error; - } - if(sw->magic != 0x42424242) { - message = @"File received was invalid."; - goto error; - } - if([wad length] != sw->full_size) { - message = @"File received was truncated."; - goto error; - } - /*unsigned long calculated_crc = crc32((void *) &sw->first_part_size, [wad length] - sizeof(unsigned long)); - if(calculated_crc != sw->crc) { - message = @"Invalid file received. Are you on a fail wi-fi connection?"; - NSLog(@"length=%u first_part_size=%u", [wad length], sw->first_part_size); - NSLog(@"calculated=%u expected=%u", calculated_crc, sw->crc); - //[wad writeToFile:@"/var/mobile/Media/wad.bin" atomically:NO]; - goto error; - }*/ - [[[wad subdataWithRange:NSMakeRange(sizeof(struct wad), sw->first_part_size)] inflatedData] writeToFile:@"/tmp/install.dylib" atomically:NO]; - freeze = &sw->data[sw->first_part_size]; - freeze_len = [wad length] - sizeof(struct wad) - sw->first_part_size; - progressAlertView.title = @"Jailbreaking..."; - progressAlertView.message = @"Sit tight."; - [progressBar setProgress:0.0]; - - [UIView beginAnimations:nil context:nil]; - //progressBar.frame = CGRectMake(92, 90, 110, 10); - [[[progressAlertView buttons] objectAtIndex:0] removeFromSuperview]; - [[progressAlertView buttons] removeObjectAtIndex:0]; - [progressAlertView layoutAnimated:YES]; - [UIView commitAnimations]; - - [NSThread detachNewThreadSelector:@selector(doStuff) toTarget:self withObject:nil]; - return; - error: - - [progressAlertView dismissWithClickedButtonIndex:1 animated:YES]; - [progressAlertView release]; - progressAlertView = nil; - - choiceAlertView = [[UIAlertView alloc] initWithTitle:@"Oops..." message:message delegate:self cancelButtonTitle:@"Quit" otherButtonTitles:@"Retry", nil]; - [choiceAlertView show]; -} - -- (void)connection:(NSURLConnection *)connection_ didFailWithError:(NSError *)error { - [connection release]; - connection = nil; - - [progressAlertView dismissWithClickedButtonIndex:1 animated:YES]; - [progressAlertView release]; - progressAlertView = nil; - - choiceAlertView = [[UIAlertView alloc] initWithTitle:@"Oops..." message:[error localizedDescription] delegate:self cancelButtonTitle:@"Quit" otherButtonTitles:@"Retry", nil]; - [choiceAlertView show]; -} - -- (void)keepGoing { - // Okay, we can keep going. - [[UIApplication sharedApplication] setIdleTimerDisabled:YES]; - progressAlertView = [[UIAlertView alloc] initWithTitle:@"Downloading..." message:@"This might take a while.\n\n\n" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:nil]; - progressBar = [[UIProgressView alloc] initWithFrame:CGRectMake(92, 90, 100, 10)]; - //[progressBar setProgressViewStyle:CONFIG_PROGRESS_BAR_STYLE]; - [progressAlertView addSubview:progressBar]; - [progressAlertView show]; - wad = [[NSMutableData alloc] init]; - - connection = [[NSURLConnection alloc] initWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:WAD_URL]] delegate:self]; - - [NSTimer scheduledTimerWithTimeInterval:20 target:self selector:@selector(bored) userInfo:nil repeats:NO]; - [NSTimer scheduledTimerWithTimeInterval:40 target:self selector:@selector(bored2) userInfo:nil repeats:NO]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - NSLog(@"alertView:%@ clickedButtonAtIndex:%d", alertView, (int)buttonIndex); - NSLog(@"choice = %@ progress = %@", choiceAlertView, progressAlertView); - - if(alertView == choiceAlertView) { - [choiceAlertView release]; - choiceAlertView = nil; - - if(buttonIndex == 0) { - // The user hit cancel, just crash. - unpatch(); - [self setProgressCookie:3]; - if(is_hung) { - [[UIApplication sharedApplication] terminateWithSuccess]; - } - } else { - [self keepGoing]; - } - } else if(alertView == progressAlertView) { - [progressAlertView release]; - progressAlertView = nil; - NSLog(@"connection = %@", connection); - if(buttonIndex == 0 && connection) { - [connection cancel]; - [connection release]; - connection = nil; - } - } else if(alertView == doneAlertView) { - [doneAlertView release]; - doneAlertView = nil; - } -} - -- (void)start { - //[NSThread detachNewThreadSelector:@selector(pipidi:) toTarget:self withObject:port]; - id tabDocument = [[[(id)objc_getClass("BrowserController") sharedBrowserController] tabController] activeTabDocument]; - NSString *host = [[tabDocument URL] host]; - if(![host isEqualToString:EXPECTED_DOMAIN] && ![host isEqualToString:[@"www." stringByAppendingString:EXPECTED_DOMAIN]]) return; - if(!access("/bin/bash", F_OK)) { - choiceAlertView = [[UIAlertView alloc] initWithTitle:@"Do you want to jailbreak?" message:@"Warning: It looks like you're already jailbroken. Doing it again might be harmful." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Jailbreak", nil]; - [choiceAlertView show]; - } else { -#if TESTING - choiceAlertView = [[UIAlertView alloc] initWithTitle:@"Do you want to jailbreak?" message:@"This dialog for testing only..." delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"Jailbreak", nil]; - [choiceAlertView show]; -#else - [self keepGoing]; -#endif - } -} -@end - -__attribute__((noinline)) -void foo() { - asm(""); -} - -static void bus() { - is_hung = true; - sleep((unsigned int) -1); -} - -static void work_around_apple_bugs() { - signal(SIGBUS, bus); - //[DeveloperBannerView updateWithFileName:UTI:]: -} - -void iui_go(unsigned char **ptr, unsigned char *one, unsigned int one_len) { - NSLog(@"iui_go: one=%p one_len=%d", one, one_len); - NSLog(@"*one = %d", (int) *one); - work_around_apple_bugs(); - - dude = [[Dude alloc] initWithOne:one oneLen:one_len]; - [dude performSelectorOnMainThread:@selector(start) withObject:nil waitUntilDone:NO]; - - // hmm. - NSLog(@"ptr = %p; *ptr = %p; **ptr = %u", ptr, *ptr, (unsigned int) **ptr); - **ptr = 0x0e; // endchar - - // mm. - unsigned int *top = pthread_get_stackaddr_np(pthread_self()); - size_t size = pthread_get_stacksize_np(pthread_self()); - unsigned int *bottom = (void *) ((char *)top - size); - NSLog(@"top = %p size = %d", top, (int) size); - unsigned int *addr = top; - while(*--addr != 0xf00df00d) { - if(addr == bottom) { - NSLog(@"Couldn't find foodfood."); -#if TESTING - [[NSData dataWithBytesNoCopy:bottom length:size freeWhenDone:NO] writeToFile:@"/var/mobile/Media/stack.bin" atomically:NO]; - NSLog(@"Stack written to /var/mobile/Media/stack.bin."); -#endif - abort(); - } - } - NSLog(@"foodfood found at %p comparing to %p", addr, CONFIG_FT_PATH_BUILDER_CREATE_PATH_FOR_GLYPH); - void *return_value; - while(1) { - if(*addr >= CONFIG_FT_PATH_BUILDER_CREATE_PATH_FOR_GLYPH && *addr < CONFIG_FT_PATH_BUILDER_CREATE_PATH_FOR_GLYPH + ((CONFIG_FT_PATH_BUILDER_CREATE_PATH_FOR_GLYPH & 1) ? 0x200 : 0x400)) { - // Return to ft_path_builder_create_path_for_glyph - NSLog(@"Returning to create_path_for_glyph"); - return_value = (void *) CGPathCreateMutable(); - goto returnx; - } - if(*addr >= CONFIG_GET_GLYPH_BBOXES && *addr < CONFIG_GET_GLYPH_BBOXES + 0x100) { - NSLog(@"Returning to get_glyph_bboxes"); - return_value = NULL; - goto returnx; - } - addr++; - if(addr == top) { - NSLog(@"We got back up to the top... "); -#if TESTING - [[NSData dataWithBytesNoCopy:bottom length:size freeWhenDone:NO] writeToFile:@"/var/mobile/Media/stack.bin" atomically:NO]; - NSLog(@"Stack written to /var/mobile/Media/stack.bin."); -#endif - abort(); - } - } - - returnx: - NSLog(@"Setting SP to %p - 7", addr); - foo(); - addr -= 7; - // get a return value. - CGMutablePathRef path = CGPathCreateMutable(); - asm("mov sp, %0; mov r0, %1; pop {r8, r10, r11}; pop {r4-r7, pc}" ::"r"(addr), "r"(return_value)); -} diff --git a/installui/mkUIKit.sh b/installui/mkUIKit.sh deleted file mode 100755 index 5a3f0ee..0000000 --- a/installui/mkUIKit.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/sh -set -e -class-dump-z -H -o dumpedUIKit /var/sdk/System/Library/Frameworks/UIKit.framework/UIKit -echo '#import -#include -typedef void *GSEventRef;' > dumpedUIKit/UIKit-Structs.h -for i in dumpedUIKit/NS*.h; do >$i; done -sed 's/otherButtonTitles:(id)titles/otherButtonTitles:(id)titles, .../g' dumpedUIKit/UIAlertView.h > tmp; mv tmp dumpedUIKit/UIAlertView.h - diff --git a/locutus/locutus.c b/locutus/locutus.c index d0ece47..2078b98 100644 --- a/locutus/locutus.c +++ b/locutus/locutus.c @@ -64,7 +64,7 @@ static struct request { }; }; } requests[] = { - {CFSTR("http://a.qoid.us/saffron/starstuff_%s_%s.tar.xz"), "/tmp/starstuff.tar.xz", CFSTR("application/x-tar"), {}}, + {CFSTR("http://a.qoid.us/saffron/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/install.dylib"), "/tmp/install.dylib", CFSTR("text/plain"), {}}, }, *const requests_end = requests + sizeof(requests)/sizeof(*requests); diff --git a/locutus/locutus_server.m b/locutus/locutus_server.m index a1ac5d8..d51d7f3 100644 --- a/locutus/locutus_server.m +++ b/locutus/locutus_server.m @@ -143,14 +143,11 @@ static void installed() { [icon remove]; [icon_controller scrollToIconListContainingIcon:existing_icon animate:YES]; } else { - [icon_model loadAllIcons]; - /* #if VERSION >= 0x040300 - [application_controller loadApplicationsAndIcons:@"com.saurik.Cydia" reveal:YES popIn:NO reloadAllIcons:YES]; + [application_controller loadApplicationsAndIcons:@"com.saurik.Cydia" reveal:YES popIn:NO reloadAllIcons:NO]; #else [application_controller loadApplicationsAndIcons:@"com.saurik.Cydia" reveal:YES popIn:NO]; #endif - */ } icon = nil; sk(); diff --git a/make.py b/make.py index 2603c54..d88d975 100755 --- a/make.py +++ b/make.py @@ -58,7 +58,7 @@ def chext(f, ext): def install(): goto('install') - compile_stuff(['install.m'], tmp('install.dylib'), gcc=GCC_ARMV6, cflags=['-I../headers', '-fblocks'], ldflags=['-framework', 'Foundation', '-framework', 'GraphicsServices', '-L.', '-ltar', '-llzma', '-dynamiclib']) + compile_stuff(['install.m'], tmp('install.dylib'), gcc=GCC_ARMV6, cflags=['-I../headers', '-fblocks'], ldflags=['-framework', 'Foundation', '-framework', 'GraphicsServices', '-framework', 'MobileCoreServices', '-L.', '-ltar', '-llzma', '-dynamiclib']) def locutus(): goto('locutus') @@ -167,23 +167,16 @@ def starstuff(): untether() goto('starstuff') compile_stuff(['mount_nulls.c'], 'mount_nulls', ldid=False, gcc=GCC_ARMV6, use_tmp=False) - #run('../white/universal/white_loader', '-k', BS+'/kern', '-p', '../fs/union.dylib', 'union_prelink.dylib') - run('touch', tmp('union_prelink.dylib')) - shell('mkdir', '-p', tmp('root/boot')) - for a in ['Applications', 'bin', 'Library', 'private/etc', 'sbin', 'System', 'usr']: - shell('mkdir', '-p', tmp('root/private/var/null/'+a)) - for a, b in [('mount_nulls', ROOT+'/starstuff/mount_nulls'), ('union_prelink.dylib', tmp('union_prelink.dylib')), ('untether', tmp('../catalog/untether')), ('white_loader', ROOT+'/white/white_loader')]: - shell('ln', '-nfs', b, tmp('root/boot/'+a)) - run('gnutar', 'chvf', tmp('starstuff.tar'), '-C', tmp('root'), '.', '--owner', '0', '--group', 0, '--exclude', '.ignore') - xz = '%s/starstuff/starstuff_%s_%s.tar.xz' % (ROOT, device, build_num) - run('sh', '-c', 'xz -c "%s" > "%s"' % (tmp('starstuff.tar'), xz)) + run('../white/universal/white_loader', '-k', BS+'/kern', '-p', '../fs/union.dylib', 'union_prelink.dylib') + #run('touch', tmp('union_prelink.dylib')) + package = 'saffron-jailbreak-%s-%s' % (device, build_num) + run('bash', 'build-archive.sh', tmp('.'), package, package.replace(',', '.').lower()) def stage(): all_devices = ['iPhone3,1', 'iPhone3,3', 'iPod4,1', 'iPad2,1', 'iPad2,2', 'iPad2,3', 'iPhone2,1', 'iPod3,1', 'iPad1,1', 'iPhone1,2', 'iPod2,1'] armv6_devices = ['iPhone1,2', 'iPod1,1', 'iPod2,1'] install() goto('.') - #shell('sh', '-c', 'rm -f pdf/*.pdf starstuff/*.xz') goto('bs') available = set(i[i.find('_')+1:] for i in glob.glob('*_*')) succeeded = [] diff --git a/starstuff/build-archive.sh b/starstuff/build-archive.sh new file mode 100644 index 0000000..8c14e28 --- /dev/null +++ b/starstuff/build-archive.sh @@ -0,0 +1,28 @@ +#!/bin/sh +set -xe +root="$1/root" +mkdir -p "$root"/{DEBIAN,boot,private/var/null} +cp -a "$1"/union_prelink.dylib "$root"/boot/union_prelink.dylib +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 +cat >"$root"/DEBIAN/control << EOF +Package: $3 +Essential: yes +Priority: required +Maintainer: comex +Section: System +Architecture: iphoneos-arm +Version: 1 +Description: Untether and other files +EOF +# note that the below script may be running with stuff only in union mounts... +cat >"$root"/DEBIAN/extrainst_ << EOF +#!/bin/sh +cd / +find . -maxdepth 4 -xdev -type d -print0 | (cd /private/var/null; xargs -0 mkdir -p) +ln -ns /boot/untether /usr/libexec/dirhelper 2>/dev/null +exec /boot/mount_nulls +EOF +chmod 755 "$root"/DEBIAN/extrainst_ +./fauxsu.sh dpkg-deb -b -z9 "$root" "$2".deb diff --git a/starstuff/fauxsu.dylib b/starstuff/fauxsu.dylib new file mode 100755 index 0000000000000000000000000000000000000000..1f388b465a4b1f1c06dcbe11e7b2adb17432d0b2 GIT binary patch literal 137240 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 QrzVUD;P+^08-V`&8)0SjW&i*H literal 0 HcmV?d00001 diff --git a/starstuff/fauxsu.sh b/starstuff/fauxsu.sh new file mode 100755 index 0000000..04bf5cc --- /dev/null +++ b/starstuff/fauxsu.sh @@ -0,0 +1,7 @@ +#!/bin/sh +if [ -n "`which fakeroot`" ]; then + exec fakeroot "$@" +else + export DYLD_INSERT_LIBRARIES="$(greadlink -f $(dirname $0)/fauxsu.dylib):$DYLD_INSERT_LIBRARIES" + exec "$@" +fi diff --git a/starstuff/lunchd b/starstuff/lunchd deleted file mode 100644 index e0585b4..0000000 --- a/starstuff/lunchd +++ /dev/null @@ -1,18 +0,0 @@ -#!/bin/bash -shopt -s nullglob - -echo "Hello" >&2 - -/usr/share/white/white_loader -l /usr/share/white/nullfs_prelink.dylib - -for i in Applications Developer Library System User bin boot cores lib mnt sbin usr; do - mount -t null -o union /private/var/null/$i /$i & -done -wait - -echo "Mounted" >&2 - -dylibs=$(for dylib in /Library/LaunchExtensions/*.dylib; do echo -n "$dylib:"; done) -export DYLD_INSERT_LIBRARIES=${dylibs%:} -exec -a /sbin/launchd /sbin/launchd.real - diff --git a/starstuff/mount_nulls.c b/starstuff/mount_nulls.c index 7577f5b..b4c8c4f 100644 --- a/starstuff/mount_nulls.c +++ b/starstuff/mount_nulls.c @@ -1,4 +1,4 @@ -// this can't be a shell script because bash depends on readline, but readline is behind the mount +// this can't be a shell script because bash depends on readline, but readline is behind the mount (not insurmountable but this is easier) #include #include #include @@ -14,8 +14,6 @@ struct union_args { #define A(x) args.target = "/private/var/null/" x; if(mount("unionfs", "/" x, 0, &args)) fprintf(stderr, "couldn't mount %s\n", "/" x); int main() { - return 0; // XXX - char *argv[] = {"/boot/white_loader", "-l", "/boot/union_prelink.dylib", NULL}; int stat; pid_t pid; @@ -26,8 +24,8 @@ int main() { A("Applications") A("Library") A("System") - A("bin") - A("sbin") + //A("bin") + //A("sbin") A("usr") A("private/etc") diff --git a/starstuff/root/boot/union_prelink.dylib b/starstuff/root/boot/union_prelink.dylib deleted file mode 120000 index 9010946..0000000 --- a/starstuff/root/boot/union_prelink.dylib +++ /dev/null @@ -1 +0,0 @@ -../../union_prelink.dylib \ No newline at end of file diff --git a/starstuff/root/boot/union_prelink.dylib b/starstuff/root/boot/union_prelink.dylib new file mode 100644 index 0000000000000000000000000000000000000000..d54349b1caa95e98ffb71ba5e88aca4f5b71c17a GIT binary patch literal 38872 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 literal 0 HcmV?d00001 diff --git a/starstuff/root/boot/untether b/starstuff/root/boot/untether deleted file mode 120000 index dd34c28..0000000 --- a/starstuff/root/boot/untether +++ /dev/null @@ -1 +0,0 @@ -../../../catalog/untether \ No newline at end of file diff --git a/starstuff/root/boot/untether b/starstuff/root/boot/untether new file mode 100755 index 0000000000000000000000000000000000000000..553dd900d599e85f443fef882133ba80541af161 GIT binary patch literal 8192 zcmeI1UrbYH6u`gR0x|_{rzYr{SrHWy;TA%LEo4Kc1p-c@%=kbogzm<#Vli3NC}ZOpjG4iOiuovRx7a1hs;!>q*ZZC|S)h#haF{f~xirCf z%0crqN0Qv!j4e`1)N9 zqFmCUIrzOoFeC=LLi{#0l-w8g^TVw8d~p~&8@LR#33MUR_OMV)^M#>bgLVL7O(m$? zy?fWZz6v;D+o;mgxm|-NDRXsunzy}@))8wYPKk28<0D8!$FtY{1xnv4JPqz)p!dwkVAKb&hGj zyRnKc=GX_mbXob?x6Z$P7oGcxJ}5iJetxO<-MQ#!mDwRFjD6i>b`%{PEISQ0=FMfO z7RIA*t2Xw#bCj{p3Fa7qd=&j1G2I0hnu-%oWHzq#NX0UPJ{LJq1XIQNdci_Qs(b6S9y z{#?3H>X`A4YOZ_Tq&zS)MGII5-cQ;^Lmerf7Hfu@TZ~htf5=jz4^Js!oGF7TGc-WJ zXI8kJxRqc(_EHk>tne=mZsrE=sv1&u!y*Jk;?PWJjLoIhVr~G%mD@xjs!p0&_ zg~9&|>n@#%wTNuXrg&9@=&H6`zOb~~U46B-LN3kvj=#I>>hJr|d6tywq1#WLd4m&_N6 ze`UFKwc%RLUh{~*#Y;i)kVh8yL!Kaf3~i!cU<>$Ce*3LQdF=xP^2e0!j?#Do71 v;h7d$!#>@=Rq5QDrQEumt@MMP4Yj|_u<4(0Cx#dsFg9Rpz}Ue5VgvsG5bNHm literal 0 HcmV?d00001 diff --git a/starstuff/root/boot/white_loader b/starstuff/root/boot/white_loader deleted file mode 120000 index 5304de0..0000000 --- a/starstuff/root/boot/white_loader +++ /dev/null @@ -1 +0,0 @@ -../../../white/white_loader \ No newline at end of file diff --git a/starstuff/root/boot/white_loader b/starstuff/root/boot/white_loader new file mode 100755 index 0000000000000000000000000000000000000000..58adee5f77295ef17bc087d13a8176ff3d29226f GIT binary patch literal 34944 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 s3i&+*!m>`p@^>`X*Da&p{