am 49dd24c2: am 1dc1fb4a: Merge "vold: suppress unused argument warning messages"
* commit '49dd24c238e86c57e97f919af7fbf8ee3d79b737':
vold: suppress unused argument warning messages
diff --git a/Android.mk b/Android.mk
index 9ad0edd..7f93229 100644
--- a/Android.mk
+++ b/Android.mk
@@ -14,7 +14,6 @@
Loop.cpp \
Devmapper.cpp \
ResponseCode.cpp \
- Xwarp.cpp \
VoldUtil.c \
fstrim.c \
cryptfs.c
diff --git a/CommandListener.cpp b/CommandListener.cpp
index ea18c1d..795c01c 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -34,7 +34,6 @@
#include "VolumeManager.h"
#include "ResponseCode.h"
#include "Process.h"
-#include "Xwarp.h"
#include "Loop.h"
#include "Devmapper.h"
#include "cryptfs.h"
@@ -49,7 +48,6 @@
registerCmd(new AsecCmd());
registerCmd(new ObbCmd());
registerCmd(new StorageCmd());
- registerCmd(new XwarpCmd());
registerCmd(new CryptfsCmd());
registerCmd(new FstrimCmd());
}
@@ -508,49 +506,6 @@
return 0;
}
-CommandListener::XwarpCmd::XwarpCmd() :
- VoldCommand("xwarp") {
-}
-
-int CommandListener::XwarpCmd::runCommand(SocketClient *cli,
- int argc, char **argv) {
- if (argc < 2) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
- return 0;
- }
-
- if (!strcmp(argv[1], "enable")) {
- if (Xwarp::enable()) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to enable xwarp", true);
- return 0;
- }
-
- cli->sendMsg(ResponseCode::CommandOkay, "Xwarp mirroring started", false);
- } else if (!strcmp(argv[1], "disable")) {
- if (Xwarp::disable()) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to disable xwarp", true);
- return 0;
- }
-
- cli->sendMsg(ResponseCode::CommandOkay, "Xwarp disabled", false);
- } else if (!strcmp(argv[1], "status")) {
- char msg[255];
- bool r;
- unsigned mirrorPos, maxSize;
-
- if (Xwarp::status(&r, &mirrorPos, &maxSize)) {
- cli->sendMsg(ResponseCode::OperationFailed, "Failed to get xwarp status", true);
- return 0;
- }
- snprintf(msg, sizeof(msg), "%s %u %u", (r ? "ready" : "not-ready"), mirrorPos, maxSize);
- cli->sendMsg(ResponseCode::XwarpStatusResult, msg, false);
- } else {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown storage cmd", false);
- }
-
- return 0;
-}
-
CommandListener::CryptfsCmd::CryptfsCmd() :
VoldCommand("cryptfs") {
}
@@ -596,7 +551,12 @@
return 0;
}
dumpArgs(argc, argv, 3);
- rc = cryptfs_enable(argv[2], argv[3]);
+ rc = cryptfs_enable(argv[2], argv[3], /*allow_reboot*/false);
+ if (rc) {
+ Process::killProcessesWithOpenFiles(DATA_MNT_POINT, 2);
+ rc = cryptfs_enable(argv[2], argv[3], true);
+ }
+
} else if (!strcmp(argv[1], "changepw")) {
if (argc != 3) {
cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs changepw <newpasswd>", false);
diff --git a/CommandListener.h b/CommandListener.h
index 8cc5b09..0bd51d2 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -65,13 +65,6 @@
int runCommand(SocketClient *c, int argc, char ** argv);
};
- class XwarpCmd : public VoldCommand {
- public:
- XwarpCmd();
- virtual ~XwarpCmd() {}
- int runCommand(SocketClient *c, int argc, char ** argv);
- };
-
class CryptfsCmd : public VoldCommand {
public:
CryptfsCmd();
diff --git a/ResponseCode.h b/ResponseCode.h
index 5e4c6fa..26ebfcd 100644
--- a/ResponseCode.h
+++ b/ResponseCode.h
@@ -33,7 +33,6 @@
static const int ShareStatusResult = 210;
static const int AsecPathResult = 211;
static const int ShareEnabledResult = 212;
- static const int XwarpStatusResult = 213;
// 400 series - The command was accepted but the requested action
// did not take place.
diff --git a/Xwarp.cpp b/Xwarp.cpp
deleted file mode 100644
index 2973ff8..0000000
--- a/Xwarp.cpp
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * Copyright (C) 2008 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.
- */
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <unistd.h>
-#include <errno.h>
-#include <string.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#define LOG_TAG "Vold"
-
-#include <cutils/log.h>
-
-#include "Xwarp.h"
-const char *Xwarp::XWARP_BACKINGFILE = "/mnt/secure/asec/xwarp.img";
-const char *Xwarp::XWARP_CFG = "/sys/fs/yaffs/mtd3/xwarp-backing-store";
-const char *Xwarp::XWARP_READY = "/sys/fs/yaffs/mtd3/xwarp-ready";
-const char *Xwarp::XWARP_MIRROR_STATUS = "/sys/fs/yaffs/mtd3/xwarp-mirror";
-
-int Xwarp::enable() {
- return doEnableDisable(true);
-}
-
-int Xwarp::disable() {
- return doEnableDisable(false);
-}
-
-int Xwarp::status(bool *ready, unsigned *mirrorPos, unsigned *maxSize) {
- FILE *fp;
-
- *ready = false;
- *mirrorPos = 0;
- *maxSize = 0;
- if (!(fp = fopen(XWARP_READY, "r"))) {
- return -1;
- }
-
- fscanf(fp, "%d", (int *) ready);
- fclose(fp);
-
- if (!(fp = fopen(XWARP_MIRROR_STATUS, "r"))) {
- return -1;
- }
-
- fscanf(fp, "%u %u", mirrorPos, maxSize);
- fclose(fp);
- return 0;
-}
-
-int Xwarp::doEnableDisable(bool enable) {
- const char *tmp;
- int fd = open(XWARP_CFG, O_WRONLY);
-
- if (fd < 0)
- return -1;
-
- tmp = (enable ? XWARP_BACKINGFILE : "");
-
- if (write(fd, tmp, strlen(tmp)+1) < 0) {
- SLOGE("Failed to write xwarp cfg (%s)", strerror(errno));
- close(fd);
- return -1;
- }
-
- close(fd);
- return 0;
-}
diff --git a/Xwarp.h b/Xwarp.h
deleted file mode 100644
index 918a843..0000000
--- a/Xwarp.h
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- * Copyright (C) 2008 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 _XWARP_H
-#define _XWARP_H
-
-#include <unistd.h>
-
-class Xwarp {
- static const char *XWARP_BACKINGFILE;
- static const char *XWARP_CFG;
- static const char *XWARP_READY;
- static const char *XWARP_MIRROR_STATUS;
-
-public:
- static int enable();
- static int disable();
- static int status(bool *ready, unsigned *mirrorPos, unsigned *maxSize);
-
-private:
- static int doEnableDisable(bool enable);
-};
-
-#endif
diff --git a/cryptfs.c b/cryptfs.c
index e545919..8c13e04 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -49,11 +49,13 @@
#include "VolumeManager.h"
#include "VoldUtil.h"
#include "crypto_scrypt.h"
+#include "ext4_utils.h"
+
+#define UNUSED __attribute__((unused))
#define UNUSED __attribute__((unused))
#define DM_CRYPT_BUF_SIZE 4096
-#define DATA_MNT_POINT "/data"
#define HASH_COUNT 2000
#define KEY_LEN_BYTES 16
@@ -1128,6 +1130,17 @@
}
if (! (rc = wait_and_unmount(DATA_MNT_POINT)) ) {
+ /* If ro.crypto.readonly is set to 1, mount the decrypted
+ * filesystem readonly. This is used when /data is mounted by
+ * recovery mode.
+ */
+ char ro_prop[PROPERTY_VALUE_MAX];
+ property_get("ro.crypto.readonly", ro_prop, "");
+ if (strlen(ro_prop) > 0 && atoi(ro_prop)) {
+ struct fstab_rec* rec = fs_mgr_get_entry_for_mount_point(fstab, DATA_MNT_POINT);
+ rec->flags |= MS_RDONLY;
+ }
+
/* If that succeeded, then mount the decrypted filesystem */
fs_mgr_do_mount(fstab, DATA_MNT_POINT, crypto_blkdev, 0);
@@ -1498,8 +1511,205 @@
#define CRYPT_INPLACE_BUFSIZE 4096
#define CRYPT_SECTORS_PER_BUFSIZE (CRYPT_INPLACE_BUFSIZE / 512)
-static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev, off64_t size,
- off64_t *size_already_done, off64_t tot_size)
+
+/* aligned 32K writes tends to make flash happy.
+ * SD card association recommends it.
+ */
+#define BLOCKS_AT_A_TIME 8
+
+struct encryptGroupsData
+{
+ int realfd;
+ int cryptofd;
+ off64_t numblocks;
+ off64_t one_pct, cur_pct, new_pct;
+ off64_t blocks_already_done, tot_numblocks;
+ char* real_blkdev, * crypto_blkdev;
+ int count;
+ off64_t offset;
+ char* buffer;
+};
+
+static void update_progress(struct encryptGroupsData* data)
+{
+ data->blocks_already_done++;
+ data->new_pct = data->blocks_already_done / data->one_pct;
+ if (data->new_pct > data->cur_pct) {
+ char buf[8];
+ data->cur_pct = data->new_pct;
+ snprintf(buf, sizeof(buf), "%lld", data->cur_pct);
+ property_set("vold.encrypt_progress", buf);
+ }
+}
+
+static int flush_outstanding_data(struct encryptGroupsData* data)
+{
+ if (data->count == 0) {
+ return 0;
+ }
+
+ SLOGV("Copying %d blocks at offset %llx", data->count, data->offset);
+
+ if (pread64(data->realfd, data->buffer,
+ info.block_size * data->count, data->offset)
+ <= 0) {
+ SLOGE("Error reading real_blkdev %s for inplace encrypt",
+ data->real_blkdev);
+ return -1;
+ }
+
+ if (pwrite64(data->cryptofd, data->buffer,
+ info.block_size * data->count, data->offset)
+ <= 0) {
+ SLOGE("Error writing crypto_blkdev %s for inplace encrypt",
+ data->crypto_blkdev);
+ return -1;
+ }
+
+ data->count = 0;
+ return 0;
+}
+
+static int encrypt_groups(struct encryptGroupsData* data)
+{
+ unsigned int i;
+ u8 *block_bitmap = 0;
+ unsigned int block;
+ off64_t ret;
+ int rc = -1;
+
+ data->buffer = malloc(info.block_size * BLOCKS_AT_A_TIME);
+ if (!data->buffer) {
+ SLOGE("Failed to allocate crypto buffer");
+ goto errout;
+ }
+
+ block_bitmap = malloc(info.block_size);
+ if (!block_bitmap) {
+ SLOGE("failed to allocate block bitmap");
+ goto errout;
+ }
+
+ for (i = 0; i < aux_info.groups; ++i) {
+ SLOGI("Encrypting group %d", i);
+
+ u32 first_block = aux_info.first_data_block + i * info.blocks_per_group;
+ u32 block_count = min(info.blocks_per_group,
+ aux_info.len_blocks - first_block);
+
+ off64_t offset = (u64)info.block_size
+ * aux_info.bg_desc[i].bg_block_bitmap;
+
+ ret = pread64(data->realfd, block_bitmap, info.block_size, offset);
+ if (ret != (int)info.block_size) {
+ SLOGE("failed to read all of block group bitmap %d", i);
+ goto errout;
+ }
+
+ offset = (u64)info.block_size * first_block;
+
+ data->count = 0;
+
+ for (block = 0; block < block_count; block++) {
+ update_progress(data);
+ if (bitmap_get_bit(block_bitmap, block)) {
+ if (data->count == 0) {
+ data->offset = offset;
+ }
+ data->count++;
+ } else {
+ if (flush_outstanding_data(data)) {
+ goto errout;
+ }
+ }
+
+ offset += info.block_size;
+
+ /* Write data if we are aligned or buffer size reached */
+ if (offset % (info.block_size * BLOCKS_AT_A_TIME) == 0
+ || data->count == BLOCKS_AT_A_TIME) {
+ if (flush_outstanding_data(data)) {
+ goto errout;
+ }
+ }
+ }
+ if (flush_outstanding_data(data)) {
+ goto errout;
+ }
+ }
+
+ rc = 0;
+
+errout:
+ free(data->buffer);
+ free(block_bitmap);
+ return rc;
+}
+
+static int cryptfs_enable_inplace_ext4(char *crypto_blkdev,
+ char *real_blkdev,
+ off64_t size,
+ off64_t *size_already_done,
+ off64_t tot_size)
+{
+ int i;
+ struct encryptGroupsData data;
+ int rc = -1;
+
+ memset(&data, 0, sizeof(data));
+ data.real_blkdev = real_blkdev;
+ 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);
+ goto errout;
+ }
+
+ if ( (data.cryptofd = open(crypto_blkdev, O_WRONLY)) < 0) {
+ SLOGE("Error opening crypto_blkdev %s for inplace encrypt\n",
+ crypto_blkdev);
+ goto errout;
+ }
+
+ if (setjmp(setjmp_env)) {
+ SLOGE("Reading extent caused an exception");
+ goto errout;
+ }
+
+ if (read_ext(data.realfd, 0) != 0) {
+ SLOGE("Failed to read extent");
+ goto errout;
+ }
+
+ data.numblocks = size / CRYPT_SECTORS_PER_BUFSIZE;
+ 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...");
+
+ data.one_pct = data.tot_numblocks / 100;
+ data.cur_pct = 0;
+
+ rc = encrypt_groups(&data);
+ if (rc) {
+ SLOGE("Error encrypting groups");
+ goto errout;
+ }
+
+ *size_already_done += size;
+ rc = 0;
+
+errout:
+ close(data.realfd);
+ close(data.cryptofd);
+
+ return rc;
+}
+
+static int cryptfs_enable_inplace_full(char *crypto_blkdev, char *real_blkdev,
+ off64_t size, off64_t *size_already_done,
+ off64_t tot_size)
{
int realfd, cryptofd;
char *buf[CRYPT_INPLACE_BUFSIZE];
@@ -1575,6 +1785,19 @@
return rc;
}
+static int cryptfs_enable_inplace(char *crypto_blkdev, char *real_blkdev,
+ off64_t size, off64_t *size_already_done,
+ off64_t tot_size)
+{
+ if (cryptfs_enable_inplace_ext4(crypto_blkdev, real_blkdev,
+ size, size_already_done, tot_size) == 0) {
+ return 0;
+ }
+
+ return cryptfs_enable_inplace_full(crypto_blkdev, real_blkdev,
+ size, size_already_done, tot_size);
+}
+
#define CRYPTO_ENABLE_WIPE 1
#define CRYPTO_ENABLE_INPLACE 2
@@ -1582,11 +1805,11 @@
static inline int should_encrypt(struct volume_info *volume)
{
- return (volume->flags & (VOL_ENCRYPTABLE | VOL_NONREMOVABLE)) ==
+ return (volume->flags & (VOL_ENCRYPTABLE | VOL_NONREMOVABLE)) ==
(VOL_ENCRYPTABLE | VOL_NONREMOVABLE);
}
-int cryptfs_enable(char *howarg, char *passwd)
+int cryptfs_enable(char *howarg, char *passwd, int allow_reboot)
{
int how = 0;
char crypto_blkdev[MAXPATHLEN], real_blkdev[MAXPATHLEN], sd_crypto_blkdev[MAXPATHLEN];
@@ -1607,7 +1830,7 @@
off64_t cur_encryption_done=0, tot_encryption_size=0;
property_get("ro.crypto.state", encrypted_state, "");
- if (strcmp(encrypted_state, "unencrypted")) {
+ if (!strcmp(encrypted_state, "encrypted")) {
SLOGE("Device is already running encrypted, aborting");
goto error_unencrypted;
}
@@ -1713,7 +1936,11 @@
/* Now unmount the /data partition. */
if (wait_and_unmount(DATA_MNT_POINT)) {
- goto error_shutting_down;
+ if (allow_reboot) {
+ goto error_shutting_down;
+ } else {
+ goto error_unencrypted;
+ }
}
/* Do extra work for a better UX when doing the long inplace encryption */
@@ -1767,7 +1994,7 @@
/* Make an encrypted master key */
if (create_encrypted_random_key(passwd, crypt_ftr.master_key, crypt_ftr.salt, &crypt_ftr)) {
SLOGE("Cannot create encrypted master key\n");
- goto error_unencrypted;
+ goto error_shutting_down;
}
/* Write the key to the end of the partition */
@@ -1839,7 +2066,7 @@
} else {
/* Shouldn't happen */
SLOGE("cryptfs_enable: internal error, unknown option\n");
- goto error_unencrypted;
+ goto error_shutting_down;
}
/* Undo the dm-crypt mapping whether we succeed or not */
diff --git a/cryptfs.h b/cryptfs.h
index bd44dfa..dc3ce3e 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -131,6 +131,8 @@
#define VOL_PRIMARY 0x4
#define VOL_PROVIDES_ASEC 0x8
+#define DATA_MNT_POINT "/data"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -141,7 +143,7 @@
int cryptfs_check_passwd(char *pw);
int cryptfs_verify_passwd(char *newpw);
int cryptfs_restart(void);
- int cryptfs_enable(char *flag, char *passwd);
+ int cryptfs_enable(char *flag, char *passwd, int allow_reboot);
int cryptfs_changepw(char *newpw);
int cryptfs_setup_volume(const char *label, int major, int minor,
char *crypto_dev_path, unsigned int max_pathlen,