Move devpath scan to separate file.
[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 int get_device_infos(const char *device,
340                      int open_exclusive,
341                      int *readonly,
342                      uint64_t *size)
343 {
344         struct stat st;
345         unsigned long size_small;
346         int fd, r = -1;
347         int flags = 0;
348
349         *readonly = 0;
350         *size = 0;
351
352         if (stat(device, &st) < 0)
353                 return -EINVAL;
354
355         /* never wipe header on mounted device */
356         if (open_exclusive && S_ISBLK(st.st_mode))
357                 flags |= O_EXCL;
358
359         /* Try to open read-write to check whether it is a read-only device */
360         fd = open(device, O_RDWR | flags);
361         if (fd == -1 && errno == EROFS) {
362                 *readonly = 1;
363                 fd = open(device, O_RDONLY | flags);
364         }
365
366         if (fd == -1 && open_exclusive && errno == EBUSY)
367                 return -EBUSY;
368
369         if (fd == -1)
370                 return -EINVAL;
371
372         /* If the device can be opened read-write, i.e. readonly is still 0, then
373          * check whether BKROGET says that it is read-only. E.g. read-only loop
374          * devices may be openend read-write but are read-only according to BLKROGET
375          */
376         if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
377                 goto out;
378
379         if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
380                 *size >>= SECTOR_SHIFT;
381                 r = 0;
382                 goto out;
383         }
384
385         if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
386                 *size = (uint64_t)size_small;
387                 r = 0;
388                 goto out;
389         }
390
391         r = -EINVAL;
392 out:
393         close(fd);
394         return r;
395 }
396
397 int device_check_and_adjust(struct crypt_device *cd,
398                             const char *device,
399                             int open_exclusive,
400                             uint64_t *size,
401                             uint64_t *offset,
402                             int *read_only)
403 {
404         int r, real_readonly;
405         uint64_t real_size;
406
407         if (!device)
408                 return -ENOTBLK;
409
410         r = get_device_infos(device, open_exclusive, &real_readonly, &real_size);
411         if (r < 0) {
412                 if (r == -EBUSY)
413                         log_err(cd, _("Cannot use device %s which is in use "
414                                       "(already mapped or mounted).\n"),
415                                       device);
416                 else
417                         log_err(cd, _("Cannot get info about device %s.\n"),
418                                 device);
419                 return r;
420         }
421
422         if (!*size) {
423                 *size = real_size;
424                 if (!*size) {
425                         log_err(cd, _("Device %s has zero size.\n"), device);
426                         return -ENOTBLK;
427                 }
428                 if (*size < *offset) {
429                         log_err(cd, _("Device %s is too small.\n"), device);
430                         return -EINVAL;
431                 }
432                 *size -= *offset;
433         }
434
435         if (real_readonly)
436                 *read_only = 1;
437
438         log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
439                 *size, *read_only ? "RO" : "RW", *offset);
440         return 0;
441 }
442
443 int wipe_device_header(const char *device, int sectors)
444 {
445         struct stat st;
446         char *buffer;
447         int size = sectors * SECTOR_SIZE;
448         int r = -1;
449         int devfd;
450         int flags = O_RDWR | O_DIRECT | O_SYNC;
451
452         if (stat(device, &st) < 0)
453                 return -EINVAL;
454
455         /* never wipe header on mounted device */
456         if (S_ISBLK(st.st_mode))
457                 flags |= O_EXCL;
458
459         devfd = open(device, flags);
460         if(devfd == -1)
461                 return errno == EBUSY ? -EBUSY : -EINVAL;
462
463         buffer = malloc(size);
464         if (!buffer) {
465                 close(devfd);
466                 return -ENOMEM;
467         }
468         memset(buffer, 0, size);
469
470         r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
471
472         free(buffer);
473         close(devfd);
474
475         return r;
476 }
477
478 /* MEMLOCK */
479 #define DEFAULT_PROCESS_PRIORITY -18
480
481 static int _priority;
482 static int _memlock_count = 0;
483
484 // return 1 if memory is locked
485 int crypt_memlock_inc(struct crypt_device *ctx)
486 {
487         if (!_memlock_count++) {
488                 log_dbg("Locking memory.");
489                 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
490                         log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
491                         _memlock_count--;
492                         return 0;
493                 }
494                 errno = 0;
495                 if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
496                         log_err(ctx, _("Cannot get process priority.\n"));
497                 else
498                         if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY))
499                                 log_err(ctx, _("setpriority %d failed: %s\n"),
500                                         DEFAULT_PROCESS_PRIORITY, strerror(errno));
501         }
502         return _memlock_count ? 1 : 0;
503 }
504
505 int crypt_memlock_dec(struct crypt_device *ctx)
506 {
507         if (_memlock_count && (!--_memlock_count)) {
508                 log_dbg("Unlocking memory.");
509                 if (munlockall() == -1)
510                         log_err(ctx, _("Cannot unlock memory.\n"));
511                 if (setpriority(PRIO_PROCESS, 0, _priority))
512                         log_err(ctx, _("setpriority %d failed: %s\n"), _priority, strerror(errno));
513         }
514         return _memlock_count ? 1 : 0;
515 }
516
517 /* DEVICE TOPOLOGY */
518
519 /* block device topology ioctls, introduced in 2.6.32 */
520 #ifndef BLKIOMIN
521 #define BLKIOMIN    _IO(0x12,120)
522 #define BLKIOOPT    _IO(0x12,121)
523 #define BLKALIGNOFF _IO(0x12,122)
524 #endif
525
526 void get_topology_alignment(const char *device,
527                             unsigned long *required_alignment, /* bytes */
528                             unsigned long *alignment_offset,   /* bytes */
529                             unsigned long default_alignment)
530 {
531         int dev_alignment_offset = 0;
532         unsigned int min_io_size = 0, opt_io_size = 0;
533         unsigned long temp_alignment = 0;
534         int fd;
535
536         *required_alignment = default_alignment;
537         *alignment_offset = 0;
538
539         fd = open(device, O_RDONLY);
540         if (fd == -1)
541                 return;
542
543         /* minimum io size */
544         if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
545                 log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
546                         device, default_alignment);
547                 goto out;
548         }
549
550         /* optimal io size */
551         if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
552                 opt_io_size = min_io_size;
553
554         /* alignment offset, bogus -1 means misaligned/unknown */
555         if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
556                 dev_alignment_offset = 0;
557         *alignment_offset = (unsigned long)dev_alignment_offset;
558
559         temp_alignment = (unsigned long)min_io_size;
560
561         if (temp_alignment < (unsigned long)opt_io_size)
562                 temp_alignment = (unsigned long)opt_io_size;
563
564         /* If calculated alignment is multiple of default, keep default */
565         if (temp_alignment && (default_alignment % temp_alignment))
566                 *required_alignment = temp_alignment;
567
568         log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
569                 min_io_size, opt_io_size, *alignment_offset, *required_alignment);
570 out:
571         (void)close(fd);
572 }