vold: Add an optional wipe paramter to the volume format command
The new wipe option to the vold format command will invoke BLKDISCARD
on the partition before invoking newfs_msdos. This will be used whenever
a full wipe of the device is wanted, as this is more secure than just
doing newfs_msdos.
Bug: 9392982
Change-Id: Ie106f1b9cc70abc61206006d1821641c27c7ccae
diff --git a/Android.mk b/Android.mk
index 098c3d0..71113df 100644
--- a/Android.mk
+++ b/Android.mk
@@ -15,6 +15,7 @@
Devmapper.cpp \
ResponseCode.cpp \
Xwarp.cpp \
+ VoldUtil.c \
fstrim.c \
cryptfs.c
diff --git a/CommandListener.cpp b/CommandListener.cpp
index f306527..5de920f 100644
--- a/CommandListener.cpp
+++ b/CommandListener.cpp
@@ -162,11 +162,16 @@
}
rc = vm->unmountVolume(argv[2], force, revert);
} else if (!strcmp(argv[1], "format")) {
- if (argc != 3) {
- cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path>", false);
+ if (argc < 3 || argc > 4 ||
+ (argc == 4 && strcmp(argv[3], "wipe"))) {
+ cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format <path> [wipe]", false);
return 0;
}
- rc = vm->formatVolume(argv[2]);
+ bool wipe = false;
+ if (argc >= 4 && !strcmp(argv[3], "wipe")) {
+ wipe = true;
+ }
+ rc = vm->formatVolume(argv[2], wipe);
} else if (!strcmp(argv[1], "share")) {
if (argc != 4) {
cli->sendMsg(ResponseCode::CommandSyntaxError,
diff --git a/Fat.cpp b/Fat.cpp
index 807f440..c967a90 100644
--- a/Fat.cpp
+++ b/Fat.cpp
@@ -30,6 +30,8 @@
#include <sys/mman.h>
#include <sys/mount.h>
#include <sys/wait.h>
+#include <linux/fs.h>
+#include <sys/ioctl.h>
#include <linux/kdev_t.h>
@@ -167,12 +169,16 @@
return rc;
}
-int Fat::format(const char *fsPath, unsigned int numSectors) {
+int Fat::format(const char *fsPath, unsigned int numSectors, bool wipe) {
int fd;
const char *args[10];
int rc;
int status;
+ if (wipe) {
+ Fat::wipe(fsPath, numSectors);
+ }
+
args[0] = MKDOSFS_PATH;
args[1] = "-F";
args[2] = "32";
@@ -220,3 +226,30 @@
}
return 0;
}
+
+void Fat::wipe(const char *fsPath, unsigned int numSectors) {
+ int fd;
+ unsigned long long range[2];
+
+ fd = open(fsPath, O_RDWR);
+ if (fd >= 0) {
+ if (numSectors == 0) {
+ numSectors = get_blkdev_size(fd);
+ }
+ if (numSectors == 0) {
+ SLOGE("Fat wipe failed to determine size of %s", fsPath);
+ close(fd);
+ return;
+ }
+ range[0] = 0;
+ range[1] = (unsigned long long)numSectors * 512;
+ if (ioctl(fd, BLKDISCARD, &range) < 0) {
+ SLOGE("Fat wipe failed to discard blocks on %s", fsPath);
+ } else {
+ SLOGI("Fat wipe %d sectors on %s succeeded", numSectors, fsPath);
+ }
+ close(fd);
+ } else {
+ SLOGE("Fat wipe failed to open device %s", fsPath);
+ }
+}
diff --git a/Fat.h b/Fat.h
index e02d88c..19614d1 100644
--- a/Fat.h
+++ b/Fat.h
@@ -26,7 +26,10 @@
bool ro, bool remount, bool executable,
int ownerUid, int ownerGid, int permMask,
bool createLost);
- static int format(const char *fsPath, unsigned int numSectors);
+ static int format(const char *fsPath, unsigned int numSectors, bool wipe);
+
+private:
+ static void wipe(const char *fsPath, unsigned int numSectors);
};
#endif
diff --git a/VoldUtil.c b/VoldUtil.c
new file mode 100644
index 0000000..b5f9946
--- /dev/null
+++ b/VoldUtil.c
@@ -0,0 +1,29 @@
+/*
+ * Copyright (C) 2013 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 <sys/ioctl.h>
+#include <linux/fs.h>
+
+unsigned int get_blkdev_size(int fd)
+{
+ unsigned int nr_sec;
+
+ if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
+ nr_sec = 0;
+ }
+
+ return nr_sec;
+}
diff --git a/VoldUtil.h b/VoldUtil.h
index 30a3add..469489a 100644
--- a/VoldUtil.h
+++ b/VoldUtil.h
@@ -17,6 +17,12 @@
#ifndef _VOLDUTIL_H
#define _VOLDUTIL_H
+#include <sys/cdefs.h>
+
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(*(a)))
+__BEGIN_DECLS
+ unsigned int get_blkdev_size(int fd);
+__END_DECLS
+
#endif
diff --git a/Volume.cpp b/Volume.cpp
index 4a00ccc..4501e90 100644
--- a/Volume.cpp
+++ b/Volume.cpp
@@ -206,7 +206,7 @@
return 0;
}
-int Volume::formatVol() {
+int Volume::formatVol(bool wipe) {
if (getState() == Volume::State_NoMedia) {
errno = ENODEV;
@@ -250,7 +250,7 @@
SLOGI("Formatting volume %s (%s)", getLabel(), devicePath);
}
- if (Fat::format(devicePath, 0)) {
+ if (Fat::format(devicePath, 0, wipe)) {
SLOGE("Failed to format (%s)", strerror(errno));
goto err;
}
diff --git a/Volume.h b/Volume.h
index c717d4d..22e247d 100644
--- a/Volume.h
+++ b/Volume.h
@@ -67,7 +67,7 @@
int mountVol();
int unmountVol(bool force, bool revert);
- int formatVol();
+ int formatVol(bool wipe);
const char *getLabel() { return mLabel; }
const char *getMountpoint() { return mMountpoint; }
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a1930d1..180387c 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -167,7 +167,7 @@
return 0;
}
-int VolumeManager::formatVolume(const char *label) {
+int VolumeManager::formatVolume(const char *label, bool wipe) {
Volume *v = lookupVolume(label);
if (!v) {
@@ -180,7 +180,7 @@
return -1;
}
- return v->formatVol();
+ return v->formatVol(wipe);
}
int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) {
@@ -414,7 +414,7 @@
if (usingExt4) {
formatStatus = Ext4::format(dmDevice, mountPoint);
} else {
- formatStatus = Fat::format(dmDevice, numImgSectors);
+ formatStatus = Fat::format(dmDevice, numImgSectors, 0);
}
if (formatStatus < 0) {
diff --git a/VolumeManager.h b/VolumeManager.h
index 198b5a9..be78516 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -83,7 +83,7 @@
int shareVolume(const char *label, const char *method);
int unshareVolume(const char *label, const char *method);
int shareEnabled(const char *path, const char *method, bool *enabled);
- int formatVolume(const char *label);
+ int formatVolume(const char *label, bool wipe);
void disableVolumeManager(void) { mVolManagerDisabled = 1; }
/* ASEC */
diff --git a/cryptfs.c b/cryptfs.c
index 1bf7049..c86e712 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -46,6 +46,7 @@
#include "cutils/properties.h"
#include "hardware_legacy/power.h"
#include "VolumeManager.h"
+#include "VoldUtil.h"
#define DM_CRYPT_BUF_SIZE 4096
#define DATA_MNT_POINT "/data"
@@ -115,17 +116,6 @@
return (unsigned int) (len / 512);
}
-static unsigned int get_blkdev_size(int fd)
-{
- unsigned int nr_sec;
-
- if ( (ioctl(fd, BLKGETSIZE, &nr_sec)) == -1) {
- nr_sec = 0;
- }
-
- return nr_sec;
-}
-
static int get_crypt_ftr_info(char **metadata_fname, off64_t *off)
{
static int cached_data = 0;