am 836e7860: am 8120c3d1: Merge "Adding e4crypt support"
* commit '836e78608dcb16a490330e051416787df2ee14db':
Adding e4crypt support
diff --git a/Android.mk b/Android.mk
index cf2b291..d087216 100644
--- a/Android.mk
+++ b/Android.mk
@@ -17,7 +17,12 @@
CheckBattery.cpp \
VoldUtil.c \
fstrim.c \
- cryptfs.c
+ cryptfs.c \
+ Disk.cpp \
+ VolumeBase.cpp \
+ PublicVolume.cpp \
+ EmulatedVolume.cpp \
+ Utils.cpp \
common_c_includes := \
system/extras/ext4_utils \
@@ -42,7 +47,8 @@
libselinux \
libutils \
libhardware \
- libsoftkeymaster
+ libsoftkeymaster \
+ libbase \
common_static_libraries := \
libfs_mgr \
@@ -51,7 +57,7 @@
libbatteryservice
vold_conlyflags := -std=c11
-vold_cflags := -Werror -Wall -Wno-missing-field-initializers
+vold_cflags := -Werror -Wall -Wno-missing-field-initializers -Wno-unused-variable -Wno-unused-parameter
include $(CLEAR_VARS)
diff --git a/DirectVolume.cpp b/DirectVolume.cpp
index 64d7744..6118453 100644
--- a/DirectVolume.cpp
+++ b/DirectVolume.cpp
@@ -136,10 +136,10 @@
for (it = mPaths->begin(); it != mPaths->end(); ++it) {
if ((*it)->match(dp)) {
/* We can handle this disk */
- int action = evt->getAction();
+ NetlinkEvent::Action action = evt->getAction();
const char *devtype = evt->findParam("DEVTYPE");
- if (action == NetlinkEvent::NlActionAdd) {
+ if (action == NetlinkEvent::Action::kAdd) {
int major = atoi(evt->findParam("MAJOR"));
int minor = atoi(evt->findParam("MINOR"));
char nodepath[255];
@@ -166,13 +166,13 @@
mVm->getBroadcaster()->sendBroadcast(ResponseCode::VolumeDiskInserted,
msg, false);
}
- } else if (action == NetlinkEvent::NlActionRemove) {
+ } else if (action == NetlinkEvent::Action::kRemove) {
if (!strcmp(devtype, "disk")) {
handleDiskRemoved(dp, evt);
} else {
handlePartitionRemoved(dp, evt);
}
- } else if (action == NetlinkEvent::NlActionChange) {
+ } else if (action == NetlinkEvent::Action::kChange) {
if (!strcmp(devtype, "disk")) {
handleDiskChanged(dp, evt);
} else {
diff --git a/Disk.cpp b/Disk.cpp
new file mode 100644
index 0000000..56dface
--- /dev/null
+++ b/Disk.cpp
@@ -0,0 +1,289 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vold"
+
+#include "Disk.h"
+#include "PublicVolume.h"
+#include "Utils.h"
+#include "VolumeBase.h"
+
+#include <base/file.h>
+#include <base/stringprintf.h>
+#include <cutils/log.h>
+#include <diskconfig/diskconfig.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+
+using android::base::ReadFileToString;
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+static const char* kSgdiskPath = "/system/bin/sgdisk";
+static const char* kSgdiskToken = " \t\n";
+
+static const char* kSysfsMmcMaxMinors = "/sys/module/mmcblk/parameters/perdev_minors";
+
+static const unsigned int kMajorBlockScsi = 8;
+static const unsigned int kMajorBlockMmc = 179;
+
+static const char* kGptBasicData = "EBD0A0A2-B9E5-4433-87C0-68B6B72699C7";
+static const char* kGptAndroidMeta = "19A710A2-B3CA-11E4-B026-10604B889DCF";
+static const char* kGptAndroidExt = "193D1EA4-B3CA-11E4-B075-10604B889DCF";
+
+enum class Table {
+ kUnknown,
+ kMbr,
+ kGpt,
+};
+
+Disk::Disk(const std::string& eventPath, dev_t device) :
+ mDevice(device), mSize(-1) {
+ mId = StringPrintf("disk:%ud:%ud", major(device), minor(device));
+ mSysPath = StringPrintf("/sys/%s", eventPath.c_str());
+ mDevPath = StringPrintf("/dev/block/vold/%ud:%ud", major(device), minor(device));
+
+ CreateDeviceNode(mDevPath, mDevice);
+}
+
+Disk::~Disk() {
+ DestroyDeviceNode(mDevPath);
+}
+
+std::shared_ptr<VolumeBase> Disk::findVolume(const std::string& id) {
+ for (std::shared_ptr<VolumeBase>& v : mParts) {
+ if (!id.compare(v->getId())) {
+ return v;
+ }
+ }
+ return nullptr;
+}
+
+status_t Disk::readMetadata() {
+ mSize = -1;
+ mLabel = "";
+
+ {
+ std::string path(mSysPath + "/size");
+ std::string tmp;
+ if (!ReadFileToString(path, &tmp)) {
+ ALOGW("Failed to read size from %s: %s", path.c_str(), strerror(errno));
+ return -errno;
+ }
+ mSize = strtoll(tmp.c_str(), nullptr, 10);
+ }
+
+ switch (major(mDevice)) {
+ case kMajorBlockScsi: {
+ std::string path(mSysPath + "/device/vendor");
+ std::string tmp;
+ if (!ReadFileToString(path, &tmp)) {
+ ALOGW("Failed to read vendor from %s: %s", path.c_str(), strerror(errno));
+ return -errno;
+ }
+ mLabel = tmp;
+ break;
+ }
+ case kMajorBlockMmc: {
+ std::string path(mSysPath + "/device/manfid");
+ std::string tmp;
+ if (!ReadFileToString(path, &tmp)) {
+ ALOGW("Failed to read manufacturer from %s: %s", path.c_str(), strerror(errno));
+ return -errno;
+ }
+ uint64_t manfid = strtoll(tmp.c_str(), nullptr, 16);
+ // Our goal here is to give the user a meaningful label, ideally
+ // matching whatever is silk-screened on the card. To reduce
+ // user confusion, this list doesn't contain white-label manfid.
+ switch (manfid) {
+ case 0x000003: mLabel = "SanDisk"; break;
+ case 0x00001b: mLabel = "Samsung"; break;
+ case 0x000028: mLabel = "Lexar"; break;
+ case 0x000074: mLabel = "Transcend"; break;
+ }
+ break;
+ }
+ default: {
+ ALOGW("Unsupported block major type %d", major(mDevice));
+ return -ENOTSUP;
+ }
+ }
+
+ return OK;
+}
+
+status_t Disk::readPartitions() {
+ int8_t maxMinors = getMaxMinors();
+ if (maxMinors < 0) {
+ return -ENOTSUP;
+ }
+
+ mParts.clear();
+
+ // Parse partition table
+ std::string path(kSgdiskPath);
+ path += " --android-dump ";
+ path += mDevPath;
+ FILE* fp = popen(path.c_str(), "r");
+ if (!fp) {
+ ALOGE("Failed to run %s: %s", path.c_str(), strerror(errno));
+ return -errno;
+ }
+
+ char line[1024];
+ Table table = Table::kUnknown;
+ while (fgets(line, sizeof(line), fp) != nullptr) {
+ char* token = strtok(line, kSgdiskToken);
+ if (!strcmp(token, "DISK")) {
+ const char* type = strtok(nullptr, kSgdiskToken);
+ ALOGD("%s: found %s partition table", mId.c_str(), type);
+ if (!strcmp(type, "mbr")) {
+ table = Table::kMbr;
+ } else if (!strcmp(type, "gpt")) {
+ table = Table::kGpt;
+ }
+ } else if (!strcmp(token, "PART")) {
+ int i = strtol(strtok(nullptr, kSgdiskToken), nullptr, 10);
+ if (i <= 0 || i > maxMinors) {
+ ALOGW("%s: ignoring partition %d beyond max supported devices",
+ mId.c_str(), i);
+ continue;
+ }
+ dev_t partDevice = makedev(major(mDevice), minor(mDevice) + i);
+
+ VolumeBase* vol = nullptr;
+ if (table == Table::kMbr) {
+ const char* type = strtok(nullptr, kSgdiskToken);
+ ALOGD("%s: MBR partition %d type %s", mId.c_str(), i, type);
+
+ switch (strtol(type, nullptr, 16)) {
+ case 0x06: // FAT16
+ case 0x0b: // W95 FAT32 (LBA)
+ case 0x0c: // W95 FAT32 (LBA)
+ case 0x0e: // W95 FAT16 (LBA)
+ vol = new PublicVolume(partDevice);
+ break;
+ }
+ } else if (table == Table::kGpt) {
+ const char* typeGuid = strtok(nullptr, kSgdiskToken);
+ const char* partGuid = strtok(nullptr, kSgdiskToken);
+ ALOGD("%s: GPT partition %d type %s, GUID %s", mId.c_str(), i,
+ typeGuid, partGuid);
+
+ if (!strcasecmp(typeGuid, kGptBasicData)) {
+ vol = new PublicVolume(partDevice);
+ } else if (!strcasecmp(typeGuid, kGptAndroidExt)) {
+ //vol = new PrivateVolume();
+ }
+ }
+
+ if (vol != nullptr) {
+ mParts.push_back(std::shared_ptr<VolumeBase>(vol));
+ }
+ }
+ }
+
+ // Ugly last ditch effort, treat entire disk as partition
+ if (table == Table::kUnknown) {
+ ALOGD("%s: unknown partition table; trying entire device", mId.c_str());
+ VolumeBase* vol = new PublicVolume(mDevice);
+ mParts.push_back(std::shared_ptr<VolumeBase>(vol));
+ }
+
+ pclose(fp);
+ return OK;
+}
+
+status_t Disk::partitionPublic() {
+ // TODO: improve this code
+
+ struct disk_info dinfo;
+ memset(&dinfo, 0, sizeof(dinfo));
+
+ if (!(dinfo.part_lst = (struct part_info *) malloc(
+ MAX_NUM_PARTS * sizeof(struct part_info)))) {
+ SLOGE("Failed to malloc prt_lst");
+ return -1;
+ }
+
+ memset(dinfo.part_lst, 0, MAX_NUM_PARTS * sizeof(struct part_info));
+ dinfo.device = strdup(mDevPath.c_str());
+ dinfo.scheme = PART_SCHEME_MBR;
+ dinfo.sect_size = 512;
+ dinfo.skip_lba = 2048;
+ dinfo.num_lba = 0;
+ dinfo.num_parts = 1;
+
+ struct part_info *pinfo = &dinfo.part_lst[0];
+
+ pinfo->name = strdup("android_sdcard");
+ pinfo->flags |= PART_ACTIVE_FLAG;
+ pinfo->type = PC_PART_TYPE_FAT32;
+ pinfo->len_kb = -1;
+
+ int rc = apply_disk_config(&dinfo, 0);
+ if (rc) {
+ SLOGE("Failed to apply disk configuration (%d)", rc);
+ goto out;
+ }
+
+out:
+ free(pinfo->name);
+ free(dinfo.device);
+ free(dinfo.part_lst);
+
+ return rc;
+}
+
+status_t Disk::partitionPrivate() {
+ return -ENOTSUP;
+}
+
+status_t Disk::partitionMixed(int8_t ratio) {
+ return -ENOTSUP;
+}
+
+int Disk::getMaxMinors() {
+ // Figure out maximum partition devices supported
+ switch (major(mDevice)) {
+ case kMajorBlockScsi: {
+ // Per Documentation/devices.txt this is static
+ return 15;
+ }
+ case kMajorBlockMmc: {
+ // Per Documentation/devices.txt this is dynamic
+ std::string tmp;
+ if (!ReadFileToString(kSysfsMmcMaxMinors, &tmp)) {
+ ALOGW("Failed to read max minors");
+ return -errno;
+ }
+ return atoi(tmp.c_str());
+ }
+ }
+
+ ALOGW("Unsupported block major type %d", major(mDevice));
+ return -ENOTSUP;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/Disk.h b/Disk.h
new file mode 100644
index 0000000..eab8976
--- /dev/null
+++ b/Disk.h
@@ -0,0 +1,92 @@
+/*
+ * 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 ANDROID_VOLD_DISK_H
+#define ANDROID_VOLD_DISK_H
+
+#include "Utils.h"
+
+#include <utils/Errors.h>
+
+#include <vector>
+
+namespace android {
+namespace vold {
+
+class VolumeBase;
+
+// events:
+// disk_created 127:4
+// disk_meta 127:4 [size] [label]
+// disk_destroyed 127:4
+
+// commands:
+// disk partition_public 127:4
+// disk partition_private 127:4
+// disk partition_mixed 127:4 50
+
+/*
+ * Representation of detected physical media.
+ *
+ * Knows how to create volumes based on the partition tables found, and also
+ * how to repartition itself.
+ */
+class Disk {
+public:
+ Disk(const std::string& eventPath, dev_t device);
+ virtual ~Disk();
+
+ const std::string& getId() { return mId; }
+ const std::string& getSysPath() { return mSysPath; }
+ const std::string& getDevPath() { return mDevPath; }
+ dev_t getDevice() { return mDevice; }
+ uint64_t getSize() { return mSize; }
+ const std::string& getLabel() { return mLabel; }
+
+ std::shared_ptr<VolumeBase> findVolume(const std::string& id);
+
+ status_t readMetadata();
+ status_t readPartitions();
+
+ status_t partitionPublic();
+ status_t partitionPrivate();
+ status_t partitionMixed(int8_t ratio);
+
+private:
+ /* ID that uniquely references this disk */
+ std::string mId;
+ /* Device path under sysfs */
+ std::string mSysPath;
+ /* Device path under dev */
+ std::string mDevPath;
+ /* Kernel device representing disk */
+ dev_t mDevice;
+ /* Size of disk, in bytes */
+ uint64_t mSize;
+ /* User-visible label, such as manufacturer */
+ std::string mLabel;
+ /* Current partitions on disk */
+ std::vector<std::shared_ptr<VolumeBase>> mParts;
+
+ int getMaxMinors();
+
+ DISALLOW_COPY_AND_ASSIGN(Disk);
+};
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/EmulatedVolume.cpp b/EmulatedVolume.cpp
new file mode 100644
index 0000000..bec1025
--- /dev/null
+++ b/EmulatedVolume.cpp
@@ -0,0 +1,132 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vold"
+
+#include "EmulatedVolume.h"
+#include "Utils.h"
+
+#include <base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+static const char* kFusePath = "/system/bin/sdcard";
+
+static const char* kUserMountPath = "/mnt/user";
+
+EmulatedVolume::EmulatedVolume(const std::string& rawPath, const std::string& nickname) :
+ VolumeBase(VolumeType::kEmulated), mFusePid(0), mPrimary(false) {
+ mRawPath = rawPath;
+ mFusePath = StringPrintf("/mnt/media_rw/emulated_fuse_%s", nickname.c_str());
+}
+
+EmulatedVolume::~EmulatedVolume() {
+}
+
+status_t EmulatedVolume::doMount() {
+ if (fs_prepare_dir(mFusePath.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) {
+ SLOGE("Failed to create mount point %s: %s", mFusePath.c_str(), strerror(errno));
+ return -errno;
+ }
+
+ if (!(mFusePid = fork())) {
+ if (execl(kFusePath,
+ "-u", "1023", // AID_MEDIA_RW
+ "-g", "1023", // AID_MEDIA_RW
+ "-d",
+ mRawPath.c_str(),
+ mFusePath.c_str())) {
+ SLOGE("Failed to exec: %s", strerror(errno));
+ }
+ _exit(1);
+ }
+
+ if (mFusePid == -1) {
+ SLOGE("Failed to fork: %s", strerror(errno));
+ return -errno;
+ }
+
+ return OK;
+}
+
+status_t EmulatedVolume::doUnmount() {
+ if (mFusePid > 0) {
+ kill(mFusePid, SIGTERM);
+ TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
+ mFusePid = 0;
+ }
+
+ ForceUnmount(mFusePath);
+
+ TEMP_FAILURE_RETRY(unlink(mFusePath.c_str()));
+
+ return OK;
+}
+
+status_t EmulatedVolume::doFormat() {
+ return -ENOTSUP;
+}
+
+status_t EmulatedVolume::bindUser(userid_t user) {
+ return bindUserInternal(user, true);
+}
+
+status_t EmulatedVolume::unbindUser(userid_t user) {
+ return bindUserInternal(user, false);
+}
+
+status_t EmulatedVolume::bindUserInternal(userid_t user, bool bind) {
+ if (!mPrimary) {
+ // Emulated volumes are only bound when primary
+ return OK;
+ }
+
+ std::string fromPath(StringPrintf("%s/%ud", mFusePath.c_str(), user));
+ std::string toPath(StringPrintf("%s/%ud/primary", kUserMountPath, user));
+
+ if (bind) {
+ mountBind(fromPath, toPath);
+ } else {
+ unmountBind(toPath);
+ }
+
+ return OK;
+}
+
+void EmulatedVolume::setPrimary(bool primary) {
+ if (getState() != VolumeState::kUnmounted) {
+ SLOGE("Primary state change requires %s to be unmounted", getId().c_str());
+ return;
+ }
+
+ mPrimary = primary;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/EmulatedVolume.h b/EmulatedVolume.h
new file mode 100644
index 0000000..972351c
--- /dev/null
+++ b/EmulatedVolume.h
@@ -0,0 +1,72 @@
+/*
+ * 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 ANDROID_VOLD_EMULATED_VOLUME_H
+#define ANDROID_VOLD_EMULATED_VOLUME_H
+
+#include "VolumeBase.h"
+
+#include <cutils/multiuser.h>
+
+namespace android {
+namespace vold {
+
+/*
+ * Shared storage emulated on top of private storage.
+ *
+ * Knows how to spawn a FUSE daemon to synthesize permissions. ObbVolume
+ * can be stacked above it.
+ *
+ * This volume is always multi-user aware, but is only binds itself to
+ * users when its primary storage. This volume should never be presented
+ * as secondary storage, since we're strongly encouraging developers to
+ * store data local to their app.
+ */
+class EmulatedVolume : public VolumeBase {
+public:
+ EmulatedVolume(const std::string& rawPath, const std::string& nickname);
+ virtual ~EmulatedVolume();
+
+ void setPrimary(bool primary);
+ bool getPrimary() { return mPrimary; }
+
+ status_t bindUser(userid_t user);
+ status_t unbindUser(userid_t user);
+
+private:
+ /* Mount point of raw storage */
+ std::string mRawPath;
+ /* Mount point of FUSE wrapper */
+ std::string mFusePath;
+ /* PID of FUSE wrapper */
+ pid_t mFusePid;
+ /* Flag indicating this is primary storage */
+ bool mPrimary;
+
+protected:
+ status_t doMount();
+ status_t doUnmount();
+ status_t doFormat();
+
+ status_t bindUserInternal(userid_t user, bool bind);
+
+ DISALLOW_COPY_AND_ASSIGN(EmulatedVolume);
+};
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/PublicVolume.cpp b/PublicVolume.cpp
new file mode 100644
index 0000000..255a6bc
--- /dev/null
+++ b/PublicVolume.cpp
@@ -0,0 +1,252 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vold"
+
+#include "Fat.h"
+#include "PublicVolume.h"
+#include "Utils.h"
+
+#include <base/stringprintf.h>
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+using android::base::StringPrintf;
+
+namespace android {
+namespace vold {
+
+static const char* kBlkidPath = "/system/bin/blkid";
+static const char* kFusePath = "/system/bin/sdcard";
+
+static const char* kUserMountPath = "/mnt/user";
+
+PublicVolume::PublicVolume(dev_t device) :
+ VolumeBase(VolumeType::kPublic), mDevice(device), mFusePid(0), mPrimary(false) {
+ mId = StringPrintf("public:%ud:%ud", major(device), minor(device));
+ mDevPath = StringPrintf("/dev/block/vold/%ud:%ud", major(device), minor(device));
+ mRawPath = StringPrintf("/mnt/media_rw/public_raw_%ud:%ud", major(device), minor(device));
+ mFusePath = StringPrintf("/mnt/media_rw/public_fuse_%ud:%ud", major(device), minor(device));
+
+ CreateDeviceNode(mDevPath, device);
+}
+
+PublicVolume::~PublicVolume() {
+ DestroyDeviceNode(mDevPath);
+}
+
+status_t PublicVolume::readMetadata() {
+ mFsUuid = "";
+ mFsLabel = "";
+
+ std::string path(StringPrintf("%s -c /dev/null %s", kBlkidPath, mDevPath.c_str()));
+ FILE* fp = popen(path.c_str(), "r");
+ if (!fp) {
+ ALOGE("Failed to run %s: %s", path.c_str(), strerror(errno));
+ return -errno;
+ }
+
+ char line[1024];
+ char value[128];
+ if (fgets(line, sizeof(line), fp) != nullptr) {
+ ALOGD("blkid identified as %s", line);
+
+ char* start = strstr(line, "UUID=");
+ if (start != nullptr && sscanf(start + 5, "\"%127[^\"]\"", value) == 1) {
+ mFsUuid = value;
+ }
+
+ start = strstr(line, "LABEL=");
+ if (start != nullptr && sscanf(start + 6, "\"%127[^\"]\"", value) == 1) {
+ mFsLabel = value;
+ }
+ } else {
+ ALOGW("blkid failed to identify %s", mDevPath.c_str());
+ return -ENODATA;
+ }
+
+ pclose(fp);
+
+ // TODO: broadcast ident to framework
+ return OK;
+}
+
+status_t PublicVolume::initAsecStage() {
+ std::string legacyPath(mRawPath + "/android_secure");
+ std::string securePath(mRawPath + "/.android_secure");
+
+ // Recover legacy secure path
+ if (!access(legacyPath.c_str(), R_OK | X_OK)
+ && access(securePath.c_str(), R_OK | X_OK)) {
+ if (rename(legacyPath.c_str(), securePath.c_str())) {
+ SLOGE("Failed to rename legacy ASEC dir: %s", strerror(errno));
+ }
+ }
+
+ if (fs_prepare_dir(securePath.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW) != 0) {
+ SLOGW("fs_prepare_dir failed: %s", strerror(errno));
+ return -errno;
+ }
+
+ return OK;
+}
+
+status_t PublicVolume::doMount() {
+ if (Fat::check(mDevPath.c_str())) {
+ SLOGE("Failed filesystem check; not mounting");
+ return -EIO;
+ }
+
+ if (fs_prepare_dir(mRawPath.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) {
+ SLOGE("Failed to create mount point %s: %s", mRawPath.c_str(), strerror(errno));
+ return -errno;
+ }
+ if (fs_prepare_dir(mFusePath.c_str(), 0770, AID_MEDIA_RW, AID_MEDIA_RW)) {
+ SLOGE("Failed to create mount point %s: %s", mFusePath.c_str(), strerror(errno));
+ return -errno;
+ }
+
+ if (Fat::doMount(mDevPath.c_str(), mRawPath.c_str(), false, false, false,
+ AID_MEDIA_RW, AID_MEDIA_RW, 0007, true)) {
+ SLOGE("Failed to mount %s: %s", mDevPath.c_str(), strerror(errno));
+ return -EIO;
+ }
+
+ if (!(mFusePid = fork())) {
+ if (mPrimary) {
+ if (execl(kFusePath,
+ "-u", "1023", // AID_MEDIA_RW
+ "-g", "1023", // AID_MEDIA_RW
+ "-d",
+ mRawPath.c_str(),
+ mFusePath.c_str())) {
+ SLOGE("Failed to exec: %s", strerror(errno));
+ }
+ } else {
+ if (execl(kFusePath,
+ "-u", "1023", // AID_MEDIA_RW
+ "-g", "1023", // AID_MEDIA_RW
+ "-w", "1023", // AID_MEDIA_RW
+ "-d",
+ mRawPath.c_str(),
+ mFusePath.c_str())) {
+ SLOGE("Failed to exec: %s", strerror(errno));
+ }
+ }
+
+ _exit(1);
+ }
+
+ if (mFusePid == -1) {
+ SLOGE("Failed to fork: %s", strerror(errno));
+ return -errno;
+ }
+
+ return OK;
+}
+
+status_t PublicVolume::doUnmount() {
+ if (mFusePid > 0) {
+ kill(mFusePid, SIGTERM);
+ TEMP_FAILURE_RETRY(waitpid(mFusePid, nullptr, 0));
+ mFusePid = 0;
+ }
+
+ ForceUnmount(mFusePath);
+ ForceUnmount(mRawPath);
+
+ TEMP_FAILURE_RETRY(unlink(mRawPath.c_str()));
+ TEMP_FAILURE_RETRY(unlink(mFusePath.c_str()));
+
+ return OK;
+}
+
+status_t PublicVolume::doFormat() {
+ if (Fat::format(mDevPath.c_str(), 0, true)) {
+ SLOGE("Failed to format: %s", strerror(errno));
+ return -errno;
+ }
+ return OK;
+}
+
+status_t PublicVolume::bindUser(userid_t user) {
+ return bindUserInternal(user, true);
+}
+
+status_t PublicVolume::unbindUser(userid_t user) {
+ return bindUserInternal(user, false);
+}
+
+status_t PublicVolume::bindUserInternal(userid_t user, bool bind) {
+ if (mPrimary) {
+ if (user == 0) {
+ std::string path(StringPrintf("%s/%ud/primary", kUserMountPath, user));
+ if (bind) {
+ mountBind(mFusePath, path);
+ } else {
+ unmountBind(path);
+ }
+ } else {
+ // Public volumes are only visible to owner when primary
+ // storage, so we don't mount for secondary users.
+ }
+ } else {
+ std::string path(StringPrintf("%s/%ud/public_%ud:%ud", kUserMountPath, user,
+ major(mDevice), minor(mDevice)));
+ if (bind) {
+ mountBind(mFusePath, path);
+ } else {
+ unmountBind(path);
+ }
+
+ if (user != 0) {
+ // To prevent information leakage between users, only owner
+ // has access to the Android directory
+ path += "/Android";
+ if (bind) {
+ if (::mount("tmpfs", path.c_str(), "tmpfs", MS_NOSUID, "mode=0000")) {
+ SLOGE("Failed to protect secondary path %s: %s",
+ path.c_str(), strerror(errno));
+ return -errno;
+ }
+ } else {
+ ForceUnmount(path);
+ }
+ }
+ }
+
+ return OK;
+}
+
+void PublicVolume::setPrimary(bool primary) {
+ if (getState() != VolumeState::kUnmounted) {
+ SLOGE("Primary state change requires %s to be unmounted", getId().c_str());
+ return;
+ }
+
+ mPrimary = primary;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/PublicVolume.h b/PublicVolume.h
new file mode 100644
index 0000000..3da0995
--- /dev/null
+++ b/PublicVolume.h
@@ -0,0 +1,89 @@
+/*
+ * 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 ANDROID_VOLD_PUBLIC_VOLUME_H
+#define ANDROID_VOLD_PUBLIC_VOLUME_H
+
+#include "VolumeBase.h"
+
+#include <cutils/multiuser.h>
+
+namespace android {
+namespace vold {
+
+/*
+ * Shared storage provided by public (vfat) partition.
+ *
+ * Knows how to mount itself and then spawn a FUSE daemon to synthesize
+ * permissions. AsecVolume and ObbVolume can be stacked above it.
+ *
+ * This volume is not inherently multi-user aware, so it has two possible
+ * modes of operation:
+ * 1. If primary storage for the device, it only binds itself to the
+ * owner user.
+ * 2. If secondary storage, it binds itself for all users, but masks
+ * away the Android directory for secondary users.
+ */
+class PublicVolume : public VolumeBase {
+public:
+ explicit PublicVolume(dev_t device);
+ virtual ~PublicVolume();
+
+ status_t readMetadata();
+ status_t initAsecStage();
+
+ void setPrimary(bool primary);
+ bool getPrimary() { return mPrimary; }
+
+ const std::string& getFsUuid() { return mFsUuid; }
+ const std::string& getFsLabel() { return mFsLabel; }
+
+ status_t bindUser(userid_t user);
+ status_t unbindUser(userid_t user);
+
+protected:
+ status_t doMount();
+ status_t doUnmount();
+ status_t doFormat();
+
+ status_t bindUserInternal(userid_t user, bool bind);
+
+private:
+ /* Kernel device representing partition */
+ dev_t mDevice;
+ /* Block device path */
+ std::string mDevPath;
+ /* Mount point of raw partition */
+ std::string mRawPath;
+ /* Mount point of FUSE wrapper */
+ std::string mFusePath;
+ /* PID of FUSE wrapper */
+ pid_t mFusePid;
+ /* Flag indicating this is primary storage */
+ bool mPrimary;
+
+ /* Parsed UUID from filesystem */
+ std::string mFsUuid;
+ /* User-visible label from filesystem */
+ std::string mFsLabel;
+
+ DISALLOW_COPY_AND_ASSIGN(PublicVolume);
+};
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/Utils.cpp b/Utils.cpp
new file mode 100644
index 0000000..6ad5d16
--- /dev/null
+++ b/Utils.cpp
@@ -0,0 +1,103 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vold"
+
+#include "sehandle.h"
+#include "Utils.h"
+#include "Process.h"
+
+#include <cutils/fs.h>
+#include <cutils/log.h>
+#include <private/android_filesystem_config.h>
+
+#include <fcntl.h>
+#include <linux/fs.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifndef UMOUNT_NOFOLLOW
+#define UMOUNT_NOFOLLOW 0x00000008 /* Don't follow symlink on umount */
+#endif
+
+namespace android {
+namespace vold {
+
+status_t CreateDeviceNode(const std::string& path, dev_t dev) {
+ const char* cpath = path.c_str();
+ status_t res = 0;
+
+ char* secontext = nullptr;
+ if (sehandle) {
+ if (!selabel_lookup(sehandle, &secontext, cpath, S_IFBLK)) {
+ setfscreatecon(secontext);
+ }
+ }
+
+ mode_t mode = 0660 | S_IFBLK;
+ if (mknod(cpath, mode, dev) < 0) {
+ if (errno != EEXIST) {
+ ALOGW("Failed to create device node for %ud:%ud at %s: %s",
+ major(dev), minor(dev), cpath, strerror(errno));
+ res = -errno;
+ }
+ }
+
+ if (secontext) {
+ setfscreatecon(nullptr);
+ freecon(secontext);
+ }
+
+ return res;
+}
+
+status_t DestroyDeviceNode(const std::string& path) {
+ const char* cpath = path.c_str();
+ if (TEMP_FAILURE_RETRY(unlink(cpath))) {
+ return -errno;
+ } else {
+ return OK;
+ }
+}
+
+status_t ForceUnmount(const std::string& path) {
+ const char* cpath = path.c_str();
+ if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
+ return OK;
+ }
+ ALOGW("Failed to unmount %s (%s), sending SIGTERM", cpath, strerror(errno));
+ Process::killProcessesWithOpenFiles(cpath, SIGTERM);
+ sleep(1);
+
+ if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
+ return OK;
+ }
+ ALOGW("Failed to unmount %s (%s), sending SIGKILL", cpath, strerror(errno));
+ Process::killProcessesWithOpenFiles(cpath, SIGKILL);
+ sleep(1);
+
+ if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
+ return OK;
+ }
+ ALOGW("Failed to unmount %s (%s)", cpath, strerror(errno));
+ return -errno;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/Utils.h b/Utils.h
new file mode 100644
index 0000000..5199af6
--- /dev/null
+++ b/Utils.h
@@ -0,0 +1,44 @@
+/*
+ * 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 ANDROID_VOLD_UTILS_H
+#define ANDROID_VOLD_UTILS_H
+
+#include <utils/Errors.h>
+
+#include <string>
+
+// DISALLOW_COPY_AND_ASSIGN disallows the copy and operator= functions. It goes in the private:
+// declarations in a class.
+#if !defined(DISALLOW_COPY_AND_ASSIGN)
+#define DISALLOW_COPY_AND_ASSIGN(TypeName) \
+ TypeName(const TypeName&) = delete; \
+ void operator=(const TypeName&) = delete
+#endif
+
+namespace android {
+namespace vold {
+
+status_t CreateDeviceNode(const std::string& path, dev_t dev);
+status_t DestroyDeviceNode(const std::string& path);
+
+/* Really unmounts the path, killing active processes along the way */
+status_t ForceUnmount(const std::string& path);
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/VolumeBase.cpp b/VolumeBase.cpp
new file mode 100644
index 0000000..307791d
--- /dev/null
+++ b/VolumeBase.cpp
@@ -0,0 +1,131 @@
+/*
+ * 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.
+ */
+
+#define LOG_TAG "Vold"
+
+#include "Utils.h"
+#include "VolumeBase.h"
+
+#include <cutils/log.h>
+
+#include <fcntl.h>
+#include <stdlib.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+namespace android {
+namespace vold {
+
+VolumeBase::VolumeBase(VolumeType type) :
+ mType(type), mState(VolumeState::kUnmounted) {
+}
+
+VolumeBase::~VolumeBase() {
+}
+
+void VolumeBase::setState(VolumeState state) {
+ mState = state;
+
+ // TODO: publish state up to framework
+}
+
+void VolumeBase::stackVolume(const std::shared_ptr<VolumeBase>& volume) {
+ mStacked.push_back(volume);
+}
+
+void VolumeBase::unstackVolume(const std::shared_ptr<VolumeBase>& volume) {
+ mStacked.remove(volume);
+}
+
+status_t VolumeBase::mount() {
+ if (getState() != VolumeState::kUnmounted) {
+ SLOGE("Must be unmounted to mount %s", getId().c_str());
+ return -EBUSY;
+ }
+
+ setState(VolumeState::kMounting);
+ status_t res = doMount();
+ if (!res) {
+ setState(VolumeState::kMounted);
+ } else {
+ setState(VolumeState::kCorrupt);
+ }
+
+ return res;
+}
+
+status_t VolumeBase::unmount() {
+ if (getState() != VolumeState::kMounted) {
+ SLOGE("Must be mounted to unmount %s", getId().c_str());
+ return -EBUSY;
+ }
+
+ setState(VolumeState::kUnmounting);
+
+ for (std::string target : mBindTargets) {
+ ForceUnmount(target);
+ }
+ mBindTargets.clear();
+
+ for (std::shared_ptr<VolumeBase> v : mStacked) {
+ if (v->unmount()) {
+ ALOGW("Failed to unmount %s stacked above %s", v->getId().c_str(),
+ getId().c_str());
+ }
+ }
+ mStacked.clear();
+
+ status_t res = doUnmount();
+ setState(VolumeState::kUnmounted);
+ return res;
+}
+
+status_t VolumeBase::format() {
+ if (getState() != VolumeState::kUnmounted
+ || getState() != VolumeState::kCorrupt) {
+ SLOGE("Must be unmounted or corrupt to format %s", getId().c_str());
+ return -EBUSY;
+ }
+
+ setState(VolumeState::kFormatting);
+ status_t res = doFormat();
+ setState(VolumeState::kUnmounted);
+ return res;
+}
+
+status_t VolumeBase::doFormat() {
+ return -ENOTSUP;
+}
+
+status_t VolumeBase::mountBind(const std::string& source, const std::string& target) {
+ if (::mount(source.c_str(), target.c_str(), "", MS_BIND, NULL)) {
+ SLOGE("Failed to bind mount %s to %s: %s", source.c_str(),
+ target.c_str(), strerror(errno));
+ return -errno;
+ }
+ mBindTargets.push_back(target);
+ return OK;
+}
+
+status_t VolumeBase::unmountBind(const std::string& target) {
+ ForceUnmount(target);
+ mBindTargets.remove(target);
+ return OK;
+}
+
+} // namespace vold
+} // namespace android
diff --git a/VolumeBase.h b/VolumeBase.h
new file mode 100644
index 0000000..04240b7
--- /dev/null
+++ b/VolumeBase.h
@@ -0,0 +1,124 @@
+/*
+ * 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 ANDROID_VOLD_VOLUME_BASE_H
+#define ANDROID_VOLD_VOLUME_BASE_H
+
+#include "Utils.h"
+
+#include <utils/Errors.h>
+
+#include <sys/types.h>
+#include <list>
+#include <string>
+
+namespace android {
+namespace vold {
+
+enum class VolumeState {
+ kUnmounted,
+ kMounting,
+ kMounted,
+ kCorrupt,
+ kFormatting,
+ kUnmounting,
+};
+
+enum class VolumeType {
+ kPublic,
+ kPrivate,
+ kEmulated,
+ kAsec,
+ kObb,
+};
+
+// events:
+// volume_created private:127:4
+// volume_state private:127:4 mounted
+// volume_meta private:127:4 [fsGuid] [label]
+// volume_destroyed public:127:4
+
+// commands:
+// volume mount public:127:4 [primary]
+// volume unmount public:127:4
+// volume bind_user public:127:4 [userId]
+// volume unbind_user public:127:4 [userId]
+// volume bind_package private:4:1 [userId] [package]
+// volume unbind_package private:4:1 [userId] [package]
+
+/*
+ * Representation of a mounted volume ready for presentation.
+ *
+ * Various subclasses handle the different mounting prerequisites, such as
+ * encryption details, etc. Volumes can also be "stacked" above other
+ * volumes to help communicate dependencies. For example, an ASEC volume
+ * can be stacked on a vfat volume.
+ *
+ * Mounted volumes can be asked to manage bind mounts to present themselves
+ * to specific users on the device.
+ *
+ * When an unmount is requested, the volume recursively unmounts any stacked
+ * volumes and removes any bind mounts before finally unmounting itself.
+ */
+class VolumeBase {
+public:
+ virtual ~VolumeBase();
+
+ VolumeType getType() { return mType; }
+ const std::string& getId() { return mId; }
+ VolumeState getState() { return mState; }
+
+ void stackVolume(const std::shared_ptr<VolumeBase>& volume);
+ void unstackVolume(const std::shared_ptr<VolumeBase>& volume);
+
+ status_t mount();
+ status_t unmount();
+ status_t format();
+
+protected:
+ explicit VolumeBase(VolumeType type);
+
+ /* ID that uniquely references this disk */
+ std::string mId;
+
+ /* Manage bind mounts for this volume */
+ status_t mountBind(const std::string& source, const std::string& target);
+ status_t unmountBind(const std::string& target);
+
+ virtual status_t doMount() = 0;
+ virtual status_t doUnmount() = 0;
+ virtual status_t doFormat();
+
+private:
+ /* Volume type */
+ VolumeType mType;
+ /* Current state of volume */
+ VolumeState mState;
+
+ /* Volumes stacked on top of this volume */
+ std::list<std::shared_ptr<VolumeBase>> mStacked;
+ /* Currently active bind mounts */
+ std::list<std::string> mBindTargets;
+
+ void setState(VolumeState state);
+
+ DISALLOW_COPY_AND_ASSIGN(VolumeBase);
+};
+
+} // namespace vold
+} // namespace android
+
+#endif
diff --git a/cryptfs.c b/cryptfs.c
index 1e8f85b..735232d 100644
--- a/cryptfs.c
+++ b/cryptfs.c
@@ -236,20 +236,6 @@
// necessary, but is necessary to ensure consistency in
// implementations.
switch (ftr->kdf_type) {
- case KDF_SCRYPT_KEYMASTER_UNPADDED:
- // This is broken: It produces a message which is shorter than
- // the public modulus, failing criterion 2.
- memcpy(to_sign, object, object_size);
- to_sign_size = object_size;
- SLOGI("Signing unpadded object");
- break;
- case KDF_SCRYPT_KEYMASTER_BADLY_PADDED:
- // This is broken: Since the value of object is uniformly
- // distributed, it produces a message that is larger than the
- // public modulus with probability 0.25.
- memcpy(to_sign, object, min(RSA_KEY_SIZE_BYTES, object_size));
- SLOGI("Signing end-padded object");
- break;
case KDF_SCRYPT_KEYMASTER:
// This ensures the most significant byte of the signed message
// is zero. We could have zero-padded to the left instead, but
@@ -1273,8 +1259,6 @@
get_device_scrypt_params(crypt_ftr);
switch (crypt_ftr->kdf_type) {
- case KDF_SCRYPT_KEYMASTER_UNPADDED:
- case KDF_SCRYPT_KEYMASTER_BADLY_PADDED:
case KDF_SCRYPT_KEYMASTER:
if (keymaster_create_key(crypt_ftr)) {
SLOGE("keymaster_create_key failed");
@@ -1395,9 +1379,7 @@
static void get_kdf_func(struct crypt_mnt_ftr *ftr, kdf_func *kdf, void** kdf_params)
{
- if (ftr->kdf_type == KDF_SCRYPT_KEYMASTER_UNPADDED ||
- ftr->kdf_type == KDF_SCRYPT_KEYMASTER_BADLY_PADDED ||
- ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
+ if (ftr->kdf_type == KDF_SCRYPT_KEYMASTER) {
*kdf = scrypt_keymaster;
*kdf_params = ftr;
} else if (ftr->kdf_type == KDF_SCRYPT) {
@@ -3343,6 +3325,7 @@
}
struct crypt_mnt_ftr crypt_ftr;
+ int rc;
/* This is only allowed after we've successfully decrypted the master key */
if (!master_key_saved) {
@@ -3368,18 +3351,20 @@
newpw = adjusted_passwd;
}
- encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD
+ rc = encrypt_master_key(crypt_type == CRYPT_TYPE_DEFAULT ? DEFAULT_PASSWORD
: newpw,
crypt_ftr.salt,
saved_master_key,
crypt_ftr.master_key,
&crypt_ftr);
-
+ free(adjusted_passwd);
+ if (rc) {
+ SLOGE("Encrypt master key failed: %d", rc);
+ return -1;
+ }
/* save the key */
put_crypt_ftr_and_key(&crypt_ftr);
- free(adjusted_passwd);
-
#ifdef CONFIG_HW_DISK_ENCRYPTION
if (!strcmp((char *)crypt_ftr.crypto_type_name, "aes-xts")) {
if (crypt_type == CRYPT_TYPE_DEFAULT) {
diff --git a/cryptfs.h b/cryptfs.h
index 1da6f94..c34410a 100644
--- a/cryptfs.h
+++ b/cryptfs.h
@@ -71,10 +71,7 @@
/* Key Derivation Function algorithms */
#define KDF_PBKDF2 1
#define KDF_SCRYPT 2
-/* TODO(paullawrence): Remove KDF_SCRYPT_KEYMASTER_UNPADDED and KDF_SCRYPT_KEYMASTER_BADLY_PADDED
- * when it is safe to do so. */
-#define KDF_SCRYPT_KEYMASTER_UNPADDED 3
-#define KDF_SCRYPT_KEYMASTER_BADLY_PADDED 4
+/* Algorithms 3 & 4 deprecated before shipping outside of google, so removed */
#define KDF_SCRYPT_KEYMASTER 5
/* Maximum allowed keymaster blob size. */
diff --git a/fstrim.c b/fstrim.c
index 2c24fc9..60c9f24 100644
--- a/fstrim.c
+++ b/fstrim.c
@@ -64,6 +64,7 @@
struct fstrim_range range = { 0 };
extern struct fstab *fstab;
int deep_trim = !!thread_arg;
+ struct fstab_rec *prev_rec = NULL;
SLOGI("Starting fstrim work...\n");
@@ -88,6 +89,16 @@
if (fs_mgr_is_voldmanaged(&fstab->recs[i])) {
continue; /* Should we trim fat32 filesystems? */
}
+ if (fs_mgr_is_notrim(&fstab->recs[i])) {
+ continue;
+ }
+
+ /* Skip the multi-type partitions, which are required to be following each other.
+ * See fs_mgr.c's mount_with_alternatives().
+ */
+ if (prev_rec && !strcmp(prev_rec->mount_point, fstab->recs[i].mount_point)) {
+ continue;
+ }
fd = open(fstab->recs[i].mount_point, O_RDONLY | O_DIRECTORY | O_CLOEXEC | O_NOFOLLOW);
if (fd < 0) {
@@ -108,6 +119,7 @@
SLOGI("Trimmed %llu bytes on %s\n", range.len, fstab->recs[i].mount_point);
}
close(fd);
+ prev_rec = &fstab->recs[i];
}
/* Log the finish time in the event log */