From 9caab76c6b5aefdeeb1715a3695491ca793b8c18 Mon Sep 17 00:00:00 2001 From: Ken Sumrall Date: Tue, 11 Jun 2013 19:10:20 -0700 Subject: [PATCH] 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 --- Android.mk | 1 + CommandListener.cpp | 11 ++++++++--- Fat.cpp | 35 ++++++++++++++++++++++++++++++++++- Fat.h | 5 ++++- VoldUtil.c | 29 +++++++++++++++++++++++++++++ VoldUtil.h | 6 ++++++ Volume.cpp | 4 ++-- Volume.h | 2 +- VolumeManager.cpp | 6 +++--- VolumeManager.h | 2 +- cryptfs.c | 12 +----------- 11 files changed, 90 insertions(+), 23 deletions(-) create mode 100644 VoldUtil.c diff --git a/Android.mk b/Android.mk index 098c3d0..71113df 100644 --- a/Android.mk +++ b/Android.mk @@ -15,6 +15,7 @@ common_src_files := \ 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 @@ int CommandListener::VolumeCmd::runCommand(SocketClient *cli, } rc = vm->unmountVolume(argv[2], force, revert); } else if (!strcmp(argv[1], "format")) { - if (argc != 3) { - cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format ", false); + if (argc < 3 || argc > 4 || + (argc == 4 && strcmp(argv[3], "wipe"))) { + cli->sendMsg(ResponseCode::CommandSyntaxError, "Usage: volume format [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 #include #include +#include +#include #include @@ -167,12 +169,16 @@ int Fat::doMount(const char *fsPath, const char *mountPoint, 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 @@ int Fat::format(const char *fsPath, unsigned int numSectors) { } 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 @@ public: 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 +#include + +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 + #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 @@ int Volume::createDeviceNode(const char *path, int major, int minor) { return 0; } -int Volume::formatVol() { +int Volume::formatVol(bool wipe) { if (getState() == Volume::State_NoMedia) { errno = ENODEV; @@ -250,7 +250,7 @@ int Volume::formatVol() { 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 @@ public: 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 @@ int VolumeManager::listVolumes(SocketClient *cli) { 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 @@ int VolumeManager::formatVolume(const char *label) { return -1; } - return v->formatVol(); + return v->formatVol(wipe); } int VolumeManager::getObbMountPath(const char *sourceFile, char *mountPath, int mountPathLen) { @@ -414,7 +414,7 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors, const cha 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 @@ public: 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 @@ static unsigned int get_fs_size(char *dev) 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;