Coverage Report

Created: 2025-08-29 06:55

/src/sleuthkit/tsk/fs/tsk_btrfs.h
Line
Count
Source (jump to first uncovered line)
1
/*
2
** The Sleuth Kit
3
**
4
** Brian Carrier [carrier <at> sleuthkit [dot] org]
5
** Copyright (c) 2003-2011 Brian Carrier.  All rights reserved
6
**
7
** TASK
8
** Copyright (c) 2015 Stefan Pöschel.  All rights reserved
9
**
10
** This software is distributed under the Common Public License 1.0
11
*/
12
13
/*
14
 * Contains the structures and function APIs for Btrfs file system support.
15
 */
16
17
#ifndef TSK_BTRFS_H_
18
#define TSK_BTRFS_H_
19
20
#include <list>
21
#include <map>
22
#include <set>
23
#include <vector>
24
25
#ifdef HAVE_LIBZ
26
#include <zlib.h>
27
#endif
28
29
30
/* If at least one supported compression available,
31
 * enable special read/walk code.
32
 */
33
#if defined(HAVE_LIBZ)
34
#define BTRFS_COMP_SUPPORT
35
#endif
36
37
#ifdef __cplusplus
38
extern "C" {
39
#endif
40
41
42
43
/*
44
 * Btrfs constants
45
 */
46
47
// general
48
347
#define BTRFS_ENDIAN                    TSK_LIT_ENDIAN
49
1.38k
#define BTRFS_SUPERBLOCK_MIRRORS_MAX    3       // use at most two SB mirror copies - as the third one at 1PB ist not used in btrfs kernel/tools code!
50
296
#define BTRFS_SUPERBLOCK_MAGIC_OFFSET   0x40
51
592
#define BTRFS_SUPERBLOCK_MAGIC_VALUE    "_BHRfS_M"
52
0
#define BTRFS_NAME_LEN_MAX              255
53
54
// raw lens
55
0
#define BTRFS_SUPERBLOCK_RAWLEN         4096
56
0
#define BTRFS_KEY_RAWLEN                17
57
0
#define BTRFS_TREE_HEADER_RAWLEN        101
58
0
#define BTRFS_KEY_POINTER_RAWLEN        33
59
0
#define BTRFS_ITEM_RAWLEN               25
60
315
#define BTRFS_CSUM_RAWLEN               32
61
62
// superblock values
63
210
#define BTRFS_CSUM_TYPE_CRC32C          0x00
64
65
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_MIXED_BACKREF   (1ULL << 0)     // not relevant
66
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_DEFAULT_SUBVOL  (1ULL << 1)     // supported (only for fsstat - we use FS_TREE as root!)
67
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_MIXED_GROUPS    (1ULL << 2)     // not relevant
68
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_COMPRESS_LZO    (1ULL << 3)     // TODO: not (yet) supported (but we handle this on EXTENT_DATA level)
69
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_COMPRESS_ZSTD   (1ULL << 4)     // TODO: not (yet) supported (but we handle this on EXTENT_DATA level)
70
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_BIG_METADATA    (1ULL << 5)     // not relevant
71
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_EXTENDED_IREF   (1ULL << 6)     // not relevant
72
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_RAID56          (1ULL << 7)     // not relevant
73
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_SKINNY_METADATA (1ULL << 8)     // supported
74
0
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_NO_HOLES        (1ULL << 9)     // supported
75
76
#define BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_SUPPORTED         \
77
0
    (BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_MIXED_BACKREF      | \
78
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_DEFAULT_SUBVOL     | \
79
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_MIXED_GROUPS       | \
80
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_COMPRESS_LZO       | \
81
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_COMPRESS_ZSTD      | \
82
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_BIG_METADATA       | \
83
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_EXTENDED_IREF      | \
84
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_RAID56             | \
85
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_SKINNY_METADATA    | \
86
0
     BTRFS_SUPERBLOCK_INCOMPAT_FLAGS_NO_HOLES)
87
88
89
// EXTENT_DATA
90
0
#define BTRFS_EXTENT_DATA_TYPE_INLINE       0
91
0
#define BTRFS_EXTENT_DATA_TYPE_REGULAR      1
92
0
#define BTRFS_EXTENT_DATA_TYPE_PREALLOC     2
93
94
0
#define BTRFS_EXTENT_DATA_COMPRESSION_NONE  0
95
0
#define BTRFS_EXTENT_DATA_COMPRESSION_ZLIB  1
96
97
0
#define BTRFS_EXTENT_DATA_ENCRYPTION_NONE   0
98
99
0
#define BTRFS_EXTENT_DATA_OTHER_ENCODING_NONE   0
100
101
#define BTRFS_EXTENT_DATA_IS_RAW(ed) \
102
0
    ((ed)->compression == BTRFS_EXTENT_DATA_COMPRESSION_NONE && \
103
0
     (ed)->encryption == BTRFS_EXTENT_DATA_ENCRYPTION_NONE && \
104
0
     (ed)->other_encoding == BTRFS_EXTENT_DATA_OTHER_ENCODING_NONE)
105
106
107
// EXTENT_ITEM
108
0
#define BTRFS_EXTENT_ITEM_FLAGS_DATA        0x01
109
0
#define BTRFS_EXTENT_ITEM_FLAGS_TREE_BLOCK  0x02
110
111
112
// key parts
113
0
#define BTRFS_OBJID_MIN      256ULL
114
0
#define BTRFS_OBJID_MAX     -256ULL
115
116
0
#define BTRFS_OBJID_EXTENT_TREE       2ULL
117
0
#define BTRFS_OBJID_FS_TREE           5ULL
118
0
#define BTRFS_OBJID_CHUNK_ITEM      256ULL
119
120
0
#define BTRFS_ITEM_TYPE_INODE_ITEM          0x01
121
0
#define BTRFS_ITEM_TYPE_INODE_REF           0x0C
122
0
#define BTRFS_ITEM_TYPE_XATTR_ITEM          0x18
123
0
#define BTRFS_ITEM_TYPE_DIR_ITEM            0x54
124
0
#define BTRFS_ITEM_TYPE_DIR_INDEX           0x60
125
0
#define BTRFS_ITEM_TYPE_EXTENT_DATA         0x6C
126
0
#define BTRFS_ITEM_TYPE_ROOT_ITEM           0x84
127
0
#define BTRFS_ITEM_TYPE_EXTENT_ITEM         0xA8
128
0
#define BTRFS_ITEM_TYPE_METADATA_ITEM       0xA9
129
#define BTRFS_ITEM_TYPE_DEV_ITEM            0xD8
130
0
#define BTRFS_ITEM_TYPE_CHUNK_ITEM          0xE4
131
132
133
// inode type/mode (modified adopted from stat.h)
134
0
#define BTRFS_S_IFMT    0170000
135
136
0
#define BTRFS_S_IFSOCK  0140000
137
0
#define BTRFS_S_IFLNK   0120000
138
0
#define BTRFS_S_IFREG   0100000
139
0
#define BTRFS_S_IFBLK   0060000
140
0
#define BTRFS_S_IFDIR   0040000
141
0
#define BTRFS_S_IFCHR   0020000
142
0
#define BTRFS_S_IFIFO   0010000
143
144
0
#define BTRFS_S_ISUID   0004000
145
0
#define BTRFS_S_ISGID   0002000
146
0
#define BTRFS_S_ISVTX   0001000
147
148
0
#define BTRFS_S_IRUSR   0000400
149
0
#define BTRFS_S_IWUSR   0000200
150
0
#define BTRFS_S_IXUSR   0000100
151
152
0
#define BTRFS_S_IRGRP   0000040
153
0
#define BTRFS_S_IWGRP   0000020
154
0
#define BTRFS_S_IXGRP   0000010
155
156
0
#define BTRFS_S_IROTH   0000004
157
0
#define BTRFS_S_IWOTH   0000002
158
0
#define BTRFS_S_IXOTH   0000001
159
160
161
162
/*
163
 * Btrfs data types (basic)
164
 */
165
166
167
    typedef struct {
168
        uint64_t device_id;
169
        uint64_t total_bytes;
170
        uint64_t bytes_used;
171
        uint32_t optimal_io_align;
172
        uint32_t optimal_io_width;
173
        uint32_t minimal_io_size;
174
        uint64_t type;
175
        uint64_t generation;
176
        uint64_t start_offset;
177
        uint32_t dev_group;
178
        uint8_t seek_speed;
179
        uint8_t bandwidth;
180
        uint8_t device_uuid[16];
181
        uint8_t fs_uuid[16];
182
    } BTRFS_DEV_ITEM;
183
184
185
    typedef struct {
186
        // csum ignored (checked on raw item)
187
        uint8_t uuid[16];
188
        uint64_t physical_address;
189
        uint64_t flags;
190
        // magic ignored (checked on raw item)
191
        uint64_t generation;
192
        uint64_t root_tree_root;
193
        uint64_t chunk_tree_root;
194
        uint64_t log_tree_root;
195
        uint64_t log_root_transid;
196
        uint64_t total_bytes;
197
        uint64_t bytes_used;
198
        uint64_t root_dir_objectid;
199
        uint64_t num_devices;
200
        uint32_t sectorsize;
201
        uint32_t nodesize;
202
        uint32_t leafsize;
203
        uint32_t stripesize;
204
        uint32_t n;
205
        uint64_t chunk_root_generation;
206
        uint64_t compat_flags;
207
        uint64_t compat_ro_flags;
208
        uint64_t incompat_flags;
209
        uint16_t csum_type;
210
        uint8_t root_level;
211
        uint8_t chunk_root_level;
212
        uint8_t log_root_level;
213
        BTRFS_DEV_ITEM dev_item;
214
        uint8_t label[256];
215
        uint8_t reserved[256];
216
        uint8_t system_chunks[2048];
217
        uint8_t _unused[1237];  // remaining bytes unused
218
    } BTRFS_SUPERBLOCK;
219
220
221
    typedef struct {
222
        // csum ignored (checked on raw item)
223
        uint8_t uuid[16];
224
        uint64_t logical_address;
225
        uint64_t flags;         // 7 bytes
226
        uint8_t backref_rev;
227
        uint8_t chunk_tree_uuid[16];
228
        uint64_t generation;
229
        uint64_t parent_tree_id;
230
        uint32_t number_of_items;
231
        uint8_t level;
232
    } BTRFS_TREE_HEADER;
233
234
235
    typedef struct {
236
        uint64_t object_id;
237
        uint8_t item_type;
238
        uint64_t offset;
239
    } BTRFS_KEY;
240
241
242
    typedef struct {
243
        int64_t seconds;
244
        uint32_t nanoseconds;
245
    } BTRFS_TIME;
246
247
248
// Key Pointer minus Key
249
    typedef struct {
250
        uint64_t block_number;
251
        uint64_t generation;
252
    } BTRFS_KEY_POINTER_REST;
253
254
255
// Item minus Key
256
    typedef struct {
257
        uint32_t data_offset;
258
        uint32_t data_size;
259
    } BTRFS_ITEM_REST;
260
261
262
263
/*
264
 * Btrfs data types (tree items)
265
 */
266
267
268
    typedef struct {
269
        uint64_t generation;
270
        uint64_t transid;
271
        uint64_t size;
272
        uint64_t blocks;
273
        uint64_t block_group;
274
        uint32_t nlink;
275
        uint32_t uid;
276
        uint32_t gid;
277
        uint32_t mode;
278
        uint64_t rdev;
279
        uint64_t flags;
280
        uint64_t sequence;
281
        uint8_t _reserved[20];
282
        BTRFS_TIME atime;
283
        BTRFS_TIME ctime;
284
        BTRFS_TIME mtime;
285
        BTRFS_TIME otime;       // reserved
286
    } BTRFS_INODE_ITEM;
287
288
289
    typedef struct BTRFS_INODE_REF {
290
        BTRFS_INODE_REF *next;  // NULL if no next entry
291
292
        uint64_t index_in_dir;
293
        char *name_in_dir;
294
    } BTRFS_INODE_REF;
295
296
297
// used for XATTR_ITEM, DIR_ITEM and DIR_INDEX
298
    typedef struct BTRFS_DIR_ENTRY {
299
        BTRFS_DIR_ENTRY *next;  // NULL if no next entry
300
301
        BTRFS_KEY child;
302
        uint64_t transid;
303
        uint8_t type;
304
305
        char *name;
306
307
        uint16_t data_len;
308
        uint8_t *data;
309
    } BTRFS_DIR_ENTRY;
310
311
312
    typedef struct {
313
        uint64_t generation;
314
        uint64_t size_decoded;
315
        uint8_t compression;
316
        uint8_t encryption;
317
        uint16_t other_encoding;
318
        uint8_t type;
319
320
        union {
321
            struct {
322
                uint8_t *data;
323
                uint32_t data_len;
324
            } rd;               // resident data
325
            struct {
326
                uint64_t extent_address;
327
                uint64_t extent_size;
328
                uint64_t file_offset;
329
                uint64_t file_bytes;
330
            } nrd;              // non-resident data
331
        };
332
    } BTRFS_EXTENT_DATA;
333
334
335
    typedef struct {
336
        BTRFS_INODE_ITEM inode;
337
        uint64_t expected_generation;
338
        uint64_t root_dir_object_id;
339
        uint64_t root_node_block_number;
340
        uint64_t byte_limit;
341
        uint64_t bytes_used;
342
        uint64_t last_snapshot_generation;
343
        uint64_t flags;
344
        uint32_t number_of_references;
345
        BTRFS_KEY drop_progress;
346
        uint8_t drop_level;
347
        uint8_t root_node_level;
348
    } BTRFS_ROOT_ITEM;
349
350
351
// used for EXTENT_ITEM and METADATA_ITEM
352
    typedef struct {
353
        uint64_t reference_count;
354
        uint64_t generation;
355
        uint64_t flags;
356
        // depending on the flags, different fields follow - ATM they are not needed and therefore ignored
357
    } BTRFS_EXTENT_ITEM;
358
359
360
// see above for BTRFS_DEV_ITEM
361
362
363
    typedef struct {
364
        uint64_t device_id;
365
        uint64_t offset;
366
        uint8_t device_uuid[16];
367
    } BTRFS_CHUNK_ITEM_STRIPE;
368
369
370
    typedef struct {
371
        uint64_t chunk_size;
372
        uint64_t referencing_root;
373
        uint64_t stripe_length;
374
        uint64_t type;
375
        uint32_t optimal_io_align;
376
        uint32_t optimal_io_width;
377
        uint32_t minimal_io_size;
378
        uint16_t number_of_stripes;
379
        uint16_t sub_stripes;
380
        BTRFS_CHUNK_ITEM_STRIPE *stripes;
381
    } BTRFS_CHUNK_ITEM;
382
383
384
385
/*
386
 * internal parameters/constants
387
 */
388
389
// direction of treenode operations
390
    typedef enum {
391
        BTRFS_FIRST,
392
        BTRFS_LAST
393
    } BTRFS_DIRECTION;
394
395
// flags for key comparison
396
0
#define BTRFS_CMP_IGNORE_OBJID      0x01        // ignore object ID
397
0
#define BTRFS_CMP_IGNORE_TYPE       0x02        // ignore item type
398
0
#define BTRFS_CMP_IGNORE_OFFSET     0x04        // ignore offset
399
0
#define BTRFS_CMP_IGNORE_LSB_TYPE   0x08        // ignore item type LSB (special flag to cover two types which only differ in LSB)
400
401
// flags for treenode search
402
0
#define BTRFS_SEARCH_ALLOW_LEFT_NEIGHBOUR   0x01        // if no item with desired key is found, return left neighbour of the in fact position
403
404
// flags for treenode steps
405
0
#define BTRFS_STEP_INITIAL  0x01        // do an initial step before key comparison
406
0
#define BTRFS_STEP_REPEAT   0x02        // do repeated steps until key matches
407
408
// special inodes: superblock + $OrphanFiles
409
0
#define BTRFS_VINUM_COUNT_SPECIAL           2
410
0
#define BTRFS_SUPERBLOCK_VINUM(fs_info)     ((fs_info)->last_inum - 1)
411
0
#define BTRFS_SUPERBLOCK_NAME               "$Superblock"
412
413
// len of custom file content
414
0
#define BTRFS_FILE_CONTENT_LEN  sizeof(BTRFS_INODE_ITEM)
415
416
417
/*
418
 * internal data types
419
 */
420
421
422
// physical <-> logical address mapping
423
    typedef struct BTRFS_CACHED_CHUNK {
424
        TSK_DADDR_T source_address;
425
        TSK_OFF_T size;
426
        TSK_DADDR_T target_address;
427
428
        /*
429
         * Chunks don't overlap, therefore operator< ensures
430
         * the correct order within the set.
431
         * We take advantage of this for finding the corresponding chunk
432
         * to an address with the help of a temporary chunk:
433
         * If two chunks overlap, they are treated as equal.
434
         */
435
0
        bool operator<(const BTRFS_CACHED_CHUNK & chunk_range) const {
436
0
            return source_address + size - 1 < chunk_range.source_address;
437
0
    }}
438
    BTRFS_CACHED_CHUNK;
439
440
    typedef std::set < BTRFS_CACHED_CHUNK > btrfs_cached_chunks_t;
441
442
    typedef struct {
443
        btrfs_cached_chunks_t log2phys;
444
        btrfs_cached_chunks_t phys2log;
445
    } BTRFS_CACHED_CHUNK_MAPPING;
446
447
448
// treenode cache
449
    typedef std::map < TSK_DADDR_T, uint8_t * >btrfs_treenode_cache_map_t;
450
    typedef std::list < TSK_DADDR_T > btrfs_treenode_cache_lru_t;
451
452
453
// real -> virtual inum mapping
454
    typedef std::map < TSK_INUM_T, TSK_INUM_T > btrfs_real2virt_inums_t;
455
456
    typedef struct {
457
        BTRFS_ROOT_ITEM ri;
458
        btrfs_real2virt_inums_t real2virt_inums;
459
    } BTRFS_SUBVOLUME;
460
461
    typedef std::map < uint64_t, BTRFS_SUBVOLUME > btrfs_subvolumes_t;
462
463
464
// virtual -> real inum mapping
465
    typedef std::pair < uint64_t, TSK_INUM_T > btrfs_real_inum_t;
466
    typedef std::vector < btrfs_real_inum_t > btrfs_virt2real_inums_t;
467
468
469
// FS info
470
    typedef struct {
471
        // super class
472
        TSK_FS_INFO fs_info;
473
474
        // Btrfs specific fields
475
        bool test;
476
        BTRFS_SUPERBLOCK *sb;
477
        int sb_mirror_index;
478
        uint64_t extent_tree_root_node_address;
479
480
        BTRFS_CACHED_CHUNK_MAPPING *chunks;
481
482
        btrfs_subvolumes_t *subvolumes;
483
        btrfs_virt2real_inums_t *virt2real_inums;
484
485
        // protects treenode_cache_map and treenode_cache_lru
486
        tsk_lock_t treenode_cache_lock;
487
        btrfs_treenode_cache_map_t *treenode_cache_map;
488
        btrfs_treenode_cache_lru_t *treenode_cache_lru;
489
    } BTRFS_INFO;
490
491
492
// treenode operations related
493
    typedef enum {
494
        BTRFS_TREENODE_FOUND,
495
        BTRFS_TREENODE_NOT_FOUND,
496
        BTRFS_TREENODE_ERROR
497
    } BTRFS_TREENODE_RESULT;
498
499
    typedef struct BTRFS_TREENODE {
500
        BTRFS_TREENODE *prev;   // NULL if no previous level
501
502
        BTRFS_TREE_HEADER header;
503
        uint8_t *data;
504
505
        uint32_t index;
506
        BTRFS_KEY key;
507
        union {
508
            BTRFS_KEY_POINTER_REST kp;
509
            BTRFS_ITEM_REST item;
510
        };
511
    } BTRFS_TREENODE;
512
513
514
// block walk related
515
    typedef struct {
516
        BTRFS_INFO *btrfs;
517
        uint64_t block;
518
519
        bool no_more_ei;
520
        BTRFS_KEY ei_key;
521
        BTRFS_TREENODE *ei_node;
522
        TSK_DADDR_T ei_start;
523
        TSK_DADDR_T ei_end;
524
        TSK_FS_BLOCK_FLAG_ENUM ei_flags;
525
526
        bool no_more_cc;
527
        const BTRFS_CACHED_CHUNK *cc;
528
    } BTRFS_BLOCKWALK;
529
530
531
// EXTENT_DATA walk related
532
    typedef struct {
533
        BTRFS_INFO *btrfs;
534
        size_t size;
535
        size_t offset;
536
537
        BTRFS_KEY key;
538
        BTRFS_TREENODE *node;
539
    } BTRFS_EXTENT_DATAWALK;
540
541
542
// inode walk related
543
    typedef struct {
544
        BTRFS_INFO *btrfs;
545
        TSK_INUM_T vinum;
546
        uint64_t subvol;
547
548
        BTRFS_KEY key;
549
        BTRFS_TREENODE *node;
550
        BTRFS_INODE_ITEM ii;
551
    } BTRFS_INODEWALK;
552
553
554
#ifdef BTRFS_COMP_SUPPORT
555
// (attribute) data walk related
556
    typedef enum {
557
        BTRFS_ED_TYPE_RAW,
558
        BTRFS_ED_TYPE_SPARSE,
559
#ifdef HAVE_LIBZ
560
        BTRFS_ED_TYPE_COMP_ZLIB,
561
#endif
562
        BTRFS_ED_TYPE_UNKNOWN
563
    } BTRFS_ED_TYPE;
564
565
    typedef struct {
566
        BTRFS_INFO *btrfs;
567
        const TSK_FS_ATTR *attr;
568
        TSK_OFF_T size;
569
570
        uint8_t *in_blockbuffer;
571
        uint8_t *tmp_blockbuffer;
572
573
        BTRFS_EXTENT_DATAWALK *edw;
574
        BTRFS_EXTENT_DATA *ed;
575
        TSK_DADDR_T ed_offset;
576
        bool ed_resident;
577
        BTRFS_ED_TYPE ed_type;
578
579
        TSK_DADDR_T last_raw_addr;
580
        size_t ed_raw_offset;
581
        size_t ed_raw_size;
582
583
        size_t ed_out_offset;
584
        size_t ed_out_size;
585
586
#ifdef HAVE_LIBZ
587
        bool zlib_state_used;
588
        z_stream_s zlib_state;
589
#endif
590
591
        const BTRFS_CACHED_CHUNK *cc;
592
    } BTRFS_DATAWALK;
593
#endif
594
595
596
597
/*
598
 * helper functions
599
 */
600
601
    extern unsigned long btrfs_csum_crc32c(const unsigned char *a_data,
602
        const int a_len);
603
604
605
606
#ifdef __cplusplus
607
}
608
#endif
609
#endif                          /* TSK_BTRFS_H_ */