Coverage Report

Created: 2024-02-25 07:20

/src/libvslvm/libvslvm/libvslvm_metadata_area.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * The metadata area functions
3
 *
4
 * Copyright (C) 2014-2023, Joachim Metz <joachim.metz@gmail.com>
5
 *
6
 * Refer to AUTHORS for acknowledgements.
7
 *
8
 * This program is free software: you can redistribute it and/or modify
9
 * it under the terms of the GNU Lesser General Public License as published by
10
 * the Free Software Foundation, either version 3 of the License, or
11
 * (at your option) any later version.
12
 *
13
 * This program is distributed in the hope that it will be useful,
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 * GNU General Public License for more details.
17
 *
18
 * You should have received a copy of the GNU Lesser General Public License
19
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
20
 */
21
22
#include <common.h>
23
#include <byte_stream.h>
24
#include <memory.h>
25
#include <types.h>
26
27
#include "libvslvm_checksum.h"
28
#include "libvslvm_definitions.h"
29
#include "libvslvm_libbfio.h"
30
#include "libvslvm_libcdata.h"
31
#include "libvslvm_libcerror.h"
32
#include "libvslvm_libcnotify.h"
33
#include "libvslvm_libcsplit.h"
34
#include "libvslvm_libfvalue.h"
35
#include "libvslvm_metadata.h"
36
#include "libvslvm_metadata_area.h"
37
#include "libvslvm_raw_location_descriptor.h"
38
39
#include "vslvm_metadata_area.h"
40
41
const char *vslvm_metadata_area_signature = "\x20LVM2\x20x[5A%r0N*>";
42
43
const uint8_t vslvm_empty_raw_location_descriptor[ 24 ] = {
44
  0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
45
  0, 0, 0, 0, 0, 0, 0, 0 };
46
47
/* Creates a metadata area
48
 * Make sure the value metadata_area is referencing, is set to NULL
49
 * Returns 1 if successful or -1 on error
50
 */
51
int libvslvm_metadata_area_initialize(
52
     libvslvm_metadata_area_t **metadata_area,
53
     libcerror_error_t **error )
54
5.92k
{
55
5.92k
  static char *function = "libvslvm_metadata_area_initialize";
56
57
5.92k
  if( metadata_area == NULL )
58
0
  {
59
0
    libcerror_error_set(
60
0
     error,
61
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
62
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
63
0
     "%s: invalid metadata area.",
64
0
     function );
65
66
0
    return( -1 );
67
0
  }
68
5.92k
  if( *metadata_area != NULL )
69
0
  {
70
0
    libcerror_error_set(
71
0
     error,
72
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
73
0
     LIBCERROR_RUNTIME_ERROR_VALUE_ALREADY_SET,
74
0
     "%s: invalid metadata area value already set.",
75
0
     function );
76
77
0
    return( -1 );
78
0
  }
79
5.92k
  *metadata_area = memory_allocate_structure(
80
5.92k
                    libvslvm_metadata_area_t );
81
82
5.92k
  if( *metadata_area == NULL )
83
0
  {
84
0
    libcerror_error_set(
85
0
     error,
86
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
87
0
     LIBCERROR_MEMORY_ERROR_INSUFFICIENT,
88
0
     "%s: unable to create metadata area.",
89
0
     function );
90
91
0
    goto on_error;
92
0
  }
93
5.92k
  if( memory_set(
94
5.92k
       *metadata_area,
95
5.92k
       0,
96
5.92k
       sizeof( libvslvm_metadata_area_t ) ) == NULL )
97
0
  {
98
0
    libcerror_error_set(
99
0
     error,
100
0
     LIBCERROR_ERROR_DOMAIN_MEMORY,
101
0
     LIBCERROR_MEMORY_ERROR_SET_FAILED,
102
0
     "%s: unable to clear metadata area.",
103
0
     function );
104
105
0
    memory_free(
106
0
     *metadata_area );
107
108
0
    *metadata_area = NULL;
109
110
0
    return( -1 );
111
0
  }
112
5.92k
  if( libcdata_array_initialize(
113
5.92k
       &( ( *metadata_area )->raw_location_descriptors_array ),
114
5.92k
       0,
115
5.92k
       error ) != 1 )
116
0
  {
117
0
    libcerror_error_set(
118
0
     error,
119
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
120
0
     LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
121
0
     "%s: unable to create raw location descriptors array.",
122
0
     function );
123
124
0
    goto on_error;
125
0
  }
126
5.92k
  return( 1 );
127
128
0
on_error:
129
0
  if( *metadata_area != NULL )
130
0
  {
131
0
    memory_free(
132
0
     *metadata_area );
133
134
0
    *metadata_area = NULL;
135
0
  }
136
0
  return( -1 );
137
5.92k
}
138
139
/* Frees a metadata area
140
 * Returns 1 if successful or -1 on error
141
 */
142
int libvslvm_metadata_area_free(
143
     libvslvm_metadata_area_t **metadata_area,
144
     libcerror_error_t **error )
145
5.92k
{
146
5.92k
  static char *function = "libvslvm_metadata_area_free";
147
5.92k
  int result            = 1;
148
149
5.92k
  if( metadata_area == NULL )
150
0
  {
151
0
    libcerror_error_set(
152
0
     error,
153
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
154
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
155
0
     "%s: invalid metadata area.",
156
0
     function );
157
158
0
    return( -1 );
159
0
  }
160
5.92k
  if( *metadata_area != NULL )
161
5.92k
  {
162
5.92k
    if( libcdata_array_free(
163
5.92k
         &( ( *metadata_area )->raw_location_descriptors_array ),
164
5.92k
         (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_raw_location_descriptor_free,
165
5.92k
         error ) != 1 )
166
0
    {
167
0
      libcerror_error_set(
168
0
       error,
169
0
       LIBCERROR_ERROR_DOMAIN_RUNTIME,
170
0
       LIBCERROR_RUNTIME_ERROR_FINALIZE_FAILED,
171
0
       "%s: unable to free raw location descriptors array.",
172
0
       function );
173
174
0
      result = -1;
175
0
    }
176
5.92k
    memory_free(
177
5.92k
     *metadata_area );
178
179
5.92k
    *metadata_area = NULL;
180
5.92k
  }
181
5.92k
  return( result );
182
5.92k
}
183
184
/* Reads the metadata area
185
 * Returns 1 if successful or -1 on error
186
 */
187
int libvslvm_metadata_area_read_data(
188
     libvslvm_metadata_area_t *metadata_area,
189
     const uint8_t *data,
190
     size_t data_size,
191
     off64_t file_offset,
192
     libcerror_error_t **error )
193
5.77k
{
194
5.77k
  libvslvm_raw_location_descriptor_t *raw_location_descriptor = NULL;
195
5.77k
  static char *function                                       = "libvslvm_metadata_area_read_data";
196
5.77k
  size_t data_offset                                          = 0;
197
5.77k
  uint64_t offset                                             = 0;
198
5.77k
  uint64_t size                                               = 0;
199
5.77k
  uint32_t calculated_checksum                                = 0;
200
5.77k
  uint32_t checksum                                           = 0;
201
5.77k
  uint32_t flags                                              = 0;
202
5.77k
  uint32_t stored_checksum                                    = 0;
203
5.77k
  int entry_index                                             = 0;
204
5.77k
  int raw_location_descriptor_index                           = 0;
205
5.77k
  int result                                                  = 0;
206
207
#if defined( HAVE_DEBUG_OUTPUT )
208
  uint64_t value_64bit                                        = 0;
209
  uint32_t value_32bit                                        = 0;
210
#endif
211
212
5.77k
  if( metadata_area == NULL )
213
0
  {
214
0
    libcerror_error_set(
215
0
     error,
216
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
217
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
218
0
     "%s: invalid metadata area.",
219
0
     function );
220
221
0
    return( -1 );
222
0
  }
223
5.77k
  if( data == NULL )
224
0
  {
225
0
    libcerror_error_set(
226
0
     error,
227
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
228
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
229
0
     "%s: invalid data.",
230
0
     function );
231
232
0
    return( -1 );
233
0
  }
234
5.77k
  if( data_size != 512 )
235
0
  {
236
0
    libcerror_error_set(
237
0
     error,
238
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
239
0
     LIBCERROR_ARGUMENT_ERROR_VALUE_OUT_OF_BOUNDS,
240
0
     "%s: invalid data size value out of bounds.",
241
0
     function );
242
243
0
    return( -1 );
244
0
  }
245
#if defined( HAVE_DEBUG_OUTPUT )
246
  if( libcnotify_verbose != 0 )
247
  {
248
    libcnotify_printf(
249
     "%s: metadata area header data:\n",
250
     function );
251
    libcnotify_print_data(
252
     data,
253
     sizeof( vslvm_metadata_area_header_t ),
254
     0 );
255
  }
256
#endif
257
5.77k
  if( memory_compare(
258
5.77k
       ( (vslvm_metadata_area_header_t *) data )->signature,
259
5.77k
       vslvm_metadata_area_signature,
260
5.77k
       8 ) != 0 )
261
33
  {
262
33
    libcerror_error_set(
263
33
     error,
264
33
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
265
33
     LIBCERROR_RUNTIME_ERROR_UNSUPPORTED_VALUE,
266
33
     "%s: unsupported metadata area signature.",
267
33
     function );
268
269
33
    goto on_error;
270
33
  }
271
5.74k
  byte_stream_copy_to_uint32_little_endian(
272
5.74k
   data,
273
5.74k
   stored_checksum );
274
275
#if defined( HAVE_DEBUG_OUTPUT )
276
  if( libcnotify_verbose != 0 )
277
  {
278
    libcnotify_printf(
279
     "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
280
     function,
281
     stored_checksum );
282
283
    libcnotify_printf(
284
     "%s: signature\t\t\t\t: %c%c%c%c%c%c%c%c%c%c%c%c%c%c%c%c\n",
285
     function,
286
     ( (vslvm_metadata_area_header_t *) data )->signature[ 0 ],
287
     ( (vslvm_metadata_area_header_t *) data )->signature[ 1 ],
288
     ( (vslvm_metadata_area_header_t *) data )->signature[ 2 ],
289
     ( (vslvm_metadata_area_header_t *) data )->signature[ 3 ],
290
     ( (vslvm_metadata_area_header_t *) data )->signature[ 4 ],
291
     ( (vslvm_metadata_area_header_t *) data )->signature[ 5 ],
292
     ( (vslvm_metadata_area_header_t *) data )->signature[ 6 ],
293
     ( (vslvm_metadata_area_header_t *) data )->signature[ 7 ],
294
     ( (vslvm_metadata_area_header_t *) data )->signature[ 8 ],
295
     ( (vslvm_metadata_area_header_t *) data )->signature[ 9 ],
296
     ( (vslvm_metadata_area_header_t *) data )->signature[ 10 ],
297
     ( (vslvm_metadata_area_header_t *) data )->signature[ 11 ],
298
     ( (vslvm_metadata_area_header_t *) data )->signature[ 12 ],
299
     ( (vslvm_metadata_area_header_t *) data )->signature[ 13 ],
300
     ( (vslvm_metadata_area_header_t *) data )->signature[ 14 ],
301
     ( (vslvm_metadata_area_header_t *) data )->signature[ 15 ] );
302
303
    byte_stream_copy_to_uint32_little_endian(
304
     ( (vslvm_metadata_area_header_t *) data )->version,
305
     value_32bit );
306
    libcnotify_printf(
307
     "%s: version\t\t\t\t: %" PRIu32 "\n",
308
     function,
309
     value_32bit );
310
311
    byte_stream_copy_to_uint64_little_endian(
312
     ( (vslvm_metadata_area_header_t *) data )->data_offset,
313
     value_64bit );
314
    libcnotify_printf(
315
     "%s: data offset\t\t\t\t: 0x%08" PRIx64 "\n",
316
     function,
317
     value_64bit );
318
319
    byte_stream_copy_to_uint64_little_endian(
320
     ( (vslvm_metadata_area_header_t *) data )->data_size,
321
     value_64bit );
322
    libcnotify_printf(
323
     "%s: data size\t\t\t\t: %" PRIu64 "\n",
324
     function,
325
     value_64bit );
326
327
    libcnotify_printf(
328
     "\n" );
329
  }
330
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
331
332
5.74k
  if( libvslvm_checksum_calculate_weak_crc32(
333
5.74k
       &calculated_checksum,
334
5.74k
       &( data[ 4 ] ),
335
5.74k
       data_size - 4,
336
5.74k
       0xf597a6cfUL,
337
5.74k
       error ) != 1 )
338
0
  {
339
0
    libcerror_error_set(
340
0
     error,
341
0
     LIBCERROR_ERROR_DOMAIN_RUNTIME,
342
0
     LIBCERROR_RUNTIME_ERROR_SET_FAILED,
343
0
     "%s: unable to calculate CRC-32.",
344
0
     function );
345
346
0
    goto on_error;
347
0
  }
348
5.74k
  if( ( stored_checksum != 0 )
349
5.74k
   && ( stored_checksum != calculated_checksum ) )
350
141
  {
351
141
    libcerror_error_set(
352
141
     error,
353
141
     LIBCERROR_ERROR_DOMAIN_INPUT,
354
141
     LIBCERROR_INPUT_ERROR_CHECKSUM_MISMATCH,
355
141
     "%s: mismatch in checksum ( 0x%08" PRIx32 " != 0x%08" PRIx32 " ).",
356
141
     function,
357
141
     stored_checksum,
358
141
     calculated_checksum );
359
360
141
    goto on_error;
361
141
  }
362
5.60k
  data_offset = sizeof( vslvm_metadata_area_header_t );
363
364
5.60k
  for( raw_location_descriptor_index = 0;
365
27.4k
       raw_location_descriptor_index < 4;
366
21.8k
       raw_location_descriptor_index++ )
367
22.1k
  {
368
#if defined( HAVE_DEBUG_OUTPUT )
369
    if( libcnotify_verbose != 0 )
370
    {
371
      libcnotify_printf(
372
       "%s: raw location descriptor: %d data:\n",
373
       function,
374
       raw_location_descriptor_index );
375
      libcnotify_print_data(
376
       &( data[ data_offset ] ),
377
       sizeof( vslvm_raw_location_descriptor_t ),
378
       0 );
379
    }
380
#endif
381
22.1k
    result = memory_compare(
382
22.1k
              &( data[ data_offset ] ),
383
22.1k
              vslvm_empty_raw_location_descriptor,
384
22.1k
              sizeof( vslvm_raw_location_descriptor_t ) );
385
386
22.1k
    if( result != 0 )
387
18.0k
    {
388
18.0k
      byte_stream_copy_to_uint64_little_endian(
389
18.0k
       ( (vslvm_raw_location_descriptor_t *) &( data[ data_offset ] ) )->offset,
390
18.0k
       offset );
391
392
18.0k
      byte_stream_copy_to_uint64_little_endian(
393
18.0k
       ( (vslvm_raw_location_descriptor_t *) &( data[ data_offset ] ) )->size,
394
18.0k
       size );
395
396
18.0k
      byte_stream_copy_to_uint32_little_endian(
397
18.0k
       ( (vslvm_raw_location_descriptor_t *) &( data[ data_offset ] ) )->checksum,
398
18.0k
       checksum );
399
400
18.0k
      byte_stream_copy_to_uint32_little_endian(
401
18.0k
       ( (vslvm_raw_location_descriptor_t *) &( data[ data_offset ] ) )->flags,
402
18.0k
       flags );
403
404
#if defined( HAVE_DEBUG_OUTPUT )
405
      if( libcnotify_verbose != 0 )
406
      {
407
        libcnotify_printf(
408
         "%s: offset\t\t\t\t: 0x%08" PRIx64 "\n",
409
         function,
410
         offset );
411
412
        libcnotify_printf(
413
         "%s: size\t\t\t\t\t: %" PRIu64 "\n",
414
         function,
415
         size );
416
417
        libcnotify_printf(
418
         "%s: checksum\t\t\t\t: 0x%08" PRIx32 "\n",
419
         function,
420
         checksum );
421
422
        libcnotify_printf(
423
         "%s: flags\t\t\t\t\t: 0x%08" PRIx32 "\n",
424
         function,
425
         flags );
426
427
        libcnotify_printf(
428
         "\n" );
429
      }
430
#endif /* defined( HAVE_DEBUG_OUTPUT ) */
431
432
18.0k
      if( ( flags & LIBVSLVM_RAW_LOCATION_DESCRIPTOR_FLAG_IGNORE ) == 0 )
433
5.82k
      {
434
5.82k
        if( libvslvm_raw_location_descriptor_initialize(
435
5.82k
             &raw_location_descriptor,
436
5.82k
             error ) != 1 )
437
0
        {
438
0
          libcerror_error_set(
439
0
           error,
440
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
441
0
           LIBCERROR_RUNTIME_ERROR_INITIALIZE_FAILED,
442
0
           "%s: unable to create raw location descriptor.",
443
0
           function );
444
445
0
          goto on_error;
446
0
        }
447
5.82k
        if( libvslvm_raw_location_descriptor_set(
448
5.82k
             raw_location_descriptor,
449
5.82k
             (off64_t) ( file_offset + offset ),
450
5.82k
             (size64_t) size,
451
5.82k
             checksum,
452
5.82k
             flags,
453
5.82k
             error ) != 1 )
454
242
        {
455
242
          libcerror_error_set(
456
242
           error,
457
242
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
458
242
           LIBCERROR_RUNTIME_ERROR_SET_FAILED,
459
242
           "%s: unable to set raw location descriptor.",
460
242
           function );
461
462
242
          goto on_error;
463
242
        }
464
5.58k
        if( libcdata_array_append_entry(
465
5.58k
             metadata_area->raw_location_descriptors_array,
466
5.58k
             &entry_index,
467
5.58k
             (intptr_t *) raw_location_descriptor,
468
5.58k
             error ) != 1 )
469
0
        {
470
0
          libcerror_error_set(
471
0
           error,
472
0
           LIBCERROR_ERROR_DOMAIN_RUNTIME,
473
0
           LIBCERROR_RUNTIME_ERROR_APPEND_FAILED,
474
0
           "%s: unable to append entry to raw location descriptors array.",
475
0
           function );
476
477
0
          goto on_error;
478
0
        }
479
5.58k
        raw_location_descriptor = NULL;
480
5.58k
      }
481
18.0k
    }
482
21.8k
    data_offset += sizeof( vslvm_raw_location_descriptor_t );
483
21.8k
  }
484
5.35k
  return( 1 );
485
486
416
on_error:
487
416
  if( raw_location_descriptor != NULL )
488
242
  {
489
242
    libvslvm_raw_location_descriptor_free(
490
242
     &raw_location_descriptor,
491
242
     NULL );
492
242
  }
493
416
  libcdata_array_empty(
494
416
   metadata_area->raw_location_descriptors_array,
495
416
   (int (*)(intptr_t **, libcerror_error_t **)) &libvslvm_raw_location_descriptor_free,
496
416
   NULL );
497
498
416
  return( -1 );
499
5.60k
}
500
501
/* Reads the metadata area
502
 * Returns 1 if successful or -1 on error
503
 */
504
int libvslvm_metadata_area_read_file_io_handle(
505
     libvslvm_metadata_area_t *metadata_area,
506
     libbfio_handle_t *file_io_handle,
507
     off64_t file_offset,
508
     libcerror_error_t **error )
509
5.92k
{
510
5.92k
  uint8_t metadata_area_header_data[ 512 ];
511
512
5.92k
  static char *function = "libvslvm_metadata_area_read_file_io_handle";
513
5.92k
  ssize_t read_count    = 0;
514
515
5.92k
  if( metadata_area == NULL )
516
0
  {
517
0
    libcerror_error_set(
518
0
     error,
519
0
     LIBCERROR_ERROR_DOMAIN_ARGUMENTS,
520
0
     LIBCERROR_ARGUMENT_ERROR_INVALID_VALUE,
521
0
     "%s: invalid metadata area.",
522
0
     function );
523
524
0
    return( -1 );
525
0
  }
526
#if defined( HAVE_DEBUG_OUTPUT )
527
  if( libcnotify_verbose != 0 )
528
  {
529
    libcnotify_printf(
530
     "%s: reading metadata area at offset: %" PRIi64 " (0x%08" PRIx64 ")\n",
531
     function,
532
     file_offset,
533
     file_offset );
534
  }
535
#endif
536
5.92k
  read_count = libbfio_handle_read_buffer_at_offset(
537
5.92k
                file_io_handle,
538
5.92k
                metadata_area_header_data,
539
5.92k
                512,
540
5.92k
                file_offset,
541
5.92k
                error );
542
543
5.92k
  if( read_count != (ssize_t) 512 )
544
149
  {
545
149
    libcerror_error_set(
546
149
     error,
547
149
     LIBCERROR_ERROR_DOMAIN_IO,
548
149
     LIBCERROR_IO_ERROR_READ_FAILED,
549
149
     "%s: unable to read metadata area header at offset: %" PRIi64 " (0x%08" PRIx64 ").",
550
149
     function,
551
149
     file_offset,
552
149
     file_offset );
553
554
149
    return( -1 );
555
149
  }
556
5.77k
  if( libvslvm_metadata_area_read_data(
557
5.77k
       metadata_area,
558
5.77k
       metadata_area_header_data,
559
5.77k
       512,
560
5.77k
       file_offset,
561
5.77k
       error ) != 1 )
562
416
  {
563
416
    libcerror_error_set(
564
416
     error,
565
416
     LIBCERROR_ERROR_DOMAIN_IO,
566
416
     LIBCERROR_IO_ERROR_READ_FAILED,
567
416
     "%s: unable to read metadata area header.",
568
416
     function );
569
570
416
    return( -1 );
571
416
  }
572
5.35k
  return( 1 );
573
5.77k
}
574