Browse code

gpt: warning on non-protective mbr detection

Kevin Lin authored on 2014/02/11 07:08:45
Showing 3 changed files
... ...
@@ -34,6 +34,7 @@
34 34
 #include "cltypes.h"
35 35
 #include "others.h"
36 36
 #include "gpt.h"
37
+#include "mbr.h"
37 38
 #include "str.h"
38 39
 #include "prtn_intxn.h"
39 40
 #include "scanners.h"
... ...
@@ -63,6 +64,7 @@ enum GPT_SCANSTATE {
63 63
 
64 64
 static int gpt_scan_partitions(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize);
65 65
 static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize);
66
+static int gpt_check_mbr(cli_ctx *ctx, size_t sectorsize);
66 67
 static void gpt_printSectors(cli_ctx *ctx, size_t sectorsize);
67 68
 static void gpt_printName(uint16_t name[], const char* msg);
68 69
 static void gpt_printGUID(uint8_t GUID[], const char* msg);
... ...
@@ -111,7 +113,7 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
111 111
     /* sector size calculatation */
112 112
     if (sectorsize == 0) {
113 113
         sectorsize = gpt_detect_size((*ctx->fmap));
114
-        cli_errmsg("cli_scangpt: detected %u sector size\n", sectorsize);
114
+        cli_dbgmsg("cli_scangpt: detected %u sector size\n", sectorsize);
115 115
     }
116 116
     if (sectorsize == 0) {
117 117
         cli_errmsg("cli_scangpt: could not detemine sector size\n");
... ...
@@ -126,6 +128,14 @@ int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
126 126
         return CL_EFORMAT;
127 127
     }
128 128
 
129
+    /* check the protective mbr */
130
+    ret = gpt_check_mbr(ctx, sectorsize);
131
+    if ((ret != CL_CLEAN) &&
132
+        !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
133
+
134
+        return ret;
135
+    }
136
+
129 137
     pos = GPT_PRIMARY_HDR_LBA * sectorsize; /* sector 1 (second sector) is the primary gpt header */
130 138
 
131 139
     /* read primary gpt header */
... ...
@@ -454,6 +464,58 @@ static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t secto
454 454
     return CL_SUCCESS;
455 455
 }
456 456
 
457
+static int gpt_check_mbr(cli_ctx *ctx, size_t sectorsize)
458
+{
459
+    struct mbr_boot_record pmbr;
460
+    off_t pos = 0, mbr_base = 0;
461
+    int ret = CL_CLEAN;
462
+    unsigned i = 0;
463
+
464
+    /* read the mbr */
465
+    mbr_base = sectorsize - sizeof(struct mbr_boot_record);
466
+    pos = (MBR_SECTOR * sectorsize) + mbr_base;
467
+
468
+    if (fmap_readn(*ctx->fmap, &pmbr, pos, sizeof(pmbr)) != sizeof(pmbr)) {
469
+        cli_dbgmsg("cli_scangpt: Invalid primary MBR header\n");
470
+        return CL_EFORMAT;
471
+    }
472
+
473
+    /* convert mbr */
474
+    mbr_convert_to_host(&pmbr);
475
+
476
+    /* check the protective mbr - warning */
477
+    if (pmbr.entries[0].type == MBR_PROTECTIVE) {
478
+        /* check the efi partition matches the gpt spec */
479
+        if (pmbr.entries[0].firstLBA != GPT_PRIMARY_HDR_LBA) {
480
+            cli_warnmsg("cli_scangpt: protective MBR first LBA is incorrect %u\n",
481
+                        pmbr.entries[0].firstLBA);
482
+        }
483
+
484
+        /* other entries are empty */
485
+        for (i = 1; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
486
+            if (pmbr.entries[i].type != MBR_EMPTY) {
487
+                cli_warnmsg("cli_scangpt: protective MBR has non-empty partition\n");
488
+                break;
489
+            }
490
+        }
491
+    }
492
+    else if (pmbr.entries[0].type == MBR_HYBRID) {
493
+        /* hybrid mbr detected */
494
+        cli_warnmsg("cli_scangpt: detected a hybrid MBR\n");
495
+    }
496
+    else {
497
+        /* non-protective mbr detected */
498
+        cli_warnmsg("cli_scangpt: detected a non-protective MBR\n");
499
+    }
500
+
501
+    /* scan the bootloader segment - pushed to scanning mbr */
502
+    /* check if MBR size matches GPT size */
503
+    /* check if the MBR and GPT partitions align - heuristic */
504
+    /* scan the MBR partitions - additional scans */
505
+
506
+    return ret;
507
+}
508
+
457 509
 static void gpt_printSectors(cli_ctx *ctx, size_t sectorsize)
458 510
 {
459 511
 #ifdef DEBUG_GPT_PARSE
... ...
@@ -67,7 +67,6 @@ enum MBR_STATE {
67 67
 static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, 
68 68
                            size_t extlbasize, size_t sectorsize);
69 69
 static void mbr_printbr(struct mbr_boot_record *record);
70
-static void mbr_convert_to_host(struct mbr_boot_record *record);
71 70
 static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize);
72 71
 static int mbr_check_ebr(struct mbr_boot_record *record);
73 72
 static int mbr_primary_prtn_intxn(cli_ctx *ctx, struct mbr_boot_record mbr, size_t sectorsize);
... ...
@@ -273,11 +272,11 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
273 273
                         logiclba = 0;
274 274
                         /* fall-through */
275 275
                     case SEEN_EXTENDED:
276
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
277
-                                   "without a partition record\n");
276
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
277
+                                    "without a partition record\n");
278 278
                         break;
279 279
                     default:
280
-                        cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
280
+                        cli_warnmsg("cli_scanebr: undefined state for EBR parsing\n");
281 281
                         return CL_EPARSE;
282 282
                     }
283 283
                 }
... ...
@@ -289,12 +288,12 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
289 289
                     case SEEN_PARTITION:
290 290
                         break;
291 291
                     case SEEN_EMPTY:
292
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
293
-                                   "without a partition record\n");
292
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
293
+                                    "without a partition record\n");
294 294
                         break;
295 295
                     case SEEN_EXTENDED:
296
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
297
-                                   "with multiple extended partition records\n");
296
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
297
+                                    "with multiple extended partition records\n");
298 298
                         return CL_EFORMAT;
299 299
                     default:
300 300
                         cli_dbgmsg("cli_scanebr: undefined state for EBR parsing\n");
... ...
@@ -309,17 +308,17 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
309 309
                         state = SEEN_PARTITION;
310 310
                         break;
311 311
                     case SEEN_PARTITION:
312
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
313
-                                   "with multiple partition records\n");
312
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
313
+                                    "with multiple partition records\n");
314 314
                         logiclba = 0; /* no extended partitions are possible */
315 315
                         break;
316 316
                     case SEEN_EXTENDED:
317
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
318
-                                   "with extended partition record first\n");
317
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
318
+                                    "with extended partition record first\n");
319 319
                         break;
320 320
                     case SEEN_EMPTY:
321
-                        cli_dbgmsg("cli_scanebr: detected a logical boot record "
322
-                                   "with empty partition record first\n");
321
+                        cli_warnmsg("cli_scanebr: detected a logical boot record "
322
+                                    "with empty partition record first\n");
323 323
                         logiclba = 0; /* no extended partitions are possible */
324 324
                         break;
325 325
                     default:
... ...
@@ -357,6 +356,20 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
357 357
     return ret;
358 358
 }
359 359
 
360
+void mbr_convert_to_host(struct mbr_boot_record *record)
361
+{
362
+    struct mbr_partition_entry *entry;
363
+    unsigned i;
364
+ 
365
+    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
366
+        entry = &record->entries[i];
367
+ 
368
+        entry->firstLBA = le32_to_host(entry->firstLBA);
369
+        entry->numLBA = le32_to_host(entry->numLBA);
370
+    }
371
+    record->signature = be16_to_host(record->signature);
372
+}
373
+
360 374
 static void mbr_printbr(struct mbr_boot_record *record)
361 375
 {
362 376
     unsigned i;
... ...
@@ -375,20 +388,6 @@ static void mbr_printbr(struct mbr_boot_record *record)
375 375
     }
376 376
 }
377 377
 
378
-static void mbr_convert_to_host(struct mbr_boot_record *record)
379
-{
380
-    struct mbr_partition_entry *entry;
381
-    unsigned i;
382
- 
383
-    for (i = 0; i < MBR_MAX_PARTITION_ENTRIES; ++i) {
384
-        entry = &record->entries[i];
385
- 
386
-        entry->firstLBA = le32_to_host(entry->firstLBA);
387
-        entry->numLBA = le32_to_host(entry->numLBA);
388
-    }
389
-    record->signature = be16_to_host(record->signature);
390
-}
391
-
392 378
 static int mbr_check_mbr(struct mbr_boot_record *record, size_t maplen, size_t sectorsize)
393 379
 {
394 380
     unsigned i = 0;
... ...
@@ -44,6 +44,8 @@
44 44
 /* MBR Partition Types */
45 45
 #define MBR_EMPTY      0x00
46 46
 #define MBR_EXTENDED   0x05
47
+#define MBR_HYBRID     0xed
48
+#define MBR_PROTECTIVE 0xee
47 49
 /* End Partition Types */
48 50
 
49 51
 #ifndef HAVE_ATTRIB_PACKED
... ...
@@ -84,5 +86,6 @@ struct mbr_boot_record {
84 84
 
85 85
 int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen);
86 86
 int cli_scanmbr(cli_ctx *ctx, size_t sectorsize);
87
+void mbr_convert_to_host(struct mbr_boot_record *record);
87 88
 
88 89
 #endif