Always zero memory in crypt_safe_alloc.
[platform/upstream/cryptsetup.git] / lib / utils_device.c
1 /*
2  * device backend utilities
3  *
4  * Copyright (C) 2004, Christophe Saout <christophe@saout.de>
5  * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
6  * Copyright (C) 2009-2012, Red Hat, Inc. All rights reserved.
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License
10  * version 2 as published by the Free Software Foundation.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program; if not, write to the Free Software
19  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20  */
21
22 #include <string.h>
23 #include <stdlib.h>
24 #include <fcntl.h>
25 #include <errno.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <sys/ioctl.h>
29 #include <linux/fs.h>
30 #include <unistd.h>
31 #include "internal.h"
32
33 struct device {
34         char *path;
35
36         char *file_path;
37         int loop_fd;
38
39         int init_done:1;
40 };
41
42 static int device_ready(const char *device)
43 {
44         int devfd, r = 0;
45         struct stat st;
46
47         if(stat(device, &st) < 0) {
48                 log_err(NULL, _("Device %s doesn't exist or access denied.\n"), device);
49                 return -EINVAL;
50         }
51
52         if (!S_ISBLK(st.st_mode))
53                 return S_ISREG(st.st_mode) ? -ENOTBLK : -EINVAL;
54
55         log_dbg("Trying to open and read device %s.", device);
56         devfd = open(device, O_RDONLY | O_DIRECT | O_SYNC);
57         if(devfd < 0) {
58                 log_err(NULL, _("Cannot open device %s.\n"), device);
59                 return -EINVAL;
60         }
61
62         close(devfd);
63         return r;
64 }
65
66 int device_alloc(struct device **device, const char *path)
67 {
68         struct device *dev;
69         int r;
70
71         if (!path) {
72                 *device = NULL;
73                 return 0;
74         }
75
76         dev = malloc(sizeof(struct device));
77         if (!dev)
78                 return -ENOMEM;
79
80         memset(dev, 0, sizeof(struct device));
81         dev->loop_fd = -1;
82
83         r = device_ready(path);
84         if (!r) {
85                 dev->init_done = 1;
86         } else if (r == -ENOTBLK) {
87                 /* alloc loop later */
88         } else if (r < 0) {
89                 free(dev);
90                 return -ENOTBLK;
91         }
92
93         dev->path = strdup(path);
94         if (!dev->path) {
95                 free(dev);
96                 return -ENOMEM;
97         }
98
99         *device = dev;
100         return 0;
101 }
102
103 void device_free(struct device *device)
104 {
105         if (!device)
106                 return;
107
108         if (device->loop_fd != -1) {
109                 log_dbg("Closed loop %s (%s).", device->path, device->file_path);
110                 close(device->loop_fd);
111         }
112
113         free(device->file_path);
114         free(device->path);
115         free(device);
116 }
117
118 /* Get block device path */
119 const char *device_block_path(const struct device *device)
120 {
121         if (!device || !device->init_done)
122                 return NULL;
123
124         return device->path;
125 }
126
127 /* Get path to device / file */
128 const char *device_path(const struct device *device)
129 {
130         if (!device)
131                 return NULL;
132
133         if (device->file_path)
134                 return device->file_path;
135
136         return device->path;
137 }
138
139 /* block device topology ioctls, introduced in 2.6.32 */
140 #ifndef BLKIOMIN
141 #define BLKIOMIN    _IO(0x12,120)
142 #define BLKIOOPT    _IO(0x12,121)
143 #define BLKALIGNOFF _IO(0x12,122)
144 #endif
145
146 void device_topology_alignment(struct device *device,
147                             unsigned long *required_alignment, /* bytes */
148                             unsigned long *alignment_offset,   /* bytes */
149                             unsigned long default_alignment)
150 {
151         int dev_alignment_offset = 0;
152         unsigned int min_io_size = 0, opt_io_size = 0;
153         unsigned long temp_alignment = 0;
154         int fd;
155
156         *required_alignment = default_alignment;
157         *alignment_offset = 0;
158
159         if (!device || !device->path) //FIXME
160                 return;
161
162         fd = open(device->path, O_RDONLY);
163         if (fd == -1)
164                 return;
165
166         /* minimum io size */
167         if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
168                 log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
169                         device->path, default_alignment);
170                 goto out;
171         }
172
173         /* optimal io size */
174         if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
175                 opt_io_size = min_io_size;
176
177         /* alignment offset, bogus -1 means misaligned/unknown */
178         if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
179                 dev_alignment_offset = 0;
180         *alignment_offset = (unsigned long)dev_alignment_offset;
181
182         temp_alignment = (unsigned long)min_io_size;
183
184         if (temp_alignment < (unsigned long)opt_io_size)
185                 temp_alignment = (unsigned long)opt_io_size;
186
187         /* If calculated alignment is multiple of default, keep default */
188         if (temp_alignment && (default_alignment % temp_alignment))
189                 *required_alignment = temp_alignment;
190
191         log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
192                 min_io_size, opt_io_size, *alignment_offset, *required_alignment);
193 out:
194         (void)close(fd);
195 }
196
197 int device_block_size(struct device *device)
198 {
199         struct stat st;
200         int fd, bsize = 0, r = -EINVAL;
201
202         if (!device)
203                 return 0;
204
205         fd = open(device->path, O_RDONLY);
206         if(fd < 0)
207                 return -EINVAL;
208
209         if (fstat(fd, &st) < 0)
210                 goto out;
211
212         if (S_ISREG(st.st_mode)) {
213                 r = (int)crypt_getpagesize();
214                 goto out;
215         }
216
217         if (ioctl(fd, BLKSSZGET, &bsize) >= 0)
218                 r = bsize;
219 out:
220         close(fd);
221         return r;
222 }
223
224 int device_read_ahead(struct device *device, uint32_t *read_ahead)
225 {
226         int fd, r = 0;
227         long read_ahead_long;
228
229         if (!device)
230                 return 0;
231
232         if ((fd = open(device->path, O_RDONLY)) < 0)
233                 return 0;
234
235         r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
236         close(fd);
237
238         if (r)
239                 *read_ahead = (uint32_t) read_ahead_long;
240
241         return r;
242 }
243
244 /* Get data size in bytes */
245 int device_size(struct device *device, uint64_t *size)
246 {
247         struct stat st;
248         int devfd, r = -EINVAL;
249
250         devfd = open(device->path, O_RDONLY);
251         if(devfd == -1)
252                 return -EINVAL;
253
254         if (fstat(devfd, &st) < 0)
255                 goto out;
256
257         if (S_ISREG(st.st_mode)) {
258                 *size = (uint64_t)st.st_size;
259                 r = 0;
260         } else if (ioctl(devfd, BLKGETSIZE64, size) >= 0)
261                 r = 0;
262 out:
263         close(devfd);
264         return r;
265 }
266
267 static int device_info(struct device *device,
268                         enum devcheck device_check,
269                         int *readonly, uint64_t *size)
270 {
271         struct stat st;
272         int fd, r = -EINVAL, flags = 0;
273
274         *readonly = 0;
275         *size = 0;
276
277         if (stat(device->path, &st) < 0)
278                 return -EINVAL;
279
280         /* never wipe header on mounted device */
281         if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
282                 flags |= O_EXCL;
283
284         /* Try to open read-write to check whether it is a read-only device */
285         fd = open(device->path, O_RDWR | flags);
286         if (fd == -1 && errno == EROFS) {
287                 *readonly = 1;
288                 fd = open(device->path, O_RDONLY | flags);
289         }
290
291         if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
292                 return -EBUSY;
293
294         if (fd == -1)
295                 return -EINVAL;
296
297         if (S_ISREG(st.st_mode)) {
298                 //FIXME: add readonly check
299                 *size = (uint64_t)st.st_size;
300                 *size >>= SECTOR_SHIFT;
301         } else {
302                 /* If the device can be opened read-write, i.e. readonly is still 0, then
303                  * check whether BKROGET says that it is read-only. E.g. read-only loop
304                  * devices may be openend read-write but are read-only according to BLKROGET
305                  */
306                 if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
307                         goto out;
308
309                 if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
310                         *size >>= SECTOR_SHIFT;
311                         r = 0;
312                         goto out;
313                 }
314         }
315         r = -EINVAL;
316 out:
317         close(fd);
318         return r;
319 }
320
321 static int device_internal_prepare(struct crypt_device *cd, struct device *device)
322 {
323         char *loop_device;
324         int r, loop_fd, readonly = 0;
325
326         if (device->init_done)
327                 return 0;
328
329         log_dbg("Allocating a free loop device.");
330         loop_device = crypt_loop_get_device();
331         if (!loop_device) {
332                 if (getuid() || geteuid())
333                         log_err(cd, _("Cannot use a loopback device, "
334                                       "running as non-root user.\n"));
335                 else
336                         log_err(cd, _("Cannot find a free loopback device.\n"));
337                 return -ENOTSUP;
338         }
339
340         /* Keep the loop open, dettached on last close. */
341         loop_fd = crypt_loop_attach(loop_device, device->path, 0, 1, &readonly);
342         if (loop_fd == -1) {
343                 log_err(cd, _("Attaching loopback device failed "
344                         "(loop device with autoclear flag is required).\n"));
345                 free(loop_device);
346                 return -EINVAL;
347         }
348
349         r = device_ready(loop_device);
350         if (r < 0) {
351                 free(loop_device);
352                 return r;
353         }
354
355         device->loop_fd = loop_fd;
356         device->file_path = device->path;
357         device->path = loop_device;
358         device->init_done = 1;
359
360         return 0;
361 }
362
363 int device_block_adjust(struct crypt_device *cd,
364                         struct device *device,
365                         enum devcheck device_check,
366                         uint64_t device_offset,
367                         uint64_t *size,
368                         uint32_t *flags)
369 {
370         int r, real_readonly;
371         uint64_t real_size;
372
373         if (!device)
374                 return -ENOTBLK;
375
376         r = device_internal_prepare(cd, device);
377         if (r)
378                 return r;
379
380         r = device_info(device, device_check, &real_readonly, &real_size);
381         if (r < 0) {
382                 if (r == -EBUSY)
383                         log_err(cd, _("Cannot use device %s which is in use "
384                                       "(already mapped or mounted).\n"),
385                                       device->path);
386                 else
387                         log_err(cd, _("Cannot get info about device %s.\n"),
388                                 device->path);
389                 return r;
390         }
391
392         if (device_offset >= real_size) {
393                 log_err(cd, _("Requested offset is beyond real size of device %s.\n"),
394                         device->path);
395                 return -EINVAL;
396         }
397
398         if (size && !*size) {
399                 *size = real_size;
400                 if (!*size) {
401                         log_err(cd, _("Device %s has zero size.\n"), device->path);
402                         return -ENOTBLK;
403                 }
404                 *size -= device_offset;
405         }
406
407         /* in case of size is set by parameter */
408         if (size && ((real_size - device_offset) < *size)) {
409                 log_dbg("Device %s: offset = %" PRIu64 " requested size = %" PRIu64
410                         ", backing device size = %" PRIu64,
411                         device->path, device_offset, *size, real_size);
412                 log_err(cd, _("Device %s is too small.\n"), device->path);
413                 return -EINVAL;
414         }
415
416         if (flags && real_readonly)
417                 *flags |= CRYPT_ACTIVATE_READONLY;
418
419         if (size)
420                 log_dbg("Calculated device size is %" PRIu64" sectors (%s), offset %" PRIu64 ".",
421                 *size, real_readonly ? "RO" : "RW", device_offset);
422         return 0;
423 }