Skip to content

Commit

Permalink
gpt/mbr: added support to specify sector size
Browse files Browse the repository at this point in the history
gpt: added sector size calculation function
  • Loading branch information
Kevin Lin committed Feb 10, 2014
1 parent 0b3aa06 commit 00acb79
Show file tree
Hide file tree
Showing 6 changed files with 68 additions and 26 deletions.
3 changes: 2 additions & 1 deletion libclamav/filetypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@
#include "default.h"
#include "iowrap.h"
#include "mbr.h"
#include "gpt.h"

#include "htmlnorm.h"
#include "entconv.h"
Expand Down Expand Up @@ -312,7 +313,7 @@ cli_file_t cli_filetype2(fmap_t *map, const struct cl_engine *engine, cli_file_t
/* raw dmgs must be a multiple of 512 */
if ((map->len % 512) == 0 && map->len > 512) {
/* check if detected MBR is protective on GPT */
if (0 == memcmp(rbuff, "EFI PART", 8)) {
if (gpt_detect_size(map) != 0) {
cli_dbgmsg("Recognized GUID Partition Table file\n");
return CL_TYPE_GPT;
}
Expand Down
40 changes: 36 additions & 4 deletions libclamav/gpt.c
Original file line number Diff line number Diff line change
Expand Up @@ -68,12 +68,37 @@ static void gpt_printName(uint16_t name[], const char* msg);
static void gpt_printGUID(uint8_t GUID[], const char* msg);
static int gpt_prtn_intxn(cli_ctx *ctx, struct gpt_header hdr, size_t sectorsize);

int cli_scangpt(cli_ctx *ctx)
/* returns 0 on failing to detect sectorsize */
size_t gpt_detect_size(fmap_t *map)
{
unsigned char *buff;

buff = (unsigned char*)fmap_need_off_once(map, 512, 8);
if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
return 512;

buff = (unsigned char*)fmap_need_off_once(map, 1024, 8);
if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
return 1024;

buff = (unsigned char*)fmap_need_off_once(map, 2048, 8);
if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
return 2048;

buff = (unsigned char*)fmap_need_off_once(map, 4096, 8);
if (0 == strncmp(buff, GPT_SIGNATURE_STR, 8))
return 4096;

return 0;
}

/* attempts to detect sector size is input as 0 */
int cli_scangpt(cli_ctx *ctx, size_t sectorsize)
{
struct gpt_header phdr, shdr;
enum GPT_SCANSTATE state = INVALID;
int ret = 0;
size_t sectorsize, maplen;
size_t maplen;
off_t pos = 0;

gpt_parsemsg("The beginning of something big: GPT parsing\n");
Expand All @@ -84,7 +109,14 @@ int cli_scangpt(cli_ctx *ctx)
}

/* sector size calculatation */
sectorsize = GPT_DEFAULT_SECTOR_SIZE;
if (sectorsize == 0) {
sectorsize = gpt_detect_size((*ctx->fmap));
cli_errmsg("cli_scangpt: detected %u sector size\n", sectorsize);
}
if (sectorsize == 0) {
cli_errmsg("cli_scangpt: could not detemine sector size\n");
return CL_EFORMAT;
}

/* size of total file must be a multiple of the sector size */
maplen = (*ctx->fmap)->real_len;
Expand Down Expand Up @@ -395,7 +427,7 @@ static int gpt_validate_header(cli_ctx *ctx, struct gpt_header hdr, size_t secto
}

/* check that valid table entry size */
if (hdr.tableEntrySize != GPT_PARTITION_ENTRY_SIZE) {
if (hdr.tableEntrySize != sizeof(struct gpt_partition_entry)) {
cli_dbgmsg("cli_scangpt: cannot parse gpt with partition entry sized %u\n",
hdr.tableEntrySize);
return CL_EFORMAT;
Expand Down
7 changes: 3 additions & 4 deletions libclamav/gpt.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,10 +32,8 @@
* values. Sector size for GPT can be found by the offset the GPT header
* signature is located (marking the beginning of the second sector.
*/
#define GPT_DEFAULT_SECTOR_SIZE 512
#define GPT_PARTITION_ENTRY_SIZE 128

#define GPT_SIGNATURE 0x4546492050415254ULL
#define GPT_SIGNATURE_STR "EFI PART"
#define GPT_PRIMARY_HDR_LBA 1
#define GPT_HDR_RESERVED 0

Expand Down Expand Up @@ -95,6 +93,7 @@ struct gpt_partition_entry {
#pragma pack
#endif

int cli_scangpt(cli_ctx *ctx);
size_t gpt_detect_size(fmap_t *map);
int cli_scangpt(cli_ctx *ctx, size_t sectorsize);

#endif
37 changes: 24 additions & 13 deletions libclamav/mbr.c
Original file line number Diff line number Diff line change
Expand Up @@ -75,27 +75,31 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl

int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen) {
struct mbr_boot_record mbr;
off_t mbr_base = 0;
size_t sectorsize = 512;

if (len < 512) {
if (len < sectorsize) {
return CL_EFORMAT;
}

memcpy(&mbr, buff+MBR_BASE_OFFSET, sizeof(mbr));
mbr_base = sectorsize - sizeof(struct mbr_boot_record);
memcpy(&mbr, buff+mbr_base, sizeof(mbr));
mbr_convert_to_host(&mbr);

//mbr_printbr(&mbr);

return mbr_check_mbr(&mbr, maplen, MBR_SECTOR_SIZE);
return mbr_check_mbr(&mbr, maplen, sectorsize);
}

int cli_scanmbr(cli_ctx *ctx)
/* sets sectorsize to default value if specfied to be 0 */
int cli_scanmbr(cli_ctx *ctx, size_t sectorsize)
{
struct mbr_boot_record mbr;
enum MBR_STATE state = SEEN_NOTHING;
int ret = CL_CLEAN;
off_t pos = 0, partoff = 0;
off_t pos = 0, mbr_base = 0, partoff = 0;
unsigned i = 0, prtncount = 0;
size_t sectorsize, maplen, partsize;
size_t maplen, partsize;

mbr_parsemsg("The start of something magnificant: MBR parsing\n");

Expand All @@ -105,7 +109,10 @@ int cli_scanmbr(cli_ctx *ctx)
}

/* sector size calculation, actual value is OS dependent */
sectorsize = MBR_SECTOR_SIZE;
if (sectorsize == 0)
sectorsize = MBR_SECTOR_SIZE;

mbr_base = sectorsize - sizeof(struct mbr_boot_record);

/* size of total file must be a multiple of the sector size */
maplen = (*ctx->fmap)->real_len;
Expand All @@ -116,7 +123,7 @@ int cli_scanmbr(cli_ctx *ctx)
}

/* sector 0 (first sector) is the master boot record */
pos = (MBR_SECTOR * sectorsize) + MBR_BASE_OFFSET;
pos = (MBR_SECTOR * sectorsize) + mbr_base;

/* read the master boot record */
if (fmap_readn(*ctx->fmap, &mbr, pos, sizeof(mbr)) != sizeof(mbr)) {
Expand All @@ -134,7 +141,7 @@ int cli_scanmbr(cli_ctx *ctx)
}

/* MBR is valid, examine bootstrap code */
ret = cli_map_scan(*ctx->fmap, 0, MBR_BASE_OFFSET, ctx, CL_TYPE_FILE_ANY);
ret = cli_map_scan(*ctx->fmap, 0, sectorsize, ctx, CL_TYPE_ANY);
if ((ret != CL_CLEAN) &&
!((ctx->options & CL_SCAN_ALLMATCHES) && (ret == CL_VIRUS))) {
return ret;
Expand Down Expand Up @@ -206,20 +213,22 @@ static int mbr_scanextprtn(cli_ctx *ctx, unsigned *prtncount, off_t extlba, size
struct mbr_boot_record ebr;
enum MBR_STATE state = SEEN_NOTHING;
int ret = CL_CLEAN;
off_t pos = 0, logiclba = 0, extoff = 0, partoff = 0;
off_t pos = 0, mbr_base = 0, logiclba = 0, extoff = 0, partoff = 0;
size_t partsize, extsize;
unsigned i = 0, j = 0;

ebr_parsemsg("The start of something exhausting: EBR parsing\n");

mbr_base = sectorsize - sizeof(struct mbr_boot_record);

logiclba = 0;
extoff = extlba * sectorsize;
extsize = extlbasize * sectorsize;
do {
pos = extlba * sectorsize; /* start of extended partition */

/* read the extended boot record */
pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
pos += (logiclba * sectorsize) + mbr_base;
if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
return CL_EFORMAT;
Expand Down Expand Up @@ -506,17 +515,19 @@ static int mbr_extended_prtn_intxn(cli_ctx *ctx, unsigned *prtncount, off_t extl
struct mbr_boot_record ebr;
prtn_intxn_list_t prtncheck;
unsigned i, pitxn;
int ret = 0, tmp = 0;
int ret = 0, mbr_base = 0, tmp = 0;
off_t pos = 0, logiclba = 0;

mbr_base = sectorsize - sizeof(struct mbr_boot_record);

prtn_intxn_list_init(&prtncheck);

logiclba = 0; i = 0;
do {
pos = extlba * sectorsize; /* start of extended partition */

/* read the extended boot record */
pos += (logiclba * sectorsize) + MBR_BASE_OFFSET;
pos += (logiclba * sectorsize) + mbr_base;
if (fmap_readn(*ctx->fmap, &ebr, pos, sizeof(ebr)) != sizeof(ebr)) {
cli_dbgmsg("cli_scanebr: Invalid extended boot record\n");
prtn_intxn_list_free(&prtncheck);
Expand Down
3 changes: 1 addition & 2 deletions libclamav/mbr.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@
#define CL_MAX_LOGICAL_PARTITIONS 50

#define MBR_SIGNATURE 0x55aa
#define MBR_BASE_OFFSET 446
#define MBR_SECTOR 0

/* MBR Status */
Expand Down Expand Up @@ -84,6 +83,6 @@ struct mbr_boot_record {
#endif

int cli_mbr_check(const unsigned char *buff, size_t len, size_t maplen);
int cli_scanmbr(cli_ctx *ctx);
int cli_scanmbr(cli_ctx *ctx, size_t sectorsize);

#endif
4 changes: 2 additions & 2 deletions libclamav/scanners.c
Original file line number Diff line number Diff line change
Expand Up @@ -2587,12 +2587,12 @@ static int magic_scandesc(cli_ctx *ctx, cli_file_t type)

case CL_TYPE_MBR:
//if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_MBR))
ret = cli_scanmbr(ctx);
ret = cli_scanmbr(ctx, 0);
break;

case CL_TYPE_GPT:
//if(SCAN_ARCHIVE && (DCONF_ARCH & ARCH_CONF_GPT))
ret = cli_scangpt(ctx);
ret = cli_scangpt(ctx, 0);
break;

case CL_TYPE_APM:
Expand Down

0 comments on commit 00acb79

Please sign in to comment.