Skip to content

Commit fcf24fe

Browse files
author
San Mehat
committed
vold: Add a versioned superblock to secure containers.
Add an un-encrypted superblock to the end of a secure container to help identify the crypto cipher used. This is required in order to provide some semblence of versioning, in case we have cause to change the crypto type on an update - say for example switching from software to hardware encryption, or from 128 -> a zillion bit keys. NOTE: This format is incompatible with previous secure containers. After this change they will no longer be mountable. Signed-off-by: San Mehat <[email protected]>
1 parent 2350c44 commit fcf24fe

File tree

6 files changed

+170
-40
lines changed

6 files changed

+170
-40
lines changed

Asec.h

+42
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/*
2+
* Copyright (C) 2008 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#ifndef _ASEC_H
18+
#define _ASEC_H
19+
20+
struct asec_superblock {
21+
#define ASEC_SB_MAGIC 0xc0def00d
22+
unsigned int magic;
23+
24+
#define ASEC_SB_VER 1
25+
unsigned char ver;
26+
27+
#define ASEC_SB_C_CIPHER_NONE 0
28+
#define ASEC_SB_C_CIPHER_TWOFISH 1
29+
#define ASEC_SB_C_CIPHER_AES 2
30+
unsigned char c_cipher;
31+
32+
#define ASEC_SB_C_CHAIN_NONE 0
33+
unsigned char c_chain;
34+
35+
#define ASEC_SB_C_OPTS_NONE 0
36+
unsigned char c_opts;
37+
38+
#define ASEC_SB_C_MODE_NONE 0
39+
unsigned char c_mode;
40+
} __attribute__((packed));
41+
42+
#endif

Devmapper.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -136,8 +136,10 @@ int Devmapper::create(const char *name, const char *loopFile, const char *key,
136136
ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG);
137137
io->target_count = 1;
138138
tgt->status = 0;
139+
139140
tgt->sector_start = 0;
140141
tgt->length = numSectors;
142+
141143
strcpy(tgt->target_type, "crypt");
142144

143145
char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec);

Fat.cpp

+18-19
Original file line numberDiff line numberDiff line change
@@ -148,34 +148,33 @@ int Fat::doMount(const char *fsPath, const char *mountPoint,
148148
return rc;
149149
}
150150

151-
int Fat::format(const char *fsPath) {
152-
unsigned int nr_sec;
151+
int Fat::format(const char *fsPath, unsigned int numSectors) {
153152
int fd;
154-
155-
if ((fd = open(fsPath, O_RDWR)) < 0) {
156-
LOGE("Error opening disk file (%s)", strerror(errno));
157-
return -1;
158-
}
159-
160-
if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
161-
LOGE("Unable to get device size (%s)", strerror(errno));
162-
close(fd);
163-
return -1;
164-
}
165-
close(fd);
166-
167-
const char *args[9];
153+
const char *args[11];
168154
int rc;
155+
169156
args[0] = MKDOSFS_PATH;
170157
args[1] = "-F";
171158
args[2] = "32";
172159
args[3] = "-O";
173160
args[4] = "android";
174161
args[5] = "-c";
175162
args[6] = "8";
176-
args[7] = fsPath;
177-
args[8] = NULL;
178-
rc = logwrap(9, args, 1);
163+
164+
if (numSectors) {
165+
char tmp[32];
166+
snprintf(tmp, sizeof(tmp), "%u", numSectors);
167+
const char *size = tmp;
168+
args[7] = "-s";
169+
args[8] = size;
170+
args[9] = fsPath;
171+
args[10] = NULL;
172+
rc = logwrap(11, args, 1);
173+
} else {
174+
args[7] = fsPath;
175+
args[8] = NULL;
176+
rc = logwrap(9, args, 1);
177+
}
179178

180179
if (rc == 0) {
181180
LOGI("Filesystem formatted OK");

Fat.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Fat {
2525
static int doMount(const char *fsPath, const char *mountPoint, bool ro,
2626
bool remount, int ownerUid, int ownerGid, int permMask,
2727
bool createLost);
28-
static int format(const char *fsPath);
28+
static int format(const char *fsPath, unsigned int numSectors);
2929
};
3030

3131
#endif

Volume.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ int Volume::formatVol() {
194194
sprintf(devicePath, "/dev/block/vold/%d:%d",
195195
MAJOR(partNode), MINOR(partNode));
196196

197-
if (Fat::format(devicePath)) {
197+
if (Fat::format(devicePath, 0)) {
198198
LOGE("Failed to format (%s)", strerror(errno));
199199
goto err;
200200
}

VolumeManager.cpp

+106-19
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "Fat.h"
3939
#include "Devmapper.h"
4040
#include "Process.h"
41+
#include "Asec.h"
4142

4243
VolumeManager *VolumeManager::sInstance = NULL;
4344

@@ -168,6 +169,11 @@ int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
168169

169170
int VolumeManager::createAsec(const char *id, unsigned int numSectors,
170171
const char *fstype, const char *key, int ownerUid) {
172+
struct asec_superblock sb;
173+
memset(&sb, 0, sizeof(sb));
174+
175+
sb.magic = ASEC_SB_MAGIC;
176+
sb.ver = ASEC_SB_VER;
171177

172178
if (numSectors < ((1024*1024)/512)) {
173179
LOGE("Invalid container size specified (%d sectors)", numSectors);
@@ -191,7 +197,18 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
191197
return -1;
192198
}
193199

194-
if (Loop::createImageFile(asecFileName, numSectors)) {
200+
/*
201+
* Add some headroom
202+
*/
203+
unsigned fatSize = (((numSectors * 4) / 512) + 1) * 2;
204+
unsigned numImgSectors = numSectors + fatSize + 2;
205+
206+
if (numImgSectors % 63) {
207+
numImgSectors += (63 - (numImgSectors % 63));
208+
}
209+
210+
// Add +1 for our superblock which is at the end
211+
if (Loop::createImageFile(asecFileName, numImgSectors + 1)) {
195212
LOGE("ASEC image file creation failed (%s)", strerror(errno));
196213
return -1;
197214
}
@@ -207,7 +224,9 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
207224
bool cleanupDm = false;
208225

209226
if (strcmp(key, "none")) {
210-
if (Devmapper::create(id, loopDevice, key, numSectors, dmDevice,
227+
// XXX: This is all we support for now
228+
sb.c_cipher = ASEC_SB_C_CIPHER_TWOFISH;
229+
if (Devmapper::create(id, loopDevice, key, numImgSectors, dmDevice,
211230
sizeof(dmDevice))) {
212231
LOGE("ASEC device mapping failed (%s)", strerror(errno));
213232
Loop::destroyByDevice(loopDevice);
@@ -216,15 +235,54 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
216235
}
217236
cleanupDm = true;
218237
} else {
238+
sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
219239
strcpy(dmDevice, loopDevice);
220240
}
221241

242+
/*
243+
* Drop down the superblock at the end of the file
244+
*/
245+
246+
int sbfd = open(loopDevice, O_RDWR);
247+
if (sbfd < 0) {
248+
LOGE("Failed to open new DM device for superblock write (%s)", strerror(errno));
249+
if (cleanupDm) {
250+
Devmapper::destroy(id);
251+
}
252+
Loop::destroyByDevice(loopDevice);
253+
unlink(asecFileName);
254+
return -1;
255+
}
256+
257+
if (lseek(sbfd, (numImgSectors * 512), SEEK_SET) < 0) {
258+
close(sbfd);
259+
LOGE("Failed to lseek for superblock (%s)", strerror(errno));
260+
if (cleanupDm) {
261+
Devmapper::destroy(id);
262+
}
263+
Loop::destroyByDevice(loopDevice);
264+
unlink(asecFileName);
265+
return -1;
266+
}
267+
268+
if (write(sbfd, &sb, sizeof(sb)) != sizeof(sb)) {
269+
close(sbfd);
270+
LOGE("Failed to write superblock (%s)", strerror(errno));
271+
if (cleanupDm) {
272+
Devmapper::destroy(id);
273+
}
274+
Loop::destroyByDevice(loopDevice);
275+
unlink(asecFileName);
276+
return -1;
277+
}
278+
close(sbfd);
279+
222280
if (strcmp(fstype, "none")) {
223281
if (strcmp(fstype, "fat")) {
224282
LOGW("Unknown fstype '%s' specified for container", fstype);
225283
}
226284

227-
if (Fat::format(dmDevice)) {
285+
if (Fat::format(dmDevice, numImgSectors)) {
228286
LOGE("ASEC FAT format failed (%s)", strerror(errno));
229287
if (cleanupDm) {
230288
Devmapper::destroy(id);
@@ -467,24 +525,53 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
467525

468526
char dmDevice[255];
469527
bool cleanupDm = false;
470-
if (strcmp(key, "none")) {
471-
if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
472-
unsigned int nr_sec = 0;
473-
int fd;
528+
int fd;
529+
unsigned int nr_sec = 0;
474530

475-
if ((fd = open(loopDevice, O_RDWR)) < 0) {
476-
LOGE("Failed to open loopdevice (%s)", strerror(errno));
477-
Loop::destroyByDevice(loopDevice);
478-
return -1;
479-
}
531+
if ((fd = open(loopDevice, O_RDWR)) < 0) {
532+
LOGE("Failed to open loopdevice (%s)", strerror(errno));
533+
Loop::destroyByDevice(loopDevice);
534+
return -1;
535+
}
480536

481-
if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
482-
LOGE("Failed to get loop size (%s)", strerror(errno));
483-
Loop::destroyByDevice(loopDevice);
484-
close(fd);
485-
return -1;
486-
}
487-
close(fd);
537+
if (ioctl(fd, BLKGETSIZE, &nr_sec)) {
538+
LOGE("Failed to get loop size (%s)", strerror(errno));
539+
Loop::destroyByDevice(loopDevice);
540+
close(fd);
541+
return -1;
542+
}
543+
544+
/*
545+
* Validate superblock
546+
*/
547+
struct asec_superblock sb;
548+
memset(&sb, 0, sizeof(sb));
549+
if (lseek(fd, ((nr_sec-1) * 512), SEEK_SET) < 0) {
550+
LOGE("lseek failed (%s)", strerror(errno));
551+
close(fd);
552+
Loop::destroyByDevice(loopDevice);
553+
return -1;
554+
}
555+
if (read(fd, &sb, sizeof(sb)) != sizeof(sb)) {
556+
LOGE("superblock read failed (%s)", strerror(errno));
557+
close(fd);
558+
Loop::destroyByDevice(loopDevice);
559+
return -1;
560+
}
561+
562+
close(fd);
563+
564+
LOGD("Container sb magic/ver (%.8x/%.2x)", sb.magic, sb.ver);
565+
if (sb.magic != ASEC_SB_MAGIC || sb.ver != ASEC_SB_VER) {
566+
LOGE("Bad container magic/version (%.8x/%.2x)", sb.magic, sb.ver);
567+
Loop::destroyByDevice(loopDevice);
568+
errno = EMEDIUMTYPE;
569+
return -1;
570+
}
571+
nr_sec--; // We don't want the devmapping to extend onto our superblock
572+
573+
if (strcmp(key, "none")) {
574+
if (Devmapper::lookupActive(id, dmDevice, sizeof(dmDevice))) {
488575
if (Devmapper::create(id, loopDevice, key, nr_sec,
489576
dmDevice, sizeof(dmDevice))) {
490577
LOGE("ASEC device mapping failed (%s)", strerror(errno));

0 commit comments

Comments
 (0)