Browse code

gpt/mbr: added support to specify sector size gpt: added sector size calculation function

Kevin Lin authored on 2014/02/11 02:00:01
Showing 6 changed files
... ...
@@ -40,6 +40,7 @@
40 40
 #include "default.h"
41 41
 #include "iowrap.h"
42 42
 #include "mbr.h"
43
+#include "gpt.h"
43 44
 
44 45
 #include "htmlnorm.h"
45 46
 #include "entconv.h"
... ...
@@ -312,7 +313,7 @@ cli_file_t cli_filetype2(fmap_t *map, const struct cl_engine *engine, cli_file_t
312 312
             /* raw dmgs must be a multiple of 512 */
313 313
             if ((map->len % 512) == 0 && map->len > 512) {
314 314
                 /* check if detected MBR is protective on GPT */
315
-                if (0 == memcmp(rbuff, "EFI PART", 8)) {
315
+                if (gpt_detect_size(map) != 0) {
316 316
                     cli_dbgmsg("Recognized GUID Partition Table file\n");
317 317
                     return CL_TYPE_GPT;
318 318
                 }
... ...
@@ -68,12 +68,37 @@ static void gpt_printName(uint16_t name[], const char* msg);
68 68
 static void gpt_printGUID(uint8_t GUID[], const char* msg);
69 69
 static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize);
70 70
 
71
-int cli_scangpt(cli_ctx *ctx)
71
+/* returns 0 on failing to detect sectorsize */
72
+size_t gpt_detect_size(fmap_t *map)
73
+{
74
+    unsigned char *buff;
75
+
76
+    buff = (unsigned char*)fmap_need_off_once(map, 512, 8);
77
+    if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
78
+        return 512;
79
+
80
+    buff = (unsigned char*)fmap_need_off_once(map, 1024, 8);
81
+    if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
82
+        return 1024;
83
+
84
+    buff = (unsigned char*)fmap_need_off_once(map, 2048, 8);
85
+    if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
86
+        return 2048;
87
+
88
+    buff = (unsigned char*)fmap_need_off_once(map, 4096, 8);
89
+    if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
90
+        return 4096;
91
+
92
+    return 0;
93
+}
94
+
95
+/* attempts to detect sector size is input as 0 */
96
+int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
72 97
 {
73 98
     struct gpt_header phdr, shdr;
74 99
     enum GPT_SCANSTATE state = INVALID;
75 100
     int ret = 0;
76
-    size_t sectorsize, maplen;
101
+    size_t maplen;
77 102
     off_t pos = 0;
78 103
 
79 104
     gpt_parsemsg("The beginning of something big: GPT parsing\n");
... ...
@@ -84,7 +109,14 @@ int cli_scangpt(cli_ctx *ctx)
84 84
     }
85 85
 
86 86
     /* sector size calculatation */
87
-    sectorsize = GPT_DEFAULT_SECTOR_SIZE;
87
+    if (sectorsize == 0) {
88
+        sectorsize = gpt_detect_size((*ctx->fmap));
89
+        cli_errmsg("cli_scangpt: detected %u sector size\n", sectorsize);
90
+    }
91
+    if (sectorsize == 0) {
92
+        cli_errmsg("cli_scangpt: could not detemine sector size\n");
93
+        return CL_EFORMAT;
94
+    }
88 95
 
89 96
     /* size of total file must be a multiple of the sector size */
90 97
     maplen = (*ctx->fmap)->real_len;
... ...
@@ -395,7 +427,7 @@ static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t secto
395 395
     }
396 396
 
397 397
     /* check that valid table entry size */
398
-    if (hdr.tableEntrySize != GPT_PARTITION_ENTRY_SIZE) {
398
+    if (hdr.tableEntrySize != sizeof(struct gpt_partition_entry)) {
399 399
         cli_dbgmsg("cli_scangpt: cannot parse gpt with partition entry sized %u\n",
400 400
                    hdr.tableEntrySize);
401 401
         return CL_EFORMAT;
... ...
@@ -32,10 +32,8 @@
32 32
  * values. Sector size for GPT can be found by the offset the GPT header
33 33
  * signature is located (marking the beginning of the second sector.
34 34
 */
35
-#define GPT_DEFAULT_SECTOR_SIZE 512
36
-#define GPT_PARTITION_ENTRY_SIZE 128
37
-
38 35
 #define GPT_SIGNATURE 0x4546492050415254ULL
36
+#define GPT_SIGNATURE_STR "EFI PART"
39 37
 #define GPT_PRIMARY_HDR_LBA 1
40 38
 #define GPT_HDR_RESERVED 0
41 39
 
... ...
@@ -95,6 +93,7 @@ struct gpt_partition_entry {
95 95
 #pragma pack
96 96
 #endif
97 97
 
98
-int cli_scangpt(cli_ctx *ctx);
98
+size_t gpt_detect_size(fmap_t *map);
99
+int cli_scangpt(cli_ctx *ctx, size_t sectorsize);
99 100
 
100 101
 #endif
... ...
@@ -75,27 +75,31 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
75 75
 
76 76
 int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) {
77 77
     struct mbr_boot_record mbr;
78
+    off_t mbr_base = 0;
79
+    size_t sectorsize = 512;
78 80
 
79
-    if (len < 512) {
81
+    if (len < sectorsize) {
80 82
         return CL_EFORMAT;
81 83
     }
82 84
 
83
-    memcpy(&mbr, buff+MBR_BASE_OFFSET, sizeof(mbr));
85
+    mbr_base = sectorsize - sizeof(struct mbr_boot_record);
86
+    memcpy(&mbr, buff+mbr_base, sizeof(mbr));
84 87
     mbr_convert_to_host(&mbr);
85 88
 
86 89
     //mbr_printbr(&mbr);
87 90
 
88
-    return mbr_check_mbr(&mbr, maplen, MBR_SECTOR_SIZE);
91
+    return mbr_check_mbr(&mbr, maplen, sectorsize);
89 92
 }
90 93
 
91
-int cli_scanmbr(cli_ctx *ctx)
94
+/* sets sectorsize to default value if specfied to be 0 */
95
+int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
92 96
 {
93 97
     struct mbr_boot_record mbr;
94 98
     enum MBR_STATE state = SEEN_NOTHING;
95 99
     int ret = CL_CLEAN;
96
-    off_t pos = 0, partoff = 0;
100
+    off_t pos = 0, mbr_base = 0, partoff = 0;
97 101
     unsigned i = 0, prtncount = 0;
98
-    size_t sectorsize, maplen, partsize;
102
+    size_t maplen, partsize;
99 103
 
100 104
     mbr_parsemsg("The start of something magnificant: MBR parsing\n");
101 105
 
... ...
@@ -105,7 +109,10 @@ int cli_scanmbr(cli_ctx *ctx)
105 105
     }
106 106
 
107 107
     /* sector size calculation, actual value is OS dependent */
108
-    sectorsize = MBR_SECTOR_SIZE;
108
+    if (sectorsize == 0)
109
+        sectorsize = MBR_SECTOR_SIZE;
110
+
111
+    mbr_base = sectorsize - sizeof(struct mbr_boot_record);
109 112
 
110 113
     /* size of total file must be a multiple of the sector size */
111 114
     maplen = (*ctx->fmap)->real_len;
... ...
@@ -116,7 +123,7 @@ int cli_scanmbr(cli_ctx *ctx)
116 116
     }
117 117
 
118 118
     /* sector 0 (first sector) is the master boot record */
119
-    pos = (MBR_SECTOR * sectorsize) + MBR_BASE_OFFSET;
119
+    pos = (MBR_SECTOR * sectorsize) + mbr_base;
120 120
 
121 121
     /* read the master boot record */
122 122
     if (fmap_readn(*ctx->fmap, &mbr, pos, sizeof(mbr)) != sizeof(mbr)) {
... ...
@@ -134,7 +141,7 @@ int cli_scanmbr(cli_ctx *ctx)
134 134
     }
135 135
 
136 136
     /* MBR is valid, examine bootstrap code */
137
-    ret = cli_map_scan(*ctx->fmap, 0, MBR_BASE_OFFSET, ctx, CL_TYPE_FILE_ANY);
137
+    ret = cli_map_scan(*ctx->fmap, 0, sectorsize, ctx, CL_TYPE_ANY);
138 138
     if ((ret != CL_CLEAN) &&
139 139
         !((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
140 140
         return ret;
... ...
@@ -206,12 +213,14 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
206 206
     struct mbr_boot_record ebr;
207 207
     enum MBR_STATE state = SEEN_NOTHING;
208 208
     int ret = CL_CLEAN;
209
-    off_t pos = 0, logiclba = 0, extoff = 0, partoff = 0;
209
+    off_t pos = 0, mbr_base = 0, logiclba = 0, extoff = 0, partoff = 0;
210 210
     size_t partsize, extsize;
211 211
     unsigned i = 0, j = 0;
212 212
 
213 213
     ebr_parsemsg("The start of something exhausting: EBR parsing\n");
214 214
 
215
+    mbr_base = sectorsize - sizeof(struct mbr_boot_record);
216
+
215 217
     logiclba = 0;
216 218
     extoff = extlba * sectorsize;
217 219
     extsize = extlbasize * sectorsize;
... ...
@@ -219,7 +228,7 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
219 219
         pos = extlba * sectorsize; /* start of extended partition */
220 220
 
221 221
         /* read the extended boot record */
222
-        pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
222
+        pos += (logiclba * sectorsize) + mbr_base;
223 223
         if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
224 224
             cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
225 225
             return CL_EFORMAT;
... ...
@@ -506,9 +515,11 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
506 506
     struct mbr_boot_record ebr;
507 507
     prtn_intxn_list_t prtncheck;
508 508
     unsigned i, pitxn;
509
-    int ret = 0, tmp = 0;
509
+    int ret = 0, mbr_base = 0, tmp = 0;
510 510
     off_t pos = 0, logiclba = 0;
511 511
 
512
+    mbr_base = sectorsize - sizeof(struct mbr_boot_record);
513
+
512 514
     prtn_intxn_list_init(&prtncheck);
513 515
 
514 516
     logiclba = 0; i = 0;
... ...
@@ -516,7 +527,7 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
516 516
         pos = extlba * sectorsize; /* start of extended partition */
517 517
 
518 518
         /* read the extended boot record */
519
-        pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
519
+        pos += (logiclba * sectorsize) + mbr_base;
520 520
         if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
521 521
             cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
522 522
             prtn_intxn_list_free(&prtncheck);
... ...
@@ -33,7 +33,6 @@
33 33
 #define CL_MAX_LOGICAL_PARTITIONS 50
34 34
 
35 35
 #define MBR_SIGNATURE 0x55aa
36
-#define MBR_BASE_OFFSET 446
37 36
 #define MBR_SECTOR 0
38 37
 
39 38
 /* MBR Status */
... ...
@@ -84,6 +83,6 @@ struct mbr_boot_record {
84 84
 #endif
85 85
 
86 86
 int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen);
87
-int cli_scanmbr(cli_ctx *ctx);
87
+int cli_scanmbr(cli_ctx *ctx, size_t sectorsize);
88 88
 
89 89
 #endif
... ...
@@ -2587,12 +2587,12 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)
2587 2587
 
2588 2588
 	case CL_TYPE_MBR:
2589 2589
 	    //if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_MBR))
2590
-		ret = cli_scanmbr(ctx);
2590
+	    ret = cli_scanmbr(ctx, 0);
2591 2591
 	    break;
2592 2592
 
2593 2593
 	case CL_TYPE_GPT:
2594 2594
 	    //if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GPT))
2595
-		ret = cli_scangpt(ctx);
2595
+	    ret = cli_scangpt(ctx, 0);
2596 2596
 	    break;
2597 2597
 
2598 2598
 	case CL_TYPE_APM: