1 /*
2 
3     File: ext2_sbn.c
4 
5     Copyright (C) 1998-2009 Christophe GRENIER <grenier@cgsecurity.org>
6 
7     This software is free software; you can redistribute it and/or modify
8     it under the terms of the GNU General Public License as published by
9     the Free Software Foundation; either version 2 of the License, or
10     (at your option) any later version.
11 
12     This program is distributed in the hope that it will be useful,
13     but WITHOUT ANY WARRANTY; without even the implied warranty of
14     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15     GNU General Public License for more details.
16 
17     You should have received a copy of the GNU General Public License along
18     with this program; if not, write the Free Software Foundation, Inc., 51
19     Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 
21  */
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25 
26 #include <stdio.h>
27 #ifdef HAVE_STDLIB_H
28 #include <stdlib.h>
29 #endif
30 #include "types.h"
31 #include "common.h"
32 #include "intrf.h"
33 #include "intrfn.h"
34 #include "fnctdsk.h"
35 #include "log.h"
36 #include "lang.h"
37 #include "ext2.h"
38 #include "ext2_sbn.h"
39 
40 // blocksize=1024, 2048, 4096, 65536
41 // blocks per blocksgroup=8*blocksize
42 static const  uint64_t group_size[4]={
43   (EXT2_MIN_BLOCK_SIZE<<0)*8*(EXT2_MIN_BLOCK_SIZE<<0),
44   (EXT2_MIN_BLOCK_SIZE<<1)*8*(EXT2_MIN_BLOCK_SIZE<<1),
45   (EXT2_MIN_BLOCK_SIZE<<2)*8*(EXT2_MIN_BLOCK_SIZE<<2),
46   (uint64_t)(EXT2_MIN_BLOCK_SIZE<<6)*8*(EXT2_MIN_BLOCK_SIZE<<6),
47 };
48 static const  uint64_t factors[3]={3,5,7};
49 
next_sb(const uint64_t hd_offset_old)50 static uint64_t next_sb(const uint64_t hd_offset_old)
51 {
52   uint64_t hd_offset=0;
53   int j;
54   for(j=0; j<4; j++)
55   {
56     int i;
57     const uint64_t offset=(j==0?2*512:0);
58     for(i=0; i<3; i++)
59     {
60       uint64_t val;
61       for(val=1; val * group_size[j] + offset <= hd_offset_old; val*=factors[i])
62 	;
63       if(hd_offset==0 || val * group_size[j] + offset < hd_offset)
64 	hd_offset=val* group_size[j] + offset;
65     }
66   }
67   if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<0 && EXT2_MIN_BLOCK_SIZE<<0 < hd_offset)
68     hd_offset=EXT2_MIN_BLOCK_SIZE<<0;
69   else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<1 && EXT2_MIN_BLOCK_SIZE<<1 < hd_offset)
70     hd_offset=EXT2_MIN_BLOCK_SIZE<<1;
71   else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<2 && EXT2_MIN_BLOCK_SIZE<<2 < hd_offset)
72     hd_offset=EXT2_MIN_BLOCK_SIZE<<2;
73   else if(hd_offset_old < EXT2_MIN_BLOCK_SIZE<<6 && EXT2_MIN_BLOCK_SIZE<<6 < hd_offset)
74     hd_offset=EXT2_MIN_BLOCK_SIZE<<6;
75   return hd_offset;
76 }
77 
search_superblock(disk_t * disk_car,partition_t * partition,const int verbose,const int dump_ind)78 list_part_t *search_superblock(disk_t *disk_car, partition_t *partition, const int verbose, const int dump_ind)
79 {
80   unsigned char *buffer=(unsigned char *)MALLOC(2*0x200);
81   uint64_t hd_offset;
82   int nbr_sb=0;
83   list_part_t *list_part=NULL;
84   int ind_stop=0;
85 #ifdef HAVE_NCURSES
86   unsigned long int old_percent=0;
87 #endif
88   struct ext2_super_block *sb=(struct ext2_super_block *)buffer;
89   partition_t *new_partition=partition_new(disk_car->arch);
90   log_trace("search_superblock\n");
91 #ifdef HAVE_NCURSES
92   aff_copy(stdscr);
93   wmove(stdscr,4,0);
94   wprintw(stdscr,"%s",disk_car->description(disk_car));
95   mvwaddstr(stdscr,5,0,msg_PART_HEADER_LONG);
96   wmove(stdscr,6,0);
97   aff_part(stdscr,AFF_PART_ORDER|AFF_PART_STATUS,disk_car,partition);
98   wmove(stdscr,22,0);
99   wattrset(stdscr, A_REVERSE);
100   waddstr(stdscr,"  Stop  ");
101   wattroff(stdscr, A_REVERSE);
102 #endif
103   for(hd_offset=0;
104       hd_offset<partition->part_size && nbr_sb<10 && ind_stop==0;
105       hd_offset=next_sb(hd_offset))
106   {
107 #ifdef HAVE_NCURSES
108     const unsigned long int percent=hd_offset*100/partition->part_size;
109     if(percent!=old_percent)
110     {
111       wmove(stdscr,9,0);
112       wclrtoeol(stdscr);
113       wprintw(stdscr, "Search ext2/ext3/ext4 superblock %10lu/%lu %lu%%",
114 	  (long unsigned)(hd_offset/disk_car->sector_size),
115 	  (long unsigned)(partition->part_size/disk_car->sector_size),
116 	  percent);
117       wrefresh(stdscr);
118       ind_stop|=check_enter_key_or_s(stdscr);
119       old_percent=percent;
120     }
121 #endif
122     if(disk_car->pread(disk_car, buffer, 1024, partition->part_offset + hd_offset) == 1024)
123     {
124       /* ext2/ext3/ext4 */
125       if(le16(sb->s_magic)==EXT2_SUPER_MAGIC)
126       {
127 	dup_partition_t(new_partition,partition);
128 	new_partition->part_offset+=hd_offset;
129 	if(recover_EXT2(disk_car,sb,new_partition,verbose,dump_ind)==0)
130 	{
131 	  int insert_error=0;
132 	  if(hd_offset<=(EXT2_MIN_BLOCK_SIZE<<2))
133 	    new_partition->part_offset-=hd_offset;
134 	  if(partition->blocksize==0)
135 	  {
136 	    partition->sborg_offset=new_partition->sborg_offset;
137 	    partition->sb_offset   =new_partition->sb_offset;
138 	    partition->sb_size     =new_partition->sb_size;
139 	    partition->blocksize   =new_partition->blocksize;
140 	  }
141 	  log_info("Ext2 superblock found at sector %llu (block=%llu, blocksize=%u)\n",
142 	      (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE,
143 	      (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)),
144 	      (unsigned int)EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size));
145 #ifdef HAVE_NCURSES
146 	  wmove(stdscr,10+nbr_sb,0);
147 	  wprintw(stdscr,"Ext2 superblock found at sector %llu (block=%llu, blocksize=%u)        \n",
148 	      (long long unsigned) hd_offset/DEFAULT_SECTOR_SIZE,
149 	      (long long unsigned) hd_offset>>(EXT2_MIN_BLOCK_LOG_SIZE+le32(sb->s_log_block_size)),
150 	      EXT2_MIN_BLOCK_SIZE<<le32(sb->s_log_block_size));
151 #endif
152 	  list_part=insert_new_partition(list_part, new_partition, 1, &insert_error);
153 	  new_partition=partition_new(disk_car->arch);
154 	  nbr_sb++;
155 	}
156       }
157     }
158   }
159   free(new_partition);
160   free(buffer);
161   return list_part;
162 }
163 
164