]> git.saurik.com Git - cydia.git/commitdiff
Carefully set NSFileProtectionNone inside of /var.
authorJay Freeman (saurik) <saurik@saurik.com>
Sat, 25 Oct 2014 12:24:11 +0000 (05:24 -0700)
committerJay Freeman (saurik) <saurik@saurik.com>
Sat, 25 Oct 2014 12:48:34 +0000 (05:48 -0700)
.gitignore
Library/move.sh
makefile
postinst.mm
setnsfpn.cpp [new file with mode: 0644]

index f8fccd44dd6e38cd628e6ed45058c47176f0039d..9a6cc7c239e1ad8a50aa6d0d6aecdefd7100d836 100644 (file)
@@ -12,4 +12,5 @@ debs
 Images/
 Version.h
 cfversion
+setnsfpn
 bins
index 98d9986f6a51bf6914691f32ffc608cc7a548bef..7e737e3c4ffb41906d1253367fbacdf367e0bd30 100755 (executable)
@@ -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##*/}
 
index 8875c783b9f04c7cb84738bfa0ee01a3e3bca5b7..bae04cecfe824b291509ecc24fbf2cc8c360b2b3 100644 (file)
--- 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
index 405b3176ecbea26888247a32fcbdbcb738b2f7a9..bbef4c8aeeeb52bb90af221441431a0148970c83 100644 (file)
@@ -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 (file)
index 0000000..6dc80c7
--- /dev/null
@@ -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 <http://www.gnu.org/licenses/>.
+**/
+/* }}} */
+
+#include <fcntl.h>
+#include <dirent.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <errno.h>
+#include <string.h>
+#include <sys/stat.h>
+
+#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<const dirent *>(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);
+}