From 82e370b360798dcc8cdf41f68744788e503bb8a2 Mon Sep 17 00:00:00 2001 From: "Jay Freeman (saurik)" Date: Sat, 25 Oct 2014 05:24:11 -0700 Subject: Carefully set NSFileProtectionNone inside of /var. --- .gitignore | 1 + Library/move.sh | 2 + makefile | 9 +++- postinst.mm | 15 ++++++ setnsfpn.cpp | 158 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 setnsfpn.cpp diff --git a/.gitignore b/.gitignore index f8fccd4..9a6cc7c 100644 --- a/.gitignore +++ b/.gitignore @@ -12,4 +12,5 @@ debs Images/ Version.h cfversion +setnsfpn bins diff --git a/Library/move.sh b/Library/move.sh index 98d9986..7e737e3 100755 --- a/Library/move.sh +++ b/Library/move.sh @@ -21,6 +21,8 @@ function mv_() { src=$1 mkdir -p /var/stash + /usr/libexec/cydia/setnsfpn /var/stash + tmp=$(mktemp -d /var/stash/_.XXXXXX) dst=${tmp}/${src##*/} diff --git a/makefile b/makefile index 8875c78..bae04ce 100644 --- a/makefile +++ b/makefile @@ -136,11 +136,15 @@ cfversion: cfversion.mm $(cycc) $(filter %.mm,$^) $(flags) $(link) -framework CoreFoundation @ldid -T0 -S $@ +setnsfpn: setnsfpn.cpp + $(cycc) $(filter %.cpp,$^) $(flags) $(link) + @ldid -T0 -S $@ + postinst: postinst.mm Sources.mm Sources.h CyteKit/stringWithUTF8Bytes.mm CyteKit/stringWithUTF8Bytes.h CyteKit/UCPlatform.h - $(cycc) $(filter %.mm,$^) $(flags) $(link) -framework CoreFoundation -framework Foundation -framework UIKit -lpcre + $(cycc) -std=c++11 $(filter %.mm,$^) $(flags) $(link) -framework CoreFoundation -framework Foundation -framework UIKit -lpcre @ldid -T0 -S $@ -debs/cydia_$(version)_iphoneos-arm.deb: MobileCydia preinst postinst cfversion $(images) $(shell find MobileCydia.app) cydia.control Library/firmware.sh Library/startup +debs/cydia_$(version)_iphoneos-arm.deb: MobileCydia preinst postinst cfversion setnsfpn $(images) $(shell find MobileCydia.app) cydia.control Library/firmware.sh Library/startup sudo rm -rf _ mkdir -p _/var/lib/cydia @@ -152,6 +156,7 @@ debs/cydia_$(version)_iphoneos-arm.deb: MobileCydia preinst postinst cfversion $ cp -a Library _/usr/libexec/cydia cp -a sysroot/usr/bin/du _/usr/libexec/cydia cp -a cfversion _/usr/libexec/cydia + cp -a setnsfpn _/usr/libexec/cydia mkdir -p _/Library cp -a LaunchDaemons _/Library/LaunchDaemons diff --git a/postinst.mm b/postinst.mm index 405b317..bbef4c8 100644 --- a/postinst.mm +++ b/postinst.mm @@ -24,6 +24,17 @@ void Finish(const char *finish) { fclose(fout); } +static bool FixProtections() { + for (const char *path : (const char *[]) {"/var/lib", "/var/cache", "/var/stash"}) { + mkdir(path, 0755); + if (system([[NSString stringWithFormat:@"/usr/libexec/cydia/setnsfpn %s", path] UTF8String]) != 0) { + fprintf(stderr, "failed to setnsfpn %s\n", path); + return false; + } + } + return true; +} + static void FixPermissions() { DIR *stash(opendir("/var/stash")); if (stash == NULL) @@ -125,6 +136,10 @@ int main(int argc, const char *argv[]) { NSAutoreleasePool *pool([[NSAutoreleasePool alloc] init]); + if (kCFCoreFoundationVersionNumber >= 1000) + if (!FixProtections()) + return 1; + size_t size; sysctlbyname("kern.osversion", NULL, &size, NULL, 0); char *osversion = new char[size]; diff --git a/setnsfpn.cpp b/setnsfpn.cpp new file mode 100644 index 0000000..6dc80c7 --- /dev/null +++ b/setnsfpn.cpp @@ -0,0 +1,158 @@ +/* Cydia - iPhone UIKit Front-End for Debian APT + * Copyright (C) 2008-2014 Jay Freeman (saurik) +*/ + +/* GNU General Public License, Version 3 {{{ */ +/* + * Cydia is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published + * by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * Cydia is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Cydia. If not, see . +**/ +/* }}} */ + +#include +#include +#include +#include +#include +#include +#include + +#define _syscall(expr) ({ typeof(expr) _value; for (;;) { \ + _value = (expr); \ + if ((long) _value != -1) \ + break; \ + if (errno != EINTR) { \ + perror(#expr); \ + return -1; \ + } \ +} _value; }) + +int $getdirentries(int, char *, int, long *) __asm("_getdirentries"); + +struct $dirent { + __uint32_t d_ino; + __uint16_t d_reclen; + __uint8_t d_type; + __uint8_t d_namlen; + char d_name[__DARWIN_MAXNAMLEN + 1]; +}; + +#define getdirentries $getdirentries +#define dirent $dirent + +enum Recurse { + RecurseYes, + RecurseNo, + RecurseMaybe, +}; + +struct File { + int fd_; + + File(int fd); + ~File(); + + operator int() const; +}; + +File::File(int fd) : + fd_(fd) +{ +} + +File::~File() { + close(fd_); +} + +File::operator int() const { + return fd_; +} + +static int setnsfpn(const char *path, size_t before, Recurse recurse) { + File fd(_syscall(open_dprotected_np(path, O_RDONLY | O_SYMLINK, 0, O_DP_GETRAWENCRYPTED))); + + if (recurse == RecurseMaybe) { + struct stat stat; + _syscall(fstat(fd, &stat)); + switch (stat.st_mode & S_IFMT) { + case S_IFLNK: + return 0; + default: + return -1; + + case S_IFDIR: + recurse = RecurseYes; + break; + case S_IFREG: + recurse = RecurseNo; + break; + } + } + + int mode(_syscall(fcntl(fd, F_GETPROTECTIONCLASS))); + if (mode != -1 && mode != 4) { + if (recurse == RecurseYes) { + long address(0); + + for (;;) { + char buffer[4096]; + int size(_syscall(getdirentries(fd, buffer, sizeof(buffer), &address))); + if (size == 0) + break; + + const char *next(buffer), *stop(next + size); + while (next != stop) { + const dirent *dir(reinterpret_cast(next)); + const char *name(dir->d_name); + size_t after(strlen(name)); + + if (false); + else if (after == 1 && name[0] == '.'); + else if (after == 2 && name[0] == '.' && name[1] == '.'); + else { + size_t both(before + 1 + after); + char sub[both + 1]; + memcpy(sub, path, before); + sub[before] = '/'; + memcpy(sub + before + 1, name, after); + sub[both] = '\0'; + + switch (dir->d_type) { + case DT_LNK: + break; + default: + return -1; + + case DT_DIR: + setnsfpn(sub, both, RecurseYes); + break; + case DT_REG: + setnsfpn(sub, both, RecurseNo); + break; + } + } + + next += dir->d_reclen; + } + } + } + + _syscall(fcntl(fd, F_SETPROTECTIONCLASS, 4)); + } + + return 0; +} + +int main(int argc, const char *argv[]) { + return setnsfpn(argv[1], strlen(argv[1]), RecurseMaybe); +} -- cgit v1.2.3