Coverage Report

Created: 2026-10-28 07:06

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/cryptsetup/lib/libdevmapper.c
Line
Count
Source
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * libdevmapper - device-mapper backend for cryptsetup
4
 *
5
 * Copyright (C) 2004 Jana Saout <jana@saout.de>
6
 * Copyright (C) 2004-2007 Clemens Fruhwirth <clemens@endorphin.org>
7
 * Copyright (C) 2009-2026 Red Hat, Inc. All rights reserved.
8
 * Copyright (C) 2009-2026 Milan Broz
9
 */
10
11
#include <stdio.h>
12
#include <stdbool.h>
13
#include <ctype.h>
14
#include <errno.h>
15
#include <libdevmapper.h>
16
#include <uuid/uuid.h>
17
#include <sys/stat.h>
18
#if HAVE_SYS_SYSMACROS_H
19
# include <sys/sysmacros.h>     /* for major, minor */
20
#endif
21
#include "internal.h"
22
23
0
#define DM_CRYPT_TARGET   "crypt"
24
0
#define DM_VERITY_TARGET  "verity"
25
0
#define DM_INTEGRITY_TARGET "integrity"
26
0
#define DM_LINEAR_TARGET  "linear"
27
0
#define DM_ERROR_TARGET         "error"
28
0
#define DM_ZERO_TARGET    "zero"
29
0
#define RETRY_COUNT   5
30
31
/* Set if DM target versions were probed */
32
static bool _dm_ioctl_checked = false;
33
static bool _dm_crypt_checked = false;
34
static bool _dm_verity_checked = false;
35
static bool _dm_integrity_checked = false;
36
static bool _dm_zero_checked = false;
37
38
static int _quiet_log = 0;
39
static uint64_t _dm_flags = 0;
40
41
static struct crypt_device *_context = NULL;
42
static bool dm_backend_initialized = false;
43
static bool dm_backend_initialized_by_crypt = false;
44
45
/* Check if we have DM flag to instruct kernel to force wipe buffers */
46
#if !HAVE_DECL_DM_TASK_SECURE_DATA
47
static int dm_task_secure_data(struct dm_task *dmt) { return 1; }
48
#endif
49
50
/* Compatibility for old device-mapper without udev support */
51
#if HAVE_DECL_DM_UDEV_DISABLE_DISK_RULES_FLAG
52
0
#define CRYPT_TEMP_UDEV_FLAGS DM_UDEV_DISABLE_SUBSYSTEM_RULES_FLAG | \
53
0
        DM_UDEV_DISABLE_DISK_RULES_FLAG | \
54
0
        DM_UDEV_DISABLE_OTHER_RULES_FLAG
55
0
#define _dm_task_set_cookie dm_task_set_cookie
56
0
#define _dm_udev_wait   dm_udev_wait
57
#else
58
#define CRYPT_TEMP_UDEV_FLAGS 0
59
static int _dm_task_set_cookie(struct dm_task *dmt, uint32_t *cookie, uint16_t flags) { return 0; }
60
static int _dm_udev_wait(uint32_t cookie) { return 0; };
61
#endif
62
63
static int _dm_use_udev(void)
64
0
{
65
#if USE_UDEV /* cannot be enabled if devmapper is too old */
66
  return dm_udev_get_sync_support();
67
#else
68
0
  return 0;
69
0
#endif
70
0
}
71
72
__attribute__((format(printf, 4, 5)))
73
static void set_dm_error(int level,
74
       const char *file __attribute__((unused)),
75
       int line __attribute__((unused)),
76
       const char *f, ...)
77
0
{
78
0
  char *msg = NULL;
79
0
  va_list va;
80
81
0
  va_start(va, f);
82
0
  if (vasprintf(&msg, f, va) > 0) {
83
0
    if (level < 4 && !_quiet_log) {
84
0
      log_err(_context, "%s", msg);
85
0
    } else {
86
      /* We do not use DM visual stack backtrace here */
87
0
      if (strncmp(msg, "<backtrace>", 11))
88
0
        log_dbg(_context, "%s", msg);
89
0
    }
90
0
  }
91
0
  free(msg);
92
0
  va_end(va);
93
0
}
94
95
static int _dm_satisfies_version(unsigned target_maj, unsigned target_min, unsigned target_patch,
96
         unsigned actual_maj, unsigned actual_min, unsigned actual_patch)
97
0
{
98
0
  if (actual_maj > target_maj)
99
0
    return 1;
100
101
0
  if (actual_maj == target_maj && actual_min > target_min)
102
0
    return 1;
103
104
0
  if (actual_maj == target_maj && actual_min == target_min && actual_patch >= target_patch)
105
0
    return 1;
106
107
0
  return 0;
108
0
}
109
110
static void _dm_set_crypt_compat(struct crypt_device *cd,
111
         unsigned crypt_maj,
112
         unsigned crypt_min,
113
         unsigned crypt_patch)
114
0
{
115
0
  if (_dm_crypt_checked || crypt_maj == 0)
116
0
    return;
117
118
0
  log_dbg(cd, "Detected dm-crypt version %i.%i.%i.",
119
0
    crypt_maj, crypt_min, crypt_patch);
120
121
0
  if (_dm_satisfies_version(1, 2, 0, crypt_maj, crypt_min, crypt_patch))
122
0
    _dm_flags |= DM_KEY_WIPE_SUPPORTED;
123
0
  else
124
0
    log_dbg(cd, "Suspend and resume disabled, no wipe key support.");
125
126
0
  if (_dm_satisfies_version(1, 10, 0, crypt_maj, crypt_min, crypt_patch))
127
0
    _dm_flags |= DM_LMK_SUPPORTED;
128
129
  /* not perfect, 2.6.33 supports with 1.7.0 */
130
0
  if (_dm_satisfies_version(1, 8, 0, crypt_maj, crypt_min, crypt_patch))
131
0
    _dm_flags |= DM_PLAIN64_SUPPORTED;
132
133
0
  if (_dm_satisfies_version(1, 11, 0, crypt_maj, crypt_min, crypt_patch))
134
0
    _dm_flags |= DM_DISCARDS_SUPPORTED;
135
136
0
  if (_dm_satisfies_version(1, 13, 0, crypt_maj, crypt_min, crypt_patch))
137
0
    _dm_flags |= DM_TCW_SUPPORTED;
138
139
0
  if (_dm_satisfies_version(1, 14, 0, crypt_maj, crypt_min, crypt_patch)) {
140
0
    _dm_flags |= DM_SAME_CPU_CRYPT_SUPPORTED;
141
0
    _dm_flags |= DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED;
142
0
  }
143
144
0
  if (_dm_satisfies_version(1, 18, 1, crypt_maj, crypt_min, crypt_patch))
145
0
    _dm_flags |= DM_KERNEL_KEYRING_SUPPORTED;
146
147
0
  if (_dm_satisfies_version(1, 17, 0, crypt_maj, crypt_min, crypt_patch)) {
148
0
    _dm_flags |= DM_SECTOR_SIZE_SUPPORTED;
149
0
    _dm_flags |= DM_CAPI_STRING_SUPPORTED;
150
0
  }
151
152
0
  if (_dm_satisfies_version(1, 19, 0, crypt_maj, crypt_min, crypt_patch))
153
0
    _dm_flags |= DM_BITLK_EBOIV_SUPPORTED;
154
155
0
  if (_dm_satisfies_version(1, 20, 0, crypt_maj, crypt_min, crypt_patch))
156
0
    _dm_flags |= DM_BITLK_ELEPHANT_SUPPORTED;
157
158
0
  if (_dm_satisfies_version(1, 22, 0, crypt_maj, crypt_min, crypt_patch))
159
0
    _dm_flags |= DM_CRYPT_NO_WORKQUEUE_SUPPORTED;
160
161
0
  if (_dm_satisfies_version(1, 26, 0, crypt_maj, crypt_min, crypt_patch))
162
0
    _dm_flags |= DM_CRYPT_HIGH_PRIORITY_SUPPORTED;
163
164
0
  if (_dm_satisfies_version(1, 28, 0, crypt_maj, crypt_min, crypt_patch))
165
0
    _dm_flags |= DM_CRYPT_INTEGRITY_KEY_SIZE_OPT_SUPPORTED;
166
167
0
  _dm_crypt_checked = true;
168
0
}
169
170
static void _dm_set_verity_compat(struct crypt_device *cd,
171
          unsigned verity_maj,
172
          unsigned verity_min,
173
          unsigned verity_patch)
174
0
{
175
0
  if (_dm_verity_checked || verity_maj == 0)
176
0
    return;
177
178
0
  log_dbg(cd, "Detected dm-verity version %i.%i.%i.",
179
0
    verity_maj, verity_min, verity_patch);
180
181
0
  _dm_flags |= DM_VERITY_SUPPORTED;
182
183
  /*
184
   * ignore_corruption, restart_on corruption is available since 1.2 (kernel 4.1)
185
   * ignore_zero_blocks since 1.3 (kernel 4.5)
186
   * (but some dm-verity targets 1.2 don't support it)
187
   * FEC is added in 1.3 as well.
188
   * Check at most once is added in 1.4 (kernel 4.17).
189
   */
190
0
  if (_dm_satisfies_version(1, 3, 0, verity_maj, verity_min, verity_patch)) {
191
0
    _dm_flags |= DM_VERITY_ON_CORRUPTION_SUPPORTED;
192
0
    _dm_flags |= DM_VERITY_FEC_SUPPORTED;
193
0
  }
194
195
0
  if (_dm_satisfies_version(1, 5, 0, verity_maj, verity_min, verity_patch))
196
0
    _dm_flags |= DM_VERITY_SIGNATURE_SUPPORTED;
197
198
0
  if (_dm_satisfies_version(1, 7, 0, verity_maj, verity_min, verity_patch))
199
0
    _dm_flags |= DM_VERITY_PANIC_CORRUPTION_SUPPORTED;
200
201
0
  if (_dm_satisfies_version(1, 9, 0, verity_maj, verity_min, verity_patch))
202
0
    _dm_flags |= DM_VERITY_TASKLETS_SUPPORTED;
203
204
  /* There is actually no correct version set, just use the last available */
205
0
  if (_dm_satisfies_version(1, 10, 0, verity_maj, verity_min, verity_patch))
206
0
    _dm_flags |= DM_VERITY_ERROR_AS_CORRUPTION_SUPPORTED;
207
208
0
  _dm_verity_checked = true;
209
0
}
210
211
static void _dm_set_integrity_compat(struct crypt_device *cd,
212
             unsigned integrity_maj,
213
             unsigned integrity_min,
214
             unsigned integrity_patch)
215
0
{
216
0
  if (_dm_integrity_checked || integrity_maj == 0)
217
0
    return;
218
219
0
  log_dbg(cd, "Detected dm-integrity version %i.%i.%i.",
220
0
    integrity_maj, integrity_min, integrity_patch);
221
222
0
  _dm_flags |= DM_INTEGRITY_SUPPORTED;
223
224
0
  if (_dm_satisfies_version(1, 2, 0, integrity_maj, integrity_min, integrity_patch))
225
0
    _dm_flags |= DM_INTEGRITY_RECALC_SUPPORTED;
226
227
0
  if (_dm_satisfies_version(1, 3, 0, integrity_maj, integrity_min, integrity_patch))
228
0
    _dm_flags |= DM_INTEGRITY_BITMAP_SUPPORTED;
229
230
0
  if (_dm_satisfies_version(1, 4, 0, integrity_maj, integrity_min, integrity_patch))
231
0
    _dm_flags |= DM_INTEGRITY_FIX_PADDING_SUPPORTED;
232
233
0
  if (_dm_satisfies_version(1, 6, 0, integrity_maj, integrity_min, integrity_patch))
234
0
    _dm_flags |= DM_INTEGRITY_DISCARDS_SUPPORTED;
235
236
0
  if (_dm_satisfies_version(1, 7, 0, integrity_maj, integrity_min, integrity_patch))
237
0
    _dm_flags |= DM_INTEGRITY_FIX_HMAC_SUPPORTED;
238
239
0
  if (_dm_satisfies_version(1, 8, 0, integrity_maj, integrity_min, integrity_patch))
240
0
    _dm_flags |= DM_INTEGRITY_RESET_RECALC_SUPPORTED;
241
242
0
  if (_dm_satisfies_version(1, 12, 0, integrity_maj, integrity_min, integrity_patch))
243
0
    _dm_flags |= DM_INTEGRITY_INLINE_MODE_SUPPORTED;
244
245
0
  if (_dm_satisfies_version(1, 15, 0, integrity_maj, integrity_min, integrity_patch))
246
0
    _dm_flags |= DM_INTEGRITY_DISCARD_KEYED_SUPPORTED;
247
248
0
  _dm_integrity_checked = true;
249
0
}
250
251
static void _dm_set_zero_compat(struct crypt_device *cd,
252
        unsigned zero_maj,
253
        unsigned zero_min,
254
        unsigned zero_patch)
255
0
{
256
0
  if (_dm_zero_checked || zero_maj == 0)
257
0
    return;
258
259
0
  log_dbg(cd, "Detected dm-zero version %i.%i.%i.",
260
0
    zero_maj, zero_min, zero_patch);
261
262
0
  _dm_zero_checked = true;
263
0
}
264
265
/* We use this for loading target module */
266
static void _dm_check_target(dm_target_type target_type)
267
0
{
268
0
#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
269
0
  struct dm_task *dmt;
270
0
  const char *target_name = NULL;
271
272
0
  if (!(_dm_flags & DM_GET_TARGET_VERSION_SUPPORTED))
273
0
    return;
274
275
0
  if (target_type == DM_CRYPT)
276
0
    target_name = DM_CRYPT_TARGET;
277
0
  else if (target_type == DM_VERITY)
278
0
    target_name = DM_VERITY_TARGET;
279
0
  else if (target_type == DM_INTEGRITY)
280
0
    target_name = DM_INTEGRITY_TARGET;
281
0
  else
282
0
    return;
283
284
0
  if (!(dmt = dm_task_create(DM_DEVICE_GET_TARGET_VERSION)))
285
0
    return;
286
287
0
  if (dm_task_set_name(dmt, target_name))
288
0
    dm_task_run(dmt);
289
290
0
  dm_task_destroy(dmt);
291
0
#endif
292
0
}
293
294
static int _dm_check_versions(struct crypt_device *cd, dm_target_type target_type)
295
0
{
296
0
  struct dm_task *dmt;
297
0
  struct dm_versions *target, *last_target;
298
0
  char dm_version[16];
299
0
  unsigned dm_maj, dm_min, dm_patch;
300
0
  int r = 0;
301
302
  /*
303
   * Backend must be initialized by the caller; if not, it's an internal
304
   * libcryptsetup error that regresses by spamming stderr with libdm warnings.
305
   */
306
0
  assert(dm_backend_initialized);
307
308
0
  if ((target_type == DM_CRYPT     && _dm_crypt_checked) ||
309
0
      (target_type == DM_VERITY    && _dm_verity_checked) ||
310
0
      (target_type == DM_INTEGRITY && _dm_integrity_checked) ||
311
0
      (target_type == DM_ZERO      && _dm_zero_checked) ||
312
0
      (target_type == DM_LINEAR) ||
313
0
      (_dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked))
314
0
    return 1;
315
316
  /* Shut up DM while checking */
317
0
  _quiet_log = 1;
318
319
0
  _dm_check_target(target_type);
320
321
0
  if (!(dmt = dm_task_create(DM_DEVICE_LIST_VERSIONS)))
322
0
    goto out;
323
324
0
  if (!dm_task_run(dmt))
325
0
    goto out;
326
327
0
  if (!dm_task_get_driver_version(dmt, dm_version, sizeof(dm_version)))
328
0
    goto out;
329
330
0
  if (!_dm_ioctl_checked) {
331
0
    if (sscanf(dm_version, "%u.%u.%u", &dm_maj, &dm_min, &dm_patch) != 3)
332
0
      goto out;
333
0
    log_dbg(cd, "Detected dm-ioctl version %u.%u.%u.", dm_maj, dm_min, dm_patch);
334
335
0
    if (_dm_satisfies_version(4, 20, 0, dm_maj, dm_min, dm_patch))
336
0
      _dm_flags |= DM_SECURE_SUPPORTED;
337
0
#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
338
0
    if (_dm_satisfies_version(4, 27, 0, dm_maj, dm_min, dm_patch))
339
0
      _dm_flags |= DM_DEFERRED_SUPPORTED;
340
0
#endif
341
0
#if HAVE_DECL_DM_DEVICE_GET_TARGET_VERSION
342
0
    if (_dm_satisfies_version(4, 41, 0, dm_maj, dm_min, dm_patch))
343
0
      _dm_flags |= DM_GET_TARGET_VERSION_SUPPORTED;
344
0
#endif
345
0
  }
346
347
0
  target = dm_task_get_versions(dmt);
348
0
  do {
349
0
    last_target = target;
350
0
    if (!strcmp(DM_CRYPT_TARGET, target->name)) {
351
0
      _dm_set_crypt_compat(cd, (unsigned)target->version[0],
352
0
               (unsigned)target->version[1],
353
0
               (unsigned)target->version[2]);
354
0
    } else if (!strcmp(DM_VERITY_TARGET, target->name)) {
355
0
      _dm_set_verity_compat(cd, (unsigned)target->version[0],
356
0
                (unsigned)target->version[1],
357
0
                (unsigned)target->version[2]);
358
0
    } else if (!strcmp(DM_INTEGRITY_TARGET, target->name)) {
359
0
      _dm_set_integrity_compat(cd, (unsigned)target->version[0],
360
0
             (unsigned)target->version[1],
361
0
             (unsigned)target->version[2]);
362
0
    } else if (!strcmp(DM_ZERO_TARGET, target->name)) {
363
0
      _dm_set_zero_compat(cd, (unsigned)target->version[0],
364
0
              (unsigned)target->version[1],
365
0
              (unsigned)target->version[2]);
366
0
    }
367
0
    target = VOIDP_CAST(struct dm_versions *)((char *) target + target->next);
368
0
  } while (last_target != target);
369
370
0
  r = 1;
371
0
  if (!_dm_ioctl_checked)
372
0
    log_dbg(cd, "Device-mapper backend running with UDEV support %sabled.",
373
0
      _dm_use_udev() ? "en" : "dis");
374
375
0
  _dm_ioctl_checked = true;
376
0
out:
377
0
  if (dmt)
378
0
    dm_task_destroy(dmt);
379
380
0
  _quiet_log = 0;
381
0
  return r;
382
0
}
383
384
static int _do_dm_flags(struct crypt_device *cd, dm_target_type target, uint64_t *flags)
385
0
{
386
0
  _dm_check_versions(cd, target);
387
0
  *flags = _dm_flags;
388
389
0
  if (target == DM_UNKNOWN &&
390
0
      _dm_crypt_checked && _dm_verity_checked && _dm_integrity_checked && _dm_zero_checked)
391
0
    return 0;
392
393
0
  if ((target == DM_CRYPT     && _dm_crypt_checked) ||
394
0
      (target == DM_VERITY    && _dm_verity_checked) ||
395
0
      (target == DM_INTEGRITY && _dm_integrity_checked) ||
396
0
      (target == DM_ZERO      && _dm_zero_checked) ||
397
0
      (target == DM_LINEAR)) /* nothing to check */
398
0
    return 0;
399
400
0
  return -ENODEV;
401
0
}
402
403
static void dm_backend_set_log_callback(void)
404
0
{
405
0
  dm_log_init(set_dm_error);
406
0
  dm_log_init_verbose(10);
407
0
}
408
409
/* This doesn't run any kernel checks, just set up userspace libdevmapper */
410
static void dm_backend_init(void)
411
0
{
412
0
  if (!dm_backend_initialized) {
413
    /* If someone initialized libdm log callback already, do not touch it. */
414
0
    if (dm_log_is_non_default())
415
0
      log_dbg(NULL, "device-mapper backend library already initialized.");
416
0
    else {
417
0
      log_dbg(NULL, "Initialising device-mapper backend library.");
418
0
      dm_backend_set_log_callback();
419
0
      dm_backend_initialized_by_crypt = true;
420
0
    }
421
422
0
    dm_backend_initialized = true;
423
0
  } else if (dm_backend_initialized_by_crypt)
424
    /* If we initialized libdm, reset log functions on every call. */
425
0
    dm_backend_set_log_callback();
426
0
}
427
428
void dm_backend_exit(void)
429
0
{
430
  /* Release dm backend only if it was initialized by libcryptsetup */
431
0
  if (dm_backend_initialized_by_crypt) {
432
0
    dm_log_init_verbose(0);
433
0
    dm_log_init(NULL);
434
0
    dm_lib_release();
435
0
    dm_backend_initialized_by_crypt = false;
436
0
  }
437
0
}
438
439
/* libdevmapper is not context friendly, switch context on every DM call. */
440
static int dm_init_context(struct crypt_device *cd, dm_target_type target)
441
0
{
442
0
  dm_backend_init();
443
0
  _context = cd;
444
0
  if (!_dm_check_versions(cd, target)) {
445
0
    if (getuid() || geteuid())
446
0
      log_err(cd, _("Cannot initialize device-mapper, "
447
0
              "running as non-root user."));
448
0
    else
449
0
      log_err(cd, _("Cannot initialize device-mapper. "
450
0
              "Is dm_mod kernel module loaded?"));
451
0
    _context = NULL;
452
0
    return -ENOTSUP;
453
0
  }
454
0
  return 0;
455
0
}
456
static void dm_exit_context(void)
457
0
{
458
0
  _context = NULL;
459
0
}
460
461
int dm_flags(struct crypt_device *cd, dm_target_type target, uint64_t *flags)
462
0
{
463
0
  int r;
464
465
  /* We have to route dm log via set_dm_error, otherwise dm_check_versions spams stderr */
466
0
  dm_backend_init();
467
0
  _context = cd;
468
469
0
  r = _do_dm_flags(cd, target, flags);
470
471
0
  dm_exit_context();
472
473
0
  return r;
474
0
}
475
476
/* Return path to DM device */
477
char *dm_device_path(const char *prefix, int major, int minor)
478
0
{
479
0
  struct dm_task *dmt;
480
0
  const char *name;
481
0
  char path[PATH_MAX];
482
483
0
  if (dm_init_context(NULL, DM_UNKNOWN))
484
0
    return NULL;
485
486
0
  if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
487
0
    goto err;
488
0
  if (!dm_task_set_minor(dmt, minor) ||
489
0
      !dm_task_set_major(dmt, major) ||
490
0
      !dm_task_no_flush(dmt) ||
491
0
      !dm_task_run(dmt) ||
492
0
      !(name = dm_task_get_name(dmt))) {
493
0
    dm_task_destroy(dmt);
494
0
    goto err;
495
0
  }
496
497
0
  if (snprintf(path, sizeof(path), "%s%s", prefix ?: "", name) < 0)
498
0
    path[0] = '\0';
499
500
0
  dm_task_destroy(dmt);
501
0
  dm_exit_context();
502
0
  return strdup(path);
503
0
err:
504
0
  dm_exit_context();
505
0
  return NULL;
506
0
}
507
508
char *dm_device_name(const char *path)
509
0
{
510
0
  struct stat st;
511
512
0
  if (stat(path, &st) < 0 || !S_ISBLK(st.st_mode))
513
0
    return NULL;
514
515
0
  return dm_device_path(NULL, major(st.st_rdev), minor(st.st_rdev));
516
0
}
517
518
static size_t int_log10(uint64_t x)
519
0
{
520
0
  uint64_t r = 0;
521
0
  for (x /= 10; x > 0; x /= 10)
522
0
    r++;
523
0
  return r;
524
0
}
525
526
static int cipher_dm2c(const char *org_c, const char *org_i, unsigned tag_size,
527
           char *c_dm, int c_dm_size,
528
           char *i_dm, int i_dm_size)
529
0
{
530
0
  int c_size = 0, i_size = 0, i;
531
0
  char cipher[MAX_CAPI_ONE_LEN], mode[MAX_CAPI_ONE_LEN], iv[MAX_CAPI_ONE_LEN+1],
532
0
       tmp[MAX_CAPI_ONE_LEN], capi[MAX_CAPI_LEN];
533
534
0
  if (!c_dm || !c_dm_size || !i_dm || !i_dm_size)
535
0
    return -EINVAL;
536
537
0
  i = sscanf(org_c, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", cipher, tmp);
538
0
  if (i != 2)
539
0
    return -EINVAL;
540
541
0
  i = sscanf(tmp, "%" MAX_CAPI_ONE_LEN_STR "[^-]-%" MAX_CAPI_ONE_LEN_STR "s", mode, iv);
542
0
  if (i == 1) {
543
0
    memset(iv, 0, sizeof(iv));
544
0
    strncpy(iv, mode, sizeof(iv)-1);
545
0
    *mode = '\0';
546
0
    if (snprintf(capi, sizeof(capi), "%s", cipher) < 0)
547
0
      return -EINVAL;
548
0
  } else if (i == 2) {
549
0
    if (snprintf(capi, sizeof(capi), "%s(%s)", mode, cipher) < 0)
550
0
      return -EINVAL;
551
0
  } else
552
0
    return -EINVAL;
553
554
0
  if (!org_i) {
555
    /* legacy mode: CIPHER-MODE-IV*/
556
0
    i_size = snprintf(i_dm, i_dm_size, "%s", "");
557
0
    c_size = snprintf(c_dm, c_dm_size, "%s", org_c);
558
0
  } else if (!strcmp(org_i, "none")) {
559
    /* IV only: capi:MODE(CIPHER)-IV */
560
0
    i_size = snprintf(i_dm, i_dm_size, " integrity:%u:none", tag_size);
561
0
    c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
562
0
  } else if (!strcmp(org_i, "aead") && !strcmp(mode, "ccm")) {
563
    /* CCM AEAD: capi:rfc4309(MODE(CIPHER))-IV */
564
0
    i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
565
0
    c_size = snprintf(c_dm, c_dm_size, "capi:rfc4309(%s)-%s", capi, iv);
566
0
  } else if (!strcmp(org_i, "aead")) {
567
    /* AEAD: capi:MODE(CIPHER))-IV */
568
0
    i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
569
0
    c_size = snprintf(c_dm, c_dm_size, "capi:%s-%s", capi, iv);
570
0
  } else if (!strcmp(org_i, "poly1305")) {
571
    /* POLY1305 AEAD: capi:rfc7539(MODE(CIPHER),POLY1305)-IV */
572
0
    i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
573
0
    c_size = snprintf(c_dm, c_dm_size, "capi:rfc7539(%s,poly1305)-%s", capi, iv);
574
0
  } else {
575
    /* other AEAD: capi:authenc(<AUTH>,MODE(CIPHER))-IV */
576
0
    i_size = snprintf(i_dm, i_dm_size, " integrity:%u:aead", tag_size);
577
0
    c_size = snprintf(c_dm, c_dm_size, "capi:authenc(%s,%s)-%s", org_i, capi, iv);
578
0
  }
579
580
0
  if (c_size < 0 || c_size >= c_dm_size)
581
0
    return -EINVAL;
582
0
  if (i_size < 0 || i_size >= i_dm_size)
583
0
    return -EINVAL;
584
585
0
  return 0;
586
0
}
587
588
static char *_uf(char *buf, size_t buf_size, const char *s, unsigned u)
589
0
{
590
0
  size_t r = snprintf(buf, buf_size, " %s:%u", s, u);
591
0
  assert(r > 0 && r < buf_size);
592
0
  return buf;
593
0
}
594
595
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMCrypt */
596
static char *get_dm_crypt_params(const struct dm_target *tgt, uint32_t flags)
597
0
{
598
0
  int r, max_size, null_cipher = 0, num_options = 0, keystr_len = 0;
599
0
  char *params = NULL, *hexkey = NULL;
600
0
  char sector_feature[32], features[512], integrity_dm[256], cipher_dm[256];
601
0
  char int_ksize_feature[32];
602
603
0
  if (!tgt)
604
0
    return NULL;
605
606
0
  r = cipher_dm2c(tgt->u.crypt.cipher, tgt->u.crypt.integrity, tgt->u.crypt.tag_size,
607
0
      cipher_dm, sizeof(cipher_dm), integrity_dm, sizeof(integrity_dm));
608
0
  if (r < 0)
609
0
    return NULL;
610
611
0
  if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
612
0
    num_options++;
613
0
  if (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT)
614
0
    num_options++;
615
0
  if (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)
616
0
    num_options++;
617
0
  if (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE)
618
0
    num_options++;
619
0
  if (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)
620
0
    num_options++;
621
0
  if (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS)
622
0
    num_options++;
623
0
  if (flags & CRYPT_ACTIVATE_HIGH_PRIORITY)
624
0
    num_options++;
625
0
  if (tgt->u.crypt.integrity)
626
0
    num_options++;
627
0
  if (tgt->u.crypt.sector_size != SECTOR_SIZE)
628
0
    num_options++;
629
0
  if (tgt->u.crypt.integrity && tgt->u.crypt.integrity_key_size)
630
0
    num_options++;
631
632
0
  if (num_options) { /* MAX length  int32 + 15 + 15 + 23 + 18 + 19 + 17 + 14 + 13 + int32 + integrity_str + 21 + int32 */
633
0
    r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s%s%s%s", num_options,
634
0
    (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) ? " allow_discards" : "",
635
0
    (flags & CRYPT_ACTIVATE_SAME_CPU_CRYPT) ? " same_cpu_crypt" : "",
636
0
    (flags & CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) ? " submit_from_crypt_cpus" : "",
637
0
    (flags & CRYPT_ACTIVATE_NO_READ_WORKQUEUE) ? " no_read_workqueue" : "",
638
0
    (flags & CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) ? " no_write_workqueue" : "",
639
0
    (flags & CRYPT_ACTIVATE_IV_LARGE_SECTORS) ? " iv_large_sectors" : "",
640
0
    (flags & CRYPT_ACTIVATE_HIGH_PRIORITY) ? " high_priority" : "",
641
0
    (tgt->u.crypt.sector_size != SECTOR_SIZE) ?
642
0
      _uf(sector_feature, sizeof(sector_feature), "sector_size", tgt->u.crypt.sector_size) : "",
643
0
    integrity_dm,
644
0
    (tgt->u.crypt.integrity && tgt->u.crypt.integrity_key_size) ?
645
0
      _uf(int_ksize_feature, sizeof(int_ksize_feature), "integrity_key_size", tgt->u.crypt.integrity_key_size) : "");
646
0
    if (r < 0 || (size_t)r >= sizeof(features))
647
0
      goto out;
648
0
  } else
649
0
    *features = '\0';
650
651
0
  if (crypt_is_cipher_null(cipher_dm))
652
0
    null_cipher = 1;
653
654
0
  if (null_cipher || crypt_volume_key_length(tgt->u.crypt.vk) == 0)
655
0
    hexkey = crypt_bytes_to_hex(0, NULL);
656
0
  else if (flags & CRYPT_ACTIVATE_KEYRING_KEY) {
657
0
    if (!crypt_volume_key_description(tgt->u.crypt.vk) ||
658
0
        crypt_volume_key_kernel_key_type(tgt->u.crypt.vk) == INVALID_KEY)
659
0
      goto out;
660
0
    keystr_len = strlen(crypt_volume_key_description(tgt->u.crypt.vk)) +
661
0
      int_log10(crypt_volume_key_length(tgt->u.crypt.vk)) +
662
0
      24 /* type and separators */;
663
0
    hexkey = crypt_safe_alloc(keystr_len);
664
0
    if (!hexkey)
665
0
      goto out;
666
0
    r = snprintf(hexkey, keystr_len, ":%zu:%s:%s", crypt_volume_key_length(tgt->u.crypt.vk),
667
0
           key_type_name(crypt_volume_key_kernel_key_type(tgt->u.crypt.vk)),
668
0
           crypt_volume_key_description(tgt->u.crypt.vk));
669
0
    if (r < 0 || r >= keystr_len)
670
0
      goto out;
671
0
  } else
672
0
    hexkey = crypt_bytes_to_hex(crypt_volume_key_length(tgt->u.crypt.vk),
673
0
              crypt_volume_key_get_key(tgt->u.crypt.vk));
674
675
0
  if (!hexkey)
676
0
    goto out;
677
678
0
  max_size = strlen(hexkey) + strlen(cipher_dm) +
679
0
       strlen(device_block_path(tgt->data_device)) +
680
0
       strlen(features) + 64;
681
0
  params = crypt_safe_alloc(max_size);
682
0
  if (!params)
683
0
    goto out;
684
685
0
  r = snprintf(params, max_size, "%s %s %" PRIu64 " %s %" PRIu64 "%s",
686
0
         cipher_dm, hexkey, tgt->u.crypt.iv_offset,
687
0
         device_block_path(tgt->data_device), tgt->u.crypt.offset,
688
0
         features);
689
0
  if (r < 0 || r >= max_size) {
690
0
    crypt_safe_free(params);
691
0
    params = NULL;
692
0
  }
693
0
out:
694
0
  crypt_safe_free(hexkey);
695
0
  return params;
696
0
}
697
698
/* https://gitlab.com/cryptsetup/cryptsetup/wikis/DMVerity */
699
static char *get_dm_verity_params(const struct dm_target *tgt, uint32_t flags)
700
0
{
701
0
  int max_size, max_fec_size, max_verify_size, r, num_options = 0;
702
0
  struct crypt_params_verity *vp;
703
0
  char *params = NULL, *hexroot = NULL, *hexsalt = NULL;
704
0
  char features[256], *fec_features = NULL, *verity_verify_args = NULL;
705
706
0
  if (!tgt || !tgt->u.verity.vp)
707
0
    return NULL;
708
709
0
  vp = tgt->u.verity.vp;
710
711
  /* These flags are not compatible */
712
0
  if ((flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) &&
713
0
      (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION))
714
0
    flags &= ~CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
715
0
  if ((flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) &&
716
0
      (flags & (CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)))
717
0
    flags &= ~CRYPT_ACTIVATE_IGNORE_CORRUPTION;
718
719
0
  if (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION)
720
0
    num_options++;
721
0
  if (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION)
722
0
    num_options++;
723
0
  if (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION)
724
0
    num_options++;
725
0
  if (flags & CRYPT_ACTIVATE_ERROR_AS_CORRUPTION)
726
0
    num_options++;
727
0
  if (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS)
728
0
    num_options++;
729
0
  if (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE)
730
0
    num_options++;
731
0
  if (flags & CRYPT_ACTIVATE_TASKLETS)
732
0
    num_options++;
733
734
0
  max_fec_size = (tgt->u.verity.fec_device ? strlen(device_block_path(tgt->u.verity.fec_device)) : 0) + 256;
735
0
  fec_features = crypt_safe_alloc(max_fec_size);
736
0
  if (!fec_features)
737
0
    goto out;
738
739
0
  if (tgt->u.verity.fec_device) {  /* MAX length 21 + path + 11 + int64 + 12 + int64 + 11 + int32 */
740
0
    num_options += 8;
741
0
    r = snprintf(fec_features, max_fec_size,
742
0
       " use_fec_from_device %s fec_start %" PRIu64 " fec_blocks %" PRIu64 " fec_roots %" PRIu32,
743
0
       device_block_path(tgt->u.verity.fec_device), tgt->u.verity.fec_offset,
744
0
       tgt->u.verity.fec_blocks, vp->fec_roots);
745
0
    if (r < 0 || r >= max_fec_size)
746
0
      goto out;
747
0
  } else
748
0
    *fec_features = '\0';
749
750
0
  max_verify_size = (tgt->u.verity.root_hash_sig_key_desc ? strlen(tgt->u.verity.root_hash_sig_key_desc) : 0) + 32;
751
0
  verity_verify_args = crypt_safe_alloc(max_verify_size);
752
0
  if (!verity_verify_args)
753
0
    goto out;
754
0
  if (tgt->u.verity.root_hash_sig_key_desc) {  /* MAX length 24 + key_str */
755
0
    num_options += 2;
756
0
    r = snprintf(verity_verify_args, max_verify_size,
757
0
        " root_hash_sig_key_desc %s", tgt->u.verity.root_hash_sig_key_desc);
758
0
    if (r < 0 || r >= max_verify_size)
759
0
      goto out;
760
0
  } else
761
0
    *verity_verify_args = '\0';
762
763
0
  if (num_options) {  /* MAX length int32 + 18 + 22 + 20 + 19 + 19 + 22 */
764
0
    r = snprintf(features, sizeof(features), " %d%s%s%s%s%s%s%s", num_options,
765
0
    (flags & CRYPT_ACTIVATE_IGNORE_CORRUPTION) ? " ignore_corruption" : "",
766
0
    (flags & CRYPT_ACTIVATE_RESTART_ON_CORRUPTION) ? " restart_on_corruption" : "",
767
0
    (flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ? " panic_on_corruption" : "",
768
0
    (flags & CRYPT_ACTIVATE_ERROR_AS_CORRUPTION) ? ((flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION) ?
769
0
      " panic_on_error" : " restart_on_error") : "",
770
0
    (flags & CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS) ? " ignore_zero_blocks" : "",
771
0
    (flags & CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) ? " check_at_most_once" : "",
772
0
    (flags & CRYPT_ACTIVATE_TASKLETS) ? " try_verify_in_tasklet" : "");
773
0
    if (r < 0 || (size_t)r >= sizeof(features))
774
0
      goto out;
775
0
  } else
776
0
    *features = '\0';
777
778
0
  hexroot = crypt_bytes_to_hex(tgt->u.verity.root_hash_size, tgt->u.verity.root_hash);
779
0
  if (!hexroot)
780
0
    goto out;
781
782
0
  hexsalt = crypt_bytes_to_hex(vp->salt_size, vp->salt);
783
0
  if (!hexsalt)
784
0
    goto out;
785
786
0
  max_size = strlen(hexroot) + strlen(hexsalt) +
787
0
       strlen(device_block_path(tgt->data_device)) +
788
0
       strlen(device_block_path(tgt->u.verity.hash_device)) +
789
0
       strlen(vp->hash_name) + strlen(features) + strlen(fec_features) + 128 +
790
0
       strlen(verity_verify_args);
791
792
0
  params = crypt_safe_alloc(max_size);
793
0
  if (!params)
794
0
    goto out;
795
796
0
  r = snprintf(params, max_size,
797
0
         "%u %s %s %u %u %" PRIu64 " %" PRIu64 " %s %s %s%s%s%s",
798
0
         vp->hash_type, device_block_path(tgt->data_device),
799
0
         device_block_path(tgt->u.verity.hash_device),
800
0
         vp->data_block_size, vp->hash_block_size,
801
0
         vp->data_size, tgt->u.verity.hash_offset,
802
0
         vp->hash_name, hexroot, hexsalt, features, fec_features,
803
0
         verity_verify_args);
804
0
  if (r < 0 || r >= max_size) {
805
0
    crypt_safe_free(params);
806
0
    params = NULL;
807
0
  }
808
0
out:
809
0
  crypt_safe_free(fec_features);
810
0
  crypt_safe_free(verity_verify_args);
811
0
  crypt_safe_free(hexroot);
812
0
  crypt_safe_free(hexsalt);
813
0
  return params;
814
0
}
815
816
static char *get_dm_integrity_params(const struct dm_target *tgt, uint32_t flags)
817
0
{
818
0
  int r, max_size, max_integrity, max_journal_integrity, max_journal_crypt, num_options = 0;
819
0
  char *params_out = NULL, *params, *hexkey, mode, feature[6][32];
820
0
  char *features, *integrity, *journal_integrity, *journal_crypt;
821
822
0
  if (!tgt)
823
0
    return NULL;
824
825
0
  max_integrity = (tgt->u.integrity.integrity && tgt->u.integrity.vk ? crypt_volume_key_length(tgt->u.integrity.vk) * 2 : 0) +
826
0
    (tgt->u.integrity.integrity ? strlen(tgt->u.integrity.integrity) : 0) + 32;
827
0
  max_journal_integrity = (tgt->u.integrity.journal_integrity && tgt->u.integrity.journal_integrity_key ?
828
0
    crypt_volume_key_length(tgt->u.integrity.journal_integrity_key) * 2 : 0) +
829
0
    (tgt->u.integrity.journal_integrity ? strlen(tgt->u.integrity.journal_integrity) : 0) + 32;
830
0
  max_journal_crypt = (tgt->u.integrity.journal_crypt && tgt->u.integrity.journal_crypt_key ?
831
0
    crypt_volume_key_length(tgt->u.integrity.journal_crypt_key) * 2 : 0) +
832
0
    (tgt->u.integrity.journal_crypt ? strlen(tgt->u.integrity.journal_crypt) : 0) + 32;
833
0
  max_size = strlen(device_block_path(tgt->data_device)) +
834
0
    (tgt->u.integrity.meta_device ? strlen(device_block_path(tgt->u.integrity.meta_device)) : 0) +
835
0
    max_integrity + max_journal_integrity + max_journal_crypt + 512;
836
837
0
  params = crypt_safe_alloc(max_size);
838
0
  features = crypt_safe_alloc(max_size);
839
0
  integrity = crypt_safe_alloc(max_integrity);
840
0
  journal_integrity = crypt_safe_alloc(max_journal_integrity);
841
0
  journal_crypt = crypt_safe_alloc(max_journal_crypt);
842
0
  if (!params || !features || !integrity || !journal_integrity || !journal_crypt)
843
0
    goto out;
844
845
0
  if (tgt->u.integrity.integrity) { /* MAX length 16 + str_integrity +  str_key */
846
0
    num_options++;
847
848
0
    if (tgt->u.integrity.vk) {
849
0
      hexkey = crypt_bytes_to_hex(crypt_volume_key_length(tgt->u.integrity.vk),
850
0
                crypt_volume_key_get_key(tgt->u.integrity.vk));
851
0
      if (!hexkey)
852
0
        goto out;
853
0
    } else
854
0
      hexkey = NULL;
855
856
0
    r = snprintf(integrity, max_integrity, " internal_hash:%s%s%s",
857
0
       tgt->u.integrity.integrity, hexkey ? ":" : "", hexkey ?: "");
858
0
    crypt_safe_free(hexkey);
859
0
    if (r < 0 || r >= max_integrity)
860
0
      goto out;
861
0
  }
862
863
0
  if (tgt->u.integrity.journal_integrity) { /* MAX length 14 + str_journal_integrity + str_key */
864
0
    num_options++;
865
866
0
    if (tgt->u.integrity.journal_integrity_key) {
867
0
      hexkey = crypt_bytes_to_hex(crypt_volume_key_length(tgt->u.integrity.journal_integrity_key),
868
0
        crypt_volume_key_get_key(tgt->u.integrity.journal_integrity_key));
869
0
      if (!hexkey)
870
0
        goto out;
871
0
    } else
872
0
      hexkey = NULL;
873
874
0
    r = snprintf(journal_integrity, max_journal_integrity, " journal_mac:%s%s%s",
875
0
       tgt->u.integrity.journal_integrity, hexkey ? ":" : "", hexkey ?: "");
876
0
    crypt_safe_free(hexkey);
877
0
    if (r < 0 || r >= max_journal_integrity)
878
0
      goto out;
879
0
  }
880
881
0
  if (tgt->u.integrity.journal_crypt) { /* MAX length 15 + str_journal_crypt + str_key */
882
0
    num_options++;
883
884
0
    if (tgt->u.integrity.journal_crypt_key) {
885
0
      hexkey = crypt_bytes_to_hex(crypt_volume_key_length(tgt->u.integrity.journal_crypt_key),
886
0
                crypt_volume_key_get_key(tgt->u.integrity.journal_crypt_key));
887
0
      if (!hexkey)
888
0
        goto out;
889
0
    } else
890
0
      hexkey = NULL;
891
892
0
    r = snprintf(journal_crypt, max_journal_crypt, " journal_crypt:%s%s%s",
893
0
       tgt->u.integrity.journal_crypt, hexkey ? ":" : "", hexkey ?: "");
894
0
    crypt_safe_free(hexkey);
895
0
    if (r < 0 || r >= max_journal_crypt)
896
0
      goto out;
897
0
  }
898
899
0
  if (tgt->u.integrity.journal_size)
900
0
    num_options++;
901
0
  if (tgt->u.integrity.journal_watermark)
902
0
    num_options++;
903
0
  if (tgt->u.integrity.journal_commit_time)
904
0
    num_options++;
905
0
  if (tgt->u.integrity.interleave_sectors)
906
0
    num_options++;
907
0
  if (tgt->u.integrity.sector_size)
908
0
    num_options++;
909
0
  if (tgt->u.integrity.buffer_sectors)
910
0
    num_options++;
911
0
  if (tgt->u.integrity.fix_padding)
912
0
    num_options++;
913
0
  if (tgt->u.integrity.fix_hmac)
914
0
    num_options++;
915
0
  if (tgt->u.integrity.legacy_recalc)
916
0
    num_options++;
917
0
  if (tgt->u.integrity.meta_device)
918
0
    num_options++;
919
0
  if (flags & CRYPT_ACTIVATE_RECALCULATE)
920
0
    num_options++;
921
0
  if (flags & CRYPT_ACTIVATE_RECALCULATE_RESET)
922
0
    num_options++;
923
0
  if (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS)
924
0
    num_options++;
925
926
0
  r = snprintf(features, max_size, "%d%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", num_options,
927
0
    tgt->u.integrity.journal_size ? _uf(feature[0], sizeof(feature[0]), /* MAX length 17 + int32 */
928
0
      "journal_sectors", (unsigned)(tgt->u.integrity.journal_size / SECTOR_SIZE)) : "",
929
0
    tgt->u.integrity.journal_watermark ? _uf(feature[1], sizeof(feature[1]), /* MAX length 19 + int32 */
930
       /* bitmap overloaded values */
931
0
       (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "sectors_per_bit" : "journal_watermark",
932
0
       tgt->u.integrity.journal_watermark) : "",
933
0
    tgt->u.integrity.journal_commit_time ? _uf(feature[2], sizeof(feature[2]), /* MAX length 23 + int32 */
934
       /* bitmap overloaded values */
935
0
       (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) ? "bitmap_flush_interval" : "commit_time",
936
0
       tgt->u.integrity.journal_commit_time) : "",
937
0
    tgt->u.integrity.interleave_sectors ? _uf(feature[3], sizeof(feature[3]), /* MAX length 20 + int32 */
938
0
      "interleave_sectors", tgt->u.integrity.interleave_sectors) : "",
939
0
    tgt->u.integrity.sector_size ? _uf(feature[4], sizeof(feature[4]), /* MAX length 12 + int32 */
940
0
      "block_size", tgt->u.integrity.sector_size) : "",
941
0
    tgt->u.integrity.buffer_sectors ? _uf(feature[5], sizeof(feature[5]), /* MAX length 16 + int32 */
942
0
      "buffer_sectors", tgt->u.integrity.buffer_sectors) : "",
943
0
    tgt->u.integrity.integrity ? integrity : "",
944
0
    tgt->u.integrity.journal_integrity ? journal_integrity : "",
945
0
    tgt->u.integrity.journal_crypt ? journal_crypt : "",
946
0
    tgt->u.integrity.fix_padding ?  " fix_padding" : "", /* MAX length 12 */
947
0
    tgt->u.integrity.fix_hmac ?  " fix_hmac" : "", /* MAX length 9 */
948
0
    tgt->u.integrity.legacy_recalc ? " legacy_recalculate" : "", /* MAX length 19 */
949
0
    flags & CRYPT_ACTIVATE_RECALCULATE ? " recalculate" : "", /* MAX length 12 */
950
0
    flags & CRYPT_ACTIVATE_RECALCULATE_RESET ? " reset_recalculate" : "", /* MAX length 18 */
951
0
    (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && !tgt->u.integrity.discard_keyed ? " allow_discards" : "", /* MAX length 15 */
952
0
    (flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) && tgt->u.integrity.discard_keyed ? " allow_discards_keyed" : "", /* MAX length 21 */
953
0
    tgt->u.integrity.meta_device ? " meta_device:" : "", /* MAX length 13 + str_device */
954
0
    tgt->u.integrity.meta_device ? device_block_path(tgt->u.integrity.meta_device) : "");
955
0
  if (r < 0 || r >= max_size)
956
0
    goto out;
957
958
0
  if (flags & CRYPT_ACTIVATE_INLINE_MODE)
959
0
    mode = 'I';
960
0
  else if (flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP)
961
0
    mode = 'B';
962
0
  else if (flags & CRYPT_ACTIVATE_RECOVERY)
963
0
    mode = 'R';
964
0
  else if (flags & CRYPT_ACTIVATE_NO_JOURNAL)
965
0
    mode = 'D';
966
0
  else
967
0
    mode = 'J';
968
969
0
  r = snprintf(params, max_size, "%s %" PRIu64 " %d %c %s",
970
0
         device_block_path(tgt->data_device), tgt->u.integrity.offset,
971
0
         tgt->u.integrity.tag_size, mode, features);
972
0
  if (r < 0 || r >= max_size)
973
0
    goto out;
974
975
0
  params_out = params;
976
0
out:
977
0
  crypt_safe_free(features);
978
0
  crypt_safe_free(integrity);
979
0
  crypt_safe_free(journal_integrity);
980
0
  crypt_safe_free(journal_crypt);
981
0
  if (!params_out)
982
0
    crypt_safe_free(params);
983
984
0
  return params_out;
985
0
}
986
987
static char *get_dm_linear_params(const struct dm_target *tgt)
988
0
{
989
0
  char *params;
990
0
  int r;
991
0
  int max_size = strlen(device_block_path(tgt->data_device)) + int_log10(tgt->u.linear.offset) + 3;
992
993
0
  params = crypt_safe_alloc(max_size);
994
0
  if (!params)
995
0
    return NULL;
996
997
0
  r = snprintf(params, max_size, "%s %" PRIu64,
998
0
         device_block_path(tgt->data_device), tgt->u.linear.offset);
999
1000
0
  if (r < 0 || r >= max_size) {
1001
0
    crypt_safe_free(params);
1002
0
    params = NULL;
1003
0
  }
1004
1005
0
  return params;
1006
0
}
1007
1008
static char *get_dm_zero_params(void)
1009
0
{
1010
0
  char *params = crypt_safe_alloc(1);
1011
0
  if (!params)
1012
0
    return NULL;
1013
1014
0
  params[0] = 0;
1015
0
  return params;
1016
0
}
1017
1018
/* DM helpers */
1019
static int _dm_remove(const char *name, int udev_wait, int deferred)
1020
0
{
1021
0
  int r = 0;
1022
0
  struct dm_task *dmt;
1023
0
  uint32_t cookie = 0;
1024
1025
0
  if (!_dm_use_udev())
1026
0
    udev_wait = 0;
1027
1028
0
  if (!(dmt = dm_task_create(DM_DEVICE_REMOVE)))
1029
0
    return 0;
1030
1031
0
  if (!dm_task_set_name(dmt, name))
1032
0
    goto out;
1033
1034
0
#if HAVE_DECL_DM_TASK_RETRY_REMOVE
1035
0
  if (!dm_task_retry_remove(dmt))
1036
0
    goto out;
1037
0
#endif
1038
0
#if HAVE_DECL_DM_TASK_DEFERRED_REMOVE
1039
0
  if (deferred && !dm_task_deferred_remove(dmt))
1040
0
    goto out;
1041
0
#endif
1042
0
  if (udev_wait && !_dm_task_set_cookie(dmt, &cookie, DM_UDEV_DISABLE_LIBRARY_FALLBACK))
1043
0
    goto out;
1044
1045
0
  r = dm_task_run(dmt);
1046
1047
0
  if (udev_wait)
1048
0
    (void)_dm_udev_wait(cookie);
1049
0
out:
1050
0
  dm_task_destroy(dmt);
1051
0
  return r;
1052
0
}
1053
1054
static int _dm_simple(int task, const char *name, uint64_t dmflags)
1055
0
{
1056
0
  int r = 0;
1057
0
  struct dm_task *dmt;
1058
1059
0
  if (!(dmt = dm_task_create(task)))
1060
0
    return 0;
1061
1062
0
  if (name && !dm_task_set_name(dmt, name))
1063
0
    goto out;
1064
1065
0
  if (task == DM_DEVICE_SUSPEND &&
1066
0
      (dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
1067
0
    goto out;
1068
1069
0
  if (task == DM_DEVICE_SUSPEND &&
1070
0
      (dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
1071
0
    goto out;
1072
1073
0
  r = dm_task_run(dmt);
1074
0
out:
1075
0
  dm_task_destroy(dmt);
1076
0
  return r;
1077
0
}
1078
1079
static int _dm_resume_device(const char *name, uint64_t dmflags);
1080
1081
static int _error_device(const char *name, size_t size)
1082
0
{
1083
0
  struct dm_task *dmt;
1084
0
  int r = 0;
1085
1086
0
  if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
1087
0
    return 0;
1088
1089
0
  if (!dm_task_set_name(dmt, name))
1090
0
    goto out;
1091
1092
0
  if (!dm_task_add_target(dmt, UINT64_C(0), size, "error", ""))
1093
0
    goto out;
1094
1095
0
  if (!dm_task_set_ro(dmt))
1096
0
    goto out;
1097
1098
0
  if (!dm_task_no_open_count(dmt))
1099
0
    goto out;
1100
1101
0
  if (!dm_task_run(dmt))
1102
0
    goto out;
1103
1104
0
  if (_dm_resume_device(name, 0)) {
1105
0
    _dm_simple(DM_DEVICE_CLEAR, name, 0);
1106
0
    goto out;
1107
0
  }
1108
1109
0
  r = 1;
1110
0
out:
1111
0
  dm_task_destroy(dmt);
1112
0
  return r;
1113
0
}
1114
1115
int dm_error_device(struct crypt_device *cd, const char *name)
1116
0
{
1117
0
  int r;
1118
0
  struct crypt_dm_active_device dmd;
1119
1120
0
  if (!name)
1121
0
    return -EINVAL;
1122
1123
0
  if (dm_init_context(cd, DM_UNKNOWN))
1124
0
    return -ENOTSUP;
1125
1126
0
  if ((dm_query_device(cd, name, 0, &dmd) >= 0) && _error_device(name, dmd.size))
1127
0
    r = 0;
1128
0
  else
1129
0
    r = -EINVAL;
1130
1131
0
  dm_targets_free(cd, &dmd);
1132
1133
0
  dm_exit_context();
1134
1135
0
  return r;
1136
0
}
1137
1138
int dm_clear_device(struct crypt_device *cd, const char *name)
1139
0
{
1140
0
  int r;
1141
1142
0
  if (!name)
1143
0
    return -EINVAL;
1144
1145
0
  if (dm_init_context(cd, DM_UNKNOWN))
1146
0
    return -ENOTSUP;
1147
1148
0
  if (_dm_simple(DM_DEVICE_CLEAR, name, 0))
1149
0
    r = 0;
1150
0
  else
1151
0
    r = -EINVAL;
1152
1153
0
  dm_exit_context();
1154
1155
0
  return r;
1156
0
}
1157
1158
int dm_remove_device(struct crypt_device *cd, const char *name, uint32_t flags)
1159
0
{
1160
0
  struct crypt_dm_active_device dmd = {};
1161
0
  int r = -EINVAL;
1162
0
  int retries = (flags & CRYPT_DEACTIVATE_FORCE) ? RETRY_COUNT : 1;
1163
0
  int deferred = (flags & CRYPT_DEACTIVATE_DEFERRED) ? 1 : 0;
1164
0
  int error_target = 0;
1165
0
  uint64_t dmt_flags;
1166
1167
0
  if (!name)
1168
0
    return -EINVAL;
1169
1170
0
  if (dm_init_context(cd, DM_UNKNOWN))
1171
0
    return -ENOTSUP;
1172
1173
0
  if (deferred && !_do_dm_flags(cd, DM_UNKNOWN, &dmt_flags) && !(dmt_flags & DM_DEFERRED_SUPPORTED)) {
1174
0
    log_err(cd, _("Requested deferred flag is not supported."));
1175
0
    dm_exit_context();
1176
0
    return -ENOTSUP;
1177
0
  }
1178
1179
0
  do {
1180
0
    r = _dm_remove(name, 1, deferred) ? 0 : -EINVAL;
1181
0
    if (--retries && r) {
1182
0
      log_dbg(cd, "WARNING: other process locked internal device %s, %s.",
1183
0
        name, retries ? "retrying remove" : "giving up");
1184
0
      sleep(1);
1185
0
      if ((flags & CRYPT_DEACTIVATE_FORCE) && !error_target) {
1186
        /* If force flag is set, replace device with error, read-only target.
1187
         * it should stop processes from reading it and also removed underlying
1188
         * device from mapping, so it is usable again.
1189
         * Anyway, if some process try to read temporary cryptsetup device,
1190
         * it is bug - no other process should try touch it (e.g. udev).
1191
         */
1192
0
        if (!dm_query_device(cd, name, 0, &dmd)) {
1193
0
          _error_device(name, dmd.size);
1194
0
          error_target = 1;
1195
0
        }
1196
0
      }
1197
0
    }
1198
0
  } while (r == -EINVAL && retries);
1199
1200
0
  dm_task_update_nodes();
1201
0
  dm_exit_context();
1202
1203
0
  return r;
1204
0
}
1205
1206
0
#define UUID_LEN 37 /* 36 + \0, libuuid ... */
1207
/*
1208
 * UUID has format: CRYPT-<devicetype>-[<uuid>-]<device name>
1209
 * CRYPT-PLAIN-name
1210
 * CRYPT-LUKS1-00000000000000000000000000000000-name
1211
 * CRYPT-TEMP-name
1212
 */
1213
static int dm_prepare_uuid(struct crypt_device *cd, const char *name, const char *type,
1214
          const char *uuid, char *buf, size_t buflen)
1215
0
{
1216
0
  char *ptr, uuid2[UUID_LEN] = {0};
1217
0
  uuid_t uu;
1218
0
  int i = 0;
1219
1220
  /* Remove '-' chars */
1221
0
  if (uuid) {
1222
0
    if (uuid_parse(uuid, uu) < 0) {
1223
0
      log_dbg(cd, "Requested UUID %s has invalid format.", uuid);
1224
0
      return 0;
1225
0
    }
1226
1227
0
    for (ptr = uuid2, i = 0; i < UUID_LEN; i++)
1228
0
      if (uuid[i] != '-') {
1229
0
        *ptr = uuid[i];
1230
0
        ptr++;
1231
0
      }
1232
0
  }
1233
1234
0
  i = snprintf(buf, buflen, DM_UUID_PREFIX "%s%s%s%s%s",
1235
0
    type ?: "", type ? "-" : "",
1236
0
    uuid2[0] ? uuid2 : "", uuid2[0] ? "-" : "",
1237
0
    name);
1238
0
  if (i < 0)
1239
0
    return 0;
1240
1241
0
  log_dbg(cd, "DM-UUID is %s", buf);
1242
0
  if ((size_t)i >= buflen)
1243
0
    log_err(cd, _("DM-UUID for device %s was truncated."), name);
1244
1245
0
  return 1;
1246
0
}
1247
1248
int lookup_dm_dev_by_uuid(struct crypt_device *cd, const char *uuid, const char *type)
1249
0
{
1250
0
  int r_udev, r;
1251
0
  char *c;
1252
0
  char dev_uuid[DM_UUID_LEN + DM_BY_ID_PREFIX_LEN] = DM_BY_ID_PREFIX;
1253
1254
0
  if (!dm_prepare_uuid(cd, "", type, uuid, dev_uuid + DM_BY_ID_PREFIX_LEN, DM_UUID_LEN))
1255
0
    return -EINVAL;
1256
1257
0
  c = strrchr(dev_uuid, '-');
1258
0
  if (!c)
1259
0
    return -EINVAL;
1260
1261
  /* cut of dm name */
1262
0
  *c = '\0';
1263
1264
  /* Either udev or sysfs can report that device is active. */
1265
0
  r = lookup_by_disk_id(dev_uuid);
1266
0
  if (r > 0)
1267
0
    return r;
1268
1269
0
  r_udev = r;
1270
0
  r = lookup_by_sysfs_uuid_field(dev_uuid + DM_BY_ID_PREFIX_LEN);
1271
1272
0
  return r == -ENOENT ? r_udev : r;
1273
0
}
1274
1275
static int _add_dm_targets(struct dm_task *dmt, struct crypt_dm_active_device *dmd)
1276
0
{
1277
0
  const char *target;
1278
0
  struct dm_target *tgt = &dmd->segment;
1279
1280
0
  do {
1281
0
    switch (tgt->type) {
1282
0
    case DM_CRYPT:
1283
0
      target = DM_CRYPT_TARGET;
1284
0
      break;
1285
0
    case DM_VERITY:
1286
0
      target = DM_VERITY_TARGET;
1287
0
      break;
1288
0
    case DM_INTEGRITY:
1289
0
      target = DM_INTEGRITY_TARGET;
1290
0
      break;
1291
0
    case DM_LINEAR:
1292
0
      target = DM_LINEAR_TARGET;
1293
0
      break;
1294
0
    case DM_ZERO:
1295
0
      target = DM_ZERO_TARGET;
1296
0
      break;
1297
0
    default:
1298
0
      return -ENOTSUP;
1299
0
    }
1300
1301
0
    if (!dm_task_add_target(dmt, tgt->offset, tgt->size, target, tgt->params))
1302
0
      return -EINVAL;
1303
1304
0
    tgt = tgt->next;
1305
0
  } while (tgt);
1306
1307
0
  return 0;
1308
0
}
1309
1310
static void _destroy_dm_targets_params(struct crypt_dm_active_device *dmd)
1311
0
{
1312
0
  struct dm_target *t = &dmd->segment;
1313
1314
0
  do {
1315
0
    crypt_safe_free(t->params);
1316
0
    t->params = NULL;
1317
0
    t = t->next;
1318
0
  } while (t);
1319
0
}
1320
1321
static int _create_dm_targets_params(struct crypt_dm_active_device *dmd)
1322
0
{
1323
0
  int r;
1324
0
  struct dm_target *tgt = &dmd->segment;
1325
1326
0
  do {
1327
0
    if (tgt->type == DM_CRYPT)
1328
0
      tgt->params = get_dm_crypt_params(tgt, dmd->flags);
1329
0
    else if (tgt->type == DM_VERITY)
1330
0
      tgt->params = get_dm_verity_params(tgt, dmd->flags);
1331
0
    else if (tgt->type == DM_INTEGRITY)
1332
0
      tgt->params = get_dm_integrity_params(tgt, dmd->flags);
1333
0
    else if (tgt->type == DM_LINEAR)
1334
0
      tgt->params = get_dm_linear_params(tgt);
1335
0
    else if (tgt->type == DM_ZERO)
1336
0
      tgt->params = get_dm_zero_params();
1337
0
    else {
1338
0
      r = -ENOTSUP;
1339
0
      goto err;
1340
0
    }
1341
1342
0
    if (!tgt->params) {
1343
0
      r = -EINVAL;
1344
0
      goto err;
1345
0
    }
1346
0
    tgt = tgt->next;
1347
0
  } while (tgt);
1348
1349
0
  return 0;
1350
0
err:
1351
0
  _destroy_dm_targets_params(dmd);
1352
0
  return r;
1353
0
}
1354
1355
static bool device_disappeared(struct crypt_device *cd, struct device *device, const char *type)
1356
0
{
1357
0
  struct stat st;
1358
1359
0
  if (!device)
1360
0
    return false;
1361
1362
  /*
1363
   * Cannot use device_check_access(cd, device, DEV_OK) as it always accesses block device,
1364
   * we want to check for underlying file presence (if device is an image).
1365
   */
1366
0
  if (stat(device_path(device), &st) < 0) {
1367
0
    log_dbg(cd, "%s device %s disappeared.", type, device_path(device));
1368
0
    return true;
1369
0
  }
1370
1371
0
  log_dbg(cd, "%s device %s is OK.", type, device_path(device));
1372
0
  return false;
1373
0
}
1374
1375
static bool dm_table_devices_disappeared(struct crypt_device *cd, struct crypt_dm_active_device *dmd)
1376
0
{
1377
0
  struct dm_target *tgt = &dmd->segment;
1378
1379
0
  do {
1380
0
    if (device_disappeared(cd, tgt->data_device, "Data"))
1381
0
      return true;
1382
0
    if (tgt->type == DM_VERITY) {
1383
0
      if (device_disappeared(cd, tgt->u.verity.hash_device, "Hash"))
1384
0
        return true;
1385
0
      if (device_disappeared(cd, tgt->u.verity.fec_device, "FEC"))
1386
0
        return true;
1387
0
    } else if (tgt->type == DM_INTEGRITY) {
1388
0
      if (device_disappeared(cd, tgt->u.integrity.meta_device, "Integrity meta"))
1389
0
        return true;
1390
0
    }
1391
0
    tgt = tgt->next;
1392
0
  } while (tgt);
1393
1394
0
  return false;
1395
0
}
1396
1397
static int _dm_create_device(struct crypt_device *cd, const char *name, const char *type,
1398
           struct crypt_dm_active_device *dmd)
1399
0
{
1400
0
  struct dm_task *dmt = NULL;
1401
0
  struct dm_info dmi;
1402
0
  char dev_uuid[DM_UUID_LEN] = {0};
1403
0
  int r = -EINVAL;
1404
0
  uint32_t cookie = 0, read_ahead = 0;
1405
0
  uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
1406
1407
0
  if (dmd->flags & CRYPT_ACTIVATE_PRIVATE)
1408
0
    udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
1409
1410
  /* All devices must have DM_UUID, only resize on old device is exception */
1411
0
  if (!dm_prepare_uuid(cd, name, type, dmd->uuid, dev_uuid, sizeof(dev_uuid)))
1412
0
    goto out;
1413
1414
0
  if (!(dmt = dm_task_create(DM_DEVICE_CREATE)))
1415
0
    goto out;
1416
1417
0
  if (!dm_task_set_name(dmt, name))
1418
0
    goto out;
1419
1420
0
  if (!dm_task_set_uuid(dmt, dev_uuid))
1421
0
    goto out;
1422
1423
0
  if (!dm_task_secure_data(dmt))
1424
0
    goto out;
1425
0
  if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
1426
0
    goto out;
1427
1428
0
  r = _create_dm_targets_params(dmd);
1429
0
  if (r)
1430
0
    goto out;
1431
1432
0
  r = _add_dm_targets(dmt, dmd);
1433
0
  if (r)
1434
0
    goto out;
1435
1436
0
  r = -EINVAL;
1437
1438
0
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
1439
0
  if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
1440
0
      !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
1441
0
    goto out;
1442
0
#endif
1443
0
  if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
1444
0
    goto out;
1445
1446
0
  if (!dm_task_run(dmt)) {
1447
0
    r = -dm_task_get_errno(dmt);
1448
0
    log_dbg(cd, "DM create task failed, dm_task errno: %i.", r);
1449
0
    if (r == -ENOKEY || r == -EKEYREVOKED || r == -EKEYEXPIRED) {
1450
      /* propagate DM errors around key management as such */
1451
0
      r = -ENOKEY;
1452
0
      goto out;
1453
0
    }
1454
1455
0
    r = dm_status_device(cd, name);
1456
0
    log_dbg(cd, "Device status returned %i.", r);
1457
0
    if (r >= 0 || r == -EEXIST) {
1458
0
      r = -EEXIST;
1459
0
      goto out;
1460
0
    }
1461
1462
    /* EEXIST above has priority */
1463
0
    if (dm_task_get_errno(dmt) == EBUSY) {
1464
0
      r = -EBUSY;
1465
0
      goto out;
1466
0
    }
1467
1468
0
    if (r != -ENODEV) {
1469
0
      r = -EINVAL;
1470
0
      goto out;
1471
0
    }
1472
1473
    /* dm-ioctl failed => -ENODEV */
1474
0
    if (dm_task_get_errno(dmt) == ENXIO)
1475
0
      goto out;
1476
1477
    /* Some device or file node disappeared => -ENODEV */
1478
0
    if (dm_table_devices_disappeared(cd, dmd))
1479
0
      goto out;
1480
1481
    /* Bail out with EBUSY better than sleep and retry. */
1482
0
    log_dbg(cd, "No referenced device missing, some device in use.");
1483
0
    r = -EBUSY;
1484
0
    goto out;
1485
0
  }
1486
1487
0
  if (dm_task_get_info(dmt, &dmi))
1488
0
    r = 0;
1489
1490
0
  if (_dm_use_udev()) {
1491
0
    (void)_dm_udev_wait(cookie);
1492
0
    cookie = 0;
1493
0
  }
1494
1495
0
  if (r < 0)
1496
0
    _dm_remove(name, 1, 0);
1497
1498
0
out:
1499
0
  if (cookie && _dm_use_udev())
1500
0
    (void)_dm_udev_wait(cookie);
1501
1502
0
  if (dmt)
1503
0
    dm_task_destroy(dmt);
1504
1505
0
  dm_task_update_nodes();
1506
1507
  /* If code just loaded target module, update versions */
1508
0
  _dm_check_versions(cd, dmd->segment.type);
1509
1510
0
  _destroy_dm_targets_params(dmd);
1511
1512
0
  return r;
1513
0
}
1514
1515
static int _dm_resume_device(const char *name, uint64_t dmflags)
1516
0
{
1517
0
  struct dm_task *dmt;
1518
0
  int r = -EINVAL;
1519
0
  uint32_t cookie = 0;
1520
0
  uint16_t udev_flags = DM_UDEV_DISABLE_LIBRARY_FALLBACK;
1521
1522
0
  if (dmflags & DM_RESUME_PRIVATE)
1523
0
    udev_flags |= CRYPT_TEMP_UDEV_FLAGS;
1524
1525
0
  if (!(dmt = dm_task_create(DM_DEVICE_RESUME)))
1526
0
    return r;
1527
1528
0
  if (!dm_task_set_name(dmt, name))
1529
0
    goto out;
1530
1531
0
  if ((dmflags & DM_SUSPEND_SKIP_LOCKFS) && !dm_task_skip_lockfs(dmt))
1532
0
    goto out;
1533
1534
0
  if ((dmflags & DM_SUSPEND_NOFLUSH) && !dm_task_no_flush(dmt))
1535
0
    goto out;
1536
1537
0
  if (_dm_use_udev() && !_dm_task_set_cookie(dmt, &cookie, udev_flags))
1538
0
    goto out;
1539
1540
0
  if (dm_task_run(dmt))
1541
0
    r = 0;
1542
0
out:
1543
0
  if (cookie && _dm_use_udev())
1544
0
    (void)_dm_udev_wait(cookie);
1545
1546
0
  dm_task_destroy(dmt);
1547
1548
0
  dm_task_update_nodes();
1549
1550
0
  return r;
1551
0
}
1552
1553
static int _dm_reload_device(struct crypt_device *cd, const char *name,
1554
           struct crypt_dm_active_device *dmd)
1555
0
{
1556
0
  int r = -EINVAL;
1557
0
  struct dm_task *dmt = NULL;
1558
0
  uint32_t read_ahead = 0;
1559
1560
  /* All devices must have DM_UUID, only resize on old device is exception */
1561
0
  if (!(dmt = dm_task_create(DM_DEVICE_RELOAD)))
1562
0
    goto out;
1563
1564
0
  if (!dm_task_set_name(dmt, name))
1565
0
    goto out;
1566
1567
0
  if (!dm_task_secure_data(dmt))
1568
0
    goto out;
1569
0
  if ((dmd->flags & CRYPT_ACTIVATE_READONLY) && !dm_task_set_ro(dmt))
1570
0
    goto out;
1571
1572
0
  r = _create_dm_targets_params(dmd);
1573
0
  if (r)
1574
0
    goto out;
1575
1576
0
  r = _add_dm_targets(dmt, dmd);
1577
0
  if (r)
1578
0
    goto out;
1579
1580
0
  r = -EINVAL;
1581
1582
0
#ifdef DM_READ_AHEAD_MINIMUM_FLAG
1583
0
  if (device_read_ahead(dmd->segment.data_device, &read_ahead) &&
1584
0
      !dm_task_set_read_ahead(dmt, read_ahead, DM_READ_AHEAD_MINIMUM_FLAG))
1585
0
    goto out;
1586
0
#endif
1587
1588
0
  if (dm_task_run(dmt))
1589
0
    r = 0;
1590
0
out:
1591
0
  if (dmt)
1592
0
    dm_task_destroy(dmt);
1593
1594
  /* If code just loaded target module, update versions */
1595
0
  _dm_check_versions(cd, dmd->segment.type);
1596
1597
0
  _destroy_dm_targets_params(dmd);
1598
1599
0
  return r;
1600
0
}
1601
1602
static void crypt_free_verity_params(struct crypt_params_verity *vp)
1603
0
{
1604
0
  if (!vp)
1605
0
    return;
1606
1607
0
  free(CONST_CAST(void*)vp->hash_name);
1608
0
  free(CONST_CAST(void*)vp->data_device);
1609
0
  free(CONST_CAST(void*)vp->hash_device);
1610
0
  free(CONST_CAST(void*)vp->fec_device);
1611
0
  free(CONST_CAST(void*)vp->salt);
1612
0
  free(vp);
1613
0
}
1614
1615
static void _dm_target_free_query_path(struct crypt_device *cd, struct dm_target *tgt)
1616
0
{
1617
0
  switch(tgt->type) {
1618
0
  case DM_CRYPT:
1619
0
    crypt_free_volume_key(tgt->u.crypt.vk);
1620
0
    free(CONST_CAST(void*)tgt->u.crypt.cipher);
1621
0
    break;
1622
0
  case DM_INTEGRITY:
1623
0
    free(CONST_CAST(void*)tgt->u.integrity.integrity);
1624
0
    crypt_free_volume_key(tgt->u.integrity.vk);
1625
1626
0
    free(CONST_CAST(void*)tgt->u.integrity.journal_integrity);
1627
0
    crypt_free_volume_key(tgt->u.integrity.journal_integrity_key);
1628
1629
0
    free(CONST_CAST(void*)tgt->u.integrity.journal_crypt);
1630
0
    crypt_free_volume_key(tgt->u.integrity.journal_crypt_key);
1631
1632
0
    device_free(cd, tgt->u.integrity.meta_device);
1633
0
    break;
1634
0
  case DM_VERITY:
1635
0
    crypt_free_verity_params(tgt->u.verity.vp);
1636
0
    device_free(cd, tgt->u.verity.hash_device);
1637
0
    free(CONST_CAST(void*)tgt->u.verity.root_hash);
1638
0
    free(CONST_CAST(void*)tgt->u.verity.root_hash_sig_key_desc);
1639
    /* fall through */
1640
0
  case DM_LINEAR:
1641
    /* fall through */
1642
0
  case DM_ERROR:
1643
    /* fall through */
1644
0
  case DM_ZERO:
1645
0
    break;
1646
0
  default:
1647
0
    log_err(cd, _("Unknown dm target type."));
1648
0
    return;
1649
0
  }
1650
1651
0
  device_free(cd, tgt->data_device);
1652
0
}
1653
1654
static void _dm_target_erase(struct crypt_device *cd, struct dm_target *tgt)
1655
0
{
1656
0
  if (tgt->direction == TARGET_EMPTY)
1657
0
    return;
1658
1659
0
  if (tgt->direction == TARGET_QUERY)
1660
0
    _dm_target_free_query_path(cd, tgt);
1661
1662
0
  if (tgt->type == DM_CRYPT)
1663
0
    free(CONST_CAST(void*)tgt->u.crypt.integrity);
1664
0
}
1665
1666
void dm_targets_free(struct crypt_device *cd, struct crypt_dm_active_device *dmd)
1667
0
{
1668
0
  struct dm_target *t = &dmd->segment, *next = t->next;
1669
1670
0
  _dm_target_erase(cd, t);
1671
1672
0
  while (next) {
1673
0
    t = next;
1674
0
    next = t->next;
1675
0
    _dm_target_erase(cd, t);
1676
0
    free(t);
1677
0
  }
1678
1679
0
  memset(&dmd->segment, 0, sizeof(dmd->segment));
1680
0
}
1681
1682
int dm_targets_allocate(struct dm_target *first, unsigned count)
1683
0
{
1684
0
  if (!first || first->next || !count)
1685
0
    return -EINVAL;
1686
1687
0
  while (--count) {
1688
0
    first->next = crypt_zalloc(sizeof(*first));
1689
0
    if (!first->next)
1690
0
      return -ENOMEM;
1691
0
    first = first->next;
1692
0
  }
1693
1694
0
  return 0;
1695
0
}
1696
1697
static int check_retry(struct crypt_device *cd, uint32_t *dmd_flags, uint64_t dmt_flags)
1698
0
{
1699
0
  int ret = 0;
1700
1701
  /* If discard not supported try to load without discard */
1702
0
  if ((*dmd_flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1703
0
      !(dmt_flags & DM_DISCARDS_SUPPORTED)) {
1704
0
    log_dbg(cd, "Discard/TRIM is not supported");
1705
0
    *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_ALLOW_DISCARDS;
1706
0
    ret = 1;
1707
0
  }
1708
1709
  /* If kernel keyring is not supported load key directly in dm-crypt */
1710
0
  if ((*dmd_flags & CRYPT_ACTIVATE_KEYRING_KEY) &&
1711
0
      !(dmt_flags & DM_KERNEL_KEYRING_SUPPORTED)) {
1712
0
    log_dbg(cd, "dm-crypt does not support kernel keyring");
1713
0
    *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_KEYRING_KEY;
1714
0
    ret = 1;
1715
0
  }
1716
1717
  /* Drop performance options if not supported */
1718
0
  if ((*dmd_flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
1719
0
      !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
1720
0
    log_dbg(cd, "dm-crypt does not support performance options");
1721
0
    *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_SAME_CPU_CRYPT | CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS);
1722
0
    ret = 1;
1723
0
  }
1724
1725
  /* Drop no workqueue options if not supported */
1726
0
  if ((*dmd_flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
1727
0
      !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
1728
0
    log_dbg(cd, "dm-crypt does not support performance options");
1729
0
    *dmd_flags = *dmd_flags & ~(CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE);
1730
0
    ret = 1;
1731
0
  }
1732
1733
  /* Drop high-priority workqueue options if not supported */
1734
0
  if ((*dmd_flags & CRYPT_ACTIVATE_HIGH_PRIORITY) &&
1735
0
      !(dmt_flags & DM_CRYPT_HIGH_PRIORITY_SUPPORTED)) {
1736
0
    log_dbg(cd, "dm-crypt does not support high-priority option");
1737
0
    *dmd_flags = *dmd_flags & ~CRYPT_ACTIVATE_HIGH_PRIORITY;
1738
0
    ret = 1;
1739
0
  }
1740
1741
0
  return ret;
1742
0
}
1743
1744
int dm_create_device(struct crypt_device *cd, const char *name,
1745
         const char *type,
1746
         struct crypt_dm_active_device *dmd)
1747
0
{
1748
0
  uint64_t dmt_flags = 0;
1749
0
  int r = -EINVAL;
1750
1751
0
  if (!type || !dmd)
1752
0
    return -EINVAL;
1753
1754
0
  if (dm_init_context(cd, dmd->segment.type))
1755
0
    return -ENOTSUP;
1756
1757
0
  r = _dm_create_device(cd, name, type, dmd);
1758
0
  if (!r || r == -EEXIST)
1759
0
    goto out;
1760
1761
0
  if (_do_dm_flags(cd, dmd->segment.type, &dmt_flags))
1762
0
    goto out;
1763
1764
0
  if ((dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR || dmd->segment.type == DM_ZERO) &&
1765
0
    check_retry(cd, &dmd->flags, dmt_flags)) {
1766
0
    log_dbg(cd, "Retrying open without incompatible options.");
1767
0
    r = _dm_create_device(cd, name, type, dmd);
1768
0
    if (!r || r == -EEXIST)
1769
0
      goto out;
1770
0
  }
1771
1772
0
  if (dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS) &&
1773
0
      !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED|DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED))) {
1774
0
    log_err(cd, _("Requested dm-crypt performance options are not supported."));
1775
0
    r = -EINVAL;
1776
0
  }
1777
1778
0
  if (dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE) &&
1779
0
      !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED)) {
1780
0
    log_err(cd, _("Requested dm-crypt performance options are not supported."));
1781
0
    r = -EINVAL;
1782
0
  }
1783
1784
0
  if (dmd->flags & (CRYPT_ACTIVATE_IGNORE_CORRUPTION|
1785
0
        CRYPT_ACTIVATE_RESTART_ON_CORRUPTION|
1786
0
        CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS|
1787
0
        CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE) &&
1788
0
      !(dmt_flags & DM_VERITY_ON_CORRUPTION_SUPPORTED)) {
1789
0
    log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
1790
0
    r = -EINVAL;
1791
0
  }
1792
1793
0
  if ((dmd->flags & CRYPT_ACTIVATE_ERROR_AS_CORRUPTION) &&
1794
0
      !(dmt_flags & DM_VERITY_ERROR_AS_CORRUPTION_SUPPORTED)) {
1795
0
    log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
1796
0
    r = -EINVAL;
1797
0
  }
1798
1799
0
  if (dmd->flags & CRYPT_ACTIVATE_TASKLETS &&
1800
0
      !(dmt_flags & DM_VERITY_TASKLETS_SUPPORTED)) {
1801
0
    log_err(cd, _("Requested dm-verity tasklets option is not supported."));
1802
0
    r = -EINVAL;
1803
0
  }
1804
1805
0
  if (dmd->flags & CRYPT_ACTIVATE_PANIC_ON_CORRUPTION &&
1806
0
      !(dmt_flags & DM_VERITY_PANIC_CORRUPTION_SUPPORTED)) {
1807
0
    log_err(cd, _("Requested dm-verity data corruption handling options are not supported."));
1808
0
    r = -EINVAL;
1809
0
  }
1810
1811
0
  if (dmd->segment.type == DM_VERITY &&
1812
0
      dmd->segment.u.verity.fec_device && !(dmt_flags & DM_VERITY_FEC_SUPPORTED)) {
1813
0
    log_err(cd, _("Requested dm-verity FEC options are not supported."));
1814
0
    r = -EINVAL;
1815
0
  }
1816
1817
0
  if (dmd->segment.type == DM_CRYPT) {
1818
0
    if (dmd->segment.u.crypt.integrity && !(dmt_flags & DM_INTEGRITY_SUPPORTED)) {
1819
0
      log_err(cd, _("Requested data integrity options are not supported."));
1820
0
      r = -EINVAL;
1821
0
    }
1822
0
    if (dmd->segment.u.crypt.sector_size != SECTOR_SIZE && !(dmt_flags & DM_SECTOR_SIZE_SUPPORTED)) {
1823
0
      log_err(cd, _("Requested sector_size option is not supported."));
1824
0
      r = -EINVAL;
1825
0
    }
1826
0
    if (dmd->segment.u.crypt.sector_size > SECTOR_SIZE &&
1827
0
        dmd->size % dmd->segment.u.crypt.sector_size) {
1828
0
      log_err(cd, _("The device size is not multiple of the requested sector size."));
1829
0
      r = -EINVAL;
1830
0
    }
1831
0
    if (dmd->segment.u.crypt.integrity_key_size && !(dmt_flags & DM_CRYPT_INTEGRITY_KEY_SIZE_OPT_SUPPORTED)) {
1832
0
      log_err(cd, _("Requested integrity_key_size option is not supported."));
1833
0
      r = -EINVAL;
1834
0
    }
1835
0
  }
1836
1837
0
  if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE) &&
1838
0
      !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED)) {
1839
0
    log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
1840
0
    r = -EINVAL;
1841
0
  }
1842
1843
0
  if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_RECALCULATE_RESET) &&
1844
0
      !(dmt_flags & DM_INTEGRITY_RESET_RECALC_SUPPORTED)) {
1845
0
    log_err(cd, _("Requested automatic recalculation of integrity tags is not supported."));
1846
0
    r = -EINVAL;
1847
0
  }
1848
1849
0
  if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1850
0
      !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED)) {
1851
0
    log_err(cd, _("Discard/TRIM is not supported."));
1852
0
    r = -EINVAL;
1853
0
  }
1854
1855
0
  if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_NO_JOURNAL_BITMAP) &&
1856
0
      !(dmt_flags & DM_INTEGRITY_BITMAP_SUPPORTED)) {
1857
0
    log_err(cd, _("Requested dm-integrity bitmap mode is not supported."));
1858
0
    r = -EINVAL;
1859
0
  }
1860
1861
0
  if (dmd->segment.type == DM_INTEGRITY && (dmd->flags & CRYPT_ACTIVATE_INLINE_MODE) &&
1862
0
      !(dmt_flags & DM_INTEGRITY_INLINE_MODE_SUPPORTED)) {
1863
0
    log_err(cd, _("Requested dm-integrity inline mode is not supported."));
1864
0
    r = -EINVAL;
1865
0
  }
1866
0
out:
1867
  /*
1868
   * Print warning if activating dm-crypt cipher_null device unless it's reencryption helper or
1869
   * keyslot encryption helper device (LUKS1 cipher_null devices).
1870
   */
1871
0
  if (!r && !(dmd->flags & CRYPT_ACTIVATE_PRIVATE) && single_segment(dmd) && dmd->segment.type == DM_CRYPT &&
1872
0
      crypt_is_cipher_null(dmd->segment.u.crypt.cipher))
1873
0
    log_dbg(cd, "Activated dm-crypt device with cipher_null. Device is not encrypted.");
1874
1875
0
  dm_exit_context();
1876
0
  return r;
1877
0
}
1878
1879
int dm_reload_device(struct crypt_device *cd, const char *name,
1880
         struct crypt_dm_active_device *dmd, uint64_t dmflags, unsigned resume)
1881
0
{
1882
0
  int r;
1883
0
  uint64_t dmt_flags;
1884
1885
0
  if (!dmd)
1886
0
    return -EINVAL;
1887
1888
0
  if (dm_init_context(cd, dmd->segment.type))
1889
0
    return -ENOTSUP;
1890
1891
0
  if (_do_dm_flags(cd, DM_INTEGRITY, &dmt_flags) || !(dmt_flags & DM_INTEGRITY_RECALC_SUPPORTED))
1892
0
    dmd->flags &= ~CRYPT_ACTIVATE_RECALCULATE;
1893
1894
0
  r = _dm_reload_device(cd, name, dmd);
1895
1896
0
  if (r == -EINVAL && (dmd->segment.type == DM_CRYPT || dmd->segment.type == DM_LINEAR)) {
1897
0
    if ((dmd->flags & (CRYPT_ACTIVATE_SAME_CPU_CRYPT|CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS)) &&
1898
0
        !_do_dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & (DM_SAME_CPU_CRYPT_SUPPORTED | DM_SUBMIT_FROM_CRYPT_CPUS_SUPPORTED)))
1899
0
      log_err(cd, _("Requested dm-crypt performance options are not supported."));
1900
0
    if ((dmd->flags & (CRYPT_ACTIVATE_NO_READ_WORKQUEUE | CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE)) &&
1901
0
        !_do_dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_CRYPT_NO_WORKQUEUE_SUPPORTED))
1902
0
      log_err(cd, _("Requested dm-crypt performance options are not supported."));
1903
0
    if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1904
0
        !_do_dm_flags(cd, DM_CRYPT, &dmt_flags) && !(dmt_flags & DM_DISCARDS_SUPPORTED))
1905
0
      log_err(cd, _("Discard/TRIM is not supported."));
1906
0
    if ((dmd->flags & CRYPT_ACTIVATE_ALLOW_DISCARDS) &&
1907
0
        !_do_dm_flags(cd, DM_INTEGRITY, &dmt_flags) && !(dmt_flags & DM_INTEGRITY_DISCARDS_SUPPORTED))
1908
0
      log_err(cd, _("Discard/TRIM is not supported."));
1909
0
  }
1910
1911
0
  if (!r && resume)
1912
0
    r = _dm_resume_device(name, dmflags | act2dmflags(dmd->flags));
1913
1914
0
  dm_exit_context();
1915
0
  return r;
1916
0
}
1917
1918
static int dm_status_dmi(const char *name, struct dm_info *dmi,
1919
        const char *target, char **status_line)
1920
0
{
1921
0
  struct dm_task *dmt;
1922
0
  uint64_t start, length;
1923
0
  char *target_type, *params = NULL;
1924
0
  int r = -EINVAL;
1925
1926
0
  if (!(dmt = dm_task_create(DM_DEVICE_STATUS)))
1927
0
    return r;
1928
1929
0
  if (!dm_task_no_flush(dmt))
1930
0
    goto out;
1931
1932
0
  if (!dm_task_set_name(dmt, name))
1933
0
    goto out;
1934
1935
0
  if (!dm_task_run(dmt))
1936
0
    goto out;
1937
1938
0
  if (!dm_task_get_info(dmt, dmi))
1939
0
    goto out;
1940
1941
0
  if (!dmi->exists) {
1942
0
    r = -ENODEV;
1943
0
    goto out;
1944
0
  }
1945
1946
0
  r = -EEXIST;
1947
0
  dm_get_next_target(dmt, NULL, &start, &length,
1948
0
         &target_type, &params);
1949
1950
0
  if (!target_type || start != 0)
1951
0
    goto out;
1952
1953
0
  if (target && strcmp(target_type, target))
1954
0
    goto out;
1955
1956
  /* for target == NULL check all supported */
1957
0
  if (!target && (strcmp(target_type, DM_CRYPT_TARGET) &&
1958
0
      strcmp(target_type, DM_VERITY_TARGET) &&
1959
0
      strcmp(target_type, DM_INTEGRITY_TARGET) &&
1960
0
      strcmp(target_type, DM_LINEAR_TARGET) &&
1961
0
      strcmp(target_type, DM_ZERO_TARGET) &&
1962
0
      strcmp(target_type, DM_ERROR_TARGET)))
1963
0
    goto out;
1964
0
  r = 0;
1965
0
out:
1966
0
  if (!r && status_line && !(*status_line = strdup(params)))
1967
0
    r = -ENOMEM;
1968
1969
0
  dm_task_destroy(dmt);
1970
1971
0
  return r;
1972
0
}
1973
1974
int dm_status_device(struct crypt_device *cd, const char *name)
1975
0
{
1976
0
  int r;
1977
0
  struct dm_info dmi;
1978
0
  struct stat st;
1979
1980
  /* libdevmapper is too clever and handles
1981
   * path argument differently with error.
1982
   * Fail early here if parameter is non-existent path.
1983
   */
1984
0
  if (strchr(name, '/') && stat(name, &st) < 0)
1985
0
    return -ENODEV;
1986
1987
0
  if (dm_init_context(cd, DM_UNKNOWN))
1988
0
    return -ENOTSUP;
1989
0
  r = dm_status_dmi(name, &dmi, NULL, NULL);
1990
0
  dm_exit_context();
1991
1992
0
  if (r < 0)
1993
0
    return r;
1994
1995
0
  return (dmi.open_count > 0) ? 1 : 0;
1996
0
}
1997
1998
int dm_status_suspended(struct crypt_device *cd, const char *name)
1999
0
{
2000
0
  int r;
2001
0
  struct dm_info dmi;
2002
2003
0
  if (dm_init_context(cd, DM_UNKNOWN))
2004
0
    return -ENOTSUP;
2005
0
  r = dm_status_dmi(name, &dmi, NULL, NULL);
2006
0
  dm_exit_context();
2007
2008
0
  if (r < 0 && r != -EEXIST)
2009
0
    return r;
2010
2011
0
  return dmi.suspended ? 1 : 0;
2012
0
}
2013
2014
static int _dm_status_verity_ok(struct crypt_device *cd, const char *name)
2015
0
{
2016
0
  int r;
2017
0
  struct dm_info dmi;
2018
0
  char *status_line = NULL;
2019
2020
0
  r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
2021
0
  if (r < 0 || !status_line) {
2022
0
    free(status_line);
2023
0
    return r;
2024
0
  }
2025
2026
0
  log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
2027
0
  r = status_line[0] == 'V' ? 1 : 0;
2028
0
  free(status_line);
2029
2030
0
  return r;
2031
0
}
2032
2033
int dm_status_verity_ok(struct crypt_device *cd, const char *name)
2034
0
{
2035
0
  int r;
2036
2037
0
  if (dm_init_context(cd, DM_VERITY))
2038
0
    return -ENOTSUP;
2039
0
  r = _dm_status_verity_ok(cd, name);
2040
0
  dm_exit_context();
2041
0
  return r;
2042
0
}
2043
2044
int dm_status_verity_repaired(struct crypt_device *cd, const char *name, uint64_t *repaired)
2045
0
{
2046
0
  int r;
2047
0
  struct dm_info dmi;
2048
0
  char *status_line = NULL, *p;
2049
0
  uint64_t val64;
2050
2051
0
  if (dm_init_context(cd, DM_VERITY))
2052
0
    return -ENOTSUP;
2053
2054
0
  r = dm_status_dmi(name, &dmi, DM_VERITY_TARGET, &status_line);
2055
0
  dm_exit_context();
2056
0
  if (r < 0 || !status_line || !*status_line) {
2057
0
    free(status_line);
2058
0
    return r;
2059
0
  }
2060
0
  p = status_line + 1;
2061
0
  while (*p == ' ')
2062
0
    p++;
2063
2064
0
  if (!*p || *p == '-' || sscanf(p, "%" PRIu64, &val64) != 1) {
2065
0
    free(status_line);
2066
0
    return -ENOTSUP;
2067
0
  }
2068
2069
0
  log_dbg(cd, "Verity volume %s status is %s.", name, status_line ?: "");
2070
2071
0
  if (repaired)
2072
0
    *repaired = val64;
2073
2074
0
  free(status_line);
2075
0
  return 0;
2076
0
}
2077
2078
int dm_status_integrity_failures(struct crypt_device *cd, const char *name, uint64_t *count)
2079
0
{
2080
0
  int r;
2081
0
  struct dm_info dmi;
2082
0
  char *status_line = NULL;
2083
2084
0
  if (dm_init_context(cd, DM_INTEGRITY))
2085
0
    return -ENOTSUP;
2086
2087
0
  r = dm_status_dmi(name, &dmi, DM_INTEGRITY_TARGET, &status_line);
2088
0
  if (r < 0 || !status_line) {
2089
0
    free(status_line);
2090
0
    dm_exit_context();
2091
0
    return r;
2092
0
  }
2093
2094
0
  log_dbg(cd, "Integrity volume %s failure status is %s.", name, status_line ?: "");
2095
0
  *count = strtoull(status_line, NULL, 10);
2096
0
  free(status_line);
2097
0
  dm_exit_context();
2098
2099
0
  return 0;
2100
0
}
2101
2102
/* FIXME use hex wrapper, user val wrappers for line parsing */
2103
static int _dm_target_query_crypt(struct crypt_device *cd, uint64_t get_flags,
2104
          char *params, struct dm_target *tgt,
2105
          uint32_t *act_flags)
2106
0
{
2107
0
  uint64_t val64;
2108
0
  char *rcipher, *rintegrity, *key_, *rdevice, *endp, buffer[3], *arg, *key_desc, keyring[64];
2109
0
  unsigned int i, val;
2110
0
  int r;
2111
0
  size_t key_size;
2112
0
  struct device *data_device = NULL;
2113
0
  char *cipher = NULL, *integrity = NULL;
2114
0
  struct volume_key *vk = NULL;
2115
0
  void *key = NULL;
2116
2117
0
  tgt->type = DM_CRYPT;
2118
0
  tgt->direction = TARGET_QUERY;
2119
0
  tgt->u.crypt.sector_size = SECTOR_SIZE;
2120
2121
0
  r = -EINVAL;
2122
2123
0
  rcipher = strsep(&params, " ");
2124
0
  rintegrity = NULL;
2125
2126
  /* skip */
2127
0
  key_ = strsep(&params, " ");
2128
0
  if (!params)
2129
0
    goto err;
2130
0
  val64 = strtoull(params, &params, 10);
2131
0
  if (*params != ' ')
2132
0
    goto err;
2133
0
  params++;
2134
2135
0
  tgt->u.crypt.iv_offset = val64;
2136
2137
  /* device */
2138
0
  rdevice = strsep(&params, " ");
2139
0
  if (get_flags & DM_ACTIVE_DEVICE) {
2140
0
    arg = crypt_lookup_dev(rdevice);
2141
0
    r = device_alloc(cd, &data_device, arg);
2142
0
    free(arg);
2143
0
    if (r < 0 && r != -ENOTBLK)
2144
0
      goto err;
2145
0
  }
2146
2147
0
  r = -EINVAL;
2148
2149
  /*offset */
2150
0
  if (!params)
2151
0
    goto err;
2152
0
  val64 = strtoull(params, &params, 10);
2153
0
  tgt->u.crypt.offset = val64;
2154
2155
0
  tgt->u.crypt.tag_size = 0;
2156
2157
  /* Features section, available since crypt target version 1.11 */
2158
0
  if (*params) {
2159
0
    if (*params != ' ')
2160
0
      goto err;
2161
0
    params++;
2162
2163
    /* Number of arguments */
2164
0
    val64 = strtoull(params, &params, 10);
2165
0
    if (*params != ' ')
2166
0
      goto err;
2167
0
    params++;
2168
2169
0
    for (i = 0; i < val64; i++) {
2170
0
      if (!params)
2171
0
        goto err;
2172
0
      arg = strsep(&params, " ");
2173
0
      if (!strcasecmp(arg, "allow_discards"))
2174
0
        *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
2175
0
      else if (!strcasecmp(arg, "same_cpu_crypt"))
2176
0
        *act_flags |= CRYPT_ACTIVATE_SAME_CPU_CRYPT;
2177
0
      else if (!strcasecmp(arg, "submit_from_crypt_cpus"))
2178
0
        *act_flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
2179
0
      else if (!strcasecmp(arg, "no_read_workqueue"))
2180
0
        *act_flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
2181
0
      else if (!strcasecmp(arg, "no_write_workqueue"))
2182
0
        *act_flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
2183
0
      else if (!strcasecmp(arg, "iv_large_sectors"))
2184
0
        *act_flags |= CRYPT_ACTIVATE_IV_LARGE_SECTORS;
2185
0
      else if (!strcasecmp(arg, "high_priority"))
2186
0
        *act_flags |= CRYPT_ACTIVATE_HIGH_PRIORITY;
2187
0
      else if (sscanf(arg, "integrity:%u:", &val) == 1) {
2188
0
        tgt->u.crypt.tag_size = val;
2189
0
        rintegrity = strchr(arg + strlen("integrity:"), ':');
2190
0
        if (!rintegrity)
2191
0
          goto err;
2192
0
        rintegrity++;
2193
0
      } else if (sscanf(arg, "integrity_key_size:%u", &val) == 1) {
2194
0
        tgt->u.crypt.integrity_key_size = val;
2195
0
      } else if (sscanf(arg, "sector_size:%u", &val) == 1) {
2196
0
        tgt->u.crypt.sector_size = val;
2197
0
      } else /* unknown option */
2198
0
        goto err;
2199
0
    }
2200
2201
    /* All parameters should be processed */
2202
0
    if (params)
2203
0
      goto err;
2204
0
  }
2205
2206
  /* cipher */
2207
0
  if (get_flags & DM_ACTIVE_CRYPT_CIPHER) {
2208
0
    r = crypt_capi_to_cipher(&cipher, &integrity, rcipher, rintegrity);
2209
0
    if (r < 0)
2210
0
      goto err;
2211
0
  }
2212
2213
0
  r = -EINVAL;
2214
2215
0
  if (key_[0] == ':')
2216
0
    *act_flags |= CRYPT_ACTIVATE_KEYRING_KEY;
2217
2218
0
  if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
2219
    /* we will trust kernel the key_string is in expected format */
2220
0
    if (key_[0] == ':') {
2221
0
      if (sscanf(key_ + 1, "%zu", &key_size) != 1)
2222
0
        goto err;
2223
0
    } else
2224
0
      key_size = strlen(key_) / 2;
2225
2226
0
    vk = crypt_alloc_volume_key(key_size, NULL);
2227
0
    if (!vk) {
2228
0
      r = -ENOMEM;
2229
0
      goto err;
2230
0
    }
2231
2232
0
    if (get_flags & DM_ACTIVE_CRYPT_KEY) {
2233
0
      if (key_[0] == ':') {
2234
        /* :<key_size>:<key_type>:<key_description> */
2235
0
        key_desc = NULL;
2236
0
        r = -ENOMEM;
2237
0
        endp = strpbrk(key_ + 1, ":");
2238
0
        if (!endp)
2239
0
          goto err;
2240
0
        key_desc = strpbrk(endp + 1, ":");
2241
0
        if (!key_desc || (size_t)(key_desc - endp) > sizeof(keyring))
2242
0
          goto err;
2243
0
        memcpy(keyring, endp + 1, key_desc - endp - 1);
2244
0
        keyring[key_desc - endp - 1] = '\0';
2245
0
        key_desc++;
2246
0
        r = crypt_volume_key_set_description(vk, key_desc, key_type_by_name(keyring));
2247
0
        if (r < 0)
2248
0
          goto err;
2249
0
      } else if (key_size) {
2250
0
        key = crypt_safe_alloc(key_size);
2251
0
        if (!key) {
2252
0
          r = -ENOMEM;
2253
0
          goto err;
2254
0
        }
2255
0
        buffer[2] = '\0';
2256
0
        for(i = 0; i < crypt_volume_key_length(vk); i++) {
2257
0
          crypt_safe_memcpy(buffer, &key_[i * 2], 2);
2258
0
          *((char *)key + i) = strtoul(buffer, &endp, 16);
2259
0
          if (endp != &buffer[2]) {
2260
0
            r = -EINVAL;
2261
0
            goto err;
2262
0
          }
2263
0
        }
2264
0
        crypt_volume_key_pass_safe_alloc(vk, &key);
2265
0
      }
2266
0
    }
2267
0
  }
2268
0
  memset(key_, 0, strlen(key_));
2269
2270
0
  if (cipher)
2271
0
    tgt->u.crypt.cipher = cipher;
2272
0
  if (integrity)
2273
0
    tgt->u.crypt.integrity = integrity;
2274
0
  if (data_device)
2275
0
    tgt->data_device = data_device;
2276
0
  if (vk)
2277
0
    tgt->u.crypt.vk = vk;
2278
0
  return 0;
2279
0
err:
2280
0
  free(cipher);
2281
0
  free(integrity);
2282
0
  device_free(cd, data_device);
2283
0
  crypt_safe_free(key);
2284
0
  crypt_free_volume_key(vk);
2285
0
  return r;
2286
0
}
2287
2288
static int _dm_target_query_verity(struct crypt_device *cd,
2289
           uint64_t get_flags,
2290
                 char *params,
2291
                 struct dm_target *tgt,
2292
           uint32_t *act_flags)
2293
0
{
2294
0
  struct crypt_params_verity *vp = NULL;
2295
0
  uint32_t val32;
2296
0
  uint64_t val64;
2297
0
  ssize_t len;
2298
0
  char *str, *str2, *arg;
2299
0
  unsigned int i, features;
2300
0
  int r;
2301
0
  struct device *data_device = NULL, *hash_device = NULL, *fec_device = NULL;
2302
0
  char *hash_name = NULL, *root_hash = NULL, *salt = NULL, *fec_dev_str = NULL;
2303
0
  char *root_hash_sig_key_desc = NULL;
2304
2305
0
  if (get_flags & DM_ACTIVE_VERITY_PARAMS) {
2306
0
    vp = crypt_zalloc(sizeof(*vp));
2307
0
    if (!vp)
2308
0
      return -ENOMEM;
2309
0
  }
2310
2311
0
  tgt->type = DM_VERITY;
2312
0
  tgt->direction = TARGET_QUERY;
2313
0
  tgt->u.verity.vp = vp;
2314
2315
  /* version */
2316
0
  val32 = strtoul(params, &params, 10);
2317
0
  if (*params != ' ')
2318
0
    return -EINVAL;
2319
0
  if (vp)
2320
0
    vp->hash_type = val32;
2321
0
  params++;
2322
2323
  /* data device */
2324
0
  str = strsep(&params, " ");
2325
0
  if (!params)
2326
0
    return -EINVAL;
2327
0
  if (get_flags & DM_ACTIVE_DEVICE) {
2328
0
    str2 = crypt_lookup_dev(str);
2329
0
    if (!str2)
2330
0
      return -EINVAL;
2331
0
    r = device_alloc(cd, &data_device, str2);
2332
0
    free(str2);
2333
0
    if (r < 0 && r != -ENOTBLK)
2334
0
      return r;
2335
0
  }
2336
2337
0
  r = -EINVAL;
2338
2339
  /* hash device */
2340
0
  str = strsep(&params, " ");
2341
0
  if (!params)
2342
0
    goto err;
2343
0
  if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
2344
0
    str2 = crypt_lookup_dev(str);
2345
0
    r = device_alloc(cd, &hash_device, str2);
2346
0
    free(str2);
2347
0
    if (r < 0 && r != -ENOTBLK)
2348
0
      goto err;
2349
0
  }
2350
2351
0
  r = -EINVAL;
2352
2353
  /* data block size*/
2354
0
  val32 = strtoul(params, &params, 10);
2355
0
  if (*params != ' ')
2356
0
    goto err;
2357
0
  if (vp)
2358
0
    vp->data_block_size = val32;
2359
0
  params++;
2360
2361
  /* hash block size */
2362
0
  val32 = strtoul(params, &params, 10);
2363
0
  if (*params != ' ')
2364
0
    goto err;
2365
0
  if (vp)
2366
0
    vp->hash_block_size = val32;
2367
0
  params++;
2368
2369
  /* data blocks */
2370
0
  val64 = strtoull(params, &params, 10);
2371
0
  if (*params != ' ')
2372
0
    goto err;
2373
0
  if (vp)
2374
0
    vp->data_size = val64;
2375
0
  params++;
2376
2377
  /* hash start */
2378
0
  val64 = strtoull(params, &params, 10);
2379
0
  if (*params != ' ')
2380
0
    goto err;
2381
0
  tgt->u.verity.hash_offset = val64;
2382
0
  params++;
2383
2384
  /* hash algorithm */
2385
0
  str = strsep(&params, " ");
2386
0
  if (!params)
2387
0
    goto err;
2388
0
  if (vp) {
2389
0
    hash_name = strdup(str);
2390
0
    if (!hash_name) {
2391
0
      r = -ENOMEM;
2392
0
      goto err;
2393
0
    }
2394
0
  }
2395
2396
  /* root digest */
2397
0
  str = strsep(&params, " ");
2398
0
  if (!params)
2399
0
    goto err;
2400
0
  len = crypt_hex_to_bytes(str, &str2, 0);
2401
0
  if (len < 0) {
2402
0
    r = len;
2403
0
    goto err;
2404
0
  }
2405
0
  tgt->u.verity.root_hash_size = len;
2406
0
  if (get_flags & DM_ACTIVE_VERITY_ROOT_HASH)
2407
0
    root_hash = str2;
2408
0
  else
2409
0
    free(str2);
2410
2411
  /* salt */
2412
0
  str = strsep(&params, " ");
2413
0
  if (vp) {
2414
0
    if (!strcmp(str, "-")) {
2415
0
      vp->salt_size = 0;
2416
0
      vp->salt = NULL;
2417
0
    } else {
2418
0
      len = crypt_hex_to_bytes(str, &str2, 0);
2419
0
      if (len < 0) {
2420
0
        r = len;
2421
0
        goto err;
2422
0
      }
2423
0
      vp->salt_size = len;
2424
0
      salt = str2;
2425
0
    }
2426
0
  }
2427
2428
0
  r = -EINVAL;
2429
2430
  /* Features section, available since verity target version 1.3 */
2431
0
  if (params) {
2432
    /* Number of arguments */
2433
0
    val64 = strtoull(params, &params, 10);
2434
0
    if (*params != ' ')
2435
0
      goto err;
2436
0
    params++;
2437
2438
0
    features = (int)val64;
2439
0
    for (i = 0; i < features; i++) {
2440
0
      r = -EINVAL;
2441
0
      if (!params)
2442
0
        goto err;
2443
0
      arg = strsep(&params, " ");
2444
0
      if (!strcasecmp(arg, "ignore_corruption"))
2445
0
        *act_flags |= CRYPT_ACTIVATE_IGNORE_CORRUPTION;
2446
0
      else if (!strcasecmp(arg, "restart_on_corruption"))
2447
0
        *act_flags |= CRYPT_ACTIVATE_RESTART_ON_CORRUPTION;
2448
0
      else if (!strcasecmp(arg, "panic_on_corruption"))
2449
0
        *act_flags |= CRYPT_ACTIVATE_PANIC_ON_CORRUPTION;
2450
0
      else if (!strcasecmp(arg, "restart_on_error") ||
2451
0
         !strcasecmp(arg, "panic_on_error"))
2452
0
        *act_flags |= CRYPT_ACTIVATE_ERROR_AS_CORRUPTION;
2453
0
      else if (!strcasecmp(arg, "ignore_zero_blocks"))
2454
0
        *act_flags |= CRYPT_ACTIVATE_IGNORE_ZERO_BLOCKS;
2455
0
      else if (!strcasecmp(arg, "check_at_most_once"))
2456
0
        *act_flags |= CRYPT_ACTIVATE_CHECK_AT_MOST_ONCE;
2457
0
      else if (!strcasecmp(arg, "try_verify_in_tasklet"))
2458
0
        *act_flags |= CRYPT_ACTIVATE_TASKLETS;
2459
0
      else if (!strcasecmp(arg, "use_fec_from_device")) {
2460
0
        str = strsep(&params, " ");
2461
0
        str2 = crypt_lookup_dev(str);
2462
0
        if (get_flags & DM_ACTIVE_VERITY_HASH_DEVICE) {
2463
0
          r = device_alloc(cd, &fec_device, str2);
2464
0
          if (r < 0 && r != -ENOTBLK) {
2465
0
            free(str2);
2466
0
            goto err;
2467
0
          }
2468
0
        }
2469
0
        if (vp) {
2470
0
          free(fec_dev_str);
2471
0
          fec_dev_str = str2;
2472
0
        } else
2473
0
          free(str2);
2474
0
        i++;
2475
0
      } else if (!strcasecmp(arg, "fec_start")) {
2476
0
        val64 = strtoull(params, &params, 10);
2477
0
        if (*params)
2478
0
          params++;
2479
0
        tgt->u.verity.fec_offset = val64;
2480
0
        if (vp)
2481
0
          vp->fec_area_offset = val64 * vp->hash_block_size;
2482
0
        i++;
2483
0
      } else if (!strcasecmp(arg, "fec_blocks")) {
2484
0
        val64 = strtoull(params, &params, 10);
2485
0
        if (*params)
2486
0
          params++;
2487
0
        tgt->u.verity.fec_blocks = val64;
2488
0
        i++;
2489
0
      } else if (!strcasecmp(arg, "fec_roots")) {
2490
0
        val32 = strtoul(params, &params, 10);
2491
0
        if (*params)
2492
0
          params++;
2493
0
        if (vp)
2494
0
          vp->fec_roots = val32;
2495
0
        i++;
2496
0
      } else if (!strcasecmp(arg, "root_hash_sig_key_desc")) {
2497
0
        str = strsep(&params, " ");
2498
0
        if (!str)
2499
0
          goto err;
2500
0
        if (vp && !root_hash_sig_key_desc) {
2501
0
          root_hash_sig_key_desc = strdup(str);
2502
0
          if (!root_hash_sig_key_desc) {
2503
0
            r = -ENOMEM;
2504
0
            goto err;
2505
0
          }
2506
          /* not stored in params, but cannot be used without vp */
2507
0
          vp->flags |= CRYPT_VERITY_ROOT_HASH_SIGNATURE;
2508
0
        }
2509
0
        i++;
2510
0
      } else /* unknown option */
2511
0
        goto err;
2512
0
    }
2513
2514
    /* All parameters should be processed */
2515
0
    if (params && *params) {
2516
0
      r = -EINVAL;
2517
0
      goto err;
2518
0
    }
2519
0
  }
2520
2521
0
  if (data_device)
2522
0
    tgt->data_device = data_device;
2523
0
  if (hash_device)
2524
0
    tgt->u.verity.hash_device = hash_device;
2525
0
  if (fec_device)
2526
0
    tgt->u.verity.fec_device = fec_device;
2527
0
  if (root_hash)
2528
0
    tgt->u.verity.root_hash = root_hash;
2529
0
  if (vp && hash_name)
2530
0
    vp->hash_name = hash_name;
2531
0
  if (vp && salt)
2532
0
    vp->salt = salt;
2533
0
  if (vp && fec_dev_str)
2534
0
    vp->fec_device = fec_dev_str;
2535
0
  if (root_hash_sig_key_desc)
2536
0
    tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
2537
2538
0
  return 0;
2539
0
err:
2540
0
  device_free(cd, data_device);
2541
0
  device_free(cd, hash_device);
2542
0
  device_free(cd, fec_device);
2543
0
  free(root_hash_sig_key_desc);
2544
0
  free(root_hash);
2545
0
  free(hash_name);
2546
0
  free(salt);
2547
0
  free(fec_dev_str);
2548
0
  free(vp);
2549
0
  return r;
2550
0
}
2551
2552
static int _dm_target_query_integrity(struct crypt_device *cd,
2553
           uint64_t get_flags,
2554
           char *params,
2555
           struct dm_target *tgt,
2556
           uint32_t *act_flags)
2557
0
{
2558
0
  uint32_t val32;
2559
0
  uint64_t val64;
2560
0
  char c, *str, *str2, *arg;
2561
0
  unsigned int i, features, val;
2562
0
  ssize_t len;
2563
0
  int r;
2564
0
  struct device *data_device = NULL, *meta_device = NULL;
2565
0
  char *integrity = NULL, *journal_crypt = NULL, *journal_integrity = NULL;
2566
0
  struct volume_key *vk = NULL;
2567
0
  struct volume_key *journal_integrity_key = NULL;
2568
0
  struct volume_key *journal_crypt_key = NULL;
2569
2570
0
  tgt->type = DM_INTEGRITY;
2571
0
  tgt->direction = TARGET_QUERY;
2572
2573
  /* data device */
2574
0
  str = strsep(&params, " ");
2575
0
  if (get_flags & DM_ACTIVE_DEVICE) {
2576
0
    str2 = crypt_lookup_dev(str);
2577
0
    r = device_alloc(cd, &data_device, str2);
2578
0
    free(str2);
2579
0
    if (r < 0 && r != -ENOTBLK)
2580
0
      return r;
2581
0
  }
2582
2583
0
  r = -EINVAL;
2584
2585
  /*offset */
2586
0
  if (!params)
2587
0
    goto err;
2588
0
  val64 = strtoull(params, &params, 10);
2589
0
  if (!*params || *params != ' ')
2590
0
    goto err;
2591
0
  tgt->u.integrity.offset = val64;
2592
2593
  /* tag size*/
2594
0
  val32 = strtoul(params, &params, 10);
2595
0
  tgt->u.integrity.tag_size = val32;
2596
0
  if (!*params || *params != ' ')
2597
0
    goto err;
2598
2599
  /* journal */
2600
0
  c = toupper(*(++params));
2601
0
  if (!*params || *(++params) != ' ' || (c != 'D' && c != 'J' && c != 'R' && c != 'B' && c != 'I'))
2602
0
    goto err;
2603
0
  if (c == 'D')
2604
0
    *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
2605
0
  if (c == 'R')
2606
0
    *act_flags |= CRYPT_ACTIVATE_RECOVERY;
2607
0
  if (c == 'B') {
2608
0
    *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
2609
0
    *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL_BITMAP;
2610
0
  }
2611
0
  if (c == 'I') {
2612
0
    *act_flags |= CRYPT_ACTIVATE_NO_JOURNAL;
2613
0
    *act_flags |= CRYPT_ACTIVATE_INLINE_MODE;
2614
0
  }
2615
2616
0
  tgt->u.integrity.sector_size = SECTOR_SIZE;
2617
2618
  /* Features section, number of arguments (always included) */
2619
0
  val64 = strtoull(params, &params, 10);
2620
0
  if (*params != ' ')
2621
0
    goto err;
2622
0
  params++;
2623
2624
0
  features = (int)val64;
2625
0
  for (i = 0; i < features; i++) {
2626
0
    r = -EINVAL;
2627
0
    if (!params)
2628
0
      goto err;
2629
0
    arg = strsep(&params, " ");
2630
0
    if (sscanf(arg, "journal_sectors:%u", &val) == 1)
2631
0
      tgt->u.integrity.journal_size = val * SECTOR_SIZE;
2632
0
    else if (sscanf(arg, "journal_watermark:%u", &val) == 1)
2633
0
      tgt->u.integrity.journal_watermark = val;
2634
0
    else if (sscanf(arg, "sectors_per_bit:%" PRIu64, &val64) == 1) {
2635
0
      if (val64 > UINT_MAX)
2636
0
        goto err;
2637
      /* overloaded value for bitmap mode */
2638
0
      tgt->u.integrity.journal_watermark = (unsigned int)val64;
2639
0
    } else if (sscanf(arg, "commit_time:%u", &val) == 1)
2640
0
      tgt->u.integrity.journal_commit_time = val;
2641
0
    else if (sscanf(arg, "bitmap_flush_interval:%u", &val) == 1)
2642
      /* overloaded value for bitmap mode */
2643
0
      tgt->u.integrity.journal_commit_time = val;
2644
0
    else if (sscanf(arg, "interleave_sectors:%u", &val) == 1)
2645
0
      tgt->u.integrity.interleave_sectors = val;
2646
0
    else if (sscanf(arg, "block_size:%u", &val) == 1)
2647
0
      tgt->u.integrity.sector_size = val;
2648
0
    else if (sscanf(arg, "buffer_sectors:%u", &val) == 1)
2649
0
      tgt->u.integrity.buffer_sectors = val;
2650
0
    else if (!strncmp(arg, "internal_hash:", 14) && !integrity) {
2651
0
      str = &arg[14];
2652
0
      arg = strsep(&str, ":");
2653
0
      if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2654
0
        integrity = strdup(arg);
2655
0
        if (!integrity) {
2656
0
          r = -ENOMEM;
2657
0
          goto err;
2658
0
        }
2659
0
      }
2660
2661
0
      if (str) {
2662
0
        len = crypt_hex_to_bytes(str, &str2, 1);
2663
0
        if (len < 0) {
2664
0
          r = len;
2665
0
          goto err;
2666
0
        }
2667
2668
0
        r = 0;
2669
0
        if (get_flags & DM_ACTIVE_CRYPT_KEY) {
2670
0
          vk = crypt_alloc_volume_key(len, str2);
2671
0
          if (!vk)
2672
0
            r = -ENOMEM;
2673
0
        } else if (get_flags & DM_ACTIVE_CRYPT_KEYSIZE) {
2674
0
          vk = crypt_alloc_volume_key(len, NULL);
2675
0
          if (!vk)
2676
0
            r = -ENOMEM;
2677
0
        }
2678
0
        crypt_safe_free(str2);
2679
0
        if (r < 0)
2680
0
          goto err;
2681
0
      }
2682
0
    } else if (!strncmp(arg, "meta_device:", 12) && !meta_device) {
2683
0
      if (get_flags & DM_ACTIVE_DEVICE) {
2684
0
        str = crypt_lookup_dev(&arg[12]);
2685
0
        r = device_alloc(cd, &meta_device, str);
2686
0
        free(str);
2687
0
        if (r < 0 && r != -ENOTBLK)
2688
0
          goto err;
2689
0
      }
2690
0
    } else if (!strncmp(arg, "journal_crypt:", 14) && !journal_crypt) {
2691
0
      str = &arg[14];
2692
0
      arg = strsep(&str, ":");
2693
0
      if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2694
0
        journal_crypt = strdup(arg);
2695
0
        if (!journal_crypt) {
2696
0
          r = -ENOMEM;
2697
0
          goto err;
2698
0
        }
2699
0
      }
2700
2701
0
      if (str) {
2702
0
        len = crypt_hex_to_bytes(str, &str2, 1);
2703
0
        if (len < 0) {
2704
0
          r = len;
2705
0
          goto err;
2706
0
        }
2707
2708
0
        r = 0;
2709
0
        if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEY) {
2710
0
          journal_crypt_key = crypt_alloc_volume_key(len, str2);
2711
0
          if (!journal_crypt_key)
2712
0
            r = -ENOMEM;
2713
0
        } else if (get_flags & DM_ACTIVE_JOURNAL_CRYPT_KEYSIZE) {
2714
0
          journal_crypt_key = crypt_alloc_volume_key(len, NULL);
2715
0
          if (!journal_crypt_key)
2716
0
            r = -ENOMEM;
2717
0
        }
2718
0
        crypt_safe_free(str2);
2719
0
        if (r < 0)
2720
0
          goto err;
2721
0
      }
2722
0
    } else if (!strncmp(arg, "journal_mac:", 12) && !journal_integrity) {
2723
0
      str = &arg[12];
2724
0
      arg = strsep(&str, ":");
2725
0
      if (get_flags & DM_ACTIVE_INTEGRITY_PARAMS) {
2726
0
        journal_integrity = strdup(arg);
2727
0
        if (!journal_integrity) {
2728
0
          r = -ENOMEM;
2729
0
          goto err;
2730
0
        }
2731
0
      }
2732
2733
0
      if (str) {
2734
0
        len = crypt_hex_to_bytes(str, &str2, 1);
2735
0
        if (len < 0) {
2736
0
          r = len;
2737
0
          goto err;
2738
0
        }
2739
2740
0
        r = 0;
2741
0
        if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEY) {
2742
0
          journal_integrity_key = crypt_alloc_volume_key(len, str2);
2743
0
          if (!journal_integrity_key)
2744
0
            r = -ENOMEM;
2745
0
        } else if (get_flags & DM_ACTIVE_JOURNAL_MAC_KEYSIZE) {
2746
0
          journal_integrity_key = crypt_alloc_volume_key(len, NULL);
2747
0
          if (!journal_integrity_key)
2748
0
            r = -ENOMEM;
2749
0
        }
2750
0
        crypt_safe_free(str2);
2751
0
        if (r < 0)
2752
0
          goto err;
2753
0
      }
2754
0
    } else if (!strcmp(arg, "recalculate")) {
2755
0
      *act_flags |= CRYPT_ACTIVATE_RECALCULATE;
2756
0
    } else if (!strcmp(arg, "reset_recalculate")) {
2757
0
      *act_flags |= CRYPT_ACTIVATE_RECALCULATE_RESET;
2758
0
    } else if (!strcmp(arg, "fix_padding")) {
2759
0
      tgt->u.integrity.fix_padding = true;
2760
0
    } else if (!strcmp(arg, "fix_hmac")) {
2761
0
      tgt->u.integrity.fix_hmac = true;
2762
0
    } else if (!strcmp(arg, "legacy_recalculate")) {
2763
0
      tgt->u.integrity.legacy_recalc = true;
2764
0
    } else if (!strcmp(arg, "allow_discards")) {
2765
0
      *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
2766
0
    } else if (!strcmp(arg, "allow_discards_keyed")) {
2767
0
      *act_flags |= CRYPT_ACTIVATE_ALLOW_DISCARDS;
2768
0
      tgt->u.integrity.discard_keyed = true;
2769
0
    } else /* unknown option */
2770
0
      goto err;
2771
0
  }
2772
2773
  /* All parameters should be processed */
2774
0
  if (params && *params) {
2775
0
    r = -EINVAL;
2776
0
    goto err;
2777
0
  }
2778
2779
0
  if (data_device)
2780
0
    tgt->data_device = data_device;
2781
0
  if (meta_device)
2782
0
    tgt->u.integrity.meta_device = meta_device;
2783
0
  if (integrity)
2784
0
    tgt->u.integrity.integrity = integrity;
2785
0
  if (journal_crypt)
2786
0
    tgt->u.integrity.journal_crypt = journal_crypt;
2787
0
  if (journal_integrity)
2788
0
    tgt->u.integrity.journal_integrity = journal_integrity;
2789
0
  if (vk)
2790
0
    tgt->u.integrity.vk = vk;
2791
0
  if (journal_integrity_key)
2792
0
    tgt->u.integrity.journal_integrity_key = journal_integrity_key;
2793
0
  if (journal_crypt_key)
2794
0
    tgt->u.integrity.journal_crypt_key = journal_crypt_key;
2795
0
  return 0;
2796
0
err:
2797
0
  device_free(cd, data_device);
2798
0
  device_free(cd, meta_device);
2799
0
  free(integrity);
2800
0
  free(journal_crypt);
2801
0
  free(journal_integrity);
2802
0
  crypt_free_volume_key(vk);
2803
0
  crypt_free_volume_key(journal_integrity_key);
2804
0
  crypt_free_volume_key(journal_crypt_key);
2805
0
  return r;
2806
0
}
2807
2808
static int _dm_target_query_linear(struct crypt_device *cd, struct dm_target *tgt,
2809
           uint64_t get_flags, char *params)
2810
0
{
2811
0
  uint64_t val64;
2812
0
  char *rdevice, *arg;
2813
0
  int r;
2814
0
  struct device *device = NULL;
2815
2816
  /* device */
2817
0
  rdevice = strsep(&params, " ");
2818
0
  if (get_flags & DM_ACTIVE_DEVICE) {
2819
0
    arg = crypt_lookup_dev(rdevice);
2820
0
    r = device_alloc(cd, &device, arg);
2821
0
    free(arg);
2822
0
    if (r < 0 && r != -ENOTBLK)
2823
0
      return r;
2824
0
  }
2825
2826
0
  r = -EINVAL;
2827
2828
  /*offset */
2829
0
  if (!params)
2830
0
    goto err;
2831
0
  val64 = strtoull(params, &params, 10);
2832
2833
  /* params should be empty now */
2834
0
  if (*params)
2835
0
    goto err;
2836
2837
0
  tgt->type = DM_LINEAR;
2838
0
  tgt->direction = TARGET_QUERY;
2839
0
  tgt->data_device = device;
2840
0
  tgt->u.linear.offset = val64;
2841
2842
0
  return 0;
2843
0
err:
2844
0
  device_free(cd, device);
2845
0
  return r;
2846
0
}
2847
2848
static int _dm_target_query_error(struct dm_target *tgt)
2849
0
{
2850
0
  tgt->type = DM_ERROR;
2851
0
  tgt->direction = TARGET_QUERY;
2852
2853
0
  return 0;
2854
0
}
2855
2856
static int _dm_target_query_zero(struct dm_target *tgt)
2857
0
{
2858
0
  tgt->type = DM_ZERO;
2859
0
  tgt->direction = TARGET_QUERY;
2860
2861
0
  return 0;
2862
0
}
2863
2864
/*
2865
 * on error retval has to be negative
2866
 *
2867
 * also currently any _dm_target_query fn does not perform cleanup on error
2868
 */
2869
static int dm_target_query(struct crypt_device *cd, struct dm_target *tgt, const uint64_t *start,
2870
        const uint64_t *length, const char *target_type,
2871
        char *params, uint64_t get_flags, uint32_t *act_flags)
2872
0
{
2873
0
  int r = -ENOTSUP;
2874
2875
0
  if (!strcmp(target_type, DM_CRYPT_TARGET))
2876
0
    r = _dm_target_query_crypt(cd, get_flags, params, tgt, act_flags);
2877
0
  else if (!strcmp(target_type, DM_VERITY_TARGET))
2878
0
    r = _dm_target_query_verity(cd, get_flags, params, tgt, act_flags);
2879
0
  else if (!strcmp(target_type, DM_INTEGRITY_TARGET))
2880
0
    r = _dm_target_query_integrity(cd, get_flags, params, tgt, act_flags);
2881
0
  else if (!strcmp(target_type, DM_LINEAR_TARGET))
2882
0
    r = _dm_target_query_linear(cd, tgt, get_flags, params);
2883
0
  else if (!strcmp(target_type, DM_ERROR_TARGET))
2884
0
    r = _dm_target_query_error(tgt);
2885
0
  else if (!strcmp(target_type, DM_ZERO_TARGET))
2886
0
    r = _dm_target_query_zero(tgt);
2887
2888
0
  if (!r) {
2889
0
    tgt->offset = *start;
2890
0
    tgt->size = *length;
2891
0
  }
2892
2893
0
  return r;
2894
0
}
2895
2896
static int _dm_query_device(struct crypt_device *cd, const char *name,
2897
        uint64_t get_flags, struct crypt_dm_active_device *dmd)
2898
0
{
2899
0
  struct dm_target *t;
2900
0
  struct dm_task *dmt;
2901
0
  struct dm_info dmi;
2902
0
  uint64_t start, length;
2903
0
  char *target_type, *params;
2904
0
  const char *tmp_uuid;
2905
0
  void *next = NULL;
2906
0
  int r = -EINVAL;
2907
2908
0
  t = &dmd->segment;
2909
2910
0
  if (!(dmt = dm_task_create(DM_DEVICE_TABLE)))
2911
0
    return r;
2912
0
  if (!dm_task_secure_data(dmt))
2913
0
    goto out;
2914
0
  if (!dm_task_set_name(dmt, name))
2915
0
    goto out;
2916
0
  r = -ENODEV;
2917
0
  if (!dm_task_run(dmt))
2918
0
    goto out;
2919
2920
0
  r = -EINVAL;
2921
0
  if (!dm_task_get_info(dmt, &dmi))
2922
0
    goto out;
2923
2924
0
  if (!dmi.exists) {
2925
0
    r = -ENODEV;
2926
0
    goto out;
2927
0
  }
2928
2929
0
  if (dmi.target_count <= 0) {
2930
0
    r = -EINVAL;
2931
0
    goto out;
2932
0
  }
2933
2934
  /* Never allow one to return empty key */
2935
0
  if ((get_flags & DM_ACTIVE_CRYPT_KEY) && dmi.suspended) {
2936
0
    log_dbg(cd, "Cannot read volume key while suspended.");
2937
0
    r = -EINVAL;
2938
0
    goto out;
2939
0
  }
2940
2941
0
  r = dm_targets_allocate(&dmd->segment, dmi.target_count);
2942
0
  if (r)
2943
0
    goto out;
2944
2945
0
  do {
2946
0
    next = dm_get_next_target(dmt, next, &start, &length,
2947
0
                                    &target_type, &params);
2948
2949
0
    r = dm_target_query(cd, t, &start, &length, target_type, params, get_flags, &dmd->flags);
2950
0
    if (!r && t->type == DM_VERITY) {
2951
0
      r = _dm_status_verity_ok(cd, name);
2952
0
      if (r == 0)
2953
0
        dmd->flags |= CRYPT_ACTIVATE_CORRUPTED;
2954
0
    }
2955
2956
0
    if (r < 0) {
2957
0
      if (r != -ENOTSUP)
2958
0
        log_err(cd, _("Failed to query dm-%s segment."), target_type);
2959
0
      goto out;
2960
0
    }
2961
2962
0
    dmd->size += length;
2963
0
    t = t->next;
2964
0
  } while (next && t);
2965
2966
0
  if (dmi.read_only)
2967
0
    dmd->flags |= CRYPT_ACTIVATE_READONLY;
2968
2969
0
  if (dmi.suspended)
2970
0
    dmd->flags |= CRYPT_ACTIVATE_SUSPENDED;
2971
2972
0
  tmp_uuid = dm_task_get_uuid(dmt);
2973
0
  if (!tmp_uuid)
2974
0
    dmd->flags |= CRYPT_ACTIVATE_NO_UUID;
2975
0
  else if (get_flags & DM_ACTIVE_UUID) {
2976
0
    if (!strncmp(tmp_uuid, DM_UUID_PREFIX, DM_UUID_PREFIX_LEN)) {
2977
0
      dmd->uuid = strdup(tmp_uuid + DM_UUID_PREFIX_LEN);
2978
0
      if (!dmd->uuid) {
2979
0
        r = -ENOMEM;
2980
0
        goto out;
2981
0
      }
2982
0
    }
2983
0
  }
2984
2985
0
  dmd->holders = 0;
2986
0
#if (HAVE_DECL_DM_DEVICE_HAS_HOLDERS && HAVE_DECL_DM_DEVICE_HAS_MOUNTED_FS)
2987
0
  if (get_flags & DM_ACTIVE_HOLDERS)
2988
0
    dmd->holders = (dm_device_has_mounted_fs(dmi.major, dmi.minor) ||
2989
0
        dm_device_has_holders(dmi.major, dmi.minor));
2990
0
#endif
2991
2992
0
  r = (dmi.open_count > 0);
2993
0
out:
2994
0
  dm_task_destroy(dmt);
2995
2996
0
  if (r < 0)
2997
0
    dm_targets_free(cd, dmd);
2998
2999
0
  return r;
3000
0
}
3001
3002
int dm_query_device(struct crypt_device *cd, const char *name,
3003
        uint64_t get_flags, struct crypt_dm_active_device *dmd)
3004
0
{
3005
0
  int r;
3006
3007
0
  if (!dmd)
3008
0
    return -EINVAL;
3009
3010
0
  memset(dmd, 0, sizeof(*dmd));
3011
3012
0
  if (dm_init_context(cd, DM_UNKNOWN))
3013
0
    return -ENOTSUP;
3014
3015
0
  r = _dm_query_device(cd, name, get_flags, dmd);
3016
3017
0
  dm_exit_context();
3018
0
  return r;
3019
0
}
3020
3021
static int _process_deps(struct crypt_device *cd, const char *prefix, struct dm_deps *deps,
3022
       char **names, size_t names_offset, size_t names_length)
3023
0
{
3024
0
#if HAVE_DECL_DM_DEVICE_GET_NAME
3025
0
  struct crypt_dm_active_device dmd;
3026
0
  char dmname[PATH_MAX];
3027
0
  unsigned i;
3028
0
  int r, major, minor, count = 0;
3029
3030
0
  if (!prefix || !deps)
3031
0
    return -EINVAL;
3032
3033
0
  for (i = 0; i < deps->count; i++) {
3034
0
    major = major(deps->device[i]);
3035
0
    if (!dm_is_dm_major(major))
3036
0
      continue;
3037
3038
0
    minor = minor(deps->device[i]);
3039
0
    if (!dm_device_get_name(major, minor, 0, dmname, PATH_MAX))
3040
0
      return -EINVAL;
3041
3042
0
    memset(&dmd, 0, sizeof(dmd));
3043
0
    r = _dm_query_device(cd, dmname, DM_ACTIVE_UUID, &dmd);
3044
0
    if (r < 0)
3045
0
      continue;
3046
3047
0
    if (!dmd.uuid ||
3048
0
        strncmp(prefix, dmd.uuid, strlen(prefix)) ||
3049
0
        crypt_string_in(dmname, names, names_length))
3050
0
      *dmname = '\0';
3051
3052
0
    dm_targets_free(cd, &dmd);
3053
0
    free(CONST_CAST(void*)dmd.uuid);
3054
3055
0
    if ((size_t)count >= (names_length - names_offset))
3056
0
      return -ENOMEM;
3057
3058
0
    if (*dmname && !(names[names_offset + count++] = strdup(dmname)))
3059
0
      return -ENOMEM;
3060
0
  }
3061
3062
0
  return count;
3063
#else
3064
  return -EINVAL;
3065
#endif
3066
0
}
3067
3068
int dm_device_deps(struct crypt_device *cd, const char *name, const char *prefix,
3069
       char **names, size_t names_length)
3070
0
{
3071
0
  struct dm_task *dmt = NULL;
3072
0
  struct dm_info dmi;
3073
0
  struct dm_deps *deps;
3074
0
  int r = -EINVAL;
3075
0
  size_t i, last = 0, offset = 0;
3076
3077
0
  if (!name || !names_length || !names)
3078
0
    return -EINVAL;
3079
3080
0
  if (dm_init_context(cd, DM_UNKNOWN))
3081
0
    return -ENOTSUP;
3082
3083
0
  while (name) {
3084
0
    if (!(dmt = dm_task_create(DM_DEVICE_DEPS)))
3085
0
      goto out;
3086
0
    if (!dm_task_set_name(dmt, name))
3087
0
      goto out;
3088
3089
0
    r = -ENODEV;
3090
0
    if (!dm_task_run(dmt))
3091
0
      goto out;
3092
3093
0
    r = -EINVAL;
3094
0
    if (!dm_task_get_info(dmt, &dmi))
3095
0
      goto out;
3096
0
    if (!(deps = dm_task_get_deps(dmt)))
3097
0
      goto out;
3098
3099
0
    r = -ENODEV;
3100
0
    if (!dmi.exists)
3101
0
      goto out;
3102
3103
0
    r = _process_deps(cd, prefix, deps, names, offset, names_length - 1);
3104
0
    if (r < 0)
3105
0
      goto out;
3106
3107
0
    dm_task_destroy(dmt);
3108
0
    dmt = NULL;
3109
3110
0
    offset += r;
3111
0
    name = names[last++];
3112
0
  }
3113
3114
0
  r = 0;
3115
0
out:
3116
0
  if (r < 0) {
3117
0
    for (i = 0; i < names_length - 1; i++)
3118
0
      free(names[i]);
3119
0
    *names = NULL;
3120
0
  }
3121
3122
0
  if (dmt)
3123
0
    dm_task_destroy(dmt);
3124
3125
0
  dm_exit_context();
3126
0
  return r;
3127
0
}
3128
3129
static int _dm_message(const char *name, const char *msg)
3130
0
{
3131
0
  int r = 0;
3132
0
  struct dm_task *dmt;
3133
3134
0
  if (!(dmt = dm_task_create(DM_DEVICE_TARGET_MSG)))
3135
0
    return 0;
3136
3137
0
  if (!dm_task_secure_data(dmt))
3138
0
    goto out;
3139
3140
0
  if (name && !dm_task_set_name(dmt, name))
3141
0
    goto out;
3142
3143
0
  if (!dm_task_set_sector(dmt, (uint64_t) 0))
3144
0
    goto out;
3145
3146
0
  if (!dm_task_set_message(dmt, msg))
3147
0
    goto out;
3148
3149
0
  r = dm_task_run(dmt);
3150
0
out:
3151
0
  dm_task_destroy(dmt);
3152
0
  return r;
3153
0
}
3154
3155
int dm_suspend_device(struct crypt_device *cd, const char *name, uint64_t dmflags)
3156
0
{
3157
0
  uint64_t dmt_flags;
3158
0
  int r = -ENOTSUP;
3159
3160
0
  if (dm_init_context(cd, DM_UNKNOWN))
3161
0
    return r;
3162
3163
0
  if (dmflags & DM_SUSPEND_WIPE_KEY) {
3164
0
    if (_do_dm_flags(cd, DM_CRYPT, &dmt_flags))
3165
0
      goto out;
3166
3167
0
    if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
3168
0
      goto out;
3169
0
  }
3170
3171
0
  r = -EINVAL;
3172
3173
0
  if (!_dm_simple(DM_DEVICE_SUSPEND, name, dmflags))
3174
0
    goto out;
3175
3176
0
  if (dmflags & DM_SUSPEND_WIPE_KEY) {
3177
0
    if (!_dm_message(name, "key wipe")) {
3178
0
      _dm_resume_device(name, 0);
3179
0
      goto out;
3180
0
    }
3181
0
  }
3182
3183
0
  r = 0;
3184
0
out:
3185
0
  dm_exit_context();
3186
0
  return r;
3187
0
}
3188
3189
int dm_resume_device(struct crypt_device *cd, const char *name, uint64_t dmflags)
3190
0
{
3191
0
  int r;
3192
3193
0
  if (dm_init_context(cd, DM_UNKNOWN))
3194
0
    return -ENOTSUP;
3195
3196
0
  r = _dm_resume_device(name, dmflags);
3197
3198
0
  dm_exit_context();
3199
3200
0
  return r;
3201
0
}
3202
3203
int dm_resume_and_reinstate_key(struct crypt_device *cd, const char *name,
3204
        const struct volume_key *vk)
3205
0
{
3206
0
  uint64_t dmt_flags;
3207
0
  int msg_size;
3208
0
  char *msg = NULL, *key = NULL;
3209
0
  int r = -ENOTSUP;
3210
3211
0
  if (dm_init_context(cd, DM_CRYPT) || _do_dm_flags(cd, DM_CRYPT, &dmt_flags))
3212
0
    return -ENOTSUP;
3213
3214
0
  if (!(dmt_flags & DM_KEY_WIPE_SUPPORTED))
3215
0
    goto out;
3216
3217
0
  if (!crypt_volume_key_length(vk))
3218
0
    msg_size = 11; // key set -
3219
0
  else if (crypt_volume_key_description(vk))
3220
0
    msg_size = strlen(crypt_volume_key_description(vk)) + int_log10(crypt_volume_key_length(vk)) + 18;
3221
0
  else
3222
0
    msg_size = crypt_volume_key_length(vk) * 2 + 10; // key set <key>
3223
3224
0
  msg = crypt_safe_alloc(msg_size);
3225
0
  if (!msg) {
3226
0
    r = -ENOMEM;
3227
0
    goto out;
3228
0
  }
3229
3230
0
  if (crypt_volume_key_description(vk)) {
3231
0
    r = snprintf(msg, msg_size, "key set :%zu:logon:%s", crypt_volume_key_length(vk),
3232
0
           crypt_volume_key_description(vk));
3233
0
  } else {
3234
0
    if (!crypt_volume_key_length(vk))
3235
0
      key = crypt_bytes_to_hex(0, NULL);
3236
0
    else
3237
0
      key = crypt_bytes_to_hex(crypt_volume_key_length(vk),
3238
0
             crypt_volume_key_get_key(vk));
3239
0
    if (!key) {
3240
0
      r = -ENOMEM;
3241
0
      goto out;
3242
0
    }
3243
3244
0
    r = snprintf(msg, msg_size, "key set %s", key);
3245
0
  }
3246
0
  if (r < 0 || r >= msg_size) {
3247
0
    r = -EINVAL;
3248
0
    goto out;
3249
0
  }
3250
0
  if (!_dm_message(name, msg) ||
3251
0
      _dm_resume_device(name, 0)) {
3252
0
    r = -EINVAL;
3253
0
    goto out;
3254
0
  }
3255
0
  r = 0;
3256
0
out:
3257
0
  crypt_safe_free(msg);
3258
0
  crypt_safe_free(key);
3259
0
  dm_exit_context();
3260
0
  return r;
3261
0
}
3262
3263
int dm_cancel_deferred_removal(struct crypt_device *cd, const char *name)
3264
0
{
3265
0
  int r;
3266
3267
0
  if (dm_init_context(cd, DM_UNKNOWN))
3268
0
    return -ENOTSUP;
3269
3270
0
  r = _dm_message(name, "@cancel_deferred_remove") ? 0 : -ENOTSUP;
3271
3272
0
  dm_exit_context();
3273
3274
0
  return r;
3275
0
}
3276
3277
const char *dm_get_dir(void)
3278
0
{
3279
0
  return dm_dir();
3280
0
}
3281
3282
int dm_get_iname(const char *name, char **iname, bool with_path)
3283
0
{
3284
0
  int r;
3285
3286
0
  if (with_path)
3287
0
    r = asprintf(iname, "%s/%s_dif", dm_get_dir(), name);
3288
0
  else
3289
0
    r = asprintf(iname, "%s_dif", name);
3290
3291
0
  return r < 0 ? -ENOMEM : 0;
3292
0
}
3293
3294
char *dm_get_active_iname(struct crypt_device *cd, const char *name)
3295
0
{
3296
0
  struct crypt_dm_active_device dmd = {}, dmdi = {};
3297
0
  struct dm_target *tgt = &dmd.segment, *tgti = &dmdi.segment;
3298
0
  char *ipath = NULL, *iname = NULL, *ret_iname = NULL;
3299
0
  struct stat st;
3300
3301
0
  if (!name)
3302
0
    return NULL;
3303
3304
0
  if (dm_query_device(cd, name, DM_ACTIVE_UUID, &dmd) < 0)
3305
0
    return NULL;
3306
3307
0
  if (!single_segment(&dmd))
3308
0
    goto out;
3309
3310
0
  if (tgt->type != DM_CRYPT || tgt->u.crypt.tag_size == 0)
3311
0
    goto out;
3312
3313
0
  if (dm_get_iname(name, &iname, false) < 0)
3314
0
    goto out;
3315
3316
0
  if (dm_get_iname(name, &ipath, true) < 0)
3317
0
    goto out;
3318
3319
0
  if (stat(ipath, &st) < 0 || !S_ISBLK(st.st_mode))
3320
0
    goto out;
3321
3322
0
  if (dm_query_device(cd, iname, DM_ACTIVE_UUID, &dmdi) < 0)
3323
0
    goto out;
3324
3325
0
  if (single_segment(&dmdi) &&
3326
0
      tgti->type == DM_INTEGRITY &&
3327
0
      dm_uuid_integrity_cmp(dmd.uuid, dmdi.uuid) == 0) {
3328
0
    ret_iname = iname;
3329
0
    iname = NULL;
3330
0
  }
3331
0
out:
3332
0
  dm_targets_free(cd, &dmdi);
3333
0
  dm_targets_free(cd, &dmd);
3334
0
  free(CONST_CAST(void*)dmd.uuid);
3335
0
  free(CONST_CAST(void*)dmdi.uuid);
3336
0
  free(ipath);
3337
0
  free(iname);
3338
3339
0
  return ret_iname;
3340
0
}
3341
3342
int dm_is_dm_device(int major)
3343
0
{
3344
0
  return dm_is_dm_major((uint32_t)major);
3345
0
}
3346
3347
int dm_is_dm_kernel_name(const char *name)
3348
0
{
3349
0
  return strncmp(name, "dm-", 3) ? 0 : 1;
3350
0
}
3351
3352
/*
3353
 * compares UUIDs returned by device-mapper (striped by cryptsetup) and uuid in header
3354
 */
3355
int dm_uuid_cmp(const char *dm_uuid, const char *hdr_uuid)
3356
0
{
3357
0
  int i, j;
3358
0
  const char *str;
3359
3360
0
  if (!dm_uuid || !hdr_uuid)
3361
0
    return -EINVAL;
3362
3363
  /* skip beyond LUKS2_HW_OPAL prefix */
3364
0
  if (!strncmp(dm_uuid, CRYPT_LUKS2_HW_OPAL, strlen(CRYPT_LUKS2_HW_OPAL)))
3365
0
    dm_uuid = dm_uuid + strlen(CRYPT_LUKS2_HW_OPAL);
3366
3367
0
  str = strchr(dm_uuid, '-');
3368
0
  if (!str)
3369
0
    return -EINVAL;
3370
3371
0
  for (i = 0, j = 1; hdr_uuid[i]; i++) {
3372
0
    if (hdr_uuid[i] == '-')
3373
0
      continue;
3374
3375
0
    if (!str[j] || str[j] == '-')
3376
0
      return -EINVAL;
3377
3378
0
    if (str[j] != hdr_uuid[i])
3379
0
      return -EINVAL;
3380
0
    j++;
3381
0
  }
3382
3383
0
  return 0;
3384
0
}
3385
3386
/*
3387
 * compares two UUIDs returned by device-mapper (striped by cryptsetup)
3388
 * used for stacked LUKS2 & INTEGRITY devices
3389
 */
3390
int dm_uuid_integrity_cmp(const char *dm_uuid, const char *dmi_uuid)
3391
0
{
3392
0
  int i;
3393
0
  const char *str, *stri;
3394
3395
0
  if (!dm_uuid || !dmi_uuid)
3396
0
    return -EINVAL;
3397
3398
  /* skip beyond LUKS2_HW_OPAL prefix */
3399
0
  if (!strncmp(dm_uuid, CRYPT_LUKS2_HW_OPAL, strlen(CRYPT_LUKS2_HW_OPAL)))
3400
0
    dm_uuid = dm_uuid + strlen(CRYPT_LUKS2_HW_OPAL);
3401
3402
0
  str = strchr(dm_uuid, '-');
3403
0
  if (!str)
3404
0
    return -EINVAL;
3405
3406
0
  stri = strchr(dmi_uuid, '-');
3407
0
  if (!stri)
3408
0
    return -EINVAL;
3409
3410
0
  for (i = 1; str[i] && str[i] != '-'; i++) {
3411
0
    if (!stri[i])
3412
0
      return -EINVAL;
3413
3414
0
    if (str[i] != stri[i])
3415
0
      return -EINVAL;
3416
0
  }
3417
3418
0
  return 0;
3419
0
}
3420
3421
/*
3422
 * compares type of active device to provided string
3423
 */
3424
int dm_uuid_type_cmp(const char *dm_uuid, const char *type)
3425
0
{
3426
0
  size_t len;
3427
3428
0
  assert(type);
3429
3430
0
  len = strlen(type);
3431
0
  if (dm_uuid && strlen(dm_uuid) > len &&
3432
0
      !strncmp(dm_uuid, type, len) && dm_uuid[len] == '-')
3433
0
    return 0;
3434
3435
0
  return -ENODEV;
3436
0
}
3437
3438
int dm_crypt_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3439
  struct device *data_device, struct volume_key *vk, const char *cipher,
3440
  uint64_t iv_offset, uint64_t data_offset,
3441
  const char *integrity, uint32_t integrity_key_size, uint32_t tag_size,
3442
  uint32_t sector_size)
3443
0
{
3444
0
  char *dm_integrity = NULL;
3445
3446
0
  if (tag_size) {
3447
    /* Space for IV metadata only */
3448
0
    dm_integrity = strdup(integrity ?: "none");
3449
0
    if (!dm_integrity)
3450
0
      return -ENOMEM;
3451
0
  }
3452
3453
0
  tgt->data_device = data_device;
3454
3455
0
  tgt->type = DM_CRYPT;
3456
0
  tgt->direction = TARGET_SET;
3457
0
  tgt->u.crypt.vk = vk;
3458
0
  tgt->offset = seg_offset;
3459
0
  tgt->size = seg_size;
3460
3461
0
  tgt->u.crypt.cipher = cipher;
3462
0
  tgt->u.crypt.integrity = dm_integrity;
3463
0
  tgt->u.crypt.iv_offset = iv_offset;
3464
0
  tgt->u.crypt.offset = data_offset;
3465
0
  tgt->u.crypt.tag_size = tag_size;
3466
0
  tgt->u.crypt.sector_size = sector_size;
3467
0
  tgt->u.crypt.integrity_key_size = integrity_key_size;
3468
3469
0
  return 0;
3470
0
}
3471
3472
int dm_verity_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3473
  struct device *data_device, struct device *hash_device, struct device *fec_device,
3474
  const char *root_hash, uint32_t root_hash_size, const char* root_hash_sig_key_desc,
3475
  uint64_t hash_offset_block, uint64_t fec_blocks, struct crypt_params_verity *vp)
3476
0
{
3477
0
  if (!data_device || !hash_device || !vp)
3478
0
    return -EINVAL;
3479
3480
0
  tgt->type = DM_VERITY;
3481
0
  tgt->direction = TARGET_SET;
3482
0
  tgt->offset = seg_offset;
3483
0
  tgt->size = seg_size;
3484
0
  tgt->data_device = data_device;
3485
3486
0
  tgt->u.verity.hash_device = hash_device;
3487
0
  tgt->u.verity.fec_device = fec_device;
3488
0
  tgt->u.verity.root_hash = root_hash;
3489
0
  tgt->u.verity.root_hash_size = root_hash_size;
3490
0
  tgt->u.verity.root_hash_sig_key_desc = root_hash_sig_key_desc;
3491
0
  tgt->u.verity.hash_offset = hash_offset_block;
3492
0
  tgt->u.verity.fec_offset = vp->fec_area_offset / vp->hash_block_size;
3493
0
  tgt->u.verity.fec_blocks = fec_blocks;
3494
0
  tgt->u.verity.vp = vp;
3495
3496
0
  return 0;
3497
0
}
3498
3499
int dm_integrity_target_set(struct crypt_device *cd,
3500
      struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3501
      struct device *meta_device,
3502
            struct device *data_device, uint64_t tag_size, uint64_t offset,
3503
      uint32_t sector_size, struct volume_key *vk,
3504
      struct volume_key *journal_crypt_key, struct volume_key *journal_mac_key,
3505
      const struct crypt_params_integrity *ip)
3506
0
{
3507
0
  uint64_t dmi_flags;
3508
3509
0
  if (!data_device)
3510
0
    return -EINVAL;
3511
3512
0
  if (dm_init_context(cd, DM_INTEGRITY))
3513
0
    return -ENOTSUP;
3514
3515
0
  tgt->type = DM_INTEGRITY;
3516
0
  tgt->direction = TARGET_SET;
3517
0
  tgt->offset = seg_offset;
3518
0
  tgt->size = seg_size;
3519
0
  tgt->data_device = data_device;
3520
0
  if (meta_device != data_device)
3521
0
    tgt->u.integrity.meta_device = meta_device;
3522
0
  tgt->u.integrity.tag_size = tag_size;
3523
0
  tgt->u.integrity.offset = offset;
3524
0
  tgt->u.integrity.sector_size = sector_size;
3525
3526
0
  tgt->u.integrity.vk = vk;
3527
0
  tgt->u.integrity.journal_crypt_key = journal_crypt_key;
3528
0
  tgt->u.integrity.journal_integrity_key = journal_mac_key;
3529
3530
0
  if (!_do_dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
3531
0
      (dmi_flags & DM_INTEGRITY_FIX_PADDING_SUPPORTED) &&
3532
0
      !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_PADDING))
3533
0
    tgt->u.integrity.fix_padding = true;
3534
3535
0
  if (!_do_dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
3536
0
      (dmi_flags & DM_INTEGRITY_FIX_HMAC_SUPPORTED) &&
3537
0
      !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_HMAC))
3538
0
    tgt->u.integrity.fix_hmac = true;
3539
3540
  /* This flag can be backported, just try to set it always */
3541
0
  if (crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_RECALC)
3542
0
    tgt->u.integrity.legacy_recalc = true;
3543
3544
0
  if (vk && !_do_dm_flags(cd, DM_INTEGRITY, &dmi_flags) &&
3545
0
      (dmi_flags & DM_INTEGRITY_DISCARD_KEYED_SUPPORTED) &&
3546
0
      !(crypt_get_compatibility(cd) & CRYPT_COMPAT_LEGACY_INTEGRITY_DISCARD))
3547
0
    tgt->u.integrity.discard_keyed = true;
3548
3549
0
  if (ip) {
3550
0
    tgt->u.integrity.journal_size = ip->journal_size;
3551
0
    tgt->u.integrity.journal_watermark = ip->journal_watermark;
3552
0
    tgt->u.integrity.journal_commit_time = ip->journal_commit_time;
3553
0
    tgt->u.integrity.interleave_sectors = ip->interleave_sectors;
3554
0
    tgt->u.integrity.buffer_sectors = ip->buffer_sectors;
3555
0
    tgt->u.integrity.journal_integrity = ip->journal_integrity;
3556
0
    tgt->u.integrity.journal_crypt = ip->journal_crypt;
3557
0
    tgt->u.integrity.integrity = ip->integrity;
3558
0
  }
3559
3560
0
  dm_exit_context();
3561
3562
0
  return 0;
3563
0
}
3564
3565
int dm_linear_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size,
3566
  struct device *data_device, uint64_t data_offset)
3567
0
{
3568
0
  if (!data_device)
3569
0
    return -EINVAL;
3570
3571
0
  tgt->type = DM_LINEAR;
3572
0
  tgt->direction = TARGET_SET;
3573
0
  tgt->offset = seg_offset;
3574
0
  tgt->size = seg_size;
3575
0
  tgt->data_device = data_device;
3576
3577
0
  tgt->u.linear.offset = data_offset;
3578
3579
0
  return 0;
3580
0
}
3581
3582
int dm_zero_target_set(struct dm_target *tgt, uint64_t seg_offset, uint64_t seg_size)
3583
0
{
3584
0
  tgt->type = DM_ZERO;
3585
0
  tgt->direction = TARGET_SET;
3586
0
  tgt->offset = seg_offset;
3587
0
  tgt->size = seg_size;
3588
3589
0
  return 0;
3590
0
}