minor updates
[platform/upstream/cryptsetup.git] / lib / libdevmapper.c
1 #include <sys/ioctl.h>
2 #include <sys/stat.h>
3 #include <stdio.h>
4 #include <dirent.h>
5 #include <errno.h>
6 #include <libdevmapper.h>
7 #include <fcntl.h>
8 #include <linux/fs.h>
9 #include <uuid/uuid.h>
10
11 #include "internal.h"
12 #include "luks.h"
13
14 #define DEVICE_DIR              "/dev"
15 #define DM_UUID_LEN             129
16 #define DM_UUID_PREFIX          "CRYPT-"
17 #define DM_UUID_PREFIX_LEN      6
18 #define DM_CRYPT_TARGET         "crypt"
19 #define RETRY_COUNT             5
20
21 /* Set if dm-crypt version was probed */
22 static int _dm_crypt_checked = 0;
23 static uint32_t _dm_crypt_flags = 0;
24
25 static int _dm_use_count = 0;
26 static struct crypt_device *_context = NULL;
27
28 /* Compatibility for old device-mapper without udev support */
29 #if HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG
30 #define CRYPT_TEMP_UDEV_FLAGS   DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | \
31                                 DM_UDEV_DISABLE_DISK_RULES_FLAG | \
32                                 DM_UDEV_DISABLE_OTHER_RULES_FLAG
33 #define _dm_task_set_cookie     dm_task_set_cookie
34 #define _dm_udev_wait           dm_udev_wait
35 #else
36 #define CRYPT_TEMP_UDEV_FLAGS   0
37 static int _dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; }
38 static int _dm_udev_wait(uint32_t cookie) { return 0; };
39 #endif
40
41 static int _dm_use_udev()
42 {
43 #ifdef USE_UDEV /* cannot be enabled if devmapper is too old */
44         return dm_udev_get_sync_support();
45 #else
46         return 0;
47 #endif
48 }
49
50 uint32_t dm_flags(void)
51 {
52         return _dm_crypt_flags;
53 }
54
55 static void set_dm_error(int level, const char *file, int line,
56                          const char *f, ...)
57 {
58         char *msg = NULL;
59         va_list va;
60
61         va_start(va, f);
62         if (vasprintf(&msg, f, va) > 0) {
63                 if (level < 4) {
64                         log_err(_context, msg);
65                         log_err(_context, "\n");
66                 } else
67                         log_dbg(msg);
68         }
69         free(msg);
70         va_end(va);
71 }
72
73 static int _dm_simple(int task, const char *name, int udev_wait);
74
75 static void _dm_set_crypt_compat(int maj, int min, int patch)
76 {
77         log_dbg("Detected dm-crypt target of version %i.%i.%i.", maj, min, patch);
78
79         if (maj >= 1 && min >=2)
80                 _dm_crypt_flags |= DM_KEY_WIPE_SUPPORTED;
81         else
82                 log_dbg("Suspend and resume disabled, no wipe key support.");
83
84         if (maj >= 1 && min >=10)
85                 _dm_crypt_flags |= DM_LMK_SUPPORTED;
86
87         _dm_crypt_checked = 1;
88 }
89
90 static int _dm_check_versions(void)
91 {
92         struct dm_task *dmt;
93         struct dm_versions *target, *last_target;
94
95         if (_dm_crypt_checked)
96                 return 1;
97
98         if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
99                 return 0;
100
101         if (!dm_task_run(dmt)) {
102                 dm_task_destroy(dmt);
103                 return 0;
104         }
105
106         target = dm_task_get_versions(dmt);
107         do {
108                 last_target = target;
109                 if (!strcmp(DM_CRYPT_TARGET, target->name)) {
110                         _dm_set_crypt_compat((int)target->version[0],
111                                              (int)target->version[1],
112                                              (int)target->version[2]);
113                 }
114                 target = (void *) target + target->next;
115         } while (last_target != target);
116
117         dm_task_destroy(dmt);
118         return 1;
119 }
120
121 int dm_init(struct crypt_device *context, int check_kernel)
122 {
123         if (!_dm_use_count++) {
124                 log_dbg("Initialising device-mapper backend%s, UDEV is %sabled.",
125                         check_kernel ? "" : " (NO kernel check requested)",
126                         _dm_use_udev() ? "en" : "dis");
127                 if (check_kernel && !_dm_check_versions()) {
128                         log_err(context, _("Cannot initialize device-mapper. Is dm_mod kernel module loaded?\n"));
129                         return -1;
130                 }
131                 if (getuid() || geteuid())
132                         log_dbg(("WARNING: Running as a non-root user. Functionality may be unavailable."));
133                 dm_log_init(set_dm_error);
134                 dm_log_init_verbose(10);
135         }
136
137         // FIXME: global context is not safe
138         if (context)
139                 _context = context;
140
141         return 1;       /* unsafe memory */
142 }
143
144 void dm_exit(void)
145 {
146         if (_dm_use_count && (!--_dm_use_count)) {
147                 log_dbg("Releasing device-mapper backend.");
148                 dm_log_init_verbose(0);
149                 dm_log_init(NULL);
150                 dm_lib_release();
151                 _context = NULL;
152         }
153 }
154
155 static char *__lookup_dev(char *path, dev_t dev, int dir_level, const int max_level)
156 {
157         struct dirent *entry;
158         struct stat st;
159         char *ptr;
160         char *result = NULL;
161         DIR *dir;
162         int space;
163
164         /* Ignore strange nested directories */
165         if (dir_level > max_level)
166                 return NULL;
167
168         path[PATH_MAX - 1] = '\0';
169         ptr = path + strlen(path);
170         *ptr++ = '/';
171         *ptr = '\0';
172         space = PATH_MAX - (ptr - path);
173
174         dir = opendir(path);
175         if (!dir)
176                 return NULL;
177
178         while((entry = readdir(dir))) {
179                 if (entry->d_name[0] == '.' ||
180                     !strncmp(entry->d_name, "..", 2))
181                         continue;
182
183                 strncpy(ptr, entry->d_name, space);
184                 if (stat(path, &st) < 0)
185                         continue;
186
187                 if (S_ISDIR(st.st_mode)) {
188                         result = __lookup_dev(path, dev, dir_level + 1, max_level);
189                         if (result)
190                                 break;
191                 } else if (S_ISBLK(st.st_mode)) {
192                         /* workaround: ignore dm-X devices, these are internal kernel names */
193                         if (dir_level == 0 && !strncmp(entry->d_name, "dm-", 3))
194                                 continue;
195                         if (st.st_rdev == dev) {
196                                 result = strdup(path);
197                                 break;
198                         }
199                 }
200         }
201
202         closedir(dir);
203         return result;
204 }
205
206 static char *lookup_dev(const char *dev_id)
207 {
208         uint32_t major, minor;
209         dev_t dev;
210         char *result = NULL, buf[PATH_MAX + 1];
211
212         if (sscanf(dev_id, "%" PRIu32 ":%" PRIu32, &major, &minor) != 2)
213                 return NULL;
214
215         dev = makedev(major, minor);
216         strncpy(buf, DEVICE_DIR, PATH_MAX);
217         buf[PATH_MAX] = '\0';
218
219         /* First try low level device */
220         if ((result = __lookup_dev(buf, dev, 0, 0)))
221                 return result;
222
223         /* If it is dm, try DM dir  */
224         if (dm_is_dm_major(major)) {
225                 strncpy(buf, dm_dir(), PATH_MAX);
226                 if ((result = __lookup_dev(buf, dev, 0, 0)))
227                         return result;
228         }
229
230         strncpy(buf, DEVICE_DIR, PATH_MAX);
231         result = __lookup_dev(buf, dev, 0, 4);
232
233         /* If not found, return NULL */
234         return result;
235 }
236
237 static int _dev_read_ahead(const char *dev, uint32_t *read_ahead)
238 {
239         int fd, r = 0;
240         long read_ahead_long;
241
242         if ((fd = open(dev, O_RDONLY)) < 0)
243                 return 0;
244
245         r = ioctl(fd, BLKRAGET, &read_ahead_long) ? 0 : 1;
246         close(fd);
247
248         if (r)
249                 *read_ahead = (uint32_t) read_ahead_long;
250
251         return r;
252 }
253
254 static void hex_key(char *hexkey, size_t key_size, const char *key)
255 {
256         int i;
257
258         for(i = 0; i < key_size; i++)
259                 sprintf(&hexkey[i * 2], "%02x", (unsigned char)key[i]);
260 }
261
262 static char *get_params(const char *device, uint64_t skip, uint64_t offset,
263                         const char *cipher, size_t key_size, const char *key)
264 {
265         char *params;
266         char *hexkey;
267
268         hexkey = crypt_safe_alloc(key_size * 2 + 1);
269         if (!hexkey)
270                 return NULL;
271
272         hex_key(hexkey, key_size, key);
273
274         params = crypt_safe_alloc(strlen(hexkey) + strlen(cipher) + strlen(device) + 64);
275         if (!params)
276                 goto out;
277
278         sprintf(params, "%s %s %" PRIu64 " %s %" PRIu64,
279                 cipher, hexkey, skip, device, offset);
280
281 out:
282         crypt_safe_free(hexkey);
283         return params;
284 }
285
286 /* DM helpers */
287 static int _dm_simple(int task, const char *name, int udev_wait)
288 {
289         int r = 0;
290         struct dm_task *dmt;
291         uint32_t cookie = 0;
292
293         if (!_dm_use_udev())
294                 udev_wait = 0;
295
296         if (!(dmt = dm_task_create(task)))
297                 return 0;
298
299         if (name && !dm_task_set_name(dmt, name))
300                 goto out;
301
302         if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, 0))
303                 goto out;
304
305         r = dm_task_run(dmt);
306
307         if (udev_wait)
308                 (void)_dm_udev_wait(cookie);
309
310       out:
311         dm_task_destroy(dmt);
312         return r;
313 }
314
315 static int _error_device(const char *name, size_t size)
316 {
317         struct dm_task *dmt;
318         int r = 0;
319
320         if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
321                 return 0;
322
323         if (!dm_task_set_name(dmt, name))
324                 goto error;
325
326         if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
327                 goto error;
328
329         if (!dm_task_set_ro(dmt))
330                 goto error;
331
332         if (!dm_task_no_open_count(dmt))
333                 goto error;
334
335         if (!dm_task_run(dmt))
336                 goto error;
337
338         if (!_dm_simple(DM_DEVICE_RESUME, name, 1)) {
339                 _dm_simple(DM_DEVICE_CLEAR, name, 0);
340                 goto error;
341         }
342
343         r = 1;
344
345 error:
346         dm_task_destroy(dmt);
347         return r;
348 }
349
350 int dm_remove_device(const char *name, int force, uint64_t size)
351 {
352         int r = -EINVAL;
353         int retries = force ? RETRY_COUNT : 1;
354         int error_target = 0;
355
356         if (!name || (force && !size))
357                 return -EINVAL;
358
359         do {
360                 r = _dm_simple(DM_DEVICE_REMOVE, name, 1) ? 0 : -EINVAL;
361                 if (--retries && r) {
362                         log_dbg("WARNING: other process locked internal device %s, %s.",
363                                 name, retries ? "retrying remove" : "giving up");
364                         if (force && (crypt_get_debug_level() == CRYPT_LOG_DEBUG))
365                                 debug_processes_using_device(name);
366                         sleep(1);
367                         if (force && !error_target) {
368                                 /* If force flag is set, replace device with error, read-only target.
369                                  * it should stop processes from reading it and also removed underlying
370                                  * device from mapping, so it is usable again.
371                                  * Force flag should be used only for temporary devices, which are
372                                  * intended to work inside cryptsetup only!
373                                  * Anyway, if some process try to read temporary cryptsetup device,
374                                  * it is bug - no other process should try touch it (e.g. udev).
375                                  */
376                                 _error_device(name, size);
377                                 error_target = 1;
378                         }
379                 }
380         } while (r == -EINVAL && retries);
381
382         dm_task_update_nodes();
383
384         return r;
385 }
386
387 #define UUID_LEN 37 /* 36 + \0, libuuid ... */
388 /*
389  * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
390  * CRYPT-PLAIN-name
391  * CRYPT-LUKS1-00000000000000000000000000000000-name
392  * CRYPT-TEMP-name
393  */
394 static void dm_prepare_uuid(const char *name, const char *type, const char *uuid, char *buf, size_t buflen)
395 {
396         char *ptr, uuid2[UUID_LEN] = {0};
397         uuid_t uu;
398         int i = 0;
399
400         /* Remove '-' chars */
401         if (uuid && !uuid_parse(uuid, uu)) {
402                 for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
403                         if (uuid[i] != '-') {
404                                 *ptr = uuid[i];
405                                 ptr++;
406                         }
407         }
408
409         i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
410                 type ?: "", type ? "-" : "",
411                 uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
412                 name);
413
414         log_dbg("DM-UUID is %s", buf);
415         if (i >= buflen)
416                 log_err(NULL, _("DM-UUID for device %s was truncated.\n"), name);
417 }
418
419 int dm_create_device(const char *name,
420                      const char *device,
421                      const char *cipher,
422                      const char *type,
423                      const char *uuid,
424                      uint64_t size,
425                      uint64_t skip,
426                      uint64_t offset,
427                      size_t key_size,
428                      const char *key,
429                      int read_only,
430                      int reload)
431 {
432         struct dm_task *dmt = NULL;
433         struct dm_info dmi;
434         char *params = NULL;
435         char *error = NULL;
436         char dev_uuid[DM_UUID_LEN] = {0};
437         int r = -EINVAL;
438         uint32_t read_ahead = 0;
439         uint32_t cookie = 0;
440         uint16_t udev_flags = 0;
441
442         params = get_params(device, skip, offset, cipher, key_size, key);
443         if (!params)
444                 goto out_no_removal;
445
446         if (type && !strncmp(type, "TEMP", 4))
447                 udev_flags = CRYPT_TEMP_UDEV_FLAGS;
448
449         /* All devices must have DM_UUID, only resize on old device is exception */
450         if (reload) {
451                 if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
452                         goto out_no_removal;
453
454                 if (!dm_task_set_name(dmt, name))
455                         goto out_no_removal;
456         } else {
457                 dm_prepare_uuid(name, type, uuid, dev_uuid, sizeof(dev_uuid));
458
459                 if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
460                         goto out_no_removal;
461
462                 if (!dm_task_set_name(dmt, name))
463                         goto out_no_removal;
464
465                 if (!dm_task_set_uuid(dmt, dev_uuid))
466                         goto out_no_removal;
467
468                 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
469                         goto out_no_removal;
470         }
471
472         if (read_only && !dm_task_set_ro(dmt))
473                 goto out_no_removal;
474         if (!dm_task_add_target(dmt, 0, size, DM_CRYPT_TARGET, params))
475                 goto out_no_removal;
476
477 #ifdef DM_READ_AHEAD_MINIMUM_FLAG
478         if (_dev_read_ahead(device, &read_ahead) &&
479             !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
480                 goto out_no_removal;
481 #endif
482
483         if (!dm_task_run(dmt))
484                 goto out_no_removal;
485
486         if (reload) {
487                 dm_task_destroy(dmt);
488                 if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
489                         goto out;
490                 if (!dm_task_set_name(dmt, name))
491                         goto out;
492                 if (uuid && !dm_task_set_uuid(dmt, dev_uuid))
493                         goto out;
494                 if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
495                         goto out;
496                 if (!dm_task_run(dmt))
497                         goto out;
498         }
499
500         if (!dm_task_get_info(dmt, &dmi))
501                 goto out;
502
503         r = 0;
504 out:
505         if (_dm_use_udev()) {
506                 (void)_dm_udev_wait(cookie);
507                 cookie = 0;
508         }
509
510         if (r < 0 && !reload) {
511                 if (get_error())
512                         error = strdup(get_error());
513
514                 dm_remove_device(name, 0, 0);
515
516                 if (error) {
517                         set_error(error);
518                         free(error);
519                 }
520         }
521
522 out_no_removal:
523         if (cookie && _dm_use_udev())
524                 (void)_dm_udev_wait(cookie);
525
526         if (params)
527                 crypt_safe_free(params);
528         if (dmt)
529                 dm_task_destroy(dmt);
530
531         dm_task_update_nodes();
532         return r;
533 }
534
535 int dm_status_device(const char *name)
536 {
537         struct dm_task *dmt;
538         struct dm_info dmi;
539         uint64_t start, length;
540         char *target_type, *params;
541         void *next = NULL;
542         int r = -EINVAL;
543
544         if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
545                 goto out;
546
547         if (!dm_task_set_name(dmt, name))
548                 goto out;
549
550         if (!dm_task_run(dmt))
551                 goto out;
552
553         if (!dm_task_get_info(dmt, &dmi))
554                 goto out;
555
556         if (!dmi.exists) {
557                 r = -ENODEV;
558                 goto out;
559         }
560
561         next = dm_get_next_target(dmt, next, &start, &length,
562                                   &target_type, &params);
563         if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
564             start != 0 || next)
565                 r = -EINVAL;
566         else
567                 r = (dmi.open_count > 0);
568 out:
569         if (dmt)
570                 dm_task_destroy(dmt);
571
572         return r;
573 }
574
575 int dm_query_device(const char *name,
576                     char **device,
577                     uint64_t *size,
578                     uint64_t *skip,
579                     uint64_t *offset,
580                     char **cipher,
581                     int *key_size,
582                     char **key,
583                     int *read_only,
584                     int *suspended,
585                     char **uuid)
586 {
587         struct dm_task *dmt;
588         struct dm_info dmi;
589         uint64_t start, length, val64;
590         char *target_type, *params, *rcipher, *key_, *rdevice, *endp, buffer[3], *tmp_uuid;
591         void *next = NULL;
592         int i, r = -EINVAL;
593
594         if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
595                 goto out;
596         if (!dm_task_set_name(dmt, name))
597                 goto out;
598         r = -ENODEV;
599         if (!dm_task_run(dmt))
600                 goto out;
601
602         r = -EINVAL;
603         if (!dm_task_get_info(dmt, &dmi))
604                 goto out;
605
606         if (!dmi.exists) {
607                 r = -ENODEV;
608                 goto out;
609         }
610
611         next = dm_get_next_target(dmt, next, &start, &length,
612                                   &target_type, &params);
613         if (!target_type || strcmp(target_type, DM_CRYPT_TARGET) != 0 ||
614             start != 0 || next)
615                 goto out;
616
617         if (size)
618                 *size = length;
619
620         rcipher = strsep(&params, " ");
621         /* cipher */
622         if (cipher)
623                 *cipher = strdup(rcipher);
624
625         /* skip */
626         key_ = strsep(&params, " ");
627         if (!params)
628                 goto out;
629         val64 = strtoull(params, &params, 10);
630         if (*params != ' ')
631                 goto out;
632         params++;
633         if (skip)
634                 *skip = val64;
635
636         /* device */
637         rdevice = strsep(&params, " ");
638         if (device)
639                 *device = lookup_dev(rdevice);
640
641         /*offset */
642         if (!params)
643                 goto out;
644         val64 = strtoull(params, &params, 10);
645         if (*params)
646                 goto out;
647         if (offset)
648                 *offset = val64;
649
650         /* key_size */
651         if (key_size)
652                 *key_size = strlen(key_) / 2;
653
654         /* key */
655         if (key_size && key) {
656                 *key = crypt_safe_alloc(*key_size);
657                 if (!*key) {
658                         r = -ENOMEM;
659                         goto out;
660                 }
661
662                 buffer[2] = '\0';
663                 for(i = 0; i < *key_size; i++) {
664                         memcpy(buffer, &key_[i * 2], 2);
665                         (*key)[i] = strtoul(buffer, &endp, 16);
666                         if (endp != &buffer[2]) {
667                                 crypt_safe_free(key);
668                                 *key = NULL;
669                                 goto out;
670                         }
671                 }
672         }
673         memset(key_, 0, strlen(key_));
674
675         if (read_only)
676                 *read_only = dmi.read_only;
677
678         if (suspended)
679                 *suspended = dmi.suspended;
680
681         if (uuid && (tmp_uuid = (char*)dm_task_get_uuid(dmt)) &&
682             !strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN))
683                 *uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
684
685         r = (dmi.open_count > 0);
686 out:
687         if (dmt)
688                 dm_task_destroy(dmt);
689
690         return r;
691 }
692
693 static int _dm_message(const char *name, const char *msg)
694 {
695         int r = 0;
696         struct dm_task *dmt;
697
698         if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
699                 return 0;
700
701         if (name && !dm_task_set_name(dmt, name))
702                 goto out;
703
704         if (!dm_task_set_sector(dmt, (uint64_t) 0))
705                 goto out;
706
707         if (!dm_task_set_message(dmt, msg))
708                 goto out;
709
710         r = dm_task_run(dmt);
711
712       out:
713         dm_task_destroy(dmt);
714         return r;
715 }
716
717 int dm_suspend_and_wipe_key(const char *name)
718 {
719         if (!_dm_check_versions())
720                 return -ENOTSUP;
721
722         if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
723                 return -ENOTSUP;
724
725         if (!_dm_simple(DM_DEVICE_SUSPEND, name, 0))
726                 return -EINVAL;
727
728         if (!_dm_message(name, "key wipe")) {
729                 _dm_simple(DM_DEVICE_RESUME, name, 1);
730                 return -EINVAL;
731         }
732
733         return 0;
734 }
735
736 int dm_resume_and_reinstate_key(const char *name,
737                                 size_t key_size,
738                                 const char *key)
739 {
740         int msg_size = key_size * 2 + 10; // key set <key>
741         char *msg;
742         int r = 0;
743
744         if (!_dm_check_versions())
745                 return -ENOTSUP;
746
747         if (!(_dm_crypt_flags & DM_KEY_WIPE_SUPPORTED))
748                 return -ENOTSUP;
749
750         msg = crypt_safe_alloc(msg_size);
751         if (!msg)
752                 return -ENOMEM;
753
754         memset(msg, 0, msg_size);
755         strcpy(msg, "key set ");
756         hex_key(&msg[8], key_size, key);
757
758         if (!_dm_message(name, msg) ||
759             !_dm_simple(DM_DEVICE_RESUME, name, 1))
760                 r = -EINVAL;
761
762         crypt_safe_free(msg);
763         return r;
764 }
765
766 const char *dm_get_dir(void)
767 {
768         return dm_dir();
769 }