Move crypt commands to a different listener in vold

In order to prevent this bug from happening, we must allow vold cryptfs
commands to complete while a long running mount is underway.

While waiting for vold to be changed to a binder interface, we will simply
create two listeners, one for cryptfs and one for everything else.

Bug: 19197175
Change-Id: If74142aa81abd58f718a9de6c9e387f6ea442754
diff --git a/Android.mk b/Android.mk
index a1d5aa0..8912959 100644
--- a/Android.mk
+++ b/Android.mk
@@ -3,6 +3,7 @@
 common_src_files := \
 	VolumeManager.cpp \
 	CommandListener.cpp \
+	CryptCommandListener.cpp \
 	VoldCommand.cpp \
 	NetlinkManager.cpp \
 	NetlinkHandler.cpp \
diff --git a/CommandListener.cpp b/CommandListener.cpp
index 267b482..81318aa 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -57,7 +57,6 @@
     registerCmd(new AsecCmd());
     registerCmd(new ObbCmd());
     registerCmd(new StorageCmd());
-    registerCmd(new CryptfsCmd());
     registerCmd(new FstrimCmd());
 }
 
@@ -566,219 +565,6 @@
     return 0;
 }
 
-CommandListener::CryptfsCmd::CryptfsCmd() :
-                 VoldCommand("cryptfs") {
-}
-
-static int getType(const char* type)
-{
-    if (!strcmp(type, "default")) {
-        return CRYPT_TYPE_DEFAULT;
-    } else if (!strcmp(type, "password")) {
-        return CRYPT_TYPE_PASSWORD;
-    } else if (!strcmp(type, "pin")) {
-        return CRYPT_TYPE_PIN;
-    } else if (!strcmp(type, "pattern")) {
-        return CRYPT_TYPE_PATTERN;
-    } else {
-        return -1;
-    }
-}
-
-int CommandListener::CryptfsCmd::runCommand(SocketClient *cli,
-                                                      int argc, char **argv) {
-    if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
-        cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false);
-        return 0;
-    }
-
-    if (argc < 2) {
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
-        return 0;
-    }
-
-    int rc = 0;
-
-    if (!strcmp(argv[1], "checkpw")) {
-        if (argc != 3) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs checkpw <passwd>", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, 2);
-        rc = cryptfs_check_passwd(argv[2]);
-    } else if (!strcmp(argv[1], "restart")) {
-        if (argc != 2) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs restart", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = cryptfs_restart();
-    } else if (!strcmp(argv[1], "cryptocomplete")) {
-        if (argc != 2) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs cryptocomplete", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = cryptfs_crypto_complete();
-    } else if (!strcmp(argv[1], "enablecrypto")) {
-        const char* syntax = "Usage: cryptfs enablecrypto <wipe|inplace> "
-                             "default|password|pin|pattern [passwd]";
-        if ( (argc != 4 && argc != 5)
-             || (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace")) ) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
-            return 0;
-        }
-        dumpArgs(argc, argv, 4);
-
-        int tries;
-        for (tries = 0; tries < 2; ++tries) {
-            int type = getType(argv[3]);
-            if (type == -1) {
-                cli->sendMsg(ResponseCode::CommandSyntaxError, syntax,
-                             false);
-                return 0;
-            } else if (type == CRYPT_TYPE_DEFAULT) {
-              rc = cryptfs_enable_default(argv[2], /*allow_reboot*/false);
-            } else {
-                rc = cryptfs_enable(argv[2], type, argv[4],
-                                    /*allow_reboot*/false);
-            }
-
-            if (rc == 0) {
-                break;
-            } else if (tries == 0) {
-                Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
-            }
-        }
-    } else if (!strcmp(argv[1], "enablefilecrypto")) {
-        const char* syntax = "Usage: cryptfs enablefilecrypto";
-        if (argc != 2) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = cryptfs_enable_file();
-    } else if (!strcmp(argv[1], "changepw")) {
-        const char* syntax = "Usage: cryptfs changepw "
-                             "default|password|pin|pattern [newpasswd]";
-        const char* password;
-        if (argc == 3) {
-            password = "";
-        } else if (argc == 4) {
-            password = argv[3];
-        } else {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
-            return 0;
-        }
-        int type = getType(argv[2]);
-        if (type == -1) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
-            return 0;
-        }
-        SLOGD("cryptfs changepw %s {}", argv[2]);
-        rc = cryptfs_changepw(type, password);
-    } else if (!strcmp(argv[1], "verifypw")) {
-        if (argc != 3) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false);
-            return 0;
-        }
-        SLOGD("cryptfs verifypw {}");
-        rc = cryptfs_verify_passwd(argv[2]);
-    } else if (!strcmp(argv[1], "getfield")) {
-        char *valbuf;
-        int valbuf_len = PROPERTY_VALUE_MAX;
-
-        if (argc != 3) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs getfield <fieldname>", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-
-        // Increase the buffer size until it is big enough for the field value stored.
-        while (1) {
-            valbuf = (char*)malloc(valbuf_len);
-            if (valbuf == NULL) {
-                cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", false);
-                return 0;
-            }
-            rc = cryptfs_getfield(argv[2], valbuf, valbuf_len);
-            if (rc != CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL) {
-                break;
-            }
-            free(valbuf);
-            valbuf_len *= 2;
-        }
-        if (rc == CRYPTO_GETFIELD_OK) {
-            cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false);
-        }
-        free(valbuf);
-    } else if (!strcmp(argv[1], "setfield")) {
-        if (argc != 4) {
-            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs setfield <fieldname> <value>", false);
-            return 0;
-        }
-        dumpArgs(argc, argv, -1);
-        rc = cryptfs_setfield(argv[2], argv[3]);
-    } else if (!strcmp(argv[1], "mountdefaultencrypted")) {
-        SLOGD("cryptfs mountdefaultencrypted");
-        dumpArgs(argc, argv, -1);
-        rc = cryptfs_mount_default_encrypted();
-    } else if (!strcmp(argv[1], "getpwtype")) {
-        SLOGD("cryptfs getpwtype");
-        dumpArgs(argc, argv, -1);
-        switch(cryptfs_get_password_type()) {
-        case CRYPT_TYPE_PASSWORD:
-            cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false);
-            return 0;
-        case CRYPT_TYPE_PATTERN:
-            cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false);
-            return 0;
-        case CRYPT_TYPE_PIN:
-            cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false);
-            return 0;
-        case CRYPT_TYPE_DEFAULT:
-            cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false);
-            return 0;
-        default:
-          /** @TODO better error and make sure handled by callers */
-            cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false);
-            return 0;
-        }
-    } else if (!strcmp(argv[1], "getpw")) {
-        SLOGD("cryptfs getpw");
-        dumpArgs(argc, argv, -1);
-        const char* password = cryptfs_get_password();
-        if (password) {
-            char* message = 0;
-            int size = asprintf(&message, "{{sensitive}} %s", password);
-            if (size != -1) {
-                cli->sendMsg(ResponseCode::CommandOkay, message, false);
-                memset(message, 0, size);
-                free (message);
-                return 0;
-            }
-        }
-        rc = -1;
-    } else if (!strcmp(argv[1], "clearpw")) {
-        SLOGD("cryptfs clearpw");
-        dumpArgs(argc, argv, -1);
-        cryptfs_clear_password();
-        rc = 0;
-    } else {
-        dumpArgs(argc, argv, -1);
-        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
-        return 0;
-    }
-
-    // Always report that the command succeeded and return the error code.
-    // The caller will check the return value to see what the error was.
-    char msg[255];
-    snprintf(msg, sizeof(msg), "%d", rc);
-    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
-
-    return 0;
-}
-
 CommandListener::FstrimCmd::FstrimCmd() :
                  VoldCommand("fstrim") {
 }
diff --git a/CommandListener.h b/CommandListener.h
index 8cc1a04..6ed099b 100644
--- a/CommandListener.h
+++ b/CommandListener.h
@@ -67,13 +67,6 @@
         int runCommand(SocketClient *c, int argc, char ** argv);
     };
 
-    class CryptfsCmd : public VoldCommand {
-    public:
-        CryptfsCmd();
-        virtual ~CryptfsCmd() {}
-        int runCommand(SocketClient *c, int argc, char ** argv);
-    };
-
     class FstrimCmd : public VoldCommand {
     public:
         FstrimCmd();
diff --git a/CryptCommandListener.cpp b/CryptCommandListener.cpp
new file mode 100644
index 0000000..2e46919
--- /dev/null
+++ b/CryptCommandListener.cpp
@@ -0,0 +1,304 @@
+/*
+ * Copyright (C) 2015 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 <stdlib.h>
+#include <sys/socket.h>
+#include <sys/types.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fs_mgr.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdint.h>
+#include <inttypes.h>
+
+#define LOG_TAG "VoldCryptCmdListener"
+
+#include <base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <cutils/sockets.h>
+
+#include <sysutils/SocketClient.h>
+#include <private/android_filesystem_config.h>
+
+#include "CryptCommandListener.h"
+#include "Process.h"
+#include "ResponseCode.h"
+#include "cryptfs.h"
+
+#define DUMP_ARGS 0
+
+CryptCommandListener::CryptCommandListener() :
+FrameworkListener("cryptd", true) {
+    registerCmd(new CryptfsCmd());
+}
+
+#if DUMP_ARGS
+void CryptCommandListener::dumpArgs(int argc, char **argv, int argObscure) {
+    char buffer[4096];
+    char *p = buffer;
+
+    memset(buffer, 0, sizeof(buffer));
+    int i;
+    for (i = 0; i < argc; i++) {
+        unsigned int len = strlen(argv[i]) + 1; // Account for space
+        if (i == argObscure) {
+            len += 2; // Account for {}
+        }
+        if (((p - buffer) + len) < (sizeof(buffer)-1)) {
+            if (i == argObscure) {
+                *p++ = '{';
+                *p++ = '}';
+                *p++ = ' ';
+                continue;
+            }
+            strcpy(p, argv[i]);
+            p+= strlen(argv[i]);
+            if (i != (argc -1)) {
+                *p++ = ' ';
+            }
+        }
+    }
+    SLOGD("%s", buffer);
+}
+#else
+void CryptCommandListener::dumpArgs(int /*argc*/, char ** /*argv*/, int /*argObscure*/) { }
+#endif
+
+int CryptCommandListener::sendGenericOkFail(SocketClient *cli, int cond) {
+    if (!cond) {
+        return cli->sendMsg(ResponseCode::CommandOkay, "Command succeeded", false);
+    } else {
+        return cli->sendMsg(ResponseCode::OperationFailed, "Command failed", false);
+    }
+}
+
+CryptCommandListener::CryptfsCmd::CryptfsCmd() :
+                 VoldCommand("cryptfs") {
+}
+
+static int getType(const char* type)
+{
+    if (!strcmp(type, "default")) {
+        return CRYPT_TYPE_DEFAULT;
+    } else if (!strcmp(type, "password")) {
+        return CRYPT_TYPE_PASSWORD;
+    } else if (!strcmp(type, "pin")) {
+        return CRYPT_TYPE_PIN;
+    } else if (!strcmp(type, "pattern")) {
+        return CRYPT_TYPE_PATTERN;
+    } else {
+        return -1;
+    }
+}
+
+int CryptCommandListener::CryptfsCmd::runCommand(SocketClient *cli,
+                                                 int argc, char **argv) {
+    if ((cli->getUid() != 0) && (cli->getUid() != AID_SYSTEM)) {
+        cli->sendMsg(ResponseCode::CommandNoPermission, "No permission to run cryptfs commands", false);
+        return 0;
+    }
+
+    if (argc < 2) {
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Missing Argument", false);
+        return 0;
+    }
+
+    int rc = 0;
+
+    if (!strcmp(argv[1], "checkpw")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs checkpw <passwd>", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, 2);
+        rc = cryptfs_check_passwd(argv[2]);
+    } else if (!strcmp(argv[1], "restart")) {
+        if (argc != 2) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs restart", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_restart();
+    } else if (!strcmp(argv[1], "cryptocomplete")) {
+        if (argc != 2) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs cryptocomplete", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_crypto_complete();
+    } else if (!strcmp(argv[1], "enablecrypto")) {
+        const char* syntax = "Usage: cryptfs enablecrypto <wipe|inplace> "
+                             "default|password|pin|pattern [passwd]";
+        if ( (argc != 4 && argc != 5)
+             || (strcmp(argv[2], "wipe") && strcmp(argv[2], "inplace")) ) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
+            return 0;
+        }
+        dumpArgs(argc, argv, 4);
+
+        int tries;
+        for (tries = 0; tries < 2; ++tries) {
+            int type = getType(argv[3]);
+            if (type == -1) {
+                cli->sendMsg(ResponseCode::CommandSyntaxError, syntax,
+                             false);
+                return 0;
+            } else if (type == CRYPT_TYPE_DEFAULT) {
+              rc = cryptfs_enable_default(argv[2], /*allow_reboot*/false);
+            } else {
+                rc = cryptfs_enable(argv[2], type, argv[4],
+                                    /*allow_reboot*/false);
+            }
+
+            if (rc == 0) {
+                break;
+            } else if (tries == 0) {
+                Process::killProcessesWithOpenFiles(DATA_MNT_POINT, SIGKILL);
+            }
+        }
+    } else if (!strcmp(argv[1], "enablefilecrypto")) {
+        const char* syntax = "Usage: cryptfs enablefilecrypto";
+        if (argc != 2) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_enable_file();
+    } else if (!strcmp(argv[1], "changepw")) {
+        const char* syntax = "Usage: cryptfs changepw "
+                             "default|password|pin|pattern [newpasswd]";
+        const char* password;
+        if (argc == 3) {
+            password = "";
+        } else if (argc == 4) {
+            password = argv[3];
+        } else {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
+            return 0;
+        }
+        int type = getType(argv[2]);
+        if (type == -1) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, syntax, false);
+            return 0;
+        }
+        SLOGD("cryptfs changepw %s {}", argv[2]);
+        rc = cryptfs_changepw(type, password);
+    } else if (!strcmp(argv[1], "verifypw")) {
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs verifypw <passwd>", false);
+            return 0;
+        }
+        SLOGD("cryptfs verifypw {}");
+        rc = cryptfs_verify_passwd(argv[2]);
+    } else if (!strcmp(argv[1], "getfield")) {
+        char *valbuf;
+        int valbuf_len = PROPERTY_VALUE_MAX;
+
+        if (argc != 3) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs getfield <fieldname>", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+
+        // Increase the buffer size until it is big enough for the field value stored.
+        while (1) {
+            valbuf = (char*)malloc(valbuf_len);
+            if (valbuf == NULL) {
+                cli->sendMsg(ResponseCode::OperationFailed, "Failed to allocate memory", false);
+                return 0;
+            }
+            rc = cryptfs_getfield(argv[2], valbuf, valbuf_len);
+            if (rc != CRYPTO_GETFIELD_ERROR_BUF_TOO_SMALL) {
+                break;
+            }
+            free(valbuf);
+            valbuf_len *= 2;
+        }
+        if (rc == CRYPTO_GETFIELD_OK) {
+            cli->sendMsg(ResponseCode::CryptfsGetfieldResult, valbuf, false);
+        }
+        free(valbuf);
+    } else if (!strcmp(argv[1], "setfield")) {
+        if (argc != 4) {
+            cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: cryptfs setfield <fieldname> <value>", false);
+            return 0;
+        }
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_setfield(argv[2], argv[3]);
+    } else if (!strcmp(argv[1], "mountdefaultencrypted")) {
+        SLOGD("cryptfs mountdefaultencrypted");
+        dumpArgs(argc, argv, -1);
+        rc = cryptfs_mount_default_encrypted();
+    } else if (!strcmp(argv[1], "getpwtype")) {
+        SLOGD("cryptfs getpwtype");
+        dumpArgs(argc, argv, -1);
+        switch(cryptfs_get_password_type()) {
+        case CRYPT_TYPE_PASSWORD:
+            cli->sendMsg(ResponseCode::PasswordTypeResult, "password", false);
+            return 0;
+        case CRYPT_TYPE_PATTERN:
+            cli->sendMsg(ResponseCode::PasswordTypeResult, "pattern", false);
+            return 0;
+        case CRYPT_TYPE_PIN:
+            cli->sendMsg(ResponseCode::PasswordTypeResult, "pin", false);
+            return 0;
+        case CRYPT_TYPE_DEFAULT:
+            cli->sendMsg(ResponseCode::PasswordTypeResult, "default", false);
+            return 0;
+        default:
+          /** @TODO better error and make sure handled by callers */
+            cli->sendMsg(ResponseCode::OpFailedStorageNotFound, "Error", false);
+            return 0;
+        }
+    } else if (!strcmp(argv[1], "getpw")) {
+        SLOGD("cryptfs getpw");
+        dumpArgs(argc, argv, -1);
+        const char* password = cryptfs_get_password();
+        if (password) {
+            char* message = 0;
+            int size = asprintf(&message, "{{sensitive}} %s", password);
+            if (size != -1) {
+                cli->sendMsg(ResponseCode::CommandOkay, message, false);
+                memset(message, 0, size);
+                free (message);
+                return 0;
+            }
+        }
+        rc = -1;
+    } else if (!strcmp(argv[1], "clearpw")) {
+        SLOGD("cryptfs clearpw");
+        dumpArgs(argc, argv, -1);
+        cryptfs_clear_password();
+        rc = 0;
+    } else {
+        dumpArgs(argc, argv, -1);
+        cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs cmd", false);
+        return 0;
+    }
+
+    // Always report that the command succeeded and return the error code.
+    // The caller will check the return value to see what the error was.
+    char msg[255];
+    snprintf(msg, sizeof(msg), "%d", rc);
+    cli->sendMsg(ResponseCode::CommandOkay, msg, false);
+
+    return 0;
+}
diff --git a/CryptCommandListener.h b/CryptCommandListener.h
new file mode 100644
index 0000000..1653239
--- /dev/null
+++ b/CryptCommandListener.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2015 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 _CRYPTCOMMANDLISTENER_H__
+#define _CRYPTCOMMANDLISTENER_H__
+
+#include <sysutils/FrameworkListener.h>
+#include <utils/Errors.h>
+#include "VoldCommand.h"
+
+class CryptCommandListener : public FrameworkListener {
+public:
+    CryptCommandListener();
+    virtual ~CryptCommandListener() {}
+
+private:
+    static void dumpArgs(int argc, char **argv, int argObscure);
+    static int sendGenericOkFail(SocketClient *cli, int cond);
+
+    class CryptfsCmd : public VoldCommand {
+    public:
+        CryptfsCmd();
+        virtual ~CryptfsCmd() {}
+        int runCommand(SocketClient *c, int argc, char ** argv);
+    };
+    int getSocket();
+};
+
+#endif
diff --git a/main.cpp b/main.cpp
index fb8ffc4..290093f 100644
--- a/main.cpp
+++ b/main.cpp
@@ -17,6 +17,7 @@
 #include "Disk.h"
 #include "VolumeManager.h"
 #include "CommandListener.h"
+#include "CryptCommandListener.h"
 #include "NetlinkManager.h"
 #include "cryptfs.h"
 #include "sehandle.h"
@@ -56,6 +57,7 @@
 
     VolumeManager *vm;
     CommandListener *cl;
+    CryptCommandListener *ccl;
     NetlinkManager *nm;
 
     parse_args(argc, argv);
@@ -67,6 +69,7 @@
 
     // Quickly throw a CLOEXEC on the socket we just inherited from init
     fcntl(android_get_control_socket("vold"), F_SETFD, FD_CLOEXEC);
+    fcntl(android_get_control_socket("cryptd"), F_SETFD, FD_CLOEXEC);
 
     mkdir("/dev/block/vold", 0755);
 
@@ -89,6 +92,7 @@
     }
 
     cl = new CommandListener();
+    ccl = new CryptCommandListener();
     vm->setBroadcaster((SocketListener *) cl);
     nm->setBroadcaster((SocketListener *) cl);
 
@@ -117,6 +121,11 @@
         exit(1);
     }
 
+    if (ccl->startListener()) {
+        PLOG(ERROR) << "Unable to start CryptCommandListener";
+        exit(1);
+    }
+
     // Eventually we'll become the monitoring thread
     while(1) {
         sleep(1000);
diff --git a/vdc.c b/vdc.c
index 764063c..c6b2c92 100644
--- a/vdc.c
+++ b/vdc.c
@@ -54,7 +54,12 @@
         exit(5);
     }
 
-    while ((sock = socket_local_client("vold",
+    const char* sockname = "vold";
+    if (!strcmp(argv[1], "cryptfs")) {
+        sockname = "cryptd";
+    }
+
+    while ((sock = socket_local_client(sockname,
                                  ANDROID_SOCKET_NAMESPACE_RESERVED,
                                  SOCK_STREAM)) < 0) {
         if(!wait_for_socket) {
@@ -74,6 +79,7 @@
 
 static int do_cmd(int sock, int argc, char **argv) {
     char final_cmd[255] = "0 "; /* 0 is a (now required) sequence number */
+
     int i;
     size_t ret;
 
@@ -166,4 +172,3 @@
     fprintf(stderr,
             "Usage: %s [--wait] <monitor>|<cmd> [arg1] [arg2...]\n", progname);
  }
-