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 #include <stdio.h> 18 #include <fcntl.h> 19 #include <unistd.h> 20 #include <errno.h> 21 #include <string.h> 22 23 #include <sys/types.h> 24 #include <sys/ioctl.h> 25 #include <sys/stat.h> 26 27 #include <linux/kdev_t.h> 28 29 #define LOG_TAG "Vold" 30 31 #include <cutils/log.h> 32 33 #include <sysutils/SocketClient.h> 34 35 #include "Devmapper.h" 36 dumpState(SocketClient * c)37 int Devmapper::dumpState(SocketClient *c) { 38 39 char *buffer = (char *) malloc(1024 * 64); 40 if (!buffer) { 41 SLOGE("Error allocating memory (%s)", strerror(errno)); 42 return -1; 43 } 44 memset(buffer, 0, (1024 * 64)); 45 46 char *buffer2 = (char *) malloc(4096); 47 if (!buffer2) { 48 SLOGE("Error allocating memory (%s)", strerror(errno)); 49 free(buffer); 50 return -1; 51 } 52 53 int fd; 54 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 55 SLOGE("Error opening devmapper (%s)", strerror(errno)); 56 free(buffer); 57 free(buffer2); 58 return -1; 59 } 60 61 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 62 ioctlInit(io, (1024 * 64), NULL, 0); 63 64 if (ioctl(fd, DM_LIST_DEVICES, io)) { 65 SLOGE("DM_LIST_DEVICES ioctl failed (%s)", strerror(errno)); 66 free(buffer); 67 free(buffer2); 68 close(fd); 69 return -1; 70 } 71 72 struct dm_name_list *n = (struct dm_name_list *) (((char *) buffer) + io->data_start); 73 if (!n->dev) { 74 free(buffer); 75 free(buffer2); 76 close(fd); 77 return 0; 78 } 79 80 unsigned nxt = 0; 81 do { 82 n = (struct dm_name_list *) (((char *) n) + nxt); 83 84 memset(buffer2, 0, 4096); 85 struct dm_ioctl *io2 = (struct dm_ioctl *) buffer2; 86 ioctlInit(io2, 4096, n->name, 0); 87 if (ioctl(fd, DM_DEV_STATUS, io2)) { 88 if (errno != ENXIO) { 89 SLOGE("DM_DEV_STATUS ioctl failed (%s)", strerror(errno)); 90 } 91 io2 = NULL; 92 } 93 94 char *tmp; 95 if (!io2) { 96 asprintf(&tmp, "%s %llu:%llu (no status available)", n->name, MAJOR(n->dev), MINOR(n->dev)); 97 } else { 98 asprintf(&tmp, "%s %llu:%llu %d %d 0x%.8x %llu:%llu", n->name, MAJOR(n->dev), 99 MINOR(n->dev), io2->target_count, io2->open_count, io2->flags, MAJOR(io2->dev), 100 MINOR(io2->dev)); 101 } 102 c->sendMsg(0, tmp, false); 103 free(tmp); 104 nxt = n->next; 105 } while (nxt); 106 107 free(buffer); 108 free(buffer2); 109 close(fd); 110 return 0; 111 } 112 ioctlInit(struct dm_ioctl * io,size_t dataSize,const char * name,unsigned flags)113 void Devmapper::ioctlInit(struct dm_ioctl *io, size_t dataSize, 114 const char *name, unsigned flags) { 115 memset(io, 0, dataSize); 116 io->data_size = dataSize; 117 io->data_start = sizeof(struct dm_ioctl); 118 io->version[0] = 4; 119 io->version[1] = 0; 120 io->version[2] = 0; 121 io->flags = flags; 122 if (name) { 123 strncpy(io->name, name, sizeof(io->name)); 124 } 125 } 126 lookupActive(const char * name,char * ubuffer,size_t len)127 int Devmapper::lookupActive(const char *name, char *ubuffer, size_t len) { 128 char *buffer = (char *) malloc(4096); 129 if (!buffer) { 130 SLOGE("Error allocating memory (%s)", strerror(errno)); 131 return -1; 132 } 133 134 int fd; 135 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 136 SLOGE("Error opening devmapper (%s)", strerror(errno)); 137 free(buffer); 138 return -1; 139 } 140 141 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 142 143 ioctlInit(io, 4096, name, 0); 144 if (ioctl(fd, DM_DEV_STATUS, io)) { 145 if (errno != ENXIO) { 146 SLOGE("DM_DEV_STATUS ioctl failed for lookup (%s)", strerror(errno)); 147 } 148 free(buffer); 149 close(fd); 150 return -1; 151 } 152 close(fd); 153 154 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 155 free(buffer); 156 snprintf(ubuffer, len, "/dev/block/dm-%u", minor); 157 return 0; 158 } 159 create(const char * name,const char * loopFile,const char * key,unsigned int numSectors,char * ubuffer,size_t len)160 int Devmapper::create(const char *name, const char *loopFile, const char *key, 161 unsigned int numSectors, char *ubuffer, size_t len) { 162 char *buffer = (char *) malloc(4096); 163 if (!buffer) { 164 SLOGE("Error allocating memory (%s)", strerror(errno)); 165 return -1; 166 } 167 168 int fd; 169 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 170 SLOGE("Error opening devmapper (%s)", strerror(errno)); 171 free(buffer); 172 return -1; 173 } 174 175 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 176 177 // Create the DM device 178 ioctlInit(io, 4096, name, 0); 179 180 if (ioctl(fd, DM_DEV_CREATE, io)) { 181 SLOGE("Error creating device mapping (%s)", strerror(errno)); 182 free(buffer); 183 close(fd); 184 return -1; 185 } 186 187 // Set the legacy geometry 188 ioctlInit(io, 4096, name, 0); 189 190 char *geoParams = buffer + sizeof(struct dm_ioctl); 191 // bps=512 spc=8 res=32 nft=2 sec=8190 mid=0xf0 spt=63 hds=64 hid=0 bspf=8 rdcl=2 infs=1 bkbs=2 192 strcpy(geoParams, "0 64 63 0"); 193 geoParams += strlen(geoParams) + 1; 194 geoParams = (char *) _align(geoParams, 8); 195 if (ioctl(fd, DM_DEV_SET_GEOMETRY, io)) { 196 SLOGE("Error setting device geometry (%s)", strerror(errno)); 197 free(buffer); 198 close(fd); 199 return -1; 200 } 201 202 // Retrieve the device number we were allocated 203 ioctlInit(io, 4096, name, 0); 204 if (ioctl(fd, DM_DEV_STATUS, io)) { 205 SLOGE("Error retrieving devmapper status (%s)", strerror(errno)); 206 free(buffer); 207 close(fd); 208 return -1; 209 } 210 211 unsigned minor = (io->dev & 0xff) | ((io->dev >> 12) & 0xfff00); 212 snprintf(ubuffer, len, "/dev/block/dm-%u", minor); 213 214 // Load the table 215 struct dm_target_spec *tgt; 216 tgt = (struct dm_target_spec *) &buffer[sizeof(struct dm_ioctl)]; 217 218 ioctlInit(io, 4096, name, DM_STATUS_TABLE_FLAG); 219 io->target_count = 1; 220 tgt->status = 0; 221 222 tgt->sector_start = 0; 223 tgt->length = numSectors; 224 225 strcpy(tgt->target_type, "crypt"); 226 227 char *cryptParams = buffer + sizeof(struct dm_ioctl) + sizeof(struct dm_target_spec); 228 sprintf(cryptParams, "twofish %s 0 %s 0", key, loopFile); 229 cryptParams += strlen(cryptParams) + 1; 230 cryptParams = (char *) _align(cryptParams, 8); 231 tgt->next = cryptParams - buffer; 232 233 if (ioctl(fd, DM_TABLE_LOAD, io)) { 234 SLOGE("Error loading mapping table (%s)", strerror(errno)); 235 free(buffer); 236 close(fd); 237 return -1; 238 } 239 240 // Resume the new table 241 ioctlInit(io, 4096, name, 0); 242 243 if (ioctl(fd, DM_DEV_SUSPEND, io)) { 244 SLOGE("Error Resuming (%s)", strerror(errno)); 245 free(buffer); 246 close(fd); 247 return -1; 248 } 249 250 free(buffer); 251 252 close(fd); 253 return 0; 254 } 255 destroy(const char * name)256 int Devmapper::destroy(const char *name) { 257 char *buffer = (char *) malloc(4096); 258 if (!buffer) { 259 SLOGE("Error allocating memory (%s)", strerror(errno)); 260 return -1; 261 } 262 263 int fd; 264 if ((fd = open("/dev/device-mapper", O_RDWR)) < 0) { 265 SLOGE("Error opening devmapper (%s)", strerror(errno)); 266 free(buffer); 267 return -1; 268 } 269 270 struct dm_ioctl *io = (struct dm_ioctl *) buffer; 271 272 // Create the DM device 273 ioctlInit(io, 4096, name, 0); 274 275 if (ioctl(fd, DM_DEV_REMOVE, io)) { 276 if (errno != ENXIO) { 277 SLOGE("Error destroying device mapping (%s)", strerror(errno)); 278 } 279 free(buffer); 280 close(fd); 281 return -1; 282 } 283 284 free(buffer); 285 close(fd); 286 return 0; 287 } 288 _align(void * ptr,unsigned int a)289 void *Devmapper::_align(void *ptr, unsigned int a) 290 { 291 register unsigned long agn = --a; 292 293 return (void *) (((unsigned long) ptr + agn) & ~agn); 294 } 295 296