Merge "Fast ext4 encryption"
diff --git a/Android.mk b/Android.mk
index 2625b29..249681c 100644
--- a/Android.mk
+++ b/Android.mk
@@ -19,7 +19,6 @@
 	cryptfs.c
 
 common_c_includes := \
-	$(KERNEL_HEADERS) \
 	system/extras/ext4_utils \
 	external/openssl/include \
 	external/stlport/stlport \
@@ -82,7 +81,7 @@
 
 LOCAL_MODULE:= vdc
 
-LOCAL_C_INCLUDES := $(KERNEL_HEADERS)
+LOCAL_C_INCLUDES :=
 
 LOCAL_CFLAGS := 
 
diff --git a/Volume.cpp b/Volume.cpp
index 6dd1cc0..c290200 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -260,7 +260,7 @@
     // Only initialize the MBR if we are formatting the entire device
     if (formatEntireDevice) {
         sprintf(devicePath, "/dev/block/vold/%d:%d",
-                MAJOR(diskNode), MINOR(diskNode));
+                major(diskNode), minor(diskNode));
 
         if (initializeMbr(devicePath)) {
             SLOGE("Failed to initialize MBR (%s)", strerror(errno));
@@ -269,7 +269,7 @@
     }
 
     sprintf(devicePath, "/dev/block/vold/%d:%d",
-            MAJOR(partNode), MINOR(partNode));
+            major(partNode), minor(partNode));
 
     if (mDebug) {
         SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
@@ -415,8 +415,8 @@
     for (i = 0; i < n; i++) {
         char devicePath[255];
 
-        sprintf(devicePath, "/dev/block/vold/%d:%d", MAJOR(deviceNodes[i]),
-                MINOR(deviceNodes[i]));
+        sprintf(devicePath, "/dev/block/vold/%d:%d", major(deviceNodes[i]),
+                minor(deviceNodes[i]));
 
         SLOGI("%s being considered for volume %s\n", devicePath, getLabel());
 
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 2a9cd20..f9b7b6a 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -209,6 +209,12 @@
 int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
     char asecFileName[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("getAsecMountPath: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -233,6 +239,12 @@
 int VolumeManager::getAsecFilesystemPath(const char *id, char *buffer, int maxlen) {
     char asecFileName[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("getAsecFilesystemPath: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -258,6 +270,12 @@
     struct asec_superblock sb;
     memset(&sb, 0, sizeof(sb));
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("createAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     const bool wantFilesystem = strcmp(fstype, "none");
     bool usingExt4 = false;
     if (wantFilesystem) {
@@ -481,6 +499,12 @@
     char loopDevice[255];
     char mountPoint[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("finalizeAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -538,6 +562,12 @@
         return -1;
     }
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("fixupAsecPermissions: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -651,6 +681,18 @@
 
     const char *dir;
 
+    if (!isLegalAsecId(id1)) {
+        SLOGE("renameAsec: Invalid asec id1 \"%s\"", id1);
+        errno = EINVAL;
+        return -1;
+    }
+
+    if (!isLegalAsecId(id2)) {
+        SLOGE("renameAsec: Invalid asec id2 \"%s\"", id2);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id1, asecFilename1, sizeof(asecFilename1), &dir)) {
         SLOGE("Couldn't find ASEC %s", id1);
         return -1;
@@ -707,6 +749,12 @@
     char asecFileName[255];
     char mountPoint[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("unmountAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -831,6 +879,12 @@
     char asecFileName[255];
     char mountPoint[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("destroyAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -863,6 +917,38 @@
     return 0;
 }
 
+/*
+ * Legal ASEC ids consist of alphanumeric characters, '-',
+ * '_', or '.'. ".." is not allowed. The first or last character
+ * of the ASEC id cannot be '.' (dot).
+ */
+bool VolumeManager::isLegalAsecId(const char *id) const {
+    size_t i;
+    size_t len = strlen(id);
+
+    if (len == 0) {
+        return false;
+    }
+    if ((id[0] == '.') || (id[len - 1] == '.')) {
+        return false;
+    }
+
+    for (i = 0; i < len; i++) {
+        if (id[i] == '.') {
+            // i=0 is guaranteed never to have a dot. See above.
+            if (id[i-1] == '.') return false;
+            continue;
+        }
+        if (id[i] == '_' || id[i] == '-') continue;
+        if (id[i] >= 'a' && id[i] <= 'z') continue;
+        if (id[i] >= 'A' && id[i] <= 'Z') continue;
+        if (id[i] >= '0' && id[i] <= '9') continue;
+        return false;
+    }
+
+    return true;
+}
+
 bool VolumeManager::isAsecInDirectory(const char *dir, const char *asecName) const {
     int dirfd = open(dir, O_DIRECTORY);
     if (dirfd < 0) {
@@ -887,6 +973,12 @@
     const int idLen = strlen(id);
     char *asecName;
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("findAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (asprintf(&asecName, "%s.asec", id) < 0) {
         SLOGE("Couldn't allocate string to write ASEC name");
         return -1;
@@ -923,6 +1015,12 @@
     char asecFileName[255];
     char mountPoint[255];
 
+    if (!isLegalAsecId(id)) {
+        SLOGE("mountAsec: Invalid asec id \"%s\"", id);
+        errno = EINVAL;
+        return -1;
+    }
+
     if (findAsec(id, asecFileName, sizeof(asecFileName))) {
         SLOGE("Couldn't find ASEC %s", id);
         return -1;
@@ -1293,7 +1391,7 @@
     char nodepath[255];
     int written = snprintf(nodepath,
              sizeof(nodepath), "/dev/block/vold/%d:%d",
-             MAJOR(d), MINOR(d));
+             major(d), minor(d));
 
     if ((written < 0) || (size_t(written) >= sizeof(nodepath))) {
         SLOGE("shareVolume failed: couldn't construct nodepath");
@@ -1415,7 +1513,7 @@
         if ((d=(*i)->getShareDevice()) != (dev_t)0) {
             (*i)->getVolInfo(&vol_list[n]);
             snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
-                     "/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
+                     "/dev/block/vold/%d:%d", major(d), minor(d));
             n++;
         }
     }
diff --git a/VolumeManager.h b/VolumeManager.h
index 9d69d6a..cc8958d 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -154,6 +154,7 @@
     void readInitialState();
     bool isMountpointMounted(const char *mp);
     bool isAsecInDirectory(const char *dir, const char *asec) const;
+    bool isLegalAsecId(const char *id) const;
 };
 
 extern "C" {
diff --git a/fstrim.c b/fstrim.c
index 73705f9..2bd0577 100644
--- a/fstrim.c
+++ b/fstrim.c
@@ -116,7 +116,7 @@
     /* Release the wakelock that let us work */
     release_wake_lock(FSTRIM_WAKELOCK);
 
-    return (void *)ret;
+    return (void *)(uintptr_t)ret;
 }
 
 int fstrim_filesystems(void)