Merge "prevent ioctl_init() to write outside buffer"
diff --git a/Android.mk b/Android.mk
index f7e8170..20072b1 100644
--- a/Android.mk
+++ b/Android.mk
@@ -22,7 +22,6 @@
 common_c_includes := \
 	system/extras/ext4_utils \
 	system/extras/f2fs_utils \
-	external/openssl/include \
 	external/scrypt/lib/crypto \
 	frameworks/native/include \
 	system/security/keystore \
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 004cead..2e90ecb 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -619,6 +619,14 @@
                 Process::killProcessesWithOpenFiles(DATA_MNT_POINT, 2);
             }
         }
+    } else if (!strcmp(argv[1], "maybeenabledefaultcrypto")) {
+        if (argc != 2) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError,
+                         "Usage: cryptfs maybeenabledefaultcrypto", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_maybe_enable_default_crypto();
     } else if (!strcmp(argv[1], "changepw")) {
         const char* syntax = "Usage: cryptfs changepw "
                              "default|password|pin|pattern [newpasswd]";
diff --git a/Loop.cpp b/Loop.cpp
index ca26093..1ed5bd0 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -121,7 +121,7 @@
         errno = ENOENT;
         return -1;
     }
-    strncpy(buffer, filename, len -1);
+    strlcpy(buffer, filename, len);
     return 0;
 }
 
@@ -191,7 +191,7 @@
         return -1;
     }
 
-    strncpy(loopDeviceBuffer, filename, len -1);
+    strlcpy(loopDeviceBuffer, filename, len);
 
     int file_fd;
 
diff --git a/NetlinkManager.cpp b/NetlinkManager.cpp
index dbba303..d2e16b2 100644
--- a/NetlinkManager.cpp
+++ b/NetlinkManager.cpp
@@ -16,6 +16,7 @@
 
 #include <stdio.h>
 #include <errno.h>
+#include <string.h>
 
 #include <sys/socket.h>
 #include <sys/select.h>
diff --git a/Process.cpp b/Process.cpp
index b675436..cc06998 100644
--- a/Process.cpp
+++ b/Process.cpp
@@ -110,7 +110,7 @@
         if (readSymLink(path, link, sizeof(link)) && pathMatchesMountPoint(link, mountPoint)) {
             if (openFilename) {
                 memset(openFilename, 0, max);
-                strncpy(openFilename, link, max-1);
+                strlcpy(openFilename, link, max);
             }
             closedir(dir);
             return 1;
@@ -140,7 +140,7 @@
         if (path && pathMatchesMountPoint(path, mountPoint)) {
             if (openFilename) {
                 memset(openFilename, 0, max);
-                strncpy(openFilename, path, max-1);
+                strlcpy(openFilename, path, max);
             }
             fclose(file);
             return 1;
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a41e583..4c5bb58 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -1203,14 +1203,12 @@
     int dirfd = open(dir, O_DIRECTORY);
     if (dirfd < 0) {
         SLOGE("Couldn't open internal ASEC dir (%s)", strerror(errno));
-        return -1;
+        return false;
     }
 
-    bool ret = false;
-
-    if (!faccessat(dirfd, asecName, F_OK, AT_SYMLINK_NOFOLLOW)) {
-        ret = true;
-    }
+    struct stat sb;
+    bool ret = (fstatat(dirfd, asecName, &sb, AT_SYMLINK_NOFOLLOW) == 0)
+        && S_ISREG(sb.st_mode);
 
     close(dirfd);
 
diff --git a/cryptfs.c b/cryptfs.c
index f45a200..91879e3 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -36,6 +36,7 @@
 #include <string.h>
 #include <sys/mount.h>
 #include <openssl/evp.h>
+#include <openssl/sha.h>
 #include <errno.h>
 #include <ext4.h>
 #include <linux/kdev_t.h>
@@ -567,6 +568,7 @@
         /* Need to initialize the persistent data area */
         if (lseek64(fd, pdata_offset, SEEK_SET) == -1) {
             SLOGE("Cannot seek to persisent data offset\n");
+            free(pdata);
             return;
         }
         /* Write all zeros to the first copy, making it invalid */
@@ -581,6 +583,7 @@
         crypt_ftr->persist_data_offset[0] = pdata_offset;
         crypt_ftr->persist_data_offset[1] = pdata_offset + CRYPT_PERSIST_DATA_SIZE;
         crypt_ftr->minor_version = 1;
+        free(pdata);
     }
 
     if ((crypt_ftr->major_version == 1) && (crypt_ftr->minor_version == 1)) {
@@ -867,13 +870,13 @@
     }
 
     /* Write the new copy first, if successful, then erase the old copy */
-    if (lseek(fd, write_offset, SEEK_SET) < 0) {
+    if (lseek64(fd, write_offset, SEEK_SET) < 0) {
         SLOGE("Cannot seek to write persistent data");
         goto err2;
     }
     if (unix_write(fd, persist_data, crypt_ftr.persist_data_size) ==
         (int) crypt_ftr.persist_data_size) {
-        if (lseek(fd, erase_offset, SEEK_SET) < 0) {
+        if (lseek64(fd, erase_offset, SEEK_SET) < 0) {
             SLOGE("Cannot seek to erase previous persistent data");
             goto err2;
         }
@@ -3242,6 +3245,49 @@
                           DEFAULT_PASSWORD, allow_reboot);
 }
 
+static int device_is_force_encrypted() {
+    int ret = -1;
+    char value[PROP_VALUE_MAX];
+    ret = __system_property_get("ro.vold.forceencryption", value);
+    if (ret < 0)
+        return 0;
+    return strcmp(value, "1") ? 0 : 1;
+}
+
+int cryptfs_maybe_enable_default_crypto()
+{
+    // Enable default crypt if /forceencrypt or /encryptable and
+    // ro.vold.forceencrypt=1, else mount data and continue unencrypted
+    struct fstab_rec *fstab_rec = 0;
+    fstab_rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
+    if (!fstab_rec) {
+        SLOGE("Error getting fstab record");
+        return -1;
+    }
+
+    // See if we should encrypt?
+    if (      !fs_mgr_is_encryptable(fstab_rec)
+           || (!fs_mgr_is_force_encrypted(fstab_rec)
+               && !device_is_force_encrypted())) {
+        int rc = 0;
+
+        rc = fs_mgr_do_mount(fstab, DATA_MNT_POINT, fstab_rec->blk_device, 0);
+        property_set("vold.decrypt", "trigger_load_persist_props");
+
+        /* Create necessary paths on /data */
+        if (prep_data_fs()) {
+            return -1;
+        }
+
+        property_set("ro.crypto.state", "unencrypted");
+        property_set("vold.decrypt", "trigger_restart_framework");
+        SLOGD("Unencrypted - restart_framework\n");
+        return rc;
+    }
+
+    return cryptfs_enable_default("inplace", 0);
+}
+
 int cryptfs_changepw(int crypt_type, const char *newpw)
 {
     struct crypt_mnt_ftr crypt_ftr;
diff --git a/cryptfs.h b/cryptfs.h
index 66e0b4c..67592a5 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -27,7 +27,6 @@
  */
 
 #include <cutils/properties.h>
-#include <openssl/sha.h>
 
 /* The current cryptfs version */
 #define CURRENT_MAJOR_VERSION 1
@@ -84,6 +83,10 @@
 /* __le32 and __le16 defined in system/extras/ext4_utils/ext4_utils.h */
 #define __le8  unsigned char
 
+#if !defined(SHA256_DIGEST_LENGTH)
+#define SHA256_DIGEST_LENGTH 32
+#endif
+
 struct crypt_mnt_ftr {
   __le32 magic;         /* See above */
   __le16 major_version;
@@ -215,6 +218,7 @@
   int cryptfs_enable(char *flag, int type, char *passwd, int allow_reboot);
   int cryptfs_changepw(int type, const char *newpw);
   int cryptfs_enable_default(char *flag, int allow_reboot);
+  int cryptfs_maybe_enable_default_crypto();
   int cryptfs_setup_volume(const char *label, int major, int minor,
                            char *crypto_dev_path, unsigned int max_pathlen,
                            int *new_major, int *new_minor);
diff --git a/tests/Android.mk b/tests/Android.mk
index bcdcfca..f974e7f 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -5,8 +5,7 @@
 LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk
 
 LOCAL_C_INCLUDES := \
-    system/core/fs_mgr/include \
-    external/openssl/include \
+    system/core/fs_mgr/include
 
 LOCAL_SHARED_LIBRARIES := \
     liblog \
diff --git a/vdc.c b/vdc.c
index dcd2bc3..6927e92 100644
--- a/vdc.c
+++ b/vdc.c
@@ -145,8 +145,7 @@
                     int code;
                     char tmp[4];
 
-                    strncpy(tmp, buffer + offset, 3);
-                    tmp[3] = '\0';
+                    strlcpy(tmp, buffer + offset, sizeof(tmp));
                     code = atoi(tmp);
 
                     printf("%s\n", buffer + offset);