Fix verbose mode compiler warnings.
[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 static int sector_size(int fd) 
112 {
113         int bsize;
114         if (ioctl(fd,BLKSSZGET, &bsize) < 0)
115                 return -EINVAL;
116         else
117                 return bsize;
118 }
119
120 int sector_size_for_device(const char *device)
121 {
122         int fd = open(device, O_RDONLY);
123         int r;
124         if(fd < 0)
125                 return -EINVAL;
126         r = sector_size(fd);
127         close(fd);
128         return r;
129 }
130
131 ssize_t write_blockwise(int fd, const void *orig_buf, size_t count)
132 {
133         void *hangover_buf, *hangover_buf_base = NULL;
134         void *buf, *buf_base = NULL;
135         int r, hangover, solid, bsize, alignment;
136         ssize_t ret = -1;
137
138         if ((bsize = sector_size(fd)) < 0)
139                 return bsize;
140
141         hangover = count % bsize;
142         solid = count - hangover;
143         alignment = get_alignment(fd);
144
145         if ((long)orig_buf & (alignment - 1)) {
146                 buf = aligned_malloc(&buf_base, count, alignment);
147                 if (!buf)
148                         goto out;
149                 memcpy(buf, orig_buf, count);
150         } else
151                 buf = (void *)orig_buf;
152
153         r = write(fd, buf, solid);
154         if (r < 0 || r != solid)
155                 goto out;
156
157         if (hangover) {
158                 hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
159                 if (!hangover_buf)
160                         goto out;
161
162                 r = read(fd, hangover_buf, bsize);
163                 if(r < 0 || r != bsize) goto out;
164
165                 r = lseek(fd, -bsize, SEEK_CUR);
166                 if (r < 0)
167                         goto out;
168                 memcpy(hangover_buf, buf + solid, hangover);
169
170                 r = write(fd, hangover_buf, bsize);
171                 if(r < 0 || r != bsize) goto out;
172                 free(hangover_buf_base);
173         }
174         ret = count;
175  out:
176         if (buf != orig_buf)
177                 free(buf_base);
178         return ret;
179 }
180
181 ssize_t read_blockwise(int fd, void *orig_buf, size_t count) {
182         void *hangover_buf, *hangover_buf_base;
183         void *buf, *buf_base = NULL;
184         int r, hangover, solid, bsize, alignment;
185         ssize_t ret = -1;
186
187         if ((bsize = sector_size(fd)) < 0)
188                 return bsize;
189
190         hangover = count % bsize;
191         solid = count - hangover;
192         alignment = get_alignment(fd);
193
194         if ((long)orig_buf & (alignment - 1)) {
195                 buf = aligned_malloc(&buf_base, count, alignment);
196                 if (!buf)
197                         return -1;
198         } else
199                 buf = orig_buf;
200
201         r = read(fd, buf, solid);
202         if(r < 0 || r != solid)
203                 goto out;
204
205         if (hangover) {
206                 hangover_buf = aligned_malloc(&hangover_buf_base, bsize, alignment);
207                 if (!hangover_buf)
208                         goto out;
209                 r = read(fd, hangover_buf, bsize);
210                 if (r <  0 || r != bsize)
211                         goto out;
212
213                 memcpy(buf + solid, hangover_buf, hangover);
214                 free(hangover_buf_base);
215         }
216         ret = count;
217  out:
218         if (buf != orig_buf) {
219                 memcpy(orig_buf, buf, count);
220                 free(buf_base);
221         }
222         return ret;
223 }
224
225 /* 
226  * Combines llseek with blockwise write. write_blockwise can already deal with short writes
227  * but we also need a function to deal with short writes at the start. But this information
228  * is implicitly included in the read/write offset, which can not be set to non-aligned 
229  * boundaries. Hence, we combine llseek with write.
230  */
231
232 ssize_t write_lseek_blockwise(int fd, const char *buf, size_t count, off_t offset) {
233         int bsize = sector_size(fd);
234         const char *orig_buf = buf;
235         char frontPadBuf[bsize];
236         int frontHang = offset % bsize;
237         int r;
238         int innerCount = count < bsize ? count : bsize;
239
240         if (bsize < 0)
241                 return bsize;
242
243         lseek(fd, offset - frontHang, SEEK_SET);
244         if(offset % bsize) {
245                 r = read(fd,frontPadBuf,bsize);
246                 if(r < 0) return -1;
247
248                 memcpy(frontPadBuf+frontHang, buf, innerCount);
249
250                 lseek(fd, offset - frontHang, SEEK_SET);
251                 r = write(fd,frontPadBuf,bsize);
252                 if(r < 0) return -1;
253
254                 buf += innerCount;
255                 count -= innerCount;
256         }
257         if(count <= 0) return buf - orig_buf;
258
259         return write_blockwise(fd, buf, count) + innerCount;
260 }
261
262 int device_ready(struct crypt_device *cd, const char *device, int mode)
263 {
264         int devfd, r = 0;
265         ssize_t s;
266         struct stat st;
267         char buf[512];
268
269         if(stat(device, &st) < 0) {
270                 log_err(cd, _("Device %s doesn't exist or access denied.\n"), device);
271                 return -EINVAL;
272         }
273
274         if (!S_ISBLK(st.st_mode))
275                 return -ENOTBLK;
276
277         log_dbg("Trying to open and read device %s.", device);
278         devfd = open(device, mode | O_DIRECT | O_SYNC);
279         if(devfd < 0) {
280                 log_err(cd, _("Cannot open device %s for %s%s access.\n"), device,
281                         (mode & O_EXCL) ? _("exclusive ") : "",
282                         (mode & O_RDWR) ? _("writable") : _("read-only"));
283                 return -EINVAL;
284         }
285
286          /* Try to read first sector */
287         s = read_blockwise(devfd, buf, sizeof(buf));
288         if (s < 0 || s != sizeof(buf)) {
289                 log_verbose(cd, _("Cannot read device %s.\n"), device);
290                 r = -EIO;
291         }
292
293         memset(buf, 0, sizeof(buf));
294         close(devfd);
295
296         return r;
297 }
298
299 int get_device_infos(const char *device,
300                      int open_exclusive,
301                      int *readonly,
302                      uint64_t *size)
303 {
304         struct stat st;
305         unsigned long size_small;
306         int fd, r = -1;
307         int flags = 0;
308
309         *readonly = 0;
310         *size = 0;
311
312         if (stat(device, &st) < 0)
313                 return -EINVAL;
314
315         /* never wipe header on mounted device */
316         if (open_exclusive && S_ISBLK(st.st_mode))
317                 flags |= O_EXCL;
318
319         /* Try to open read-write to check whether it is a read-only device */
320         fd = open(device, O_RDWR | flags);
321         if (fd == -1 && errno == EROFS) {
322                 *readonly = 1;
323                 fd = open(device, O_RDONLY | flags);
324         }
325
326         if (fd == -1 && open_exclusive && errno == EBUSY)
327                 return -EBUSY;
328
329         if (fd == -1)
330                 return -EINVAL;
331
332 #ifdef BLKROGET
333         /* If the device can be opened read-write, i.e. readonly is still 0, then
334          * check whether BKROGET says that it is read-only. E.g. read-only loop
335          * devices may be openend read-write but are read-only according to BLKROGET
336          */
337         if (*readonly == 0 && (r = ioctl(fd, BLKROGET, readonly)) < 0)
338                 goto out;
339 #else
340 #error BLKROGET not available
341 #endif
342
343 #ifdef BLKGETSIZE64
344         if (ioctl(fd, BLKGETSIZE64, size) >= 0) {
345                 *size >>= SECTOR_SHIFT;
346                 r = 0;
347                 goto out;
348         }
349 #endif
350
351 #ifdef BLKGETSIZE
352         if (ioctl(fd, BLKGETSIZE, &size_small) >= 0) {
353                 *size = (uint64_t)size_small;
354                 r = 0;
355                 goto out;
356         }
357
358 #else
359 #       error Need at least the BLKGETSIZE ioctl!
360 #endif
361         r = -EINVAL;
362 out:
363         close(fd);
364         return r;
365 }
366
367 int device_check_and_adjust(struct crypt_device *cd,
368                             const char *device,
369                             int open_exclusive,
370                             uint64_t *size,
371                             uint64_t *offset,
372                             int *read_only)
373 {
374         int r, real_readonly;
375         uint64_t real_size;
376
377         if (!device)
378                 return -ENOTBLK;
379
380         r = get_device_infos(device, open_exclusive, &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);
386                 else
387                         log_err(cd, _("Cannot get info about device %s.\n"),
388                                 device);
389                 return r;
390         }
391
392         if (!*size) {
393                 *size = real_size;
394                 if (!*size) {
395                         log_err(cd, _("Device %s has zero size.\n"), device);
396                         return -ENOTBLK;
397                 }
398                 if (*size < *offset) {
399                         log_err(cd, _("Device %s is too small.\n"), device);
400                         return -EINVAL;
401                 }
402                 *size -= *offset;
403         }
404
405         if (real_readonly)
406                 *read_only = 1;
407
408         log_dbg("Calculated device size is %" PRIu64 " sectors (%s), offset %" PRIu64 ".",
409                 *size, *read_only ? "RO" : "RW", *offset);
410         return 0;
411 }
412
413 int wipe_device_header(const char *device, int sectors)
414 {
415         struct stat st;
416         char *buffer;
417         int size = sectors * SECTOR_SIZE;
418         int r = -1;
419         int devfd;
420         int flags = O_RDWR | O_DIRECT | O_SYNC;
421
422         if (stat(device, &st) < 0)
423                 return -EINVAL;
424
425         /* never wipe header on mounted device */
426         if (S_ISBLK(st.st_mode))
427                 flags |= O_EXCL;
428
429         devfd = open(device, flags);
430         if(devfd == -1)
431                 return errno == EBUSY ? -EBUSY : -EINVAL;
432
433         buffer = malloc(size);
434         if (!buffer) {
435                 close(devfd);
436                 return -ENOMEM;
437         }
438         memset(buffer, 0, size);
439
440         r = write_blockwise(devfd, buffer, size) < size ? -EIO : 0;
441
442         free(buffer);
443         close(devfd);
444
445         return r;
446 }
447
448 /* MEMLOCK */
449 #define DEFAULT_PROCESS_PRIORITY -18
450
451 static int _priority;
452 static int _memlock_count = 0;
453
454 // return 1 if memory is locked
455 int crypt_memlock_inc(struct crypt_device *ctx)
456 {
457         if (!_memlock_count++) {
458                 log_dbg("Locking memory.");
459                 if (mlockall(MCL_CURRENT | MCL_FUTURE) == -1) {
460                         log_err(ctx, _("WARNING!!! Possibly insecure memory. Are you root?\n"));
461                         _memlock_count--;
462                         return 0;
463                 }
464                 errno = 0;
465                 if (((_priority = getpriority(PRIO_PROCESS, 0)) == -1) && errno)
466                         log_err(ctx, _("Cannot get process priority.\n"));
467                 else
468                         if (setpriority(PRIO_PROCESS, 0, DEFAULT_PROCESS_PRIORITY))
469                                 log_err(ctx, _("setpriority %d failed: %s\n"),
470                                         DEFAULT_PROCESS_PRIORITY, strerror(errno));
471         }
472         return _memlock_count ? 1 : 0;
473 }
474
475 int crypt_memlock_dec(struct crypt_device *ctx)
476 {
477         if (_memlock_count && (!--_memlock_count)) {
478                 log_dbg("Unlocking memory.");
479                 if (munlockall() == -1)
480                         log_err(ctx, _("Cannot unlock memory.\n"));
481                 if (setpriority(PRIO_PROCESS, 0, _priority))
482                         log_err(ctx, _("setpriority %d failed: %s\n"), _priority, strerror(errno));
483         }
484         return _memlock_count ? 1 : 0;
485 }
486
487 /* DEVICE TOPOLOGY */
488
489 /* block device topology ioctls, introduced in 2.6.32 */
490 #ifndef BLKIOMIN
491 #define BLKIOMIN    _IO(0x12,120)
492 #define BLKIOOPT    _IO(0x12,121)
493 #define BLKALIGNOFF _IO(0x12,122)
494 #endif
495
496 void get_topology_alignment(const char *device,
497                             unsigned long *required_alignment, /* bytes */
498                             unsigned long *alignment_offset,   /* bytes */
499                             unsigned long default_alignment)
500 {
501         int dev_alignment_offset = 0;
502         unsigned int min_io_size = 0, opt_io_size = 0;
503         unsigned long temp_alignment = 0;
504         int fd;
505
506         *required_alignment = default_alignment;
507         *alignment_offset = 0;
508
509         fd = open(device, O_RDONLY);
510         if (fd == -1)
511                 return;
512
513         /* minimum io size */
514         if (ioctl(fd, BLKIOMIN, &min_io_size) == -1) {
515                 log_dbg("Topology info for %s not supported, using default offset %lu bytes.",
516                         device, default_alignment);
517                 goto out;
518         }
519
520         /* optimal io size */
521         if (ioctl(fd, BLKIOOPT, &opt_io_size) == -1)
522                 opt_io_size = min_io_size;
523
524         /* alignment offset, bogus -1 means misaligned/unknown */
525         if (ioctl(fd, BLKALIGNOFF, &dev_alignment_offset) == -1 || dev_alignment_offset < 0)
526                 dev_alignment_offset = 0;
527         *alignment_offset = (unsigned long)dev_alignment_offset;
528
529         temp_alignment = (unsigned long)min_io_size;
530
531         if (temp_alignment < (unsigned long)opt_io_size)
532                 temp_alignment = (unsigned long)opt_io_size;
533
534         /* If calculated alignment is multiple of default, keep default */
535         if (temp_alignment && (default_alignment % temp_alignment))
536                 *required_alignment = temp_alignment;
537
538         log_dbg("Topology: IO (%u/%u), offset = %lu; Required alignment is %lu bytes.",
539                 min_io_size, opt_io_size, *alignment_offset, *required_alignment);
540 out:
541         (void)close(fd);
542 }