Coverage Report

Created: 2025-10-12 06:56

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