• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

systemd / systemd / 26546993077

27 May 2026 08:34PM UTC coverage: 72.995% (+0.3%) from 72.667%
26546993077

push

github

bluca
test-pressure: set timeout to make not wait forever

If this runs on a slow or busy machine, then we may not get enough
pressure to trigger the event sources. In such case, the test does not
finish. It is problematic when the test is _not_ run with 'meson test',
e.g. debian/ubuntu CIs.

Let's introduce a timeout for each event loop, and skip test cases
gracefully.

8 of 12 new or added lines in 1 file covered. (66.67%)

19671 existing lines in 226 files now uncovered.

337119 of 461841 relevant lines covered (72.99%)

1326365.62 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

83.19
/src/shared/cryptsetup-util.c
1
/* SPDX-License-Identifier: LGPL-2.1-or-later */
2

3
#include <stdlib.h>
4

5
#include "sd-dlopen.h"
6
#include "sd-json.h"
7

8
#include "alloc-util.h"
9
#include "cryptsetup-util.h"
10
#include "dlfcn-util.h"
11
#include "escape.h"
12
#include "hexdecoct.h"
13
#include "hmac.h"
14
#include "log.h"
15
#include "parse-util.h"
16
#include "string-util.h"
17
#include "strv.h"
18

19
#if HAVE_LIBCRYPTSETUP
20
DLSYM_PROTOTYPE(crypt_activate_by_passphrase) = NULL;
21
DLSYM_PROTOTYPE(crypt_activate_by_signed_key) = NULL;
22
DLSYM_PROTOTYPE(crypt_activate_by_token_pin) = NULL;
23
DLSYM_PROTOTYPE(crypt_activate_by_volume_key) = NULL;
24
DLSYM_PROTOTYPE(crypt_deactivate) = NULL;
25
DLSYM_PROTOTYPE(crypt_deactivate_by_name) = NULL;
26
DLSYM_PROTOTYPE(crypt_format) = NULL;
27
DLSYM_PROTOTYPE(crypt_free) = NULL;
28
DLSYM_PROTOTYPE(crypt_get_cipher) = NULL;
29
DLSYM_PROTOTYPE(crypt_get_cipher_mode) = NULL;
30
DLSYM_PROTOTYPE(crypt_get_data_offset) = NULL;
31
DLSYM_PROTOTYPE(crypt_get_device_name) = NULL;
32
DLSYM_PROTOTYPE(crypt_get_dir) = NULL;
33
DLSYM_PROTOTYPE(crypt_get_type) = NULL;
34
DLSYM_PROTOTYPE(crypt_get_uuid) = NULL;
35
DLSYM_PROTOTYPE(crypt_get_verity_info) = NULL;
36
DLSYM_PROTOTYPE(crypt_get_volume_key_size) = NULL;
37
DLSYM_PROTOTYPE(crypt_header_restore) = NULL;
38
DLSYM_PROTOTYPE(crypt_init) = NULL;
39
DLSYM_PROTOTYPE(crypt_init_by_name) = NULL;
40
DLSYM_PROTOTYPE(crypt_init_data_device) = NULL;
41
DLSYM_PROTOTYPE(crypt_keyslot_add_by_volume_key) = NULL;
42
DLSYM_PROTOTYPE(crypt_keyslot_destroy) = NULL;
43
DLSYM_PROTOTYPE(crypt_keyslot_max) = NULL;
44
DLSYM_PROTOTYPE(crypt_keyslot_status) = NULL;
45
DLSYM_PROTOTYPE(crypt_load) = NULL;
46
DLSYM_PROTOTYPE(crypt_logf) = NULL;
47
DLSYM_PROTOTYPE(crypt_metadata_locking) = NULL;
48
DLSYM_PROTOTYPE(crypt_persistent_flags_get) = NULL;
49
DLSYM_PROTOTYPE(crypt_persistent_flags_set) = NULL;
50
DLSYM_PROTOTYPE(crypt_reencrypt_init_by_passphrase) = NULL;
51
DLSYM_PROTOTYPE(crypt_reencrypt_run);
52
DLSYM_PROTOTYPE(crypt_resize) = NULL;
53
DLSYM_PROTOTYPE(crypt_resume_by_volume_key) = NULL;
54
DLSYM_PROTOTYPE(crypt_set_data_device) = NULL;
55
DLSYM_PROTOTYPE(crypt_set_data_offset) = NULL;
56
DLSYM_PROTOTYPE(crypt_set_debug_level) = NULL;
UNCOV
57
static int missing_crypt_set_keyring_to_link(
×
58
                struct crypt_device *cd,
59
                const char *key_description,
60
                const char *old_key_description,
61
                const char *key_type_desc,
62
                const char *keyring_to_link_vk) {
UNCOV
63
        return -ENOSYS;
×
64
}
65
DLSYM_PROTOTYPE(crypt_set_keyring_to_link) = missing_crypt_set_keyring_to_link;
66
DLSYM_PROTOTYPE(crypt_set_log_callback) = NULL;
67
DLSYM_PROTOTYPE(crypt_set_metadata_size) = NULL;
68
DLSYM_PROTOTYPE(crypt_set_pbkdf_type) = NULL;
69
DLSYM_PROTOTYPE(crypt_status) = NULL;
70
DLSYM_PROTOTYPE(crypt_suspend) = NULL;
71
DLSYM_PROTOTYPE(crypt_token_external_path) = NULL;
72
DLSYM_PROTOTYPE(crypt_token_json_get) = NULL;
73
DLSYM_PROTOTYPE(crypt_token_json_set) = NULL;
74
DLSYM_PROTOTYPE(crypt_token_max) = NULL;
UNCOV
75
static int missing_crypt_token_set_external_path(const char *path) {
×
76
        return -ENOSYS;
×
77
}
78
DLSYM_PROTOTYPE(crypt_token_set_external_path) = missing_crypt_token_set_external_path;
79
DLSYM_PROTOTYPE(crypt_token_status) = NULL;
80
DLSYM_PROTOTYPE(crypt_volume_key_get) = NULL;
81
DLSYM_PROTOTYPE(crypt_volume_key_keyring) = NULL;
82
DLSYM_PROTOTYPE(crypt_wipe) = NULL;
83
DLSYM_PROTOTYPE(crypt_get_integrity_info) = NULL;
84

85
static void cryptsetup_log_glue(int level, const char *msg, void *usrptr) {
36,245✔
86

87
        switch (level) {
36,245✔
88
        case CRYPT_LOG_NORMAL:
89
                level = LOG_NOTICE;
90
                break;
91
        case CRYPT_LOG_ERROR:
44✔
92
                level = LOG_ERR;
44✔
93
                break;
44✔
94
        case CRYPT_LOG_VERBOSE:
4✔
95
                level = LOG_INFO;
4✔
96
                break;
4✔
97
        case CRYPT_LOG_DEBUG:
36,197✔
98
                level = LOG_DEBUG;
36,197✔
99
                break;
36,197✔
100
        default:
UNCOV
101
                log_error("Unknown libcryptsetup log level: %d", level);
×
102
                level = LOG_ERR;
103
        }
104

105
        log_full(level, "%s", msg);
36,245✔
106
}
36,245✔
107

108
void cryptsetup_enable_logging(struct crypt_device *cd) {
13,298✔
109
        /* It's OK to call this with a NULL parameter, in which case libcryptsetup will set the default log
110
         * function.
111
         *
112
         * Note that this is also called from dlopen_cryptsetup(), which we call here too. Sounds like an
113
         * endless loop, but isn't because we break it via the check for 'cryptsetup_dl' early in
114
         * dlopen_cryptsetup(). */
115

116
        if (dlopen_cryptsetup(LOG_DEBUG) < 0)
13,298✔
117
                return; /* If this fails, let's gracefully ignore the issue, this is just debug logging after
118
                         * all, and if this failed we already generated a debug log message that should help
119
                         * to track things down. */
120

121
        sym_crypt_set_log_callback(cd, cryptsetup_log_glue, NULL);
13,298✔
122
        sym_crypt_set_debug_level(DEBUG_LOGGING ? CRYPT_DEBUG_ALL : CRYPT_DEBUG_NONE);
13,367✔
123
}
124

125
int cryptsetup_set_minimal_pbkdf(struct crypt_device *cd) {
47✔
126

127
        /* With CRYPT_PBKDF_NO_BENCHMARK flag set .time_ms member is ignored
128
         * while .iterations must be set at least to recommended minimum value. */
129

130
        static const struct crypt_pbkdf_type minimal_pbkdf = {
47✔
131
                .hash = "sha512",
132
                .type = CRYPT_KDF_PBKDF2,
133
                .iterations = 1000, /* recommended minimum count for pbkdf2
134
                                     * according to NIST SP 800-132, ch. 5.2 */
135
                .flags = CRYPT_PBKDF_NO_BENCHMARK
136
        };
137

138
        int r;
47✔
139

140
        /* Sets a minimal PKBDF in case we already have a high entropy key. */
141

142
        r = sym_crypt_set_pbkdf_type(cd, &minimal_pbkdf);
47✔
143
        if (r < 0)
47✔
UNCOV
144
                return r;
×
145

146
        return 0;
147
}
148

149
int cryptsetup_get_token_as_json(
5,717✔
150
                struct crypt_device *cd,
151
                int idx,
152
                const char *verify_type,
153
                sd_json_variant **ret) {
154

155
        _cleanup_(sd_json_variant_unrefp) sd_json_variant *v = NULL;
5,717✔
156
        const char *text;
5,717✔
157
        int r;
5,717✔
158

159
        assert(cd);
5,717✔
160

161
        /* Extracts and parses the LUKS2 JSON token data from a LUKS2 device. Optionally verifies the type of
162
         * the token. Returns:
163
         *
164
         *      -EINVAL → token index out of range or "type" field missing
165
         *      -ENOENT → token doesn't exist
166
         * -EMEDIUMTYPE → "verify_type" specified and doesn't match token's type
167
         */
168

169
        r = sym_crypt_token_json_get(cd, idx, &text);
5,717✔
170
        if (r < 0)
5,717✔
171
                return r;
172

173
        r = sd_json_parse(text, 0, &v, NULL, NULL);
404✔
174
        if (r < 0)
404✔
175
                return r;
176

177
        if (verify_type) {
404✔
178
                sd_json_variant *w;
240✔
179

180
                w = sd_json_variant_by_key(v, "type");
240✔
181
                if (!w)
240✔
182
                        return -EINVAL;
183

184
                if (!streq_ptr(sd_json_variant_string(w), verify_type))
240✔
185
                        return -EMEDIUMTYPE;
186
        }
187

188
        if (ret)
180✔
189
                *ret = TAKE_PTR(v);
180✔
190

191
        return 0;
192
}
193

194
int cryptsetup_add_token_json(struct crypt_device *cd, sd_json_variant *v) {
47✔
195
        _cleanup_free_ char *text = NULL;
47✔
196
        int r;
47✔
197

198
        r = sd_json_variant_format(v, 0, &text);
47✔
199
        if (r < 0)
47✔
UNCOV
200
                return log_debug_errno(r, "Failed to format token data for LUKS: %m");
×
201

202
        log_debug("Adding token text <%s>", text);
47✔
203

204
        r = sym_crypt_token_json_set(cd, CRYPT_ANY_TOKEN, text);
47✔
205
        if (r < 0)
47✔
UNCOV
206
                return log_debug_errno(r, "Failed to write token data to LUKS: %m");
×
207

208
        return 0;
209
}
210

211
int cryptsetup_get_volume_key_prefix(
7✔
212
                struct crypt_device *cd,
213
                const char *volume_name,
214
                char **ret) {
215

216
        _cleanup_free_ char *volume = NULL;
7✔
217
        const char *uuid;
7✔
218
        char *s;
7✔
219

220
        assert(ret);
7✔
221

222
        uuid = sym_crypt_get_uuid(cd);
7✔
223
        if (!uuid)
7✔
UNCOV
224
                return log_debug_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to get LUKS UUID.");
×
225

226
        if (volume_name)
7✔
227
                /* avoid ambiguity around ":" once we join things below */
228
                volume = xescape(volume_name, ":");
7✔
229
        else
UNCOV
230
                volume = strjoin("luks-", uuid);
×
231
        if (!volume)
7✔
UNCOV
232
                return log_oom_debug();
×
233

234
        s = strjoin("cryptsetup:", volume, ":", uuid);
7✔
235
        if (!s)
7✔
UNCOV
236
                return log_oom_debug();
×
237

238
        *ret = s;
7✔
239

240
        return 0;
7✔
241
}
242

243
/* The hash must match what measure_volume_key() extends to the SHA256 bank of the TPM2. */
244
int cryptsetup_get_volume_key_id(
7✔
245
                struct crypt_device *cd,
246
                const char *volume_name,
247
                const void *volume_key,
248
                size_t volume_key_size,
249
                char **ret) {
250

251
        _cleanup_free_ char *prefix = NULL;
7✔
252
        uint8_t digest[SHA256_DIGEST_SIZE];
7✔
253
        char *hex;
7✔
254
        int r;
7✔
255

256
        assert(ret);
7✔
257

258
        r = cryptsetup_get_volume_key_prefix(cd, volume_name, &prefix);
7✔
259
        if (r < 0)
7✔
UNCOV
260
                return log_debug_errno(r, "Failed to get LUKS volume key prefix.");
×
261

262
        hmac_sha256(volume_key, volume_key_size, prefix, strlen(prefix), digest);
7✔
263

264
        hex = hexmem(digest, sizeof(digest));
7✔
265
        if (!hex)
7✔
UNCOV
266
                return log_oom_debug();
×
267

268
        *ret = hex;
7✔
269

270
        return 0;
7✔
271
}
272
#endif
273

274
int dlopen_cryptsetup(int log_level) {
28,619✔
275
#if HAVE_LIBCRYPTSETUP
276
        static void *cryptsetup_dl = NULL;
28,619✔
277
        int r;
28,619✔
278

279
        /* libcryptsetup added crypt_reencrypt() in 2.2.0, and marked it obsolete in 2.4.0, replacing it with
280
         * crypt_reencrypt_run(), which takes one extra argument but is otherwise identical. The old call is
281
         * still available though, and given we want to support 2.2.0 for a while longer, we'll use the old
282
         * symbol if the new one is not available. */
283

284
        SD_ELF_NOTE_DLOPEN(
28,619✔
285
                        "cryptsetup",
286
                        "Support for disk encryption, integrity, and authentication",
287
                        SD_ELF_NOTE_DLOPEN_PRIORITY_SUGGESTED,
288
                        "libcryptsetup.so.12");
289

290
        r = dlopen_many_sym_or_warn(
28,619✔
291
                        &cryptsetup_dl, "libcryptsetup.so.12", log_level,
292
                        DLSYM_ARG(crypt_activate_by_passphrase),
293
                        DLSYM_ARG(crypt_activate_by_signed_key),
294
                        DLSYM_ARG(crypt_activate_by_token_pin),
295
                        DLSYM_ARG(crypt_activate_by_volume_key),
296
                        DLSYM_ARG(crypt_deactivate),
297
                        DLSYM_ARG(crypt_deactivate_by_name),
298
                        DLSYM_ARG(crypt_format),
299
                        DLSYM_ARG(crypt_free),
300
                        DLSYM_ARG(crypt_get_cipher),
301
                        DLSYM_ARG(crypt_get_cipher_mode),
302
                        DLSYM_ARG(crypt_get_data_offset),
303
                        DLSYM_ARG(crypt_get_device_name),
304
                        DLSYM_ARG(crypt_get_dir),
305
                        DLSYM_ARG(crypt_get_type),
306
                        DLSYM_ARG(crypt_get_uuid),
307
                        DLSYM_ARG(crypt_get_verity_info),
308
                        DLSYM_ARG(crypt_get_volume_key_size),
309
                        DLSYM_ARG(crypt_header_restore),
310
                        DLSYM_ARG(crypt_init),
311
                        DLSYM_ARG(crypt_init_by_name),
312
                        DLSYM_ARG(crypt_init_data_device),
313
                        DLSYM_ARG(crypt_keyslot_add_by_volume_key),
314
                        DLSYM_ARG(crypt_keyslot_destroy),
315
                        DLSYM_ARG(crypt_keyslot_max),
316
                        DLSYM_ARG(crypt_keyslot_status),
317
                        DLSYM_ARG(crypt_load),
318
                        DLSYM_ARG(crypt_logf),
319
                        DLSYM_ARG(crypt_metadata_locking),
320
                        DLSYM_ARG(crypt_persistent_flags_get),
321
                        DLSYM_ARG(crypt_persistent_flags_set),
322
                        DLSYM_ARG(crypt_reencrypt_init_by_passphrase),
323
                        DLSYM_ARG(crypt_reencrypt_run),
324
                        DLSYM_ARG(crypt_resize),
325
                        DLSYM_ARG(crypt_resume_by_volume_key),
326
                        DLSYM_ARG(crypt_set_data_device),
327
                        DLSYM_ARG(crypt_set_data_offset),
328
                        DLSYM_ARG(crypt_set_debug_level),
329
                        DLSYM_ARG(crypt_set_log_callback),
330
                        DLSYM_ARG(crypt_set_metadata_size),
331
                        DLSYM_ARG(crypt_set_pbkdf_type),
332
                        DLSYM_ARG(crypt_status),
333
                        DLSYM_ARG(crypt_suspend),
334
                        DLSYM_ARG(crypt_token_external_path),
335
                        DLSYM_ARG(crypt_token_json_get),
336
                        DLSYM_ARG(crypt_token_json_set),
337
                        DLSYM_ARG(crypt_token_max),
338
                        DLSYM_ARG(crypt_token_status),
339
                        DLSYM_ARG(crypt_volume_key_get),
340
                        DLSYM_ARG(crypt_volume_key_keyring),
341
                        DLSYM_ARG(crypt_wipe),
342
                        DLSYM_ARG(crypt_get_integrity_info));
343
        if (r <= 0)
28,619✔
344
                return r;
345

346
        /* Optional symbols: present in libcryptsetup 2.7+ only. If unresolved, the prototype keeps its
347
         * static initializer pointing at a fallback that returns -ENOSYS, so call sites can invoke the
348
         * symbol unconditionally. */
349
        DLSYM_OPTIONAL(cryptsetup_dl, crypt_set_keyring_to_link);
12,905✔
350
        DLSYM_OPTIONAL(cryptsetup_dl, crypt_token_set_external_path);
12,905✔
351

352
        /* Redirect the default logging calls of libcryptsetup to our own logging infra. (Note that
353
         * libcryptsetup also maintains per-"struct crypt_device" log functions, which we'll also set
354
         * whenever allocating a "struct crypt_device" context. Why set both? To be defensive: maybe some
355
         * other code loaded into this process also changes the global log functions of libcryptsetup, who
356
         * knows? And if so, we still want our own objects to log via our own infra, at the very least.) */
357
        cryptsetup_enable_logging(NULL);
12,905✔
358

359
        const char *e = secure_getenv("SYSTEMD_CRYPTSETUP_TOKEN_PATH");
12,905✔
360
        if (e) {
12,905✔
361
                r = sym_crypt_token_set_external_path(e);
×
362
                if (r == -ENOSYS)
×
363
                        log_debug("Loaded libcryptsetup does not support setting the external token path, not setting it to '%s'.", e);
×
364
                else if (r < 0)
×
UNCOV
365
                        log_debug_errno(r, "Failed to set the libcryptsetup external token path to '%s', ignoring: %m", e);
×
366
        }
367

368
        return 1;
369
#else
370
        return log_full_errno(log_level, SYNTHETIC_ERRNO(EOPNOTSUPP),
371
                              "libcryptsetup support is not compiled in.");
372
#endif
373
}
374

375
int cryptsetup_get_keyslot_from_token(sd_json_variant *v) {
16✔
376
        int keyslot, r;
16✔
377
        sd_json_variant *w;
16✔
378

379
        /* Parses the "keyslots" field of a LUKS2 token object. The field can be an array, but here we assume
380
         * that it contains a single element only, since that's the only way we ever generate it
381
         * ourselves. */
382

383
        w = sd_json_variant_by_key(v, "keyslots");
16✔
384
        if (!w)
16✔
385
                return -ENOENT;
16✔
386
        if (!sd_json_variant_is_array(w) || sd_json_variant_elements(w) != 1)
16✔
387
                return -EMEDIUMTYPE;
388

389
        w = sd_json_variant_by_index(w, 0);
16✔
390
        if (!w)
16✔
391
                return -ENOENT;
392
        if (!sd_json_variant_is_string(w))
16✔
393
                return -EMEDIUMTYPE;
394

395
        r = safe_atoi(sd_json_variant_string(w), &keyslot);
16✔
396
        if (r < 0)
16✔
397
                return r;
398
        if (keyslot < 0)
16✔
UNCOV
399
                return -EINVAL;
×
400

401
        return keyslot;
402
}
403

404
const char* mangle_none(const char *s) {
210✔
405
        /* A helper that turns cryptsetup/integritysetup/veritysetup "options" strings into NULL if they are effectively empty */
406
        return isempty(s) || STR_IN_SET(s, "-", "none") ? NULL : s;
420✔
407
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc