Coverage Report

Created: 2025-06-13 06:36

/src/cryptsetup/lib/utils_blkid.c
Line
Count
Source (jump to first uncovered line)
1
// SPDX-License-Identifier: GPL-2.0-or-later
2
/*
3
 * blkid probe utilities
4
 *
5
 * Copyright (C) 2018-2025 Red Hat, Inc. All rights reserved.
6
 */
7
8
#include <errno.h>
9
#include <stdbool.h>
10
#include <stdio.h>
11
#include <stdlib.h>
12
#include <string.h>
13
#include <unistd.h>
14
15
#include "utils_blkid.h"
16
#include "utils_io.h"
17
18
#if HAVE_BLKID
19
20
#include <blkid/blkid.h>
21
/* make bad checksums flag optional */
22
#ifndef BLKID_SUBLKS_BADCSUM
23
#define BLKID_SUBLKS_BADCSUM 0
24
#endif
25
struct blkid_handle {
26
  int fd;
27
  blkid_probe pr;
28
};
29
#if !HAVE_BLKID_WIPE
30
static size_t crypt_getpagesize(void)
31
{
32
  long r = sysconf(_SC_PAGESIZE);
33
  return r <= 0 ? 4096 : (size_t)r;
34
}
35
#endif
36
37
void blk_set_chains_for_wipes(struct blkid_handle *h)
38
0
{
39
0
  blkid_probe_enable_partitions(h->pr, 1);
40
0
  blkid_probe_set_partitions_flags(h->pr, 0
41
0
#if HAVE_BLKID_WIPE
42
0
  | BLKID_PARTS_MAGIC
43
0
#endif
44
0
  );
45
46
0
  blkid_probe_enable_superblocks(h->pr, 1);
47
0
  blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_LABEL   |
48
0
             BLKID_SUBLKS_UUID    |
49
0
             BLKID_SUBLKS_TYPE    |
50
0
             BLKID_SUBLKS_USAGE   |
51
0
             BLKID_SUBLKS_VERSION |
52
0
             BLKID_SUBLKS_MAGIC   |
53
0
             BLKID_SUBLKS_BADCSUM);
54
0
}
55
56
void blk_set_chains_for_full_print(struct blkid_handle *h)
57
0
{
58
0
  blk_set_chains_for_wipes(h);
59
0
}
60
61
void blk_set_chains_for_superblocks(struct blkid_handle *h)
62
6.61k
{
63
6.61k
  blkid_probe_enable_superblocks(h->pr, 1);
64
6.61k
  blkid_probe_set_superblocks_flags(h->pr, BLKID_SUBLKS_TYPE);
65
6.61k
}
66
67
void blk_set_chains_for_fast_detection(struct blkid_handle *h)
68
6.61k
{
69
6.61k
  blkid_probe_enable_partitions(h->pr, 1);
70
6.61k
  blkid_probe_set_partitions_flags(h->pr, 0);
71
6.61k
  blk_set_chains_for_superblocks(h);
72
6.61k
}
73
74
int blk_init_by_path(struct blkid_handle **h, const char *path)
75
6.61k
{
76
6.61k
  struct blkid_handle *tmp = malloc(sizeof(*tmp));
77
6.61k
  if (!tmp)
78
0
    return -ENOMEM;
79
80
6.61k
  tmp->fd = -1;
81
82
6.61k
  tmp->pr = blkid_new_probe_from_filename(path);
83
6.61k
  if (!tmp->pr) {
84
0
    free(tmp);
85
0
    return -EINVAL;
86
0
  }
87
88
6.61k
  *h = tmp;
89
6.61k
  return 0;
90
6.61k
}
91
92
int blk_init_by_fd(struct blkid_handle **h, int fd)
93
0
{
94
0
  struct blkid_handle *tmp = malloc(sizeof(*tmp));
95
0
  if (!tmp)
96
0
    return -ENOMEM;
97
98
0
  tmp->pr = blkid_new_probe();
99
0
  if (!tmp->pr) {
100
0
    free(tmp);
101
0
    return -EINVAL;
102
0
  }
103
104
0
  if (blkid_probe_set_device(tmp->pr, fd, 0, 0)) {
105
0
    blkid_free_probe(tmp->pr);
106
0
    free(tmp);
107
0
    return -EINVAL;
108
0
  }
109
110
0
  tmp->fd = fd;
111
112
0
  *h = tmp;
113
0
  return 0;
114
0
}
115
116
static int blk_superblocks_luks(struct blkid_handle *h, bool enable)
117
6.61k
{
118
6.61k
  char luks[] = "crypto_LUKS";
119
6.61k
  char *luks_filter[] = {
120
6.61k
    luks,
121
6.61k
    NULL
122
6.61k
  };
123
6.61k
  return blkid_probe_filter_superblocks_type(h->pr,
124
6.61k
      enable ? BLKID_FLTR_ONLYIN : BLKID_FLTR_NOTIN,
125
6.61k
      luks_filter);
126
6.61k
}
127
128
int blk_superblocks_filter_luks(struct blkid_handle *h)
129
6.61k
{
130
6.61k
  return blk_superblocks_luks(h, false);
131
6.61k
}
132
133
int blk_superblocks_only_luks(struct blkid_handle *h)
134
0
{
135
0
  return blk_superblocks_luks(h, true);
136
0
}
137
138
blk_probe_status blk_probe(struct blkid_handle *h)
139
0
{
140
0
  blk_probe_status pr = PRB_FAIL;
141
142
0
  int r = blkid_do_probe(h->pr);
143
144
0
  if (r == 0)
145
0
    pr = PRB_OK;
146
0
  else if (r == 1)
147
0
    pr = PRB_EMPTY;
148
149
0
  return pr;
150
0
}
151
152
blk_probe_status blk_safeprobe(struct blkid_handle *h)
153
6.61k
{
154
6.61k
  switch (blkid_do_safeprobe(h->pr)) {
155
0
  case -2:
156
0
    return PRB_AMBIGUOUS;
157
4.59k
  case 1:
158
4.59k
    return PRB_EMPTY;
159
1.37k
  case 0:
160
1.37k
    return PRB_OK;
161
646
  default:
162
646
    return PRB_FAIL;
163
6.61k
  }
164
6.61k
}
165
166
int blk_is_partition(struct blkid_handle *h)
167
1.37k
{
168
1.37k
  return blkid_probe_has_value(h->pr, "PTTYPE");
169
1.37k
}
170
171
int blk_is_superblock(struct blkid_handle *h)
172
1.14k
{
173
1.14k
  return blkid_probe_has_value(h->pr, "TYPE");
174
1.14k
}
175
176
const char *blk_get_partition_type(struct blkid_handle *h)
177
229
{
178
229
  const char *value = NULL;
179
229
  (void) blkid_probe_lookup_value(h->pr, "PTTYPE", &value, NULL);
180
229
  return value;
181
229
}
182
183
const char *blk_get_superblock_type(struct blkid_handle *h)
184
1.14k
{
185
1.14k
  const char *value = NULL;
186
1.14k
  (void) blkid_probe_lookup_value(h->pr, "TYPE", &value, NULL);
187
1.14k
  return value;
188
1.14k
}
189
190
void blk_free(struct blkid_handle *h)
191
6.61k
{
192
6.61k
  if (!h)
193
0
    return;
194
195
6.61k
  if (h->pr)
196
6.61k
    blkid_free_probe(h->pr);
197
198
6.61k
  free(h);
199
6.61k
}
200
201
#if !HAVE_BLKID_WIPE
202
static int blk_step_back(struct blkid_handle *h)
203
{
204
#if HAVE_BLKID_STEP_BACK
205
  return blkid_probe_step_back(h->pr);
206
#else
207
  blkid_reset_probe(h->pr);
208
  blkid_probe_set_device(h->pr, h->fd, 0, 0);
209
  return 0;
210
#endif
211
}
212
#endif /* not HAVE_BLKID_WIPE */
213
214
int blk_do_wipe(struct blkid_handle *h)
215
0
{
216
0
#if HAVE_BLKID_WIPE
217
0
  return blkid_do_wipe(h->pr, 0);
218
#else
219
  const char *offset;
220
  off_t offset_val;
221
  void *buf;
222
  ssize_t ret;
223
  size_t alignment, len, bsize = blkid_probe_get_sectorsize(h->pr);
224
225
  if (h->fd < 0 || !bsize)
226
    return -EINVAL;
227
228
  if (blk_is_partition(h)) {
229
    if (blkid_probe_lookup_value(h->pr, "PTMAGIC_OFFSET", &offset, NULL))
230
      return -EINVAL;
231
    if (blkid_probe_lookup_value(h->pr, "PTMAGIC", NULL, &len))
232
      return -EINVAL;
233
  } else if (blk_is_superblock(h)) {
234
    if (blkid_probe_lookup_value(h->pr, "SBMAGIC_OFFSET", &offset, NULL))
235
      return -EINVAL;
236
    if (blkid_probe_lookup_value(h->pr, "SBMAGIC", NULL, &len))
237
      return -EINVAL;
238
  } else
239
    return 0;
240
241
  alignment = crypt_getpagesize();
242
243
  if (posix_memalign(&buf, alignment, len))
244
    return -EINVAL;
245
  memset(buf, 0, len);
246
247
  offset_val = strtoll(offset, NULL, 10);
248
249
  /* TODO: missing crypt_wipe_fd() */
250
  ret = write_lseek_blockwise(h->fd, bsize, alignment, buf, len, offset_val);
251
  free(buf);
252
  if (ret < 0)
253
    return -EIO;
254
255
  if ((size_t)ret == len) {
256
    blk_step_back(h);
257
    return 0;
258
  }
259
260
  return -EIO;
261
#endif
262
0
}
263
264
int blk_supported(void)
265
6.61k
{
266
6.61k
  return 1;
267
6.61k
}
268
269
unsigned blk_get_block_size(struct blkid_handle *h)
270
0
{
271
0
  unsigned block_size = 0;
272
0
  const char *data;
273
0
  if (!blk_is_superblock(h) || !blkid_probe_has_value(h->pr, "BLOCK_SIZE") ||
274
0
      blkid_probe_lookup_value(h->pr, "BLOCK_SIZE", &data, NULL) ||
275
0
      sscanf(data, "%u", &block_size) != 1)
276
0
    block_size = 0;
277
278
0
  return block_size;
279
0
}
280
281
#else /* HAVE_BLKID */
282
#pragma GCC diagnostic ignored "-Wunused-parameter"
283
284
void blk_set_chains_for_wipes(struct blkid_handle *h)
285
{
286
}
287
288
void blk_set_chains_for_full_print(struct blkid_handle *h)
289
{
290
}
291
292
void blk_set_chains_for_superblocks(struct blkid_handle *h)
293
{
294
}
295
296
void blk_set_chains_for_fast_detection(struct blkid_handle *h)
297
{
298
}
299
300
int blk_init_by_path(struct blkid_handle **h, const char *path)
301
{
302
  return -ENOTSUP;
303
}
304
305
int blk_init_by_fd(struct blkid_handle **h, int fd)
306
{
307
  return -ENOTSUP;
308
}
309
310
int blk_superblocks_filter_luks(struct blkid_handle *h)
311
{
312
  return -ENOTSUP;
313
}
314
315
int blk_superblocks_only_luks(struct blkid_handle *h)
316
{
317
  return -ENOTSUP;
318
}
319
320
blk_probe_status blk_probe(struct blkid_handle *h)
321
{
322
  return PRB_FAIL;
323
}
324
325
blk_probe_status blk_safeprobe(struct blkid_handle *h)
326
{
327
  return PRB_FAIL;
328
}
329
330
int blk_is_partition(struct blkid_handle *h)
331
{
332
  return 0;
333
}
334
335
int blk_is_superblock(struct blkid_handle *h)
336
{
337
  return 0;
338
}
339
340
const char *blk_get_partition_type(struct blkid_handle *h)
341
{
342
  return NULL;
343
}
344
345
const char *blk_get_superblock_type(struct blkid_handle *h)
346
{
347
  return NULL;
348
}
349
350
void blk_free(struct blkid_handle *h)
351
{
352
}
353
354
int blk_do_wipe(struct blkid_handle *h)
355
{
356
  return -ENOTSUP;
357
}
358
359
int blk_supported(void)
360
{
361
  return 0;
362
}
363
364
unsigned blk_get_block_size(struct blkid_handle *h)
365
{
366
  return 0;
367
}
368
#endif