38
38
#include " Fat.h"
39
39
#include " Devmapper.h"
40
40
#include " Process.h"
41
+ #include " Asec.h"
41
42
42
43
VolumeManager *VolumeManager::sInstance = NULL ;
43
44
@@ -168,6 +169,11 @@ int VolumeManager::getAsecMountPath(const char *id, char *buffer, int maxlen) {
168
169
169
170
int VolumeManager::createAsec (const char *id, unsigned int numSectors,
170
171
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;
171
177
172
178
if (numSectors < ((1024 *1024 )/512 )) {
173
179
LOGE (" Invalid container size specified (%d sectors)" , numSectors);
@@ -191,7 +197,18 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
191
197
return -1 ;
192
198
}
193
199
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 )) {
195
212
LOGE (" ASEC image file creation failed (%s)" , strerror (errno));
196
213
return -1 ;
197
214
}
@@ -207,7 +224,9 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
207
224
bool cleanupDm = false ;
208
225
209
226
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,
211
230
sizeof (dmDevice))) {
212
231
LOGE (" ASEC device mapping failed (%s)" , strerror (errno));
213
232
Loop::destroyByDevice (loopDevice);
@@ -216,15 +235,54 @@ int VolumeManager::createAsec(const char *id, unsigned int numSectors,
216
235
}
217
236
cleanupDm = true ;
218
237
} else {
238
+ sb.c_cipher = ASEC_SB_C_CIPHER_NONE;
219
239
strcpy (dmDevice, loopDevice);
220
240
}
221
241
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
+
222
280
if (strcmp (fstype, " none" )) {
223
281
if (strcmp (fstype, " fat" )) {
224
282
LOGW (" Unknown fstype '%s' specified for container" , fstype);
225
283
}
226
284
227
- if (Fat::format (dmDevice)) {
285
+ if (Fat::format (dmDevice, numImgSectors )) {
228
286
LOGE (" ASEC FAT format failed (%s)" , strerror (errno));
229
287
if (cleanupDm) {
230
288
Devmapper::destroy (id);
@@ -467,24 +525,53 @@ int VolumeManager::mountAsec(const char *id, const char *key, int ownerUid) {
467
525
468
526
char dmDevice[255 ];
469
527
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 ;
474
530
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
+ }
480
536
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))) {
488
575
if (Devmapper::create (id, loopDevice, key, nr_sec,
489
576
dmDevice, sizeof (dmDevice))) {
490
577
LOGE (" ASEC device mapping failed (%s)" , strerror (errno));
0 commit comments