* Add --shared option for creating non-overlapping crypt segments.
[platform/upstream/cryptsetup.git] / lib / utils.c
1 /*
2  * utils - miscellaneous device utilities for cryptsetup
3  *
4  * Copyright (C) 2004, Christophe Saout <christophe@saout.de>
5  * Copyright (C) 2004-2007, Clemens Fruhwirth <clemens@endorphin.org>
6  * Copyright (C) 2009-2011, 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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
20  */
21
22 #include <stdio.h>
23 #include <string.h>
24 #include <stdlib.h>
25 #include <stddef.h>
26 #include <stdarg.h>
27 #include <errno.h>
28 #include <linux/fs.h>
29 #include <sys/types.h>
30 #include <unistd.h>
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <sys/ioctl.h>
34 #include <fcntl.h>
35 #include <sys/mman.h>
36 #include <sys/resource.h>
37
38 #include "libcryptsetup.h"
39 #include "internal.h"
40
41 static char *error=NULL;
42
43 __attribute__((format(printf, 1, 0)))
44 void set_error_va(const char *fmt, va_list va)
45 {
46         int r;
47
48         if(error) {
49                 free(error);
50                 error = NULL;
51         }
52
53         if(!fmt) return;
54
55         r = vasprintf(&error, fmt, va);
56         if (r < 0) {
57                 free(error);
58                 error = NULL;
59                 return;
60         }
61
62         if (r && error[r - 1] == '\n')
63                 error[r - 1] = '\0';
64 }
65
66 __attribute__((format(printf, 1, 2)))
67 void set_error(const char *fmt, ...)
68 {
69         va_list va;
70
71         va_start(va, fmt);
72         set_error_va(fmt, va);
73         va_end(va);
74 }
75
76 const char *get_error(void)
77 {
78         return error;
79 }
80
81 static int get_alignment(int fd)
82 {
83         int alignment = DEFAULT_MEM_ALIGNMENT;
84
85 #ifdef _PC_REC_XFER_ALIGN
86         alignment = fpathconf(fd, _PC_REC_XFER_ALIGN);
87         if (alignment < 0)
88                 alignment = DEFAULT_MEM_ALIGNMENT;
89 #endif
90         return alignment;
91 }
92
93 static void *aligned_malloc(void **base, int size, int alignment)
94 {
95 #ifdef HAVE_POSIX_MEMALIGN
96         return posix_memalign(base, alignment, size) ? NULL : *base;
97 #else
98 /* Credits go to Michal's padlock patches for this alignment code */
99         char *ptr;
100
101         ptr  = malloc(size + alignment);
102         if(ptr == NULL) return NULL;
103
104         *base = ptr;
105         if(alignment > 1 && ((long)ptr & (alignment - 1))) {
106                 ptr += alignment - ((long)(ptr) & (alignment - 1));
107         }
108         return ptr;
109 #endif
110 }
111
112 int device_read_ahead(const char *dev, uint32_t *read_ahead)
113 {
114         int fd, r = 0;
115         long read_ahead_long;
116
117         if ((fd = open(dev, O_RDONLY)) < 0)
118                 return 0;
119
120         r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
121         close(fd);
122
123         if (r)
124                 *read_ahead = (uint32_t) read_ahead_long;
125
126         return r;
127 }
128
129 static int sector_size(int fd) 
130 {
131         int bsize;
132         if (ioctl(fd,BLKSSZGET, &bsize) < 0)
133                 return -EINVAL;
134         else
135                 return bsize;
136 }
137
138 int sector_size_for_device(const char *device)
139 {
140         int fd = open(device, O_RDONLY);
141         int r;
142         if(fd < 0)
143                 return -EINVAL;
144         r = sector_size(fd);
145         close(fd);
146         return r;
147 }
148
149 ssize_t write_blockwise(int fd, void *orig_buf, size_t count)
150 {
151         void *hangover_buf, *hangover_buf_base = NULL;
152         void *buf, *buf_base = NULL;
153         int r, hangover, solid, bsize, alignment;
154         ssize_t ret = -1;
155
156         if ((bsize = sector_size(fd)) < 0)
157                 return bsize;
158
159         hangover = count % bsize;
160         solid = count - hangover;
161         alignment = get_alignment(fd);
162
163         if ((long)orig_buf & (alignment - 1)) {
164                 buf = aligned_malloc(&buf_base, count, alignment);
165                 if (!buf)
166                         goto out;
167                 memcpy(buf, orig_buf, count);
168         } else
169                 buf = orig_buf;
170
171         r = write(fd, buf, solid);
172         if (r < 0 || r != solid)
173                 goto out;
174
175         if (hangover) {
176                 hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
177                 if (!hangover_buf)
178                         goto out;
179
180                 r = read(fd, hangover_buf, bsize);
181                 if (r < 0 || r != bsize)
182                         goto out;
183
184                 r = lseek(fd, -bsize, SEEK_CUR);
185                 if (r < 0)
186                         goto out;
187                 memcpy(hangover_buf, (char*)buf + solid, hangover);
188
189                 r = write(fd, hangover_buf, bsize);
190                 if (r < 0 || r != bsize)
191                         goto out;
192         }
193         ret = count;
194 out:
195         free(hangover_buf_base);
196         if (buf != orig_buf)
197                 free(buf_base);
198         return ret;
199 }
200
201 ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
202         void *hangover_buf, *hangover_buf_base = NULL;
203         void *buf, *buf_base = NULL;
204         int r, hangover, solid, bsize, alignment;
205         ssize_t ret = -1;
206
207         if ((bsize = sector_size(fd)) < 0)
208                 return bsize;
209
210         hangover = count % bsize;
211         solid = count - hangover;
212         alignment = get_alignment(fd);
213
214         if ((long)orig_buf & (alignment - 1)) {
215                 buf = aligned_malloc(&buf_base, count, alignment);
216                 if (!buf)
217                         return -1;
218         } else
219                 buf = orig_buf;
220
221         r = read(fd, buf, solid);
222         if(r < 0 || r != solid)
223                 goto out;
224
225         if (hangover) {
226                 hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
227                 if (!hangover_buf)
228                         goto out;
229                 r = read(fd, hangover_buf, bsize);
230                 if (r <  0 || r != bsize)
231                         goto out;
232
233                 memcpy((char *)buf + solid, hangover_buf, hangover);
234         }
235         ret = count;
236 out:
237         free(hangover_buf_base);
238         if (buf != orig_buf) {
239                 memcpy(orig_buf, buf, count);
240                 free(buf_base);
241         }
242         return ret;
243 }
244
245 /*
246  * Combines llseek with blockwise write. write_blockwise can already deal with short writes
247  * but we also need a function to deal with short writes at the start. But this information
248  * is implicitly included in the read/write offset, which can not be set to non-aligned
249  * boundaries. Hence, we combine llseek with write.
250  */
251 ssize_t write_lseek_blockwise(int fd, char *buf, size_t count, off_t offset) {
252         char *frontPadBuf;
253         void *frontPadBuf_base = NULL;
254         int r, bsize, frontHang;
255         size_t innerCount = 0;
256         ssize_t ret = -1;
257
258         if ((bsize = sector_size(fd)) < 0)
259                 return bsize;
260
261         frontHang = offset % bsize;
262
263         if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
264                 goto out;
265
266         if (frontHang) {
267                 frontPadBuf = aligned_malloc(&frontPadBuf_base,
268                                              bsize, get_alignment(fd));
269                 if (!frontPadBuf)
270                         goto out;
271
272                 r = read(fd, frontPadBuf, bsize);
273                 if (r < 0 || r != bsize)
274                         goto out;
275
276                 innerCount = bsize - frontHang;
277                 if (innerCount > count)
278                         innerCount = count;
279
280                 memcpy(frontPadBuf + frontHang, buf, innerCount);
281
282                 if (lseek(fd, offset - frontHang, SEEK_SET) < 0)
283                         goto out;
284
285                 r = write(fd, frontPadBuf, bsize);
286                 if (r < 0 || r != bsize)
287                         goto out;
288
289                 buf += innerCount;
290                 count -= innerCount;
291         }
292
293         ret = count ? write_blockwise(fd, buf, count) : 0;
294         if (ret >= 0)
295                 ret += innerCount;
296 out:
297         free(frontPadBuf_base);
298
299         return ret;
300 }
301
302 int device_ready(struct crypt_device *cd, const char *device, int mode)
303 {
304         int devfd, r = 0;
305         ssize_t s;
306         struct stat st;
307         char buf[512];
308
309         if(stat(device, &st) < 0) {
310                 log_err(cd, _("Device %s doesn't exist or access denied.\n"), device);
311                 return -EINVAL;
312         }
313
314         if (!S_ISBLK(st.st_mode))
315                 return -ENOTBLK;
316
317         log_dbg("Trying to open and read device %s.", device);
318         devfd = open(device, mode | O_DIRECT | O_SYNC);
319         if(devfd < 0) {
320                 log_err(cd, _("Cannot open device %s for %s%s access.\n"), device,
321                         (mode & O_EXCL) ? _("exclusive ") : "",
322                         (mode & O_RDWR) ? _("writable") : _("read-only"));
323                 return -EINVAL;
324         }
325
326          /* Try to read first sector */
327         s = read_blockwise(devfd, buf, sizeof(buf));
328         if (s < 0 || s != sizeof(buf)) {
329                 log_verbose(cd, _("Cannot read device %s.\n"), device);
330                 r = -EIO;
331         }
332
333         memset(buf, 0, sizeof(buf));
334         close(devfd);
335
336         return r;
337 }
338
339 static int get_device_infos(const char *device, enum devcheck device_check,
340                             int *readonly, uint64_t *size)
341 {
342         struct stat st;
343         unsigned long size_small;
344         int fd, r = -1;
345         int flags = 0;
346
347         *readonly = 0;
348         *size = 0;
349
350         if (stat(device, &st) < 0)
351                 return -EINVAL;
352
353         /* never wipe header on mounted device */
354         if (device_check == DEV_EXCL && S_ISBLK(st.st_mode))
355                 flags |= O_EXCL;
356
357         /* Try to open read-write to check whether it is a read-only device */
358         fd = open(device, O_RDWR | flags);
359         if (fd == -1 && errno == EROFS) {
360                 *readonly = 1;
361                 fd = open(device, O_RDONLY | flags);
362         }
363
364         if (fd == -1 && device_check == DEV_EXCL && errno == EBUSY)
365                 return -EBUSY;
366
367         if (fd == -1)
368                 return -EINVAL;
369
370         /* If the device can be opened read-write, i.e. readonly is still 0, then
371          * check whether BKROGET says that it is read-only. E.g. read-only loop
372          * devices may be openend read-write but are read-only according to BLKROGET
373          */
374         if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
375                 goto out;
376
377         if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
378                 *size >>= SECTOR_SHIFT;
379                 r = 0;
380                 goto out;
381         }
382
383         if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
384                 *size = (uint64_t)size_small;
385                 r = 0;
386                 goto out;
387         }
388
389         r = -EINVAL;
390 out:
391         close(fd);
392         return r;
393 }
394
395 int device_check_and_adjust(struct crypt_device *cd,
396                             const char *device,
397                             enum devcheck device_check,
398                             uint64_t *size,
399                             uint64_t *offset,
400                             int *read_only)
401 {
402         int r, real_readonly;
403         uint64_t real_size;
404
405         if (!device)
406                 return -ENOTBLK;
407
408         r = get_device_infos(device, device_check, &real_readonly, &real_size);
409         if (r < 0) {
410                 if (r == -EBUSY)
411                         log_err(cd, _("Cannot use device %s which is in use "
412                                       "(already mapped or mounted).\n"),
413                                       device);
414                 else
415                         log_err(cd, _("Cannot get info about device %s.\n"),
416                                 device);
417                 return r;
418         }
419
420         if (!*size) {
421                 *size = real_size;
422                 if (!*size) {
423                         log_err(cd, _("Device %s has zero size.\n"), device);
424                         return -ENOTBLK;
425                 }
426                 if (*size < *offset) {
427                         log_err(cd, _("Device %s is too small.\n"), device);
428                         return -EINVAL;
429                 }
430                 *size -= *offset;
431         }
432
433         if (device_check == DEV_SHARED) {
434                 log_dbg("Checking crypt segments for device %s.", device);
435                 r = crypt_sysfs_check_crypt_segment(device, *offset, *size);
436                 if (r < 0) {
437                         log_err(cd, "Cannot use device %s (crypt segments "
438                                     "overlaps or in use by another device).\n",
439                                     device);
440                         return r;
441                 }
442         }
443
444         if (real_readonly)
445                 *read_only = 1;
446
447         log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
448                 *size, *read_only ? "RO" : "RW", *offset);
449         return 0;
450 }
451
452 int wipe_device_header(const char *device, int sectors)
453 {
454         struct stat st;
455         char *buffer;
456         int size = sectors * SECTOR_SIZE;
457         int r = -1;
458         int devfd;
459         int flags = O_RDWR | O_DIRECT | O_SYNC;
460
461         if (stat(device, &st) < 0)
462                 return -EINVAL;
463
464         /* never wipe header on mounted device */
465         if (S_ISBLK(st.st_mode))
466                 flags |= O_EXCL;
467
468         devfd = open(device, flags);
469         if(devfd == -1)
470                 return errno == EBUSY ? -EBUSY : -EINVAL;
471
472         buffer = malloc(size);
473         if (!buffer) {
474                 close(devfd);
475                 return -ENOMEM;
476         }
477         memset(buffer, 0, size);
478
479         r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
480
481         free(buffer);
482         close(devfd);
483
484         return r;
485 }
486
487 /* MEMLOCK */
488 #define DEFAULT_PROCESS_PRIORITY -18
489
490 static int _priority;
491 static int _memlock_count = 0;
492
493 // return 1 if memory is locked
494 int crypt_memlock_inc(struct crypt_device *ctx)
495 {
496         if (!_memlock_count++) {
497                 log_dbg("Locking memory.");
498                 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
499                         log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
500                         _memlock_count--;
501                         return 0;
502                 }
503                 errno = 0;
504                 if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
505                         log_err(ctx, _("Cannot get process priority.\n"));
506                 else
507                         if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY))
508                                 log_err(ctx, _("setpriority %d failed: %s\n"),
509                                         DEFAULT_PROCESS_PRIORITY, strerror(errno));
510         }
511         return _memlock_count ? 1 : 0;
512 }
513
514 int crypt_memlock_dec(struct crypt_device *ctx)
515 {
516         if (_memlock_count && (!--_memlock_count)) {
517                 log_dbg("Unlocking memory.");
518                 if (munlockall() == -1)
519                         log_err(ctx, _("Cannot unlock memory.\n"));
520                 if (setpriority(PRIO_PROCESS, 0, _priority))
521                         log_err(ctx, _("setpriority %d failed: %s\n"), _priority, strerror(errno));
522         }
523         return _memlock_count ? 1 : 0;
524 }
525
526 /* DEVICE TOPOLOGY */
527
528 /* block device topology ioctls, introduced in 2.6.32 */
529 #ifndef BLKIOMIN
530 #define BLKIOMIN    _IO(0x12,120)
531 #define BLKIOOPT    _IO(0x12,121)
532 #define BLKALIGNOFF _IO(0x12,122)
533 #endif
534
535 void get_topology_alignment(const char *device,
536                             unsigned long *required_alignment, /* bytes */
537                             unsigned long *alignment_offset,   /* bytes */
538                             unsigned long default_alignment)
539 {
540         int dev_alignment_offset = 0;
541         unsigned int min_io_size = 0, opt_io_size = 0;
542         unsigned long temp_alignment = 0;
543         int fd;
544
545         *required_alignment = default_alignment;
546         *alignment_offset = 0;
547
548         fd = open(device, O_RDONLY);
549         if (fd == -1)
550                 return;
551
552         /* minimum io size */
553         if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
554                 log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
555                         device, default_alignment);
556                 goto out;
557         }
558
559         /* optimal io size */
560         if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
561                 opt_io_size = min_io_size;
562
563         /* alignment offset, bogus -1 means misaligned/unknown */
564         if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
565                 dev_alignment_offset = 0;
566         *alignment_offset = (unsigned long)dev_alignment_offset;
567
568         temp_alignment = (unsigned long)min_io_size;
569
570         if (temp_alignment < (unsigned long)opt_io_size)
571                 temp_alignment = (unsigned long)opt_io_size;
572
573         /* If calculated alignment is multiple of default, keep default */
574         if (temp_alignment && (default_alignment % temp_alignment))
575                 *required_alignment = temp_alignment;
576
577         log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
578                 min_io_size, opt_io_size, *alignment_offset, *required_alignment);
579 out:
580         (void)close(fd);
581 }