Add kernel version to DM debug output.
[platform/upstream/cryptsetup.git] / lib / libdevmapper.c
1 /*
2  * libdevmapper - device-mapper backend 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-2012, Red Hat, Inc. All rights reserved.
7  * Copyright (C) 2009-2012, Milan Broz
8  *
9  * This program is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU General Public License
11  * as published by the Free Software Foundation; either version 2
12  * of the License, or (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22  */
23
24 #include <stdio.h>
25 #include <dirent.h>
26 #include <errno.h>
27 #include <libdevmapper.h>
28 #include <fcntl.h>
29 #include <linux/fs.h>
30 #include <uuid/uuid.h>
31 #include <sys/utsname.h>
32
33 #include "internal.h"
34
35 #define DM_UUID_LEN             129
36 #define DM_UUID_PREFIX          "CRYPT-"
37 #define DM_UUID_PREFIX_LEN      6
38 #define DM_CRYPT_TARGET         "crypt"
39 #define DM_VERITY_TARGET        "verity"
40 #define RETRY_COUNT             5
41
42 /* Set if dm-crypt version was probed */
43 static int _dm_crypt_checked = 0;
44 static int _quiet_log = 0;
45 static uint32_t _dm_crypt_flags = 0;
46
47 static struct crypt_device *_context = NULL;
48 static int _dm_use_count = 0;
49
50 /* Check if we have DM flag to instruct kernel to force wipe buffers */
51 #if !HAVE_DECL_DM_TASK_SECURE_DATA
52 static int dm_task_secure_data(struct dm_task *dmt) { return 1; }
53 #endif
54
55 /* Compatibility for old device-mapper without udev support */
56 #if HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG
57 #define CRYPT_TEMP_UDEV_FLAGS   DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | \
58                                 DM_UDEV_DISABLE_DISK_RULES_FLAG | \
59                                 DM_UDEV_DISABLE_OTHER_RULES_FLAG
60 #define _dm_task_set_cookie     dm_task_set_cookie
61 #define _dm_udev_wait           dm_udev_wait
62 #else
63 #define CRYPT_TEMP_UDEV_FLAGS   0
64 static int _dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; }
65 static int _dm_udev_wait(uint32_t cookie) { return 0; };
66 #endif
67
68 static int _dm_use_udev(void)
69 {
70 #ifdef USE_UDEV /* cannot be enabled if devmapper is too old */
71         return dm_udev_get_sync_support();
72 #else
73         return 0;
74 #endif
75 }
76
77 __attribute__((format(printf, 4, 5)))
78 static void set_dm_error(int level,
79                          const char *file __attribute__((unused)),
80                          int line __attribute__((unused)),
81                          const char *f, ...)
82 {
83         char *msg = NULL;
84         va_list va;
85
86         va_start(va, f);
87         if (vasprintf(&msg, f, va) > 0) {
88                 if (level < 4 && !_quiet_log) {
89                         log_err(_context, msg);
90                         log_err(_context, "\n");
91                 } else {
92                         /* We do not use DM visual stack backtrace here */
93                         if (strncmp(msg, "<backtrace>", 11))
94                                 log_dbg(msg);
95                 }
96         }
97         free(msg);
98         va_end(va);
99 }
100
101 static int _dm_simple(int task, const char *name, int udev_wait);
102
103 static void _dm_set_crypt_compat(const char *dm_version, unsigned crypt_maj,
104                                  unsigned crypt_min, unsigned crypt_patch)
105 {
106         unsigned dm_maj, dm_min, dm_patch;
107
108         if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3)
109                 dm_maj = dm_min = dm_patch = 0;
110
111         log_dbg("Detected dm-crypt version %i.%i.%i, dm-ioctl version %u.%u.%u.",
112                 crypt_maj, crypt_min, crypt_patch, dm_maj, dm_min, dm_patch);
113
114         if (crypt_maj >= 1 && crypt_min >= 2)
115                 _dm_crypt_flags |= DM_KEY_WIPE_SUPPORTED;
116         else
117                 log_dbg("Suspend and resume disabled, no wipe key support.");
118
119         if (crypt_maj >= 1 && crypt_min >= 10)
120                 _dm_crypt_flags |= DM_LMK_SUPPORTED;
121
122         if (dm_maj >= 4 && dm_min >= 20)
123                 _dm_crypt_flags |= DM_SECURE_SUPPORTED;
124
125         /* not perfect, 2.6.33 supports with 1.7.0 */
126         if (crypt_maj >= 1 && crypt_min >= 8)
127                 _dm_crypt_flags |= DM_PLAIN64_SUPPORTED;
128
129         if (crypt_maj >= 1 && crypt_min >= 11)
130                 _dm_crypt_flags |= DM_DISCARDS_SUPPORTED;
131
132         /* Repeat test if dm-crypt is not present */
133         if (crypt_maj > 0)
134                 _dm_crypt_checked = 1;
135 }
136
137 static void _dm_set_verity_compat(const char *dm_version, unsigned verity_maj,
138                                    unsigned verity_min, unsigned verity_patch)
139 {
140         if (verity_maj > 0)
141                 _dm_crypt_flags |= DM_VERITY_SUPPORTED;
142
143         log_dbg("Detected dm-verity version %i.%i.%i.",
144                 verity_maj, verity_min, verity_patch);
145 }
146
147 static void _dm_kernel_info(void)
148 {
149         struct utsname uts;
150
151         if (!uname(&uts))
152                 log_dbg("Detected kernel %s %s %s.",
153                         uts.sysname, uts.release, uts.machine);
154
155 }
156
157 static int _dm_check_versions(void)
158 {
159         struct dm_task *dmt;
160         struct dm_versions *target, *last_target;
161         char dm_version[16];
162         int r = 0;
163
164         if (_dm_crypt_checked)
165                 return 1;
166
167         _dm_kernel_info();
168
169         /* Shut up DM while checking */
170         _quiet_log = 1;
171
172         /* FIXME: add support to DM so it forces crypt target module load here */
173         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
174                 goto out;
175
176         if (!dm_task_run(dmt))
177                 goto out;
178
179         if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
180                 goto out;
181
182         target = dm_task_get_versions(dmt);
183         do {
184                 last_target = target;
185                 if (!strcmp(DM_CRYPT_TARGET, target->name)) {
186                         _dm_set_crypt_compat(dm_version,
187                                              (unsigned)target->version[0],
188                                              (unsigned)target->version[1],
189                                              (unsigned)target->version[2]);
190                 } else if (!strcmp(DM_VERITY_TARGET, target->name)) {
191                         _dm_set_verity_compat(dm_version,
192                                              (unsigned)target->version[0],
193                                              (unsigned)target->version[1],
194                                              (unsigned)target->version[2]);
195                 }
196                 target = (struct dm_versions *)((char *) target + target->next);
197         } while (last_target != target);
198
199         r = 1;
200         log_dbg("Device-mapper backend running with UDEV support %sabled.",
201                 _dm_use_udev() ? "en" : "dis");
202 out:
203         if (dmt)
204                 dm_task_destroy(dmt);
205
206         _quiet_log = 0;
207         return r;
208 }
209
210 uint32_t dm_flags(void)
211 {
212         _dm_check_versions();
213         return _dm_crypt_flags;
214 }
215
216 /* This doesn't run any kernel checks, just set up userspace libdevmapper */
217 void dm_backend_init(void)
218 {
219         if (!_dm_use_count++) {
220                 log_dbg("Initialising device-mapper backend library.");
221                 dm_log_init(set_dm_error);
222                 dm_log_init_verbose(10);
223         }
224 }
225
226 void dm_backend_exit(void)
227 {
228         if (_dm_use_count && (!--_dm_use_count)) {
229                 log_dbg("Releasing device-mapper backend.");
230                 dm_log_init_verbose(0);
231                 dm_log_init(NULL);
232                 dm_lib_release();
233         }
234 }
235
236 /*
237  * libdevmapper is not context friendly, switch context on every DM call.
238  * FIXME: this is not safe if called in parallel but neither is DM lib.
239  */
240 static int dm_init_context(struct crypt_device *cd)
241 {
242         _context = cd;
243         if (!_dm_check_versions()) {
244                 if (getuid() || geteuid())
245                         log_err(cd, _("Cannot initialize device-mapper, "
246                                       "running as non-root user.\n"));
247                 else
248                         log_err(cd, _("Cannot initialize device-mapper. "
249                                       "Is dm_mod kernel module loaded?\n"));
250                 _context = NULL;
251                 return -ENOTSUP;
252         }
253         return 0;
254 }
255 static void dm_exit_context(void)
256 {
257         _context = NULL;
258 }
259
260 /* Return path to DM device */
261 char *dm_device_path(const char *prefix, int major, int minor)
262 {
263         struct dm_task *dmt;
264         const char *name;
265         char path[PATH_MAX];
266
267         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
268                 return NULL;
269         if (!dm_task_set_minor(dmt, minor) ||
270             !dm_task_set_major(dmt, major) ||
271             !dm_task_run(dmt) ||
272             !(name = dm_task_get_name(dmt))) {
273                 dm_task_destroy(dmt);
274                 return NULL;
275         }
276
277         if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
278                 path[0] = '\0';
279
280         dm_task_destroy(dmt);
281
282         return strdup(path);
283 }
284
285 static void hex_key(char *hexkey, size_t key_size, const char *key)
286 {
287         unsigned i;
288
289         for(i = 0; i < key_size; i++)
290                 sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
291 }
292
293 /* http://code.google.com/p/cryptsetup/wiki/DMCrypt */
294 static char *get_dm_crypt_params(struct crypt_dm_active_device *dmd)
295 {
296         int r, max_size, null_cipher = 0;
297         char *params, *hexkey;
298         const char *features = "";
299
300         if (!dmd)
301                 return NULL;
302
303         if (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) {
304                 if (dm_flags() & DM_DISCARDS_SUPPORTED) {
305                         features = " 1 allow_discards";
306                         log_dbg("Discard/TRIM is allowed.");
307                 } else
308                         log_dbg("Discard/TRIM is not supported by the kernel.");
309         }
310
311         if (!strncmp(dmd->u.crypt.cipher, "cipher_null-", 12))
312                 null_cipher = 1;
313
314         hexkey = crypt_safe_alloc(null_cipher ? 2 : (dmd->u.crypt.vk->keylength * 2 + 1));
315         if (!hexkey)
316                 return NULL;
317
318         if (null_cipher)
319                 strncpy(hexkey, "-", 2);
320         else
321                 hex_key(hexkey, dmd->u.crypt.vk->keylength, dmd->u.crypt.vk->key);
322
323         max_size = strlen(hexkey) + strlen(dmd->u.crypt.cipher) +
324                    strlen(device_block_path(dmd->data_device)) +
325                    strlen(features) + 64;
326         params = crypt_safe_alloc(max_size);
327         if (!params)
328                 goto out;
329
330         r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
331                      dmd->u.crypt.cipher, hexkey, dmd->u.crypt.iv_offset,
332                      device_block_path(dmd->data_device), dmd->u.crypt.offset,
333                      features);
334         if (r < 0 || r >= max_size) {
335                 crypt_safe_free(params);
336                 params = NULL;
337         }
338 out:
339         crypt_safe_free(hexkey);
340         return params;
341 }
342
343 /* http://code.google.com/p/cryptsetup/wiki/DMVerity */
344 static char *get_dm_verity_params(struct crypt_params_verity *vp,
345                                    struct crypt_dm_active_device *dmd)
346 {
347         int max_size, r;
348         char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
349
350         if (!vp || !dmd)
351                 return NULL;
352
353         hexroot = crypt_safe_alloc(dmd->u.verity.root_hash_size * 2 + 1);
354         if (!hexroot)
355                 goto out;
356         hex_key(hexroot, dmd->u.verity.root_hash_size, dmd->u.verity.root_hash);
357
358         hexsalt = crypt_safe_alloc(vp->salt_size ? vp->salt_size * 2 + 1 : 2);
359         if (!hexsalt)
360                 goto out;
361         if (vp->salt_size)
362                 hex_key(hexsalt, vp->salt_size, vp->salt);
363         else
364                 strncpy(hexsalt, "-", 2);
365
366         max_size = strlen(hexroot) + strlen(hexsalt) +
367                    strlen(device_block_path(dmd->data_device)) +
368                    strlen(device_block_path(dmd->u.verity.hash_device)) +
369                    strlen(vp->hash_name) + 128;
370
371         params = crypt_safe_alloc(max_size);
372         if (!params)
373                 goto out;
374
375         r = snprintf(params, max_size,
376                      "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s",
377                      vp->hash_type, device_block_path(dmd->data_device),
378                      device_block_path(dmd->u.verity.hash_device),
379                      vp->data_block_size, vp->hash_block_size,
380                      vp->data_size, dmd->u.verity.hash_offset,
381                      vp->hash_name, hexroot, hexsalt);
382         if (r < 0 || r >= max_size) {
383                 crypt_safe_free(params);
384                 params = NULL;
385         }
386 out:
387         crypt_safe_free(hexroot);
388         crypt_safe_free(hexsalt);
389         return params;
390
391 }
392
393 /* DM helpers */
394 static int _dm_simple(int task, const char *name, int udev_wait)
395 {
396         int r = 0;
397         struct dm_task *dmt;
398         uint32_t cookie = 0;
399
400         if (!_dm_use_udev())
401                 udev_wait = 0;
402
403         if (!(dmt = dm_task_create(task)))
404                 return 0;
405
406         if (name && !dm_task_set_name(dmt, name))
407                 goto out;
408
409 #if HAVE_DECL_DM_TASK_RETRY_REMOVE
410         /* Used only in DM_DEVICE_REMOVE */
411         if (name && !dm_task_retry_remove(dmt))
412                 goto out;
413 #endif
414         if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, 0))
415                 goto out;
416
417         r = dm_task_run(dmt);
418
419         if (udev_wait)
420                 (void)_dm_udev_wait(cookie);
421
422       out:
423         dm_task_destroy(dmt);
424         return r;
425 }
426
427 static int _error_device(const char *name, size_t size)
428 {
429         struct dm_task *dmt;
430         int r = 0;
431
432         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
433                 return 0;
434
435         if (!dm_task_set_name(dmt, name))
436                 goto error;
437
438         if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
439                 goto error;
440
441         if (!dm_task_set_ro(dmt))
442                 goto error;
443
444         if (!dm_task_no_open_count(dmt))
445                 goto error;
446
447         if (!dm_task_run(dmt))
448                 goto error;
449
450         if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
451                 _dm_simple(DM_DEVICE_CLEAR, name, 0);
452                 goto error;
453         }
454
455         r = 1;
456
457 error:
458         dm_task_destroy(dmt);
459         return r;
460 }
461
462 int dm_remove_device(struct crypt_device *cd, const char *name,
463                      int force, uint64_t size)
464 {
465         int r = -EINVAL;
466         int retries = force ? RETRY_COUNT : 1;
467         int error_target = 0;
468
469         if (!name || (force && !size))
470                 return -EINVAL;
471
472         if (dm_init_context(cd))
473                 return -ENOTSUP;
474
475         do {
476                 r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL;
477                 if (--retries && r) {
478                         log_dbg("WARNING: other process locked internal device %s, %s.",
479                                 name, retries ? "retrying remove" : "giving up");
480                         sleep(1);
481                         if (force && !error_target) {
482                                 /* If force flag is set, replace device with error, read-only target.
483                                  * it should stop processes from reading it and also removed underlying
484                                  * device from mapping, so it is usable again.
485                                  * Force flag should be used only for temporary devices, which are
486                                  * intended to work inside cryptsetup only!
487                                  * Anyway, if some process try to read temporary cryptsetup device,
488                                  * it is bug - no other process should try touch it (e.g. udev).
489                                  */
490                                 _error_device(name, size);
491                                 error_target = 1;
492                         }
493                 }
494         } while (r == -EINVAL && retries);
495
496         dm_task_update_nodes();
497         dm_exit_context();
498
499         return r;
500 }
501
502 #define UUID_LEN 37 /* 36 + \0, libuuid ... */
503 /*
504  * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
505  * CRYPT-PLAIN-name
506  * CRYPT-LUKS1-00000000000000000000000000000000-name
507  * CRYPT-TEMP-name
508  */
509 static int dm_prepare_uuid(const char *name, const char *type, const char *uuid, char *buf, size_t buflen)
510 {
511         char *ptr, uuid2[UUID_LEN] = {0};
512         uuid_t uu;
513         unsigned i = 0;
514
515         /* Remove '-' chars */
516         if (uuid) {
517                 if (uuid_parse(uuid, uu) < 0) {
518                         log_dbg("Requested UUID %s has invalid format.", uuid);
519                         return -EINVAL;
520                 }
521
522                 for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
523                         if (uuid[i] != '-') {
524                                 *ptr = uuid[i];
525                                 ptr++;
526                         }
527         }
528
529         i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
530                 type ?: "", type ? "-" : "",
531                 uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
532                 name);
533
534         log_dbg("DM-UUID is %s", buf);
535         if (i >= buflen)
536                 log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
537
538         return 0;
539 }
540
541 static int _dm_create_device(const char *name, const char *type,
542                              struct device *device, uint32_t flags,
543                              const char *uuid, uint64_t size,
544                              char *params, int reload)
545 {
546         struct dm_task *dmt = NULL;
547         struct dm_info dmi;
548         char dev_uuid[DM_UUID_LEN] = {0};
549         int r = -EINVAL;
550         uint32_t read_ahead = 0;
551         uint32_t cookie = 0;
552         uint16_t udev_flags = 0;
553
554         if (flags & CRYPT_ACTIVATE_PRIVATE)
555                 udev_flags = CRYPT_TEMP_UDEV_FLAGS;
556
557         /* All devices must have DM_UUID, only resize on old device is exception */
558         if (reload) {
559                 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
560                         goto out_no_removal;
561
562                 if (!dm_task_set_name(dmt, name))
563                         goto out_no_removal;
564         } else {
565                 r = dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
566                 if (r < 0)
567                         return r;
568
569                 if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
570                         goto out_no_removal;
571
572                 if (!dm_task_set_name(dmt, name))
573                         goto out_no_removal;
574
575                 if (!dm_task_set_uuid(dmt, dev_uuid))
576                         goto out_no_removal;
577
578                 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
579                         goto out_no_removal;
580         }
581
582         if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
583                 goto out_no_removal;
584         if ((flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
585                 goto out_no_removal;
586
587         if (!dm_task_add_target(dmt, 0, size,
588                 !strcmp("VERITY", type) ? DM_VERITY_TARGET : DM_CRYPT_TARGET, params))
589                 goto out_no_removal;
590
591 #ifdef DM_READ_AHEAD_MINIMUM_FLAG
592         if (device_read_ahead(device, &read_ahead) &&
593             !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
594                 goto out_no_removal;
595 #endif
596
597         if (!dm_task_run(dmt))
598                 goto out_no_removal;
599
600         if (reload) {
601                 dm_task_destroy(dmt);
602                 if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
603                         goto out;
604                 if (!dm_task_set_name(dmt, name))
605                         goto out;
606                 if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
607                         goto out;
608                 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
609                         goto out;
610                 if (!dm_task_run(dmt))
611                         goto out;
612         }
613
614         if (!dm_task_get_info(dmt, &dmi))
615                 goto out;
616
617         r = 0;
618 out:
619         if (_dm_use_udev()) {
620                 (void)_dm_udev_wait(cookie);
621                 cookie = 0;
622         }
623
624         if (r < 0 && !reload)
625                 _dm_simple(DM_DEVICE_REMOVE, name, 1);
626
627 out_no_removal:
628         if (cookie && _dm_use_udev())
629                 (void)_dm_udev_wait(cookie);
630
631         if (params)
632                 crypt_safe_free(params);
633         if (dmt)
634                 dm_task_destroy(dmt);
635
636         dm_task_update_nodes();
637         return r;
638 }
639
640 int dm_create_device(struct crypt_device *cd, const char *name,
641                      const char *type,
642                      struct crypt_dm_active_device *dmd,
643                      int reload)
644 {
645         char *table_params = NULL;
646         int r = -EINVAL;
647
648         if (!type)
649                 return -EINVAL;
650
651         if (dm_init_context(cd))
652                 return -ENOTSUP;
653
654         if (dmd->target == DM_CRYPT)
655                 table_params = get_dm_crypt_params(dmd);
656         else if (dmd->target == DM_VERITY)
657                 table_params = get_dm_verity_params(dmd->u.verity.vp, dmd);
658
659         if (table_params)
660                 r = _dm_create_device(name, type, dmd->data_device,
661                                       dmd->flags, dmd->uuid, dmd->size,
662                                       table_params, reload);
663         dm_exit_context();
664         return r;
665 }
666
667 static int dm_status_dmi(const char *name, struct dm_info *dmi,
668                           const char *target, char **status_line)
669 {
670         struct dm_task *dmt;
671         uint64_t start, length;
672         char *target_type, *params = NULL;
673         void *next = NULL;
674         int r = -EINVAL;
675
676         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
677                 goto out;
678
679         if (!dm_task_set_name(dmt, name))
680                 goto out;
681
682         if (!dm_task_run(dmt))
683                 goto out;
684
685         if (!dm_task_get_info(dmt, dmi))
686                 goto out;
687
688         if (!dmi->exists) {
689                 r = -ENODEV;
690                 goto out;
691         }
692
693         next = dm_get_next_target(dmt, next, &start, &length,
694                                   &target_type, &params);
695
696         if (!target_type || start != 0 || next)
697                 goto out;
698
699         if (target && strcmp(target_type, target))
700                 goto out;
701
702         /* for target == NULL check all supported */
703         if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
704                         strcmp(target_type, DM_VERITY_TARGET)))
705                 goto out;
706         r = 0;
707 out:
708         if (!r && status_line && !(*status_line = strdup(params)))
709                 r = -ENOMEM;
710
711         if (dmt)
712                 dm_task_destroy(dmt);
713
714         return r;
715 }
716
717 int dm_status_device(struct crypt_device *cd, const char *name)
718 {
719         int r;
720         struct dm_info dmi;
721         struct stat st;
722
723         /* libdevmapper is too clever and handles
724          * path argument differenly with error.
725          * Fail early here if parameter is non-existent path.
726          */
727         if (strchr(name, '/') && stat(name, &st) < 0)
728                 return -ENODEV;
729
730         if (dm_init_context(cd))
731                 return -ENOTSUP;
732         r = dm_status_dmi(name, &dmi, NULL, NULL);
733         dm_exit_context();
734         if (r < 0)
735                 return r;
736
737         return (dmi.open_count > 0);
738 }
739
740 int dm_status_suspended(struct crypt_device *cd, const char *name)
741 {
742         int r;
743         struct dm_info dmi;
744
745         if (dm_init_context(cd))
746                 return -ENOTSUP;
747         r = dm_status_dmi(name, &dmi, DM_CRYPT_TARGET, NULL);
748         dm_exit_context();
749         if (r < 0)
750                 return r;
751
752         return dmi.suspended ? 1 : 0;
753 }
754
755 static int _dm_status_verity_ok(const char *name)
756 {
757         int r;
758         struct dm_info dmi;
759         char *status_line = NULL;
760
761         r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
762         if (r < 0 || !status_line) {
763                 free(status_line);
764                 return r;
765         }
766
767         log_dbg("Verity volume %s status is %s.", name, status_line ?: "");
768         r = status_line[0] == 'V' ? 1 : 0;
769         free(status_line);
770
771         return r;
772 }
773
774 int dm_status_verity_ok(struct crypt_device *cd, const char *name)
775 {
776         int r;
777
778         if (dm_init_context(cd))
779                 return -ENOTSUP;
780         r = _dm_status_verity_ok(name);
781         dm_exit_context();
782         return r;
783 }
784
785 /* FIXME use hex wrapper, user val wrappers for line parsing */
786 static int _dm_query_crypt(uint32_t get_flags,
787                            struct dm_info *dmi,
788                            char *params,
789                            struct crypt_dm_active_device *dmd)
790 {
791         uint64_t val64;
792         char *rcipher, *key_, *rdevice, *endp, buffer[3], *arg;
793         unsigned int i;
794         int r;
795
796         memset(dmd, 0, sizeof(*dmd));
797         dmd->target = DM_CRYPT;
798
799         rcipher = strsep(&params, " ");
800         /* cipher */
801         if (get_flags & DM_ACTIVE_CRYPT_CIPHER)
802                 dmd->u.crypt.cipher = strdup(rcipher);
803
804         /* skip */
805         key_ = strsep(&params, " ");
806         if (!params)
807                 return -EINVAL;
808         val64 = strtoull(params, &params, 10);
809         if (*params != ' ')
810                 return -EINVAL;
811         params++;
812
813         dmd->u.crypt.iv_offset = val64;
814
815         /* device */
816         rdevice = strsep(&params, " ");
817         if (get_flags & DM_ACTIVE_DEVICE) {
818                 arg = crypt_lookup_dev(rdevice);
819                 r = device_alloc(&dmd->data_device, arg);
820                 free(arg);
821                 if (r < 0 && r != -ENOTBLK)
822                         return r;
823         }
824
825         /*offset */
826         if (!params)
827                 return -EINVAL;
828         val64 = strtoull(params, &params, 10);
829         dmd->u.crypt.offset = val64;
830
831         /* Features section, available since crypt target version 1.11 */
832         if (*params) {
833                 if (*params != ' ')
834                         return -EINVAL;
835                 params++;
836
837                 /* Number of arguments */
838                 val64 = strtoull(params, &params, 10);
839                 if (*params != ' ')
840                         return -EINVAL;
841                 params++;
842
843                 for (i = 0; i < val64; i++) {
844                         if (!params)
845                                 return -EINVAL;
846                         arg = strsep(&params, " ");
847                         if (!strcasecmp(arg, "allow_discards"))
848                                 dmd->flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
849                         else /* unknown option */
850                                 return -EINVAL;
851                 }
852
853                 /* All parameters shold be processed */
854                 if (params)
855                         return -EINVAL;
856         }
857
858         /* Never allow to return empty key */
859         if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi->suspended) {
860                 log_dbg("Cannot read volume key while suspended.");
861                 return -EINVAL;
862         }
863
864         if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
865                 dmd->u.crypt.vk = crypt_alloc_volume_key(strlen(key_) / 2, NULL);
866                 if (!dmd->u.crypt.vk)
867                         return -ENOMEM;
868
869                 if (get_flags & DM_ACTIVE_CRYPT_KEY) {
870                         buffer[2] = '\0';
871                         for(i = 0; i < dmd->u.crypt.vk->keylength; i++) {
872                                 memcpy(buffer, &key_[i * 2], 2);
873                                 dmd->u.crypt.vk->key[i] = strtoul(buffer, &endp, 16);
874                                 if (endp != &buffer[2]) {
875                                         crypt_free_volume_key(dmd->u.crypt.vk);
876                                         dmd->u.crypt.vk = NULL;
877                                         return -EINVAL;
878                                 }
879                         }
880                 }
881         }
882         memset(key_, 0, strlen(key_));
883
884         return 0;
885 }
886
887 static int _dm_query_verity(uint32_t get_flags,
888                              struct dm_info *dmi,
889                              char *params,
890                              struct crypt_dm_active_device *dmd)
891 {
892         struct crypt_params_verity *vp = NULL;
893         uint32_t val32;
894         uint64_t val64;
895         ssize_t len;
896         char *str, *str2;
897         int r;
898
899         if (get_flags & DM_ACTIVE_VERITY_PARAMS)
900                 vp = dmd->u.verity.vp;
901
902         memset(dmd, 0, sizeof(*dmd));
903
904         dmd->target = DM_VERITY;
905         dmd->u.verity.vp = vp;
906
907         /* version */
908         val32 = strtoul(params, &params, 10);
909         if (*params != ' ')
910                 return -EINVAL;
911         if (vp)
912                 vp->hash_type = val32;
913         params++;
914
915         /* data device */
916         str = strsep(&params, " ");
917         if (!params)
918                 return -EINVAL;
919         if (get_flags & DM_ACTIVE_DEVICE) {
920                 str2 = crypt_lookup_dev(str);
921                 r = device_alloc(&dmd->data_device, str2);
922                 free(str2);
923                 if (r < 0 && r != -ENOTBLK)
924                         return r;
925         }
926
927         /* hash device */
928         str = strsep(&params, " ");
929         if (!params)
930                 return -EINVAL;
931         if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
932                 str2 = crypt_lookup_dev(str);
933                 r = device_alloc(&dmd->u.verity.hash_device, str2);
934                 free(str2);
935                 if (r < 0 && r != -ENOTBLK)
936                         return r;
937         }
938
939         /* data block size*/
940         val32 = strtoul(params, &params, 10);
941         if (*params != ' ')
942                 return -EINVAL;
943         if (vp)
944                 vp->data_block_size = val32;
945         params++;
946
947         /* hash block size */
948         val32 = strtoul(params, &params, 10);
949         if (*params != ' ')
950                 return -EINVAL;
951         if (vp)
952                 vp->hash_block_size = val32;
953         params++;
954
955         /* data blocks */
956         val64 = strtoull(params, &params, 10);
957         if (*params != ' ')
958                 return -EINVAL;
959         if (vp)
960                 vp->data_size = val64;
961         params++;
962
963         /* hash start */
964         val64 = strtoull(params, &params, 10);
965         if (*params != ' ')
966                 return -EINVAL;
967         dmd->u.verity.hash_offset = val64;
968         params++;
969
970         /* hash algorithm */
971         str = strsep(&params, " ");
972         if (!params)
973                 return -EINVAL;
974         if (vp)
975                 vp->hash_name = strdup(str);
976
977         /* root digest */
978         str = strsep(&params, " ");
979         if (!params)
980                 return -EINVAL;
981         len = crypt_hex_to_bytes(str, &str2, 0);
982         if (len < 0)
983                 return len;
984         dmd->u.verity.root_hash_size = len;
985         if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
986                 dmd->u.verity.root_hash = str2;
987         else
988                 free(str2);
989
990         /* salt */
991         str = strsep(&params, " ");
992         if (params)
993                 return -EINVAL;
994         if (vp) {
995                 if (!strcmp(str, "-")) {
996                         vp->salt_size = 0;
997                         vp->salt = NULL;
998                 } else {
999                         len = crypt_hex_to_bytes(str, &str2, 0);
1000                         if (len < 0)
1001                                 return len;
1002                         vp->salt_size = len;
1003                         vp->salt = str2;
1004                 }
1005         }
1006
1007         return 0;
1008 }
1009
1010 int dm_query_device(struct crypt_device *cd, const char *name,
1011                     uint32_t get_flags, struct crypt_dm_active_device *dmd)
1012 {
1013         struct dm_task *dmt;
1014         struct dm_info dmi;
1015         uint64_t start, length;
1016         char *target_type, *params;
1017         const char *tmp_uuid;
1018         void *next = NULL;
1019         int r = -EINVAL;
1020
1021         if (dm_init_context(cd))
1022                 return -ENOTSUP;
1023         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
1024                 goto out;
1025         if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
1026                 goto out;
1027         if (!dm_task_set_name(dmt, name))
1028                 goto out;
1029         r = -ENODEV;
1030         if (!dm_task_run(dmt))
1031                 goto out;
1032
1033         r = -EINVAL;
1034         if (!dm_task_get_info(dmt, &dmi))
1035                 goto out;
1036
1037         if (!dmi.exists) {
1038                 r = -ENODEV;
1039                 goto out;
1040         }
1041
1042         next = dm_get_next_target(dmt, next, &start, &length,
1043                                   &target_type, &params);
1044
1045         if (!target_type || start != 0 || next)
1046                 goto out;
1047
1048         if (!strcmp(target_type, DM_CRYPT_TARGET)) {
1049                 r = _dm_query_crypt(get_flags, &dmi, params, dmd);
1050         } else if (!strcmp(target_type, DM_VERITY_TARGET)) {
1051                 r = _dm_query_verity(get_flags, &dmi, params, dmd);
1052                 if (r < 0)
1053                         goto out;
1054                 r = _dm_status_verity_ok(name);
1055                 if (r < 0)
1056                         goto out;
1057                 if (r == 0)
1058                         dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
1059                 r = 0;
1060         } else
1061                 r = -EINVAL;
1062
1063         if (r < 0)
1064                 goto out;
1065
1066         dmd->size = length;
1067
1068         if (dmi.read_only)
1069                 dmd->flags |= CRYPT_ACTIVATE_READONLY;
1070
1071         tmp_uuid = dm_task_get_uuid(dmt);
1072         if (!tmp_uuid)
1073                 dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
1074         else if (get_flags & DM_ACTIVE_UUID) {
1075                 if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
1076                         dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
1077         }
1078
1079         r = (dmi.open_count > 0);
1080 out:
1081         if (dmt)
1082                 dm_task_destroy(dmt);
1083
1084         dm_exit_context();
1085         return r;
1086 }
1087
1088 static int _dm_message(const char *name, const char *msg)
1089 {
1090         int r = 0;
1091         struct dm_task *dmt;
1092
1093         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
1094                 return 0;
1095
1096         if ((dm_flags() & DM_SECURE_SUPPORTED) && !dm_task_secure_data(dmt))
1097                 goto out;
1098
1099         if (name && !dm_task_set_name(dmt, name))
1100                 goto out;
1101
1102         if (!dm_task_set_sector(dmt, (uint64_t) 0))
1103                 goto out;
1104
1105         if (!dm_task_set_message(dmt, msg))
1106                 goto out;
1107
1108         r = dm_task_run(dmt);
1109
1110       out:
1111         dm_task_destroy(dmt);
1112         return r;
1113 }
1114
1115 int dm_suspend_and_wipe_key(struct crypt_device *cd, const char *name)
1116 {
1117         int r = -ENOTSUP;
1118
1119         if (dm_init_context(cd))
1120                 return -ENOTSUP;
1121
1122         if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
1123                 goto out;
1124
1125         if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0)) {
1126                 r = -EINVAL;
1127                 goto out;
1128         }
1129
1130         if (!_dm_message(name, "key wipe")) {
1131                 _dm_simple(DM_DEVICE_RESUME, name, 1);
1132                 r = -EINVAL;
1133                 goto out;
1134         }
1135         r = 0;
1136 out:
1137         dm_exit_context();
1138         return r;
1139 }
1140
1141 int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
1142                                 size_t key_size, const char *key)
1143 {
1144         int msg_size = key_size * 2 + 10; // key set <key>
1145         char *msg = NULL;
1146         int r = -ENOTSUP;
1147
1148         if (dm_init_context(cd))
1149                 return -ENOTSUP;
1150
1151         if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
1152                 goto out;
1153
1154         msg = crypt_safe_alloc(msg_size);
1155         if (!msg) {
1156                 r = -ENOMEM;
1157                 goto out;
1158         }
1159
1160         strcpy(msg, "key set ");
1161         hex_key(&msg[8], key_size, key);
1162
1163         if (!_dm_message(name, msg) ||
1164             !_dm_simple(DM_DEVICE_RESUME, name, 1)) {
1165                 r = -EINVAL;
1166                 goto out;
1167         }
1168         r = 0;
1169 out:
1170         crypt_safe_free(msg);
1171         dm_exit_context();
1172         return r;
1173 }
1174
1175 const char *dm_get_dir(void)
1176 {
1177         return dm_dir();
1178 }
1179
1180 int dm_is_dm_device(int major, int minor)
1181 {
1182         return dm_is_dm_major((uint32_t)major);
1183 }
1184
1185 int dm_is_dm_kernel_name(const char *name)
1186 {
1187         return strncmp(name, "dm-", 3) ? 0 : 1;
1188 }