Coverage Report

Created: 2025-07-23 06:40

/src/sleuthkit/tsk/vs/bsd.c
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) 2006-2011 Brian Carrier, Basis Technology.  All rights reserved
6
 * Copyright (c) 2003-2005 Brian Carrier.  All rights reserved
7
 *
8
 * This software is distributed under the Common Public License 1.0
9
 */
10
11
/** \file bsd.c
12
 * Contains the internal functions required to process BSD disk labels.
13
 */
14
#include "tsk_vs_i.h"
15
#include "tsk_bsd.h"
16
17
18
/*
19
 * Return a buffer with a description of the partition type.  The buffer
20
 * must be freed by the caller.
21
 */
22
static char *
23
bsd_get_desc(uint8_t fstype)
24
0
{
25
0
    char *str = tsk_malloc(64);
26
0
    if (str == NULL)
27
0
        return "";
28
29
0
    switch (fstype) {
30
31
0
    case 0:
32
0
        strncpy(str, "Unused (0x00)", 64);
33
0
        break;
34
0
    case 1:
35
0
        strncpy(str, "Swap (0x01)", 64);
36
0
        break;
37
0
    case 2:
38
0
        strncpy(str, "Version 6 (0x02)", 64);
39
0
        break;
40
0
    case 3:
41
0
        strncpy(str, "Version 7 (0x03)", 64);
42
0
        break;
43
0
    case 4:
44
0
        strncpy(str, "System V (0x04)", 64);
45
0
        break;
46
0
    case 5:
47
0
        strncpy(str, "4.1BSD (0x05)", 64);
48
0
        break;
49
0
    case 6:
50
0
        strncpy(str, "Eighth Edition (0x06)", 64);
51
0
        break;
52
0
    case 7:
53
0
        strncpy(str, "4.2BSD (0x07)", 64);
54
0
        break;
55
0
    case 8:
56
0
        strncpy(str, "MSDOS (0x08)", 64);
57
0
        break;
58
0
    case 9:
59
0
        strncpy(str, "4.4LFS (0x09)", 64);
60
0
        break;
61
0
    case 10:
62
0
        strncpy(str, "Unknown (0x0A)", 64);
63
0
        break;
64
0
    case 11:
65
0
        strncpy(str, "HPFS (0x0B)", 64);
66
0
        break;
67
0
    case 12:
68
0
        strncpy(str, "ISO9660 (0x0C)", 64);
69
0
        break;
70
0
    case 13:
71
0
        strncpy(str, "Boot (0x0D)", 64);
72
0
        break;
73
0
    case 14:
74
0
        strncpy(str, "Vinum (0x0E)", 64);
75
0
        break;
76
0
    default:
77
0
        snprintf(str, 64, "Unknown Type (0x%.2x)", fstype);
78
0
        break;
79
0
    }
80
81
0
    return str;
82
0
}
83
84
/*
85
 * Process the partition table at the sector address
86
 *
87
 * Return 1 on error and 0 if no error
88
 */
89
static uint8_t
90
bsd_load_table(TSK_VS_INFO * a_vs)
91
0
{
92
0
    char *sect_buf;
93
0
    bsd_disklabel *dlabel;
94
0
    uint32_t idx = 0;
95
0
    ssize_t cnt;
96
0
    char *table_str;
97
0
    TSK_DADDR_T laddr = a_vs->offset / a_vs->block_size + BSD_PART_SOFFSET;     // used for printing only
98
0
    TSK_DADDR_T max_addr = (a_vs->img_info->size - a_vs->offset) / a_vs->block_size;    // max sector
99
100
0
    if (tsk_verbose)
101
0
        tsk_fprintf(stderr,
102
0
            "bsd_load_table: Table Sector: %" PRIuDADDR "\n", laddr);
103
104
0
    if ((sect_buf = tsk_malloc(a_vs->block_size)) == NULL)
105
0
        return 1;
106
0
    dlabel = (bsd_disklabel *) sect_buf;
107
108
    /* read the block */
109
0
    cnt = tsk_vs_read_block
110
0
        (a_vs, BSD_PART_SOFFSET, sect_buf, a_vs->block_size);
111
0
    if (cnt != a_vs->block_size) {
112
0
        if (cnt >= 0) {
113
0
            tsk_error_reset();
114
0
            tsk_error_set_errno(TSK_ERR_VS_READ);
115
0
        }
116
0
        tsk_error_set_errstr2("BSD Disk Label in Sector: %" PRIuDADDR,
117
0
            laddr);
118
0
        free(sect_buf);
119
0
        return 1;
120
0
    }
121
122
    /* Check the magic  */
123
0
    if (tsk_vs_guessu32(a_vs, dlabel->magic, BSD_MAGIC)) {
124
0
        tsk_error_reset();
125
0
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
126
0
        tsk_error_set_errstr("BSD partition table (magic #1) (Sector: %"
127
0
            PRIuDADDR ") %" PRIx32, laddr, tsk_getu32(a_vs->endian,
128
0
                dlabel->magic));
129
0
        free(sect_buf);
130
0
        return 1;
131
0
    }
132
133
    /* Check the second magic value */
134
0
    if (tsk_getu32(a_vs->endian, dlabel->magic2) != BSD_MAGIC) {
135
0
        tsk_error_reset();
136
0
        tsk_error_set_errno(TSK_ERR_VS_MAGIC);
137
0
        tsk_error_set_errstr("BSD disk label (magic #2) (Sector: %"
138
0
            PRIuDADDR ")  %" PRIx32, laddr, tsk_getu32(a_vs->endian,
139
0
                dlabel->magic2));
140
0
        free(sect_buf);
141
0
        return 1;
142
0
    }
143
144
    /* Add an entry of 1 length for the table  to the internal structure */
145
0
    if ((table_str = tsk_malloc(32)) == NULL) {
146
0
        free(sect_buf);
147
0
        return 1;
148
0
    }
149
150
0
    snprintf(table_str, 32, "Partition Table");
151
0
    if (NULL == tsk_vs_part_add(a_vs, BSD_PART_SOFFSET,
152
0
            (TSK_DADDR_T) 1, TSK_VS_PART_FLAG_META, table_str, -1, -1)) {
153
0
        free(sect_buf);
154
0
        return 1;
155
0
    }
156
157
    /* Cycle through the partitions, there are either 8 or 16 */
158
0
    for (idx = 0; idx < tsk_getu16(a_vs->endian, dlabel->num_parts); idx++) {
159
160
0
        uint32_t part_start;
161
0
        uint32_t part_size;
162
163
0
        part_start = tsk_getu32(a_vs->endian, dlabel->part[idx].start_sec);
164
0
        part_size = tsk_getu32(a_vs->endian, dlabel->part[idx].size_sec);
165
166
0
        if (tsk_verbose)
167
0
            tsk_fprintf(stderr,
168
0
                "load_table: %" PRIu32 "  Starting Sector: %" PRIu32
169
0
                "  Size: %" PRIu32 "  Type: %d\n", idx, part_start,
170
0
                part_size, dlabel->part[idx].fstype);
171
172
0
        if (part_size == 0)
173
0
            continue;
174
175
        // make sure the first couple are in the image bounds
176
0
        if ((idx < 2) && (part_start > max_addr)) {
177
0
            tsk_error_reset();
178
0
            tsk_error_set_errno(TSK_ERR_VS_BLK_NUM);
179
0
            tsk_error_set_errstr
180
0
                ("bsd_load_table: Starting sector too large for image");
181
0
            free(sect_buf);
182
0
            return 1;
183
0
        }
184
185
186
        /* Add the partition to the internal sorted list */
187
0
        if (NULL == tsk_vs_part_add(a_vs, (TSK_DADDR_T) part_start,
188
0
                (TSK_DADDR_T) part_size, TSK_VS_PART_FLAG_ALLOC,
189
0
                bsd_get_desc(dlabel->part[idx].fstype), -1, idx)) {
190
0
            free(sect_buf);
191
0
            return 1;
192
0
        }
193
0
    }
194
195
0
    free(sect_buf);
196
0
    return 0;
197
0
}
198
199
200
static void
201
bsd_close(TSK_VS_INFO * a_vs)
202
0
{
203
0
    a_vs->tag = 0;
204
0
    tsk_vs_part_free(a_vs);
205
0
    free(a_vs);
206
0
}
207
208
/*
209
 * analyze the image in img_info and process it as BSD
210
 * Initialize the TSK_VS_INFO structure
211
 *
212
 * Return TSK_VS_INFO or NULL if not BSD or an error
213
 */
214
TSK_VS_INFO *
215
tsk_vs_bsd_open(TSK_IMG_INFO * img_info, TSK_DADDR_T offset)
216
0
{
217
0
    TSK_VS_INFO *vs;
218
219
    // clean up any errors that are lying around
220
0
    tsk_error_reset();
221
222
0
    if (img_info->sector_size == 0) {
223
0
        tsk_error_reset();
224
0
        tsk_error_set_errno(TSK_ERR_VS_ARG);
225
0
        tsk_error_set_errstr("tsk_vs_bsd_open: sector size is 0");
226
0
        return NULL;
227
0
    }
228
229
0
    vs = (TSK_VS_INFO *) tsk_malloc(sizeof(*vs));
230
0
    if (vs == NULL)
231
0
        return NULL;
232
233
0
    vs->img_info = img_info;
234
0
    vs->vstype = TSK_VS_TYPE_BSD;
235
0
    vs->tag = TSK_VS_INFO_TAG;
236
237
    /* use the offset provided */
238
0
    vs->offset = offset;
239
240
    /* initialize settings */
241
0
    vs->part_list = NULL;
242
0
    vs->part_count = 0;
243
0
    vs->endian = 0;
244
0
    vs->block_size = img_info->sector_size;
245
246
    /* Assign functions */
247
0
    vs->close = bsd_close;
248
249
    /* Load the partitions into the sorted list */
250
0
    if (bsd_load_table(vs)) {
251
0
        bsd_close(vs);
252
0
        return NULL;
253
0
    }
254
255
    /* fill in the sorted list with the 'unknown' values */
256
0
    if (tsk_vs_part_unused(vs)) {
257
0
        bsd_close(vs);
258
0
        return NULL;
259
0
    }
260
261
0
    return vs;
262
0
}