summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorChristophe Grenier <grenier@cgsecurity.org>2012-08-12 20:43:38 +0200
committerChristophe Grenier <grenier@cgsecurity.org>2012-08-12 20:43:38 +0200
commit88372cd6b6176c21d9b870518b3d513f1f2317bd (patch)
tree500987779181b1b003095654ed774e438d4ddd79 /src
parentde04a6886a6fb2dda1eb38c26691091f955a1918 (diff)
TestDisk: add Linux swap using 8k pagefile detection
Diffstat (limited to 'src')
-rw-r--r--src/analyse.c3
-rw-r--r--src/common.h3
-rw-r--r--src/godmode.c2
-rw-r--r--src/partnone.c11
-rw-r--r--src/swap.c73
-rw-r--r--src/swap.h9
6 files changed, 87 insertions, 14 deletions
diff --git a/src/analyse.c b/src/analyse.c
index c901c9b..b39a6a7 100644
--- a/src/analyse.c
+++ b/src/analyse.c
@@ -165,7 +165,8 @@ int search_type_0(const unsigned char *buffer, disk_t *disk, partition_t *partit
log_trace("search_type_0 lba=%lu\n",
(long unsigned)(partition->part_offset/disk->sector_size));
}
- if(memcmp(swap_header->magic.magic, "SWAP", 4)==0 &&
+ if((memcmp(swap_header->magic.magic, "SWAP", 4)==0 ||
+ memcmp(swap_header->magic8k.magic, "SWAP", 4)==0) &&
recover_Linux_SWAP(swap_header, partition)==0)
return 1;
if(memcmp((const char *)pv->id,LVM_ID,sizeof(pv->id)) == 0 &&
diff --git a/src/common.h b/src/common.h
index aa529ae..236b860 100644
--- a/src/common.h
+++ b/src/common.h
@@ -242,6 +242,9 @@ enum upart_type {
UP_JFS,
UP_LINSWAP,
UP_LINSWAP2,
+ UP_LINSWAP_8K,
+ UP_LINSWAP2_8K,
+ UP_LINSWAP2_8KBE,
UP_LUKS,
UP_LVM,
UP_LVM2,
diff --git a/src/godmode.c b/src/godmode.c
index d83ef37..c717733 100644
--- a/src/godmode.c
+++ b/src/godmode.c
@@ -689,7 +689,7 @@ static list_part_t *search_part(disk_t *disk_car, const list_part_t *list_part_o
test_nbr=14;
else
{
- if(disk_car->pread(disk_car, buffer_disk0, 8 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 8 * DEFAULT_SECTOR_SIZE)
+ if(disk_car->pread(disk_car, buffer_disk0, 16 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 16 * DEFAULT_SECTOR_SIZE)
res=search_type_2(buffer_disk0,disk_car,partition,verbose,dump_ind);
else
res=-1;
diff --git a/src/partnone.c b/src/partnone.c
index 6c49e06..03e1548 100644
--- a/src/partnone.c
+++ b/src/partnone.c
@@ -104,6 +104,9 @@ static const struct systypes none_sys_types[] = {
{UP_JFS, "JFS"},
{UP_LINSWAP, "Linux SWAP"},
{UP_LINSWAP2, "Linux SWAP 2"},
+ {UP_LINSWAP_8K, "Linux SWAP"},
+ {UP_LINSWAP2_8K, "Linux SWAP 2"},
+ {UP_LINSWAP2_8KBE, "Linux SWAP 2"},
{UP_LUKS, "Linux LUKS"},
{UP_LVM, "Linux LVM"},
{UP_LVM2, "Linux LVM2"},
@@ -195,7 +198,7 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa
partition_reset(partition,&arch_none);
if(res<=0)
{
- if(disk->pread(disk, buffer_disk, 8 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 8 * DEFAULT_SECTOR_SIZE)
+ if(disk->pread(disk, buffer_disk, 16 * DEFAULT_SECTOR_SIZE, partition->part_offset) == 16 * DEFAULT_SECTOR_SIZE)
res=search_type_2(buffer_disk, disk, partition,verbose,0);
}
if(res<=0)
@@ -208,8 +211,7 @@ static list_part_t *read_part_none(disk_t *disk, const int verbose, const int sa
}
if(res<=0)
{
- if(disk->pread(disk, buffer_disk, 4096, partition->part_offset + 4096) == 4096)
- res=search_type_8(buffer_disk, disk, partition,verbose,0);
+ res=search_type_8(buffer_disk, disk, partition,verbose,0);
}
if(res<=0)
{
@@ -376,6 +378,9 @@ static int check_part_none(disk_t *disk_car,const int verbose,partition_t *parti
break;
case UP_LINSWAP:
case UP_LINSWAP2:
+ case UP_LINSWAP_8K:
+ case UP_LINSWAP2_8K:
+ case UP_LINSWAP2_8KBE:
ret=check_Linux_SWAP(disk_car, partition);
break;
case UP_LUKS:
diff --git a/src/swap.c b/src/swap.c
index 6267087..42763d2 100644
--- a/src/swap.c
+++ b/src/swap.c
@@ -36,10 +36,13 @@
static int set_Linux_SWAP_info(const union swap_header *swap_header,partition_t *partition);
static int test_Linux_SWAP(const union swap_header *swap_header, partition_t *partition);
+/* Page size can be 4k or 8k */
+#define MAX_PAGE_SIZE 8192
+
int check_Linux_SWAP(disk_t *disk_car, partition_t *partition)
{
- unsigned char *buffer=(unsigned char*)MALLOC(SWAP_SIZE);
- if(disk_car->pread(disk_car, buffer, SWAP_SIZE, partition->part_offset) != SWAP_SIZE)
+ unsigned char *buffer=(unsigned char*)MALLOC(MAX_PAGE_SIZE);
+ if(disk_car->pread(disk_car, buffer, MAX_PAGE_SIZE, partition->part_offset) != MAX_PAGE_SIZE)
{
free(buffer);
return 1;
@@ -57,15 +60,33 @@ int check_Linux_SWAP(disk_t *disk_car, partition_t *partition)
static int set_Linux_SWAP_info(const union swap_header *swap_header,partition_t *partition)
{
partition->fsname[0]='\0';
+ partition->blocksize=4096;
switch(partition->upart_type)
{
case UP_LINSWAP:
- snprintf(partition->info,sizeof(partition->info),"SWAP version %u",swap_header->info.version);
+ snprintf(partition->info, sizeof(partition->info), "SWAP version %u, pagesize=%u",
+ le32(swap_header->info.version), partition->blocksize);
break;
case UP_LINSWAP2:
- snprintf(partition->info,sizeof(partition->info),"SWAP2 version %u",swap_header->info.version);
+ snprintf(partition->info, sizeof(partition->info), "SWAP2 version %u, pagesize=%u",
+ le32(swap_header->info.version), partition->blocksize);
/* set_part_name(partition,swap_header->info.volume_name,16); */
break;
+ case UP_LINSWAP_8K:
+ partition->blocksize=8192;
+ snprintf(partition->info, sizeof(partition->info), "SWAP version %u, pagesize=%u",
+ le32(swap_header->info.version), partition->blocksize);
+ break;
+ case UP_LINSWAP2_8K:
+ partition->blocksize=8192;
+ snprintf(partition->info, sizeof(partition->info), "SWAP2 version %u, pagesize=%u",
+ le32(swap_header->info.version), partition->blocksize);
+ break;
+ case UP_LINSWAP2_8KBE:
+ partition->blocksize=8192;
+ snprintf(partition->info, sizeof(partition->info), "SWAP2 version %u, pagesize=%u",
+ be32(swap_header->info.version), partition->blocksize);
+ break;
default:
partition->info[0]='\0';
break;
@@ -82,11 +103,22 @@ static int test_Linux_SWAP(const union swap_header *swap_header, partition_t *pa
}
if(memcmp(swap_header->magic.magic,"SWAPSPACE2",10)==0)
{
- if(swap_header->info.last_page==0)
- return 1;
partition->upart_type=UP_LINSWAP2;
return 0;
}
+ if(memcmp(swap_header->magic8k.magic,"SWAP-SPACE",10)==0)
+ {
+ partition->upart_type=UP_LINSWAP_8K;
+ return 0;
+ }
+ if(memcmp(swap_header->magic8k.magic,"SWAPSPACE2",10)==0)
+ {
+ if(le32(swap_header->info.version) <= be32(swap_header->info.version))
+ partition->upart_type=UP_LINSWAP2_8K;
+ else
+ partition->upart_type=UP_LINSWAP2_8KBE;
+ return 0;
+ }
return 1;
}
@@ -114,7 +146,34 @@ int recover_Linux_SWAP(const union swap_header *swap_header, partition_t *partit
}
break;
case UP_LINSWAP2:
- partition->part_size=(uint64_t)(swap_header->info.last_page - 1)*PAGE_SIZE;
+ if(swap_header->info.last_page==0)
+ partition->part_size=PAGE_SIZE;
+ else
+ partition->part_size=(uint64_t)(le32(swap_header->info.last_page) - 1)*PAGE_SIZE;
+ break;
+ case UP_LINSWAP_8K:
+ {
+ int i, j;
+ for(i=PAGE_8K - 10 - 1; i>=0; i--)
+ if(swap_header->magic8k.reserved[i]!=(char)0)
+ break;
+ for(j=7;j>=0;j--)
+ if((swap_header->magic8k.reserved[i]&(1<<j))!=(char)0)
+ break;
+ partition->part_size=(uint64_t)((8*i+j+1)*PAGE_8K);
+ }
+ break;
+ case UP_LINSWAP2_8K:
+ if(swap_header->info.last_page==0)
+ partition->part_size=PAGE_8K;
+ else
+ partition->part_size=(uint64_t)(le32(swap_header->info.last_page) - 1)*PAGE_8K;
+ break;
+ case UP_LINSWAP2_8KBE:
+ if(swap_header->info.last_page==0)
+ partition->part_size=PAGE_8K;
+ else
+ partition->part_size=(uint64_t)(be32(swap_header->info.last_page) - 1)*PAGE_8K;
break;
default:
return 1;
diff --git a/src/swap.h b/src/swap.h
index b496e1a..831b85d 100644
--- a/src/swap.h
+++ b/src/swap.h
@@ -23,8 +23,8 @@
extern "C" {
#endif
-#define PAGE_SIZE 0x1000 /* PAGE de 4K pour P_LINSWAP */
-#define SWAP_SIZE PAGE_SIZE
+#define PAGE_SIZE 0x1000 /* 4k page */
+#define PAGE_8K 0x2000 /* 8K page */
union swap_header {
struct
@@ -42,6 +42,11 @@ union swap_header {
unsigned int padding[125];
unsigned int badpages[1];
} info;
+ struct
+ {
+ char reserved[PAGE_8K- 10];
+ char magic[10];
+ } magic8k;
};
int check_Linux_SWAP(disk_t *disk_car, partition_t *partition);