Coverage Report

Created: 2026-09-13 06:12

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