Skip to content

Commit 29d8da8

Browse files
author
Ken Sumrall
committed
vold: allow to store key in a file on another partition
Add support for keeping the keys in a separate file on another partition, for devices with no space reserved for a footer after the userdata filesystem. Add support for encrypting the volumes managed by vold, if they meet certain criteria, namely being marked as nonremovable and encryptable in vold.fstab. A bit of trickiness is required to keep vold happy. Change-Id: Idf0611f74b56c1026c45742ca82e0c26e58828fe
1 parent 10a9e42 commit 29d8da8

9 files changed

+552
-89
lines changed

DirectVolume.cpp

+63
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
#include "DirectVolume.h"
3030
#include "VolumeManager.h"
3131
#include "ResponseCode.h"
32+
#include "cryptfs.h"
3233

3334
// #define PARTITION_DEBUG
3435

@@ -61,6 +62,10 @@ int DirectVolume::addPath(const char *path) {
6162
return 0;
6263
}
6364

65+
void DirectVolume::setFlags(int flags) {
66+
mFlags = flags;
67+
}
68+
6469
dev_t DirectVolume::getDiskDevice() {
6570
return MKDEV(mDiskMajor, mDiskMinor);
6671
}
@@ -354,3 +359,61 @@ int DirectVolume::getDeviceNodes(dev_t *devs, int max) {
354359
devs[0] = MKDEV(mDiskMajor, mPartMinors[mPartIdx -1]);
355360
return 1;
356361
}
362+
363+
/*
364+
* Called from base to update device info,
365+
* e.g. When setting up an dm-crypt mapping for the sd card.
366+
*/
367+
int DirectVolume::updateDeviceInfo(char *new_path, int new_major, int new_minor)
368+
{
369+
PathCollection::iterator it;
370+
371+
if (mPartIdx == -1) {
372+
SLOGE("Can only change device info on a partition\n");
373+
return -1;
374+
}
375+
376+
/*
377+
* This is to change the sysfs path associated with a partition, in particular,
378+
* for an internal SD card partition that is encrypted. Thus, the list is
379+
* expected to be only 1 entry long. Check that and bail if not.
380+
*/
381+
if (mPaths->size() != 1) {
382+
SLOGE("Cannot change path if there are more than one for a volume\n");
383+
return -1;
384+
}
385+
386+
it = mPaths->begin();
387+
free(*it); /* Free the string storage */
388+
mPaths->erase(it); /* Remove it from the list */
389+
addPath(new_path); /* Put the new path on the list */
390+
391+
mDiskMajor = new_major;
392+
mDiskMinor = new_minor;
393+
/* Ugh, virual block devices don't use minor 0 for whole disk and minor > 0 for
394+
* partition number. They don't have partitions, they are just virtual block
395+
* devices, and minor number 0 is the first dm-crypt device. Luckily the first
396+
* dm-crypt device is for the userdata partition, which gets minor number 0, and
397+
* it is not managed by vold. So the next device is minor number one, which we
398+
* will call partition one.
399+
*/
400+
mPartIdx = new_minor;
401+
mPartMinors[new_minor-1] = new_minor;
402+
403+
mIsDecrypted = 1;
404+
405+
return 0;
406+
}
407+
408+
/*
409+
* Called from base to give cryptfs all the info it needs to encrypt eligible volumes
410+
*/
411+
int DirectVolume::getVolInfo(struct volume_info *v)
412+
{
413+
strcpy(v->label, mLabel);
414+
strcpy(v->mnt_point, mMountpoint);
415+
v->flags=mFlags;
416+
/* Other fields of struct volume_info are filled in by the caller or cryptfs.c */
417+
418+
return 0;
419+
}

DirectVolume.h

+7
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ class DirectVolume : public Volume {
3535
int mPartMinors[MAX_PARTITIONS];
3636
int mDiskNumParts;
3737
unsigned char mPendingPartMap;
38+
int mIsDecrypted;
39+
int mFlags;
3840

3941
public:
4042
DirectVolume(VolumeManager *vm, const char *label, const char *mount_point, int partIdx);
@@ -47,9 +49,14 @@ class DirectVolume : public Volume {
4749
dev_t getShareDevice();
4850
void handleVolumeShared();
4951
void handleVolumeUnshared();
52+
int getVolInfo(struct volume_info *v);
53+
void setFlags(int flags);
5054

5155
protected:
5256
int getDeviceNodes(dev_t *devs, int max);
57+
int updateDeviceInfo(char *new_path, int new_major, int new_minor);
58+
int isDecrypted() { return mIsDecrypted; }
59+
int getFlags() { return mFlags; }
5360

5461
private:
5562
void handleDiskAdded(const char *devpath, NetlinkEvent *evt);

Volume.cpp

+64-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include <sys/types.h>
2626
#include <sys/mman.h>
2727
#include <sys/mount.h>
28+
#include <sys/param.h>
2829

2930
#include <linux/kdev_t.h>
3031
#include <linux/fs.h>
@@ -44,6 +45,7 @@
4445
#include "ResponseCode.h"
4546
#include "Fat.h"
4647
#include "Process.h"
48+
#include "cryptfs.h"
4749

4850
extern "C" void dos_partition_dec(void const *pp, struct dos_partition *d);
4951
extern "C" void dos_partition_enc(void *pp, struct dos_partition *d);
@@ -284,8 +286,19 @@ int Volume::mountVol() {
284286
char errmsg[255];
285287
const char* externalStorage = getenv("EXTERNAL_STORAGE");
286288
bool primaryStorage = externalStorage && !strcmp(getMountpoint(), externalStorage);
289+
char decrypt_state[PROPERTY_VALUE_MAX];
290+
char crypto_state[PROPERTY_VALUE_MAX];
291+
char encrypt_progress[PROPERTY_VALUE_MAX];
292+
int flags;
287293

288-
if (getState() == Volume::State_NoMedia) {
294+
property_get("vold.decrypt", decrypt_state, "");
295+
property_get("vold.encrypt_progress", encrypt_progress, "");
296+
297+
/* Don't try to mount the volumes if we have not yet entered the disk password
298+
* or are in the process of encrypting.
299+
*/
300+
if ((getState() == Volume::State_NoMedia) ||
301+
((!strcmp(decrypt_state, "1") || encrypt_progress[0]) && primaryStorage)) {
289302
snprintf(errmsg, sizeof(errmsg),
290303
"Volume %s %s mount failed - no media",
291304
getLabel(), getMountpoint());
@@ -312,6 +325,56 @@ int Volume::mountVol() {
312325
return -1;
313326
}
314327

328+
/* If we're running encrypted, and the volume is marked as encryptable and nonremovable,
329+
* and vold is asking to mount the primaryStorage device, then we need to decrypt
330+
* that partition, and update the volume object to point to it's new decrypted
331+
* block device
332+
*/
333+
property_get("ro.crypto.state", crypto_state, "");
334+
flags = getFlags();
335+
if (primaryStorage &&
336+
((flags & (VOL_NONREMOVABLE | VOL_ENCRYPTABLE))==(VOL_NONREMOVABLE | VOL_ENCRYPTABLE)) &&
337+
!strcmp(crypto_state, "encrypted") && !isDecrypted()) {
338+
char new_sys_path[MAXPATHLEN];
339+
char nodepath[256];
340+
int new_major, new_minor;
341+
342+
if (n != 1) {
343+
/* We only expect one device node returned when mounting encryptable volumes */
344+
SLOGE("Too many device nodes returned when mounting %d\n", getMountpoint());
345+
return -1;
346+
}
347+
348+
if (cryptfs_setup_volume(getLabel(), MAJOR(deviceNodes[0]), MINOR(deviceNodes[0]),
349+
new_sys_path, sizeof(new_sys_path),
350+
&new_major, &new_minor)) {
351+
SLOGE("Cannot setup encryption mapping for %d\n", getMountpoint());
352+
return -1;
353+
}
354+
/* We now have the new sysfs path for the decrypted block device, and the
355+
* majore and minor numbers for it. So, create the device, update the
356+
* path to the new sysfs path, and continue.
357+
*/
358+
snprintf(nodepath,
359+
sizeof(nodepath), "/dev/block/vold/%d:%d",
360+
new_major, new_minor);
361+
if (createDeviceNode(nodepath, new_major, new_minor)) {
362+
SLOGE("Error making device node '%s' (%s)", nodepath,
363+
strerror(errno));
364+
}
365+
366+
// Todo: Either create sys filename from nodepath, or pass in bogus path so
367+
// vold ignores state changes on this internal device.
368+
updateDeviceInfo(nodepath, new_major, new_minor);
369+
370+
/* Get the device nodes again, because they just changed */
371+
n = getDeviceNodes((dev_t *) &deviceNodes, 4);
372+
if (!n) {
373+
SLOGE("Failed to get device nodes (%s)\n", strerror(errno));
374+
return -1;
375+
}
376+
}
377+
315378
for (i = 0; i < n; i++) {
316379
char devicePath[255];
317380

Volume.h

+4
Original file line numberDiff line numberDiff line change
@@ -77,11 +77,15 @@ class Volume {
7777
virtual void handleVolumeUnshared();
7878

7979
void setDebug(bool enable);
80+
virtual int getVolInfo(struct volume_info *v) = 0;
8081

8182
protected:
8283
void setState(int state);
8384

8485
virtual int getDeviceNodes(dev_t *devs, int max) = 0;
86+
virtual int updateDeviceInfo(char *new_path, int new_major, int new_minor) = 0;
87+
virtual int isDecrypted(void) = 0;
88+
virtual int getFlags(void) = 0;
8589

8690
int createDeviceNode(const char *path, int major, int minor);
8791

VolumeManager.cpp

+45
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
#include "Devmapper.h"
4242
#include "Process.h"
4343
#include "Asec.h"
44+
#include "cryptfs.h"
4445

4546
VolumeManager *VolumeManager::sInstance = NULL;
4647

@@ -1130,6 +1131,50 @@ int VolumeManager::unshareVolume(const char *label, const char *method) {
11301131
return 0;
11311132
}
11321133

1134+
extern "C" int vold_unmountVol(const char *label) {
1135+
VolumeManager *vm = VolumeManager::Instance();
1136+
return vm->unmountVolume(label, true);
1137+
}
1138+
1139+
extern "C" int vold_getNumDirectVolumes(void) {
1140+
VolumeManager *vm = VolumeManager::Instance();
1141+
return vm->getNumDirectVolumes();
1142+
}
1143+
1144+
int VolumeManager::getNumDirectVolumes(void) {
1145+
VolumeCollection::iterator i;
1146+
int n=0;
1147+
1148+
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1149+
if ((*i)->getShareDevice() != (dev_t)0) {
1150+
n++;
1151+
}
1152+
}
1153+
return n;
1154+
}
1155+
1156+
extern "C" int vold_getDirectVolumeList(struct volume_info *vol_list) {
1157+
VolumeManager *vm = VolumeManager::Instance();
1158+
return vm->getDirectVolumeList(vol_list);
1159+
}
1160+
1161+
int VolumeManager::getDirectVolumeList(struct volume_info *vol_list) {
1162+
VolumeCollection::iterator i;
1163+
int n=0;
1164+
dev_t d;
1165+
1166+
for (i = mVolumes->begin(); i != mVolumes->end(); ++i) {
1167+
if ((d=(*i)->getShareDevice()) != (dev_t)0) {
1168+
(*i)->getVolInfo(&vol_list[n]);
1169+
snprintf(vol_list[n].blk_dev, sizeof(vol_list[n].blk_dev),
1170+
"/dev/block/vold/%d:%d",MAJOR(d), MINOR(d));
1171+
n++;
1172+
}
1173+
}
1174+
1175+
return 0;
1176+
}
1177+
11331178
int VolumeManager::unmountVolume(const char *label, bool force) {
11341179
Volume *v = lookupVolume(label);
11351180

VolumeManager.h

+15-1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#include <pthread.h>
2121

22+
#ifdef __cplusplus
2223
#include <utils/List.h>
2324
#include <sysutils/SocketListener.h>
2425

@@ -121,13 +122,26 @@ class VolumeManager {
121122

122123
static char *asecHash(const char *id, char *buffer, size_t len);
123124

125+
Volume *lookupVolume(const char *label);
126+
int getNumDirectVolumes(void);
127+
int getDirectVolumeList(struct volume_info *vol_list);
128+
124129
private:
125130
VolumeManager();
126131
void readInitialState();
127-
Volume *lookupVolume(const char *label);
128132
bool isMountpointMounted(const char *mp);
129133

130134
inline bool massStorageAvailable() const { return mUsbMassStorageEnabled && mUsbConnected; }
131135
void notifyUmsAvailable(bool available);
132136
};
137+
138+
extern "C" {
139+
#endif /* __cplusplus */
140+
int vold_unmountVol(const char *label);
141+
int vold_getNumDirectVolumes(void);
142+
int vold_getDirectVolumeList(struct volume_info *v);
143+
#ifdef __cplusplus
144+
}
145+
#endif
146+
133147
#endif

0 commit comments

Comments
 (0)