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