am b707d72a: am 6efa9351: Merge "Don\'t use deprecated OpenSSL functions."
* commit 'b707d72a33c8e442cafb36f724245f1c9898fb36':
diff --git a/Loop.cpp b/Loop.cpp
index 11c114f..ca26093 100644
--- a/Loop.cpp
+++ b/Loop.cpp
@@ -35,6 +35,7 @@
#include <sysutils/SocketClient.h>
#include "Loop.h"
#include "Asec.h"
+#include "sehandle.h"
int Loop::dumpState(SocketClient *c) {
int i;
@@ -132,6 +133,7 @@
for (i = 0; i < LOOP_MAX; i++) {
struct loop_info64 li;
int rc;
+ char *secontext = NULL;
sprintf(filename, "/dev/block/loop%d", i);
@@ -141,12 +143,29 @@
*/
mode_t mode = 0660 | S_IFBLK;
unsigned int dev = (0xff & i) | ((i << 12) & 0xfff00000) | (7 << 8);
+
+ if (sehandle) {
+ rc = selabel_lookup(sehandle, &secontext, filename, S_IFBLK);
+ if (rc == 0)
+ setfscreatecon(secontext);
+ }
+
if (mknod(filename, mode, dev) < 0) {
if (errno != EEXIST) {
+ int sverrno = errno;
SLOGE("Error creating loop device node (%s)", strerror(errno));
+ if (secontext) {
+ freecon(secontext);
+ setfscreatecon(NULL);
+ }
+ errno = sverrno;
return -1;
}
}
+ if (secontext) {
+ freecon(secontext);
+ setfscreatecon(NULL);
+ }
if ((fd = open(filename, O_RDWR)) < 0) {
SLOGE("Unable to open %s (%s)", filename, strerror(errno));
diff --git a/Process.cpp b/Process.cpp
index ea5fbc7..08be28e 100644
--- a/Process.cpp
+++ b/Process.cpp
@@ -170,6 +170,10 @@
return result;
}
+extern "C" void vold_killProcessesWithOpenFiles(const char *path, int action) {
+ Process::killProcessesWithOpenFiles(path, action);
+}
+
/*
* Hunt down processes that have files open at the given mount point.
* action = 0 to just warn,
diff --git a/Process.h b/Process.h
index fc0c0b7..e745ca4 100644
--- a/Process.h
+++ b/Process.h
@@ -17,6 +17,8 @@
#ifndef _PROCESS_H
#define _PROCESS_H
+#ifdef __cplusplus
+
class Process {
public:
static void killProcessesWithOpenFiles(const char *path, int action);
@@ -32,4 +34,11 @@
static int pathMatchesMountPoint(const char *path, const char *mountPoint);
};
+extern "C" {
+#endif /* __cplusplus */
+ void vold_killProcessesWithOpenFiles(const char *path, int action);
+#ifdef __cplusplus
+}
+#endif
+
#endif
diff --git a/Volume.cpp b/Volume.cpp
index 0baf008..bfad29d 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -48,6 +48,7 @@
#include "Fat.h"
#include "Process.h"
#include "cryptfs.h"
+#include "sehandle.h"
extern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
extern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
@@ -219,13 +220,30 @@
}
int Volume::createDeviceNode(const char *path, int major, int minor) {
+ char *secontext = NULL;
mode_t mode = 0660 | S_IFBLK;
dev_t dev = (major << 8) | minor;
+ int rc;
+ if (sehandle) {
+ rc = selabel_lookup(sehandle, &secontext, path, S_IFBLK);
+ if (rc == 0)
+ setfscreatecon(secontext);
+ }
if (mknod(path, mode, dev) < 0) {
if (errno != EEXIST) {
+ int sverrno = errno;
+ if (secontext) {
+ freecon(secontext);
+ setfscreatecon(NULL);
+ }
+ errno = sverrno;
return -1;
}
}
+ if (secontext) {
+ setfscreatecon(NULL);
+ freecon(secontext);
+ }
return 0;
}
diff --git a/cryptfs.c b/cryptfs.c
index 566eef9..9fba014 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -40,6 +40,7 @@
#include <ext4.h>
#include <linux/kdev_t.h>
#include <fs_mgr.h>
+#include <time.h>
#include "cryptfs.h"
#define LOG_TAG "Cryptfs"
#include "cutils/log.h"
@@ -53,6 +54,7 @@
#include "ext4_utils.h"
#include "f2fs_sparseblock.h"
#include "CheckBattery.h"
+#include "Process.h"
#include <hardware/keymaster.h>
@@ -1427,32 +1429,46 @@
return encrypt_master_key(passwd, salt, key_buf, master_key, crypt_ftr);
}
-static int wait_and_unmount(char *mountpoint)
+static int wait_and_unmount(char *mountpoint, bool kill)
{
- int i, rc;
+ int i, err, rc;
#define WAIT_UNMOUNT_COUNT 20
/* Now umount the tmpfs filesystem */
for (i=0; i<WAIT_UNMOUNT_COUNT; i++) {
- if (umount(mountpoint)) {
- if (errno == EINVAL) {
- /* EINVAL is returned if the directory is not a mountpoint,
- * i.e. there is no filesystem mounted there. So just get out.
- */
- break;
- }
- sleep(1);
- i++;
- } else {
- break;
+ if (umount(mountpoint) == 0) {
+ break;
}
+
+ if (errno == EINVAL) {
+ /* EINVAL is returned if the directory is not a mountpoint,
+ * i.e. there is no filesystem mounted there. So just get out.
+ */
+ break;
+ }
+
+ err = errno;
+
+ /* If allowed, be increasingly aggressive before the last two retries */
+ if (kill) {
+ if (i == (WAIT_UNMOUNT_COUNT - 3)) {
+ SLOGW("sending SIGHUP to processes with open files\n");
+ vold_killProcessesWithOpenFiles(mountpoint, 1);
+ } else if (i == (WAIT_UNMOUNT_COUNT - 2)) {
+ SLOGW("sending SIGKILL to processes with open files\n");
+ vold_killProcessesWithOpenFiles(mountpoint, 2);
+ }
+ }
+
+ sleep(1);
}
if (i < WAIT_UNMOUNT_COUNT) {
SLOGD("unmounting %s succeeded\n", mountpoint);
rc = 0;
} else {
- SLOGE("unmounting %s failed\n", mountpoint);
+ vold_killProcessesWithOpenFiles(mountpoint, 0);
+ SLOGE("unmounting %s failed: %s\n", mountpoint, strerror(err));
rc = -1;
}
@@ -1586,7 +1602,7 @@
return -1;
}
- if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) {
+ if (! (rc = wait_and_unmount(DATA_MNT_POINT, true)) ) {
/* If ro.crypto.readonly is set to 1, mount the decrypted
* filesystem readonly. This is used when /data is mounted by
* recovery mode.
@@ -1783,6 +1799,9 @@
if (rc == 0) {
crypt_ftr->failed_decrypt_count = 0;
+ if (orig_failed_decrypt_count != 0) {
+ put_crypt_ftr_and_key(crypt_ftr);
+ }
/* Save the name of the crypto block device
* so we can mount it when restarting the framework. */
@@ -1877,7 +1896,10 @@
create_crypto_blk_dev(&sd_crypt_ftr, saved_master_key, real_blkdev,
crypto_blkdev, label);
- stat(crypto_blkdev, &statbuf);
+ if (stat(crypto_blkdev, &statbuf) < 0) {
+ SLOGE("Error get stat for crypto_blkdev %s. err=%d(%s)\n",
+ crypto_blkdev, errno, strerror(errno));
+ }
*new_major = MAJOR(statbuf.st_rdev);
*new_minor = MINOR(statbuf.st_rdev);
@@ -1910,6 +1932,68 @@
return 0;
}
+/*
+ * TODO - transition patterns to new format in calling code
+ * and remove this vile hack, and the use of hex in
+ * the password passing code.
+ *
+ * Patterns are passed in zero based (i.e. the top left dot
+ * is represented by zero, the top middle one etc), but we want
+ * to store them '1' based.
+ * This is to allow us to migrate the calling code to use this
+ * convention. It also solves a nasty problem whereby scrypt ignores
+ * trailing zeros, so patterns ending at the top left could be
+ * truncated, and similarly, you could add the top left to any
+ * pattern and still match.
+ * adjust_passwd is a hack function that returns the alternate representation
+ * if the password appears to be a pattern (hex numbers all less than 09)
+ * If it succeeds we need to try both, and in particular try the alternate
+ * first. If the original matches, then we need to update the footer
+ * with the alternate.
+ * All code that accepts passwords must adjust them first. Since
+ * cryptfs_check_passwd is always the first function called after a migration
+ * (and indeed on any boot) we only need to do the double try in this
+ * function.
+ */
+char* adjust_passwd(const char* passwd)
+{
+ size_t index, length;
+
+ if (!passwd) {
+ return 0;
+ }
+
+ // Check even length. Hex encoded passwords are always
+ // an even length, since each character encodes to two characters.
+ length = strlen(passwd);
+ if (length % 2) {
+ SLOGW("Password not correctly hex encoded.");
+ return 0;
+ }
+
+ // Check password is old-style pattern - a collection of hex
+ // encoded bytes less than 9 (00 through 08)
+ for (index = 0; index < length; index +=2) {
+ if (passwd[index] != '0'
+ || passwd[index + 1] < '0' || passwd[index + 1] > '8') {
+ return 0;
+ }
+ }
+
+ // Allocate room for adjusted passwd and null terminate
+ char* adjusted = malloc(length + 1);
+ adjusted[length] = 0;
+
+ // Add 0x31 ('1') to each character
+ for (index = 0; index < length; index += 2) {
+ // output is 31 through 39 so set first byte to three, second to src + 1
+ adjusted[index] = '3';
+ adjusted[index + 1] = passwd[index + 1] + 1;
+ }
+
+ return adjusted;
+}
+
int cryptfs_check_passwd(char *passwd)
{
struct crypt_mnt_ftr crypt_ftr;
@@ -1919,8 +2003,31 @@
if (rc)
return rc;
- rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
- DATA_MNT_POINT, "userdata");
+ char* adjusted_passwd = adjust_passwd(passwd);
+ if (adjusted_passwd) {
+ int failed_decrypt_count = crypt_ftr.failed_decrypt_count;
+ rc = test_mount_encrypted_fs(&crypt_ftr, adjusted_passwd,
+ DATA_MNT_POINT, "userdata");
+
+ // Maybe the original one still works?
+ if (rc) {
+ // Don't double count this failure
+ crypt_ftr.failed_decrypt_count = failed_decrypt_count;
+ rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
+ DATA_MNT_POINT, "userdata");
+ if (!rc) {
+ // cryptfs_changepw also adjusts so pass original
+ // Note that adjust_passwd only recognises patterns
+ // so we can safely use CRYPT_TYPE_PATTERN
+ SLOGI("Updating pattern to new format");
+ cryptfs_changepw(CRYPT_TYPE_PATTERN, passwd);
+ }
+ }
+ free(adjusted_passwd);
+ } else {
+ rc = test_mount_encrypted_fs(&crypt_ftr, passwd,
+ DATA_MNT_POINT, "userdata");
+ }
if (rc == 0 && crypt_ftr.crypt_type != CRYPT_TYPE_DEFAULT) {
cryptfs_clear_password();
@@ -1966,6 +2073,11 @@
/* If the device has no password, then just say the password is valid */
rc = 0;
} else {
+ char* adjusted_passwd = adjust_passwd(passwd);
+ if (adjusted_passwd) {
+ passwd = adjusted_passwd;
+ }
+
decrypt_master_key(passwd, decrypted_master_key, &crypt_ftr, 0, 0);
if (!memcmp(decrypted_master_key, saved_master_key, crypt_ftr.keysize)) {
/* They match, the password is correct */
@@ -1975,6 +2087,8 @@
sleep(1);
rc = 1;
}
+
+ free(adjusted_passwd);
}
return rc;
@@ -2123,32 +2237,59 @@
data->cur_pct = data->new_pct;
snprintf(buf, sizeof(buf), "%" PRId64, data->cur_pct);
property_set("vold.encrypt_progress", buf);
- SLOGI("Encrypted %" PRId64 " percent of drive", data->cur_pct);
}
if (data->cur_pct >= 5) {
- double elapsed_time = difftime(time(NULL), data->time_started);
- off64_t remaining_blocks = data->tot_used_blocks
- - data->used_blocks_already_done;
- int remaining_time = (int)(elapsed_time * remaining_blocks
- / data->used_blocks_already_done);
+ struct timespec time_now;
+ if (clock_gettime(CLOCK_MONOTONIC, &time_now)) {
+ SLOGW("Error getting time");
+ } else {
+ double elapsed_time = difftime(time_now.tv_sec, data->time_started);
+ off64_t remaining_blocks = data->tot_used_blocks
+ - data->used_blocks_already_done;
+ int remaining_time = (int)(elapsed_time * remaining_blocks
+ / data->used_blocks_already_done);
- // Change time only if not yet set, lower, or a lot higher for
- // best user experience
- if (data->remaining_time == -1
- || remaining_time < data->remaining_time
- || remaining_time > data->remaining_time + 60) {
- char buf[8];
- snprintf(buf, sizeof(buf), "%d", remaining_time);
- property_set("vold.encrypt_time_remaining", buf);
-
- SLOGI("Encrypted %" PRId64 " percent of drive, %d seconds to go",
- data->cur_pct, remaining_time);
- data->remaining_time = remaining_time;
+ // Change time only if not yet set, lower, or a lot higher for
+ // best user experience
+ if (data->remaining_time == -1
+ || remaining_time < data->remaining_time
+ || remaining_time > data->remaining_time + 60) {
+ char buf[8];
+ snprintf(buf, sizeof(buf), "%d", remaining_time);
+ property_set("vold.encrypt_time_remaining", buf);
+ data->remaining_time = remaining_time;
+ }
}
}
}
+static void log_progress(struct encryptGroupsData const* data, bool completed)
+{
+ // Precondition - if completed data = 0 else data != 0
+
+ // Track progress so we can skip logging blocks
+ static off64_t offset = -1;
+
+ // Need to close existing 'Encrypting from' log?
+ if (completed || (offset != -1 && data->offset != offset)) {
+ SLOGI("Encrypted to sector %" PRId64,
+ offset / info.block_size * CRYPT_SECTOR_SIZE);
+ offset = -1;
+ }
+
+ // Need to start new 'Encrypting from' log?
+ if (!completed && offset != data->offset) {
+ SLOGI("Encrypting from sector %" PRId64,
+ data->offset / info.block_size * CRYPT_SECTOR_SIZE);
+ }
+
+ // Update offset
+ if (!completed) {
+ offset = data->offset + (off64_t)data->count * info.block_size;
+ }
+}
+
static int flush_outstanding_data(struct encryptGroupsData* data)
{
if (data->count == 0) {
@@ -2172,8 +2313,7 @@
data->crypto_blkdev);
return -1;
} else {
- SLOGI("Encrypted %d blocks at sector %" PRId64,
- data->count, data->offset / info.block_size * CRYPT_SECTOR_SIZE);
+ log_progress(data, false);
}
data->count = 0;
@@ -2262,6 +2402,7 @@
rc = 0;
errout:
+ log_progress(0, true);
free(data->buffer);
free(block_bitmap);
return rc;
@@ -2288,27 +2429,27 @@
data.crypto_blkdev = crypto_blkdev;
if ( (data.realfd = open(real_blkdev, O_RDWR)) < 0) {
- SLOGE("Error opening real_blkdev %s for inplace encrypt\n",
- real_blkdev);
+ SLOGE("Error opening real_blkdev %s for inplace encrypt. err=%d(%s)\n",
+ real_blkdev, errno, strerror(errno));
rc = -1;
goto errout;
}
if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
- SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n",
- crypto_blkdev);
- rc = -1;
+ SLOGE("Error opening crypto_blkdev %s for ext4 inplace encrypt. err=%d(%s)\n",
+ crypto_blkdev, errno, strerror(errno));
+ rc = ENABLE_INPLACE_ERR_DEV;
goto errout;
}
if (setjmp(setjmp_env)) {
- SLOGE("Reading extent caused an exception");
+ SLOGE("Reading ext4 extent caused an exception\n");
rc = -1;
goto errout;
}
if (read_ext(data.realfd, 0) != 0) {
- SLOGE("Failed to read extent");
+ SLOGE("Failed to read ext4 extent\n");
rc = -1;
goto errout;
}
@@ -2317,7 +2458,7 @@
data.tot_numblocks = tot_size / CRYPT_SECTORS_PER_BUFSIZE;
data.blocks_already_done = *size_already_done / CRYPT_SECTORS_PER_BUFSIZE;
- SLOGI("Encrypting filesystem in place...");
+ SLOGI("Encrypting ext4 filesystem in place...");
data.tot_used_blocks = data.numblocks;
for (i = 0; i < aux_info.groups; ++i) {
@@ -2326,7 +2467,13 @@
data.one_pct = data.tot_used_blocks / 100;
data.cur_pct = 0;
- data.time_started = time(NULL);
+
+ struct timespec time_started = {0};
+ if (clock_gettime(CLOCK_MONOTONIC, &time_started)) {
+ SLOGW("Error getting time at start");
+ // Note - continue anyway - we'll run with 0
+ }
+ data.time_started = time_started.tv_sec;
data.remaining_time = -1;
rc = encrypt_groups(&data);
@@ -2345,6 +2492,30 @@
return rc;
}
+static void log_progress_f2fs(u64 block, bool completed)
+{
+ // Precondition - if completed data = 0 else data != 0
+
+ // Track progress so we can skip logging blocks
+ static u64 last_block = (u64)-1;
+
+ // Need to close existing 'Encrypting from' log?
+ if (completed || (last_block != (u64)-1 && block != last_block + 1)) {
+ SLOGI("Encrypted to block %" PRId64, last_block);
+ last_block = -1;
+ }
+
+ // Need to start new 'Encrypting from' log?
+ if (!completed && (last_block == (u64)-1 || block != last_block + 1)) {
+ SLOGI("Encrypting from block %" PRId64, block);
+ }
+
+ // Update offset
+ if (!completed) {
+ last_block = block;
+ }
+}
+
static int encrypt_one_block_f2fs(u64 pos, void *data)
{
struct encryptGroupsData *priv_dat = (struct encryptGroupsData *)data;
@@ -2355,15 +2526,15 @@
off64_t offset = pos * CRYPT_INPLACE_BUFSIZE;
if (pread64(priv_dat->realfd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
- SLOGE("Error reading real_blkdev %s for inplace encrypt", priv_dat->crypto_blkdev);
+ SLOGE("Error reading real_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev);
return -1;
}
if (pwrite64(priv_dat->cryptofd, priv_dat->buffer, CRYPT_INPLACE_BUFSIZE, offset) <= 0) {
- SLOGE("Error writing crypto_blkdev %s for inplace encrypt", priv_dat->crypto_blkdev);
+ SLOGE("Error writing crypto_blkdev %s for f2fs inplace encrypt", priv_dat->crypto_blkdev);
return -1;
} else {
- SLOGD("Encrypted block %"PRIu64, pos);
+ log_progress_f2fs(pos, false);
}
return 0;
@@ -2379,10 +2550,10 @@
u32 i;
struct encryptGroupsData data;
struct f2fs_info *f2fs_info = NULL;
- int rc = -1;
+ int rc = ENABLE_INPLACE_ERR_OTHER;
if (previously_encrypted_upto > *size_already_done) {
SLOGD("Not fast encrypting since resuming part way through");
- return -1;
+ return ENABLE_INPLACE_ERR_OTHER;
}
memset(&data, 0, sizeof(data));
data.real_blkdev = real_blkdev;
@@ -2390,13 +2561,14 @@
data.realfd = -1;
data.cryptofd = -1;
if ( (data.realfd = open64(real_blkdev, O_RDWR)) < 0) {
- SLOGE("Error opening real_blkdev %s for inplace encrypt\n",
+ SLOGE("Error opening real_blkdev %s for f2fs inplace encrypt\n",
real_blkdev);
goto errout;
}
if ( (data.cryptofd = open64(crypto_blkdev, O_WRONLY)) < 0) {
- SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n",
- crypto_blkdev);
+ SLOGE("Error opening crypto_blkdev %s for f2fs inplace encrypt. err=%d(%s)\n",
+ crypto_blkdev, errno, strerror(errno));
+ rc = ENABLE_INPLACE_ERR_DEV;
goto errout;
}
@@ -2427,7 +2599,8 @@
rc = run_on_used_blocks(data.blocks_already_done, f2fs_info, &encrypt_one_block_f2fs, &data);
if (rc) {
- SLOGE("Error in running over blocks");
+ SLOGE("Error in running over f2fs blocks");
+ rc = ENABLE_INPLACE_ERR_OTHER;
goto errout;
}
@@ -2438,6 +2611,7 @@
if (rc)
SLOGE("Failed to encrypt f2fs filesystem on %s", real_blkdev);
+ log_progress_f2fs(0, true);
free(f2fs_info);
free(data.buffer);
close(data.realfd);
@@ -2453,20 +2627,21 @@
{
int realfd, cryptofd;
char *buf[CRYPT_INPLACE_BUFSIZE];
- int rc = -1;
+ int rc = ENABLE_INPLACE_ERR_OTHER;
off64_t numblocks, i, remainder;
off64_t one_pct, cur_pct, new_pct;
off64_t blocks_already_done, tot_numblocks;
if ( (realfd = open(real_blkdev, O_RDONLY)) < 0) {
SLOGE("Error opening real_blkdev %s for inplace encrypt\n", real_blkdev);
- return -1;
+ return ENABLE_INPLACE_ERR_OTHER;
}
if ( (cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
- SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n", crypto_blkdev);
+ SLOGE("Error opening crypto_blkdev %s for inplace encrypt. err=%d(%s)\n",
+ crypto_blkdev, errno, strerror(errno));
close(realfd);
- return -1;
+ return ENABLE_INPLACE_ERR_DEV;
}
/* This is pretty much a simple loop of reading 4K, and writing 4K.
@@ -2565,11 +2740,13 @@
return rc;
}
+/* returns on of the ENABLE_INPLACE_* return codes */
static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev,
off64_t size, off64_t *size_already_done,
off64_t tot_size,
off64_t previously_encrypted_upto)
{
+ int rc_ext4, rc_f2fs, rc_full;
if (previously_encrypted_upto) {
SLOGD("Continuing encryption from %" PRId64, previously_encrypted_upto);
}
@@ -2583,21 +2760,32 @@
* As is, cryptfs_enable_inplace_ext4 will fail on an f2fs partition, and
* then we will drop down to cryptfs_enable_inplace_f2fs.
* */
- if (cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev,
+ if ((rc_ext4 = cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev,
size, size_already_done,
- tot_size, previously_encrypted_upto) == 0) {
+ tot_size, previously_encrypted_upto)) == 0) {
return 0;
}
+ SLOGD("cryptfs_enable_inplace_ext4()=%d\n", rc_ext4);
- if (cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev,
+ if ((rc_f2fs = cryptfs_enable_inplace_f2fs(crypto_blkdev, real_blkdev,
size, size_already_done,
- tot_size, previously_encrypted_upto) == 0) {
+ tot_size, previously_encrypted_upto)) == 0) {
return 0;
}
+ SLOGD("cryptfs_enable_inplace_f2fs()=%d\n", rc_f2fs);
- return cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev,
+ rc_full = cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev,
size, size_already_done, tot_size,
previously_encrypted_upto);
+ SLOGD("cryptfs_enable_inplace_full()=%d\n", rc_full);
+
+ /* Hack for b/17898962, the following is the symptom... */
+ if (rc_ext4 == ENABLE_INPLACE_ERR_DEV
+ && rc_f2fs == ENABLE_INPLACE_ERR_DEV
+ && rc_full == ENABLE_INPLACE_ERR_DEV) {
+ return ENABLE_INPLACE_ERR_DEV;
+ }
+ return rc_full;
}
#define CRYPTO_ENABLE_WIPE 1
@@ -2677,6 +2865,12 @@
tot_encryption_size,
previously_encrypted_upto);
+ if (rc == ENABLE_INPLACE_ERR_DEV) {
+ /* Hack for b/17898962 */
+ SLOGE("cryptfs_enable: crypto block dev failure. Must reboot...\n");
+ cryptfs_reboot(reboot);
+ }
+
if (!rc) {
crypt_ftr->encrypted_upto = cur_encryption_done;
}
@@ -2826,13 +3020,13 @@
* above, so just unmount it now. We must do this _AFTER_ killing the framework,
* unlike the case for vold managed devices above.
*/
- if (wait_and_unmount(sd_mnt_point)) {
+ if (wait_and_unmount(sd_mnt_point, false)) {
goto error_shutting_down;
}
}
/* Now unmount the /data partition. */
- if (wait_and_unmount(DATA_MNT_POINT)) {
+ if (wait_and_unmount(DATA_MNT_POINT, false)) {
if (allow_reboot) {
goto error_shutting_down;
} else {
@@ -2999,7 +3193,8 @@
mkdir("/cache/recovery", 0700);
int fd = open("/cache/recovery/command", O_RDWR|O_CREAT|O_TRUNC, 0600);
if (fd >= 0) {
- write(fd, "--wipe_data", strlen("--wipe_data") + 1);
+ write(fd, "--wipe_data\n", strlen("--wipe_data\n") + 1);
+ write(fd, "--reason=cryptfs_enable_internal\n", strlen("--reason=cryptfs_enable_internal\n") + 1);
close(fd);
} else {
SLOGE("could not open /cache/recovery/command\n");
@@ -3048,7 +3243,15 @@
int cryptfs_enable(char *howarg, int type, char *passwd, int allow_reboot)
{
- return cryptfs_enable_internal(howarg, type, passwd, allow_reboot);
+ char* adjusted_passwd = adjust_passwd(passwd);
+ if (adjusted_passwd) {
+ passwd = adjusted_passwd;
+ }
+
+ int rc = cryptfs_enable_internal(howarg, type, passwd, allow_reboot);
+
+ free(adjusted_passwd);
+ return rc;
}
int cryptfs_enable_default(char *howarg, int allow_reboot)
@@ -3081,6 +3284,11 @@
crypt_ftr.crypt_type = crypt_type;
+ char* adjusted_passwd = adjust_passwd(newpw);
+ if (adjusted_passwd) {
+ newpw = adjusted_passwd;
+ }
+
encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD
: newpw,
crypt_ftr.salt,
@@ -3091,6 +3299,7 @@
/* save the key */
put_crypt_ftr_and_key(&crypt_ftr);
+ free(adjusted_passwd);
return 0;
}
diff --git a/cryptfs.h b/cryptfs.h
index 490bc11..66e0b4c 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -196,6 +196,11 @@
#define CRYPTO_COMPLETE_INCONSISTENT -3
#define CRYPTO_COMPLETE_CORRUPT -4
+/* Return values for cryptfs_enable_inplace*() */
+#define ENABLE_INPLACE_OK 0
+#define ENABLE_INPLACE_ERR_OTHER -1
+#define ENABLE_INPLACE_ERR_DEV -2 /* crypto_blkdev issue */
+
#ifdef __cplusplus
extern "C" {
#endif
diff --git a/main.cpp b/main.cpp
index d4b7d28..c07f48d 100644
--- a/main.cpp
+++ b/main.cpp
@@ -36,6 +36,7 @@
#include "NetlinkManager.h"
#include "DirectVolume.h"
#include "cryptfs.h"
+#include "sehandle.h"
static int process_config(VolumeManager *vm);
static void coldboot(const char *path);
@@ -43,6 +44,8 @@
#define FSTAB_PREFIX "/fstab."
struct fstab *fstab;
+struct selabel_handle *sehandle;
+
int main() {
VolumeManager *vm;
@@ -51,6 +54,10 @@
SLOGI("Vold 2.1 (the revenge) firing up");
+ sehandle = selinux_android_file_context_handle();
+ if (sehandle)
+ selinux_android_set_sehandle(sehandle);
+
mkdir("/dev/block/vold", 0755);
/* For when cryptfs checks and mounts an encrypted filesystem */
diff --git a/sehandle.h b/sehandle.h
new file mode 100644
index 0000000..f59d7eb
--- /dev/null
+++ b/sehandle.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _SEHANDLE_H
+#define _SEHANDLE_H
+
+#include <selinux/android.h>
+
+extern struct selabel_handle *sehandle;
+
+#endif