vold: cryptfs: Retry encryption after killing processes using /data
Currently, if a non-framework process or service is using /data,
unmounting will fail as nothing will kill it.
Instead of rebooting on unmount failure, we now kill all processes
using /data, then try one more time.
Bug: 11291208
Change-Id: I6c5276c78aa55965914ace96e1db74dc80fca3c1
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 0ac656b..e92c051 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -549,7 +549,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/cryptfs.c b/cryptfs.c
index 03d714e..7591f04 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -51,7 +51,6 @@
#include "crypto_scrypt.h"
#define DM_CRYPT_BUF_SIZE 4096
-#define DATA_MNT_POINT "/data"
#define HASH_COUNT 2000
#define KEY_LEN_BYTES 16
@@ -1576,7 +1575,7 @@
(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];
@@ -1597,7 +1596,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;
}
@@ -1703,7 +1702,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 */
@@ -1757,7 +1760,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 */
@@ -1829,7 +1832,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 162159e..e4010be 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -132,6 +132,8 @@
#define VOL_PRIMARY 0x4
#define VOL_PROVIDES_ASEC 0x8
+#define DATA_MNT_POINT "/data"
+
#ifdef __cplusplus
extern "C" {
#endif
@@ -142,7 +144,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,