Browse code

mbr: restructured code for consistency mbr: cleaned up code

Kevin Lin authored on 2014/02/08 07:09:18
Showing 2 changed files
... ...
@@ -40,6 +40,10 @@
40 40
 //#define DEBUG_MBR_PARSE
41 41
 //#define DEBUG_EBR_PARSE
42 42
 
43
+#ifndef PRTN_INTXN_DETECTION
44
+#  define PRTN_INTXN_DETECTION "heuristic.mbrprtnintersect"
45
+#endif
46
+
43 47
 #ifdef DEBUG_MBR_PARSE
44 48
 #  define mbr_parsemsg(...) cli_dbgmsg( __VA_ARGS__)
45 49
 #else
... ...
@@ -59,14 +63,14 @@ enum MBR_STATE {
59 59
     SEEN_EMPTY
60 60
 };
61 61
 
62
-static int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize);
62
+static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, 
63
+                           size_t extlbasize, size_t sectorsize);
63 64
 static void mbr_printbr(struct mbr_boot_record *record);
64 65
 static void mbr_convert_to_host(struct mbr_boot_record *record);
65
-static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen);
66
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize);
66 67
 static int mbr_check_ebr(struct mbr_boot_record *record);
67 68
 static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
68
-static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
69
-
69
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize);
70 70
 
71 71
 int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) {
72 72
     struct mbr_boot_record mbr;
... ...
@@ -80,18 +84,17 @@ int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) {
80 80
 
81 81
     //mbr_printbr(&mbr);
82 82
 
83
-    return mbr_check_mbr(&mbr, maplen);
83
+    return mbr_check_mbr(&mbr, maplen, MBR_SECTOR_SIZE);
84 84
 }
85 85
 
86 86
 int cli_scanmbr(cli_ctx *ctx)
87 87
 {
88 88
     struct mbr_boot_record mbr;
89 89
     enum MBR_STATE state = SEEN_NOTHING;
90
-    int ret = 0;
91
-    size_t sectorsize, maplen, partsize;
90
+    int ret = CL_CLEAN;
92 91
     off_t pos = 0, partoff = 0;
93
-    off_t exoff, exloff, exlcheck[CL_MAX_LOGICAL_PARTITIONS];
94
-    unsigned i, j, k, prtncount;
92
+    unsigned i = 0, prtncount = 0;
93
+    size_t sectorsize, maplen, partsize;
95 94
 
96 95
     mbr_parsemsg("The start of something magnificant: MBR parsing\n");
97 96
 
... ...
@@ -124,7 +127,7 @@ int cli_scanmbr(cli_ctx *ctx)
124 124
     mbr_convert_to_host(&mbr);
125 125
 
126 126
     /* MBR checks */
127
-    ret = mbr_check_mbr(&mbr, maplen);
127
+    ret = mbr_check_mbr(&mbr, maplen, sectorsize);
128 128
     if (ret != CL_CLEAN) {
129 129
         return ret;
130 130
     }
... ...
@@ -137,25 +140,19 @@ int cli_scanmbr(cli_ctx *ctx)
137 137
         
138 138
             return ret;
139 139
         }
140
-        ret = mbr_extended_prtn_intxn(ctx, mbr, sectorsize);
141
-        if ((ret != CL_CLEAN) &&
142
-            !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
143
-        
144
-            return ret;
145
-        }
146 140
     }
147 141
 
148 142
     /* MBR is valid, examine partitions */
149 143
     prtncount = 0;
150 144
     cli_dbgmsg("MBR Signature: %x\n", mbr.signature);
151
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
145
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES && prtncount < ctx->engine->maxpartitions; ++i) {
152 146
         cli_dbgmsg("MBR Partition Entry %u:\n", i);
153 147
         cli_dbgmsg("Status: %u\n", mbr.entries[i].status);
154 148
         cli_dbgmsg("Type: %x\n", mbr.entries[i].type);
155 149
         cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n",
156
-                   mbr.entries[i].firstLBA, mbr.entries[i].numSectors,
150
+                   mbr.entries[i].firstLBA, mbr.entries[i].numLBA,
157 151
                    (mbr.entries[i].firstLBA * sectorsize),
158
-                   (mbr.entries[i].numSectors * sectorsize));
152
+                   (mbr.entries[i].numLBA * sectorsize));
159 153
 
160 154
         /* Handle MBR entry based on type */
161 155
         if (mbr.entries[i].type == MBR_EMPTY) {
... ...
@@ -169,38 +166,18 @@ int cli_scanmbr(cli_ctx *ctx)
169 169
             }
170 170
             state = SEEN_EXTENDED; /* used only to detect mutiple extended partitions */
171 171
 
172
-            exoff = mbr.entries[i].firstLBA;
173
-            exloff = 0; j = 0;
174
-            do {
175
-                prtncount++;
176
-                /* check if a logical partition has been seen before */
177
-                for (k = 0; k < j; ++k) {
178
-                    if (exloff == exlcheck[k]) {
179
-                        cli_dbgmsg("cli_scanmbr: found a logical partition "
180
-                                   "that was previously seen!\n");
181
-                        /* do things! */
182
-                        return CL_EFORMAT;
183
-                    }
184
-                }
185
-                exlcheck[j] = exloff;
186
-
187
-                cli_dbgmsg("EBR Partition Entry %u:\n", j);
188
-                ret = mbr_scanebr(ctx, &exloff, exoff, sectorsize);
189
-                if ((ret != CL_CLEAN) &&
190
-                    !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
191
-                        return ret;
192
-                }
193
-
194
-                ++j;
195
-            } while (exloff != 0 && prtncount < ctx->engine->maxpartitions);
196
-
197
-            cli_dbgmsg("cli_scanmbr: examined %u logical partitions\n", j);
172
+            ret = mbr_scanextprtn(ctx, &prtncount, mbr.entries[i].firstLBA, 
173
+                                  mbr.entries[i].numLBA, sectorsize);
174
+            if ((ret != CL_CLEAN) &&
175
+                !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
176
+                return ret;
177
+            }
198 178
         }
199 179
         else {
200 180
             prtncount++;
201 181
 
202 182
             partoff = mbr.entries[i].firstLBA * sectorsize;
203
-            partsize = mbr.entries[i].numSectors * sectorsize;
183
+            partsize = mbr.entries[i].numLBA * sectorsize;
204 184
             mbr_parsemsg("cli_map_scan: [%u, +%u)\n", partoff, partsize);
205 185
             ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
206 186
             if ((ret != CL_CLEAN) &&
... ...
@@ -208,144 +185,158 @@ int cli_scanmbr(cli_ctx *ctx)
208 208
                     return ret;
209 209
             }
210 210
         }
211
-
212
-        if (prtncount >= ctx->engine->maxpartitions) {
213
-            cli_dbgmsg("cli_scanmbr: maximum partitions reached\n");
214
-            break;
215
-        }
216 211
     }
217 212
 
213
+    if (prtncount >= ctx->engine->maxpartitions) {
214
+        cli_dbgmsg("cli_scanmbr: maximum partitions reached\n");
215
+    }
218 216
     return ret;
219 217
 }
220 218
 
221
-int mbr_scanebr(cli_ctx *ctx, off_t *exloff, off_t exoff, size_t sectorsize) {
219
+static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t extlbasize, size_t sectorsize)
220
+{
222 221
     struct mbr_boot_record ebr;
223 222
     enum MBR_STATE state = SEEN_NOTHING;
224
-    int ret = 0;
225
-    off_t pos = 0, partoff = 0;
226
-    size_t partsize;
227
-    unsigned i;
228
-
229
-    ebr_parsemsg("The start of something excellent: EBR parsing\n");
230
-
231
-    pos = exoff * sectorsize; /* start of extended partition */
232
-    partoff = (exoff + *exloff) * sectorsize; /* start of logical partition */
233
-
234
-    /* read the extended boot record */
235
-    pos += (*exloff * sectorsize) + MBR_BASE_OFFSET;
236
-    if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
237
-        cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
238
-        return CL_EFORMAT;
239
-    }
223
+    int ret = CL_CLEAN;
224
+    off_t pos = 0, logiclba = 0, extoff = 0, partoff = 0;
225
+    size_t partsize, extsize;
226
+    unsigned i = 0, j = 0;
227
+
228
+    ebr_parsemsg("The start of something exhausting: EBR parsing\n");
229
+
230
+    logiclba = 0;
231
+    extoff = extlba * sectorsize;
232
+    extsize = extlbasize * sectorsize;
233
+    do {
234
+        pos = extlba * sectorsize; /* start of extended partition */
235
+
236
+        /* read the extended boot record */
237
+        pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
238
+        if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
239
+            cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
240
+            return CL_EFORMAT;
241
+        }
240 242
 
241
-    /* convert the little endian to host */
242
-    mbr_convert_to_host(&ebr);
243
+        /* convert the little endian to host */
244
+        mbr_convert_to_host(&ebr);
243 245
 
244
-    /* EBR checks */
245
-    ret = mbr_check_ebr(&ebr);
246
-    if (ret != CL_CLEAN) {
247
-        return ret;
248
-    }
246
+        /* EBR checks */
247
+        ret = mbr_check_ebr(&ebr);
248
+        if (ret != CL_CLEAN) {
249
+            return ret;
250
+        }
249 251
 
250
-    /* EBR is valid, examine partitions */
251
-    cli_dbgmsg("EBR Signature: %x\n", ebr.signature);
252
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
253
-        if (i < 2) {
254
-            cli_dbgmsg("Logical Partition Entry %u:\n", i);
255
-            cli_dbgmsg("Status: %u\n", ebr.entries[i].status);
256
-            cli_dbgmsg("Type: %x\n", ebr.entries[i].type);
257
-            cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n",
258
-                       ebr.entries[i].firstLBA, ebr.entries[i].numSectors,
259
-                       (ebr.entries[i].firstLBA * sectorsize),
260
-                       (ebr.entries[i].numSectors * sectorsize));
261
-
262
-            if (ebr.entries[i].type == MBR_EMPTY) {
263
-                /* empty partiton entry */
264
-                switch(state) {
265
-                case SEEN_NOTHING:
266
-                    state = SEEN_EMPTY;
267
-                    break;
268
-                case SEEN_PARTITION:
269
-                    *exloff = 0;
270
-                    break;
271
-                case SEEN_EMPTY:
272
-                    *exloff = 0;
273
-                    /* fall-through */
274
-                case SEEN_EXTENDED:
275
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
276
-                               "without a partition record\n");
277
-                    break;
278
-                default:
279
-                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
280
-                    return CL_EPARSE;
281
-                }
282
-            }
283
-            else if (ebr.entries[i].type == MBR_EXTENDED) {
284
-                switch(state) {
285
-                case SEEN_NOTHING:
286
-                    state = SEEN_EXTENDED;
287
-                    break;
288
-                case SEEN_PARTITION:
289
-                    break;
290
-                case SEEN_EMPTY:
291
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
292
-                               "without a partition record\n");
293
-                    break;
294
-                case SEEN_EXTENDED:
295
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
296
-                               "with multiple extended partition records\n");
297
-                    return CL_EFORMAT;
298
-                default:
299
-                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
300
-                    return CL_EPARSE;
252
+        /* update state */
253
+        state = SEEN_NOTHING;
254
+        (*prtncount)++;
255
+
256
+        /* EBR is valid, examine partitions */
257
+        cli_dbgmsg("EBR Partition Entry %u:\n", i++);
258
+        cli_dbgmsg("EBR Signature: %x\n", ebr.signature);
259
+        for (j = 0; j < MBR_MAX_PARTITION_ENTRIES; ++j) {
260
+            if (j < 2) {
261
+                cli_dbgmsg("Logical Partition Entry %u:\n", j);
262
+                cli_dbgmsg("Status: %u\n", ebr.entries[j].status);
263
+                cli_dbgmsg("Type: %x\n", ebr.entries[j].type);
264
+                cli_dbgmsg("Blocks: [%u, +%u), ([%u, +%u))\n",
265
+                           ebr.entries[j].firstLBA, ebr.entries[j].numLBA,
266
+                           (ebr.entries[j].firstLBA * sectorsize),
267
+                           (ebr.entries[j].numLBA * sectorsize));
268
+
269
+                if (ebr.entries[j].type == MBR_EMPTY) {
270
+                    /* empty partiton entry */
271
+                    switch(state) {
272
+                    case SEEN_NOTHING:
273
+                        state = SEEN_EMPTY;
274
+                        break;
275
+                    case SEEN_PARTITION:
276
+                        logiclba = 0;
277
+                        break;
278
+                    case SEEN_EMPTY:
279
+                        logiclba = 0;
280
+                        /* fall-through */
281
+                    case SEEN_EXTENDED:
282
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
283
+                                   "without a partition record\n");
284
+                        break;
285
+                    default:
286
+                        cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
287
+                        return CL_EPARSE;
288
+                    }
301 289
                 }
290
+                else if (ebr.entries[j].type == MBR_EXTENDED) {
291
+                    switch(state) {
292
+                    case SEEN_NOTHING:
293
+                        state = SEEN_EXTENDED;
294
+                        break;
295
+                    case SEEN_PARTITION:
296
+                        break;
297
+                    case SEEN_EMPTY:
298
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
299
+                                   "without a partition record\n");
300
+                        break;
301
+                    case SEEN_EXTENDED:
302
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
303
+                                   "with multiple extended partition records\n");
304
+                        return CL_EFORMAT;
305
+                    default:
306
+                        cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
307
+                        return CL_EPARSE;
308
+                    }
302 309
 
303
-                *exloff = ebr.entries[i].firstLBA;
304
-            }
305
-            else {
306
-                switch(state) {
307
-                case SEEN_NOTHING:
308
-                    state = SEEN_PARTITION;
309
-                    break;
310
-                case SEEN_PARTITION:
311
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
312
-                               "with multiple partition records\n");
313
-                    *exloff = 0; /* no extended partitions are possible */
314
-                    break;
315
-                case SEEN_EXTENDED:
316
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
317
-                               "with extended partition record first\n");
318
-                    break;
319
-                case SEEN_EMPTY:
320
-                    cli_dbgmsg("cli_scanebr: detected a logical boot record "
321
-                               "with empty partition record first\n");
322
-                    *exloff = 0; /* no extended partitions are possible */
323
-                    break;
324
-                default:
325
-                    cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
326
-                    return CL_EPARSE;
310
+                    logiclba = ebr.entries[j].firstLBA;
327 311
                 }
312
+                else {
313
+                    switch(state) {
314
+                    case SEEN_NOTHING:
315
+                        state = SEEN_PARTITION;
316
+                        break;
317
+                    case SEEN_PARTITION:
318
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
319
+                                   "with multiple partition records\n");
320
+                        logiclba = 0; /* no extended partitions are possible */
321
+                        break;
322
+                    case SEEN_EXTENDED:
323
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
324
+                                   "with extended partition record first\n");
325
+                        break;
326
+                    case SEEN_EMPTY:
327
+                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
328
+                                   "with empty partition record first\n");
329
+                        logiclba = 0; /* no extended partitions are possible */
330
+                        break;
331
+                    default:
332
+                        cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
333
+                        return CL_EPARSE;
334
+                    }
328 335
 
329
-                partoff += (ebr.entries[i].firstLBA * sectorsize);
330
-                partsize = ebr.entries[i].numSectors * sectorsize;
331
-                ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
332
-                if ((ret != CL_CLEAN) &&
333
-                    !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
336
+                    partoff = (extlba + logiclba + ebr.entries[j].firstLBA) * sectorsize;
337
+                    partsize = ebr.entries[j].numLBA * sectorsize;
338
+                    if (extoff + partsize > extsize) {
339
+                        cli_dbgmsg("cli_scanmbr: Invalid partition entry\n");
340
+                        return CL_EFORMAT;
341
+                    }
342
+
343
+                    ret = cli_map_scan(*ctx->fmap, partoff, partsize, ctx, CL_TYPE_PART_ANY);
344
+                    if ((ret != CL_CLEAN) &&
345
+                        !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
334 346
                         return ret;
347
+                    }
335 348
                 }
336 349
             }
337
-        }
338
-        else {
339
-            /* check the last two entries to be empty */
340
-            if (ebr.entries[i].type != MBR_EMPTY) {
341
-                cli_dbgmsg("cli_scanebr: detected a logical boot record "
342
-                           "with an entry at index %u\n", i);
343
-                /* should we attepmt to use these entries? */
344
-                return CL_EFORMAT;
350
+            else {
351
+                /* check the last two entries to be empty */
352
+                if (ebr.entries[j].type != MBR_EMPTY) {
353
+                    cli_dbgmsg("cli_scanebr: detected a non-empty partition "
354
+                               "entry at index %u\n", j);
355
+                    /* should we attempt to use these entries? */
356
+                    return CL_EFORMAT;
357
+                }
345 358
             }
346 359
         }
347
-    }
360
+    } while (logiclba != 0 && (*prtncount) < ctx->engine->maxpartitions);
348 361
 
362
+    cli_dbgmsg("cli_scanmbr: examined %u logical partitions\n", i);
349 363
     return ret;
350 364
 }
351 365
 
... ...
@@ -363,7 +354,7 @@ static void mbr_printbr(struct mbr_boot_record *record)
363 363
         cli_dbgmsg("\tlastCHS: [%u, %u, %u]\n", record->entries[i].lastCHS[0],
364 364
                    record->entries[i].lastCHS[1], record->entries[i].lastCHS[2]);
365 365
         cli_dbgmsg("\tfirstLBA: %u\n", record->entries[i].firstLBA);
366
-        cli_dbgmsg("\tnumSectors: %u\n", record->entries[i].numSectors);
366
+        cli_dbgmsg("\tnumLBA: %u\n", record->entries[i].numLBA);
367 367
     }
368 368
 }
369 369
 
... ...
@@ -376,16 +367,16 @@ static void mbr_convert_to_host(struct mbr_boot_record *record)
376 376
         entry = &record->entries[i];
377 377
  
378 378
         entry->firstLBA = le32_to_host(entry->firstLBA);
379
-        entry->numSectors = le32_to_host(entry->numSectors);
379
+        entry->numLBA = le32_to_host(entry->numLBA);
380 380
     }
381 381
     record->signature = be16_to_host(record->signature);
382 382
 }
383 383
 
384
-static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen)
384
+static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize)
385 385
 {
386 386
     unsigned i = 0;
387 387
     off_t partoff = 0;
388
-    size_t partsize = 0, sectorsize = MBR_SECTOR_SIZE;
388
+    size_t partsize = 0;
389 389
 
390 390
     for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
391 391
         /* check status */
... ...
@@ -396,7 +387,7 @@ static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen)
396 396
         }
397 397
 
398 398
         partoff = record->entries[i].firstLBA * sectorsize;
399
-        partsize = record->entries[i].numSectors * sectorsize;
399
+        partsize = record->entries[i].numLBA * sectorsize;
400 400
         if (partoff + partsize > maplen) {
401 401
             cli_dbgmsg("cli_scanmbr: Invalid partition entry\n");
402 402
             return CL_EFORMAT;
... ...
@@ -416,7 +407,7 @@ static int mbr_check_ebr(struct mbr_boot_record *record)
416 416
 {
417 417
     unsigned i = 0;
418 418
 
419
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
419
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES-2; ++i) {
420 420
         /* check status */
421 421
         if ((record->entries[i].status != MBR_STATUS_INACTIVE) && 
422 422
             (record->entries[i].status != MBR_STATUS_ACTIVE)) {
... ...
@@ -438,27 +429,31 @@ static int mbr_check_ebr(struct mbr_boot_record *record)
438 438
 static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize)
439 439
 {
440 440
     prtn_intxn_list_t prtncheck;
441
-    unsigned i, pitxn;
441
+    unsigned i = 0, pitxn = 0, prtncount = 0;
442 442
     int ret = 0, tmp = 0;
443 443
 
444 444
     prtn_intxn_list_init(&prtncheck);
445 445
 
446
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
447
-        if (mbr.entries[i].type != MBR_EMPTY) {
448
-            tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA, 
449
-                                        mbr.entries[i].numSectors);
446
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES && prtncount < ctx->engine->maxpartitions; ++i) {
447
+        if (mbr.entries[i].type == MBR_EMPTY) {
448
+            /* empty partiton entry */
449
+            prtncount++;
450
+        }
451
+        else {
452
+            tmp = prtn_intxn_list_check(&prtncheck, &pitxn, mbr.entries[i].firstLBA,
453
+                                        mbr.entries[i].numLBA);
450 454
             if (tmp != CL_CLEAN) {
451 455
                 if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
452 456
                     cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
453 457
                                "[%u, %u]\n", pitxn, i);
454
-                    cli_append_virus(ctx, "Heuristic.PartitionIntersection");
458
+                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
455 459
                     ret = tmp;
456 460
                     tmp = 0;
457 461
                 }
458 462
                 else if (tmp == CL_VIRUS) {
459 463
                     cli_dbgmsg("cli_scanmbr: detected intersection with partitions "
460 464
                                "[%u, %u]\n", pitxn, i);
461
-                    cli_append_virus(ctx, "Heuristic.PartitionIntersection");
465
+                    cli_append_virus(ctx, PRTN_INTXN_DETECTION);
462 466
                     prtn_intxn_list_free(&prtncheck);
463 467
                     return CL_VIRUS;
464 468
                 }
... ...
@@ -467,57 +462,17 @@ static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size
467 467
                     return tmp;
468 468
                 }
469 469
             }
470
-        }
471
-    }
472
-
473
-    prtn_intxn_list_free(&prtncheck);
474
-    return ret;
475
-}
476
-
477
-/* checks internal logical partitions */
478
-static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize)
479
-{
480
-    struct mbr_boot_record ebr;
481
-    prtn_intxn_list_t prtncheck;
482
-    unsigned i, j, pitxn;
483
-    int ret = 0, tmp = 0;
484
-    off_t pos = 0, exoff = 0, exloff = 0;
485
-
486
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
487
-        if (mbr.entries[i].type == MBR_EXTENDED) {
488
-
489
-            prtn_intxn_list_init(&prtncheck);
490
-
491
-            exoff = mbr.entries[i].firstLBA;
492
-            exloff = 0; j = 0;
493
-            do {
494
-                pos = exoff * sectorsize; /* start of extended partition */
495
-
496
-                /* read the extended boot record */
497
-                pos += (exloff * sectorsize) + MBR_BASE_OFFSET;
498
-                if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
499
-                    cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
500
-                    prtn_intxn_list_free(&prtncheck);
501
-                    return CL_EFORMAT;
502
-                }
503 470
 
504
-                /* convert the little endian to host */
505
-                mbr_convert_to_host(&ebr);
506
-
507
-                /* assume that logical record is first and extended is second */
508
-                tmp = prtn_intxn_list_check(&prtncheck, &pitxn, exloff, ebr.entries[0].numSectors);
471
+            if (mbr.entries[i].type == MBR_EXTENDED) {
472
+                /* check the logical partitions */
473
+                tmp = mbr_extended_prtn_intxn(ctx, &prtncount, 
474
+                                  mbr.entries[i].firstLBA, sectorsize);
509 475
                 if (tmp != CL_CLEAN) {
510 476
                     if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
511
-                        cli_dbgmsg("cli_scanebr: detected intersection with partitions "
512
-                                   "[%u, %u]\n", pitxn, i);
513
-                        cli_append_virus(ctx, "Heuristic.PartitionIntersection");
514 477
                         ret = tmp;
515 478
                         tmp = 0;
516 479
                     }
517 480
                     else if (tmp == CL_VIRUS) {
518
-                        cli_dbgmsg("cli_scanebr: detected intersection with partitions "
519
-                                   "[%u, %u]\n", pitxn, i);
520
-                        cli_append_virus(ctx, "Heuristic.PartitionIntersection");
521 481
                         prtn_intxn_list_free(&prtncheck);
522 482
                         return CL_VIRUS;
523 483
                     }
... ...
@@ -526,27 +481,80 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, siz
526 526
                         return tmp;
527 527
                     }
528 528
                 }
529
+            }
530
+            else {
531
+                prtncount++;
532
+            }
533
+        }
534
+    }
529 535
 
530
-                /* assume extended is second entry */
531
-                if (ebr.entries[1].type != MBR_EXTENDED) {
532
-                    cli_dbgmsg("cli_scanebr: second entry for EBR is not an extended partition\n");
533
-                    break;
534
-                }
536
+    prtn_intxn_list_free(&prtncheck);
537
+    return ret;
538
+}
539
+
540
+/* checks internal logical partitions */
541
+static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size_t sectorsize)
542
+{
543
+    struct mbr_boot_record ebr;
544
+    prtn_intxn_list_t prtncheck;
545
+    unsigned i, pitxn;
546
+    int ret = 0, tmp = 0;
547
+    off_t pos = 0, logiclba = 0;
548
+
549
+    prtn_intxn_list_init(&prtncheck);
535 550
 
536
-                exloff = ebr.entries[1].firstLBA;
551
+    logiclba = 0; i = 0;
552
+    do {
553
+        pos = extlba * sectorsize; /* start of extended partition */
537 554
 
538
-                ++j;
539
-            } while (exloff != 0 && j < CL_MAX_LOGICAL_PARTITIONS);
555
+        /* read the extended boot record */
556
+        pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
557
+        if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
558
+            cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
559
+            prtn_intxn_list_free(&prtncheck);
560
+            return CL_EFORMAT;
561
+        }
540 562
 
541
-            if (j == CL_MAX_LOGICAL_PARTITIONS) {
542
-                cli_dbgmsg("cli_scanebr: reached maximum number of scanned logical partitions\n");
563
+        /* convert the little endian to host */
564
+        mbr_convert_to_host(&ebr);
565
+
566
+        /* update state */
567
+        (*prtncount)++;
568
+
569
+        /* assume that logical record is first and extended is second */
570
+        tmp = prtn_intxn_list_check(&prtncheck, &pitxn, logiclba, ebr.entries[0].numLBA);
571
+        if (tmp != CL_CLEAN) {
572
+            if ((ctx->options & CL_SCAN_ALLMATCHES) && (tmp == CL_VIRUS)) {
573
+                cli_dbgmsg("cli_scanebr: detected intersection with partitions "
574
+                           "[%u, %u]\n", pitxn, i);
575
+                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
576
+                ret = tmp;
577
+                tmp = 0;
578
+            }
579
+            else if (tmp == CL_VIRUS) {
580
+                cli_dbgmsg("cli_scanebr: detected intersection with partitions "
581
+                           "[%u, %u]\n", pitxn, i);
582
+                cli_append_virus(ctx, PRTN_INTXN_DETECTION);
583
+                prtn_intxn_list_free(&prtncheck);
584
+                return CL_VIRUS;
543 585
             }
586
+            else {
587
+                prtn_intxn_list_free(&prtncheck);
588
+                return tmp;
589
+            }
590
+        }
544 591
 
545
-            prtn_intxn_list_free(&prtncheck);    
592
+        /* assume extended is second entry */
593
+        if (ebr.entries[1].type != MBR_EXTENDED) {
594
+            cli_dbgmsg("cli_scanebr: second entry for EBR is not an extended partition\n");
595
+            break;
546 596
         }
547
-    }
548 597
 
598
+        logiclba = ebr.entries[1].firstLBA;
549 599
 
550
-    return ret;
600
+        ++i;
601
+    } while (logiclba != 0 && (*prtncount) < ctx->engine->maxpartitions);
551 602
 
603
+    prtn_intxn_list_free(&prtncheck);    
604
+    return ret;
552 605
 }
... ...
@@ -66,7 +66,7 @@ struct mbr_partition_entry {
66 66
     uint8_t type;
67 67
     uint8_t lastCHS[3];
68 68
     uint32_t firstLBA  __attribute__ ((packed));
69
-    uint32_t numSectors  __attribute__ ((packed));
69
+    uint32_t numLBA  __attribute__ ((packed));
70 70
 };
71 71
 
72 72
 struct mbr_boot_record {