scan_ffs w/UFS2

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

scan_ffs w/UFS2

gwes-2
This is a patch for scan_ffs to make it find UFS2 partitions.
The following test data represents a sample of the various disks
available to me at this time. All of the tests are on 6.3 amd64.
I haven't updated to 6.4 or snapshots on this machine.

By design, scan_ffs can only find intact first superblocks.
Backup superblocks do not contain enough data to find
the partition start.
Deducing partition start addresses from backup superblocks
requires interpreting cylinder group data which would be a
separate project.

The standard warning: if this code melts your machine or makes
you turn purple, I told you so.

geoff steckel

store:gwes:10512$ fdisk sd0
Disk: sd0       geometry: 7783/255/63 [125045424 Sectors]
Offset: 0       Signature: 0xAA55
            Starting         Ending         LBA Info:
 #: id      C   H   S -      C   H   S [       start:        size ]
-------------------------------------------------------------------------------
 0: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 1: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 2: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
*3: A6      0   1   2 -   7782 254  63 [          64:   125033831 ] OpenBSD    
store:gwes:10513$ disklabel sd0
# /dev/rsd0c:
type: SCSI
disk: SCSI disk
label: SanDisk SDSSDP06
duid: 2a081791fe686cf5
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 7783
total sectors: 125045424
boundstart: 64
boundend: 125033895
drivedata: 0

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  a:          2097152               64  4.2BSD   2048 16384     1 # /
  b:         11199210          2097216    swap                    # none
  c:        125045424                0  unused                    
  d:          8388576         13296448  4.2BSD   2048 16384     1 # /tmp
  e:         14509792         21685024  4.2BSD   2048 16384     1 # /var
  f:          4194304         36194816  4.2BSD   2048 16384     1 # /usr
  g:          2097152         40389120  4.2BSD   2048 16384     1 # /usr/X11R6
  h:         15229664         42486272  4.2BSD   2048 16384     1 # /usr/local
  i:          4194304         57715936  4.2BSD   2048 16384     1 # /usr/src
  j:          8390200         61910240  4.2BSD   2048 16384 12958 # /usr/obj
  k:         54733440         70300448  4.2BSD   2048 16384 12958 # /home
store:gwes:10517$ obj/scan_ffs -s sd0c
ffs at 64 size 2097152 (1.0G) mount / time Wed Feb 13 03:55:34 2019
ffs at 13296448 size 8388576 (4.0G) mount /tmp time Wed Feb 13 03:55:57 2019
ffs at 21685024 size 14509792 (6.9G) mount /var time Wed Feb 13 03:55:51 2019
ffs at 36194816 size 4194304 (2.0G) mount /usr time Wed Feb 13 03:55:42 2019
ffs at 40389120 size 2097152 (1.0G) mount /usr/X11R6 time Wed Feb 13 03:55:53 2019
ffs at 42486272 size 15229664 (7.3G) mount /usr/local time Wed Feb 13 03:55:30 2019
ffs at 57715936 size 4194304 (2.0G) mount /usr/src time Wed Feb 13 03:55:46 2019
ffs at 61910240 size 8390200 (4.0G) mount /usr/obj time Wed Feb 13 03:55:38 2019
ffs at 70300448 size 54733440 (26.1G) mount /home time Wed Feb 13 03:55:55 2019
scan_ffs: read: Invalid argument
store:gwes:10518$ fdisk sd5
Disk: sd5       geometry: 267349/255/63 [4294961685 Sectors]
Offset: 0       Signature: 0x0
            Starting         Ending         LBA Info:
 #: id      C   H   S -      C   H   S [       start:        size ]
-------------------------------------------------------------------------------
 0: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 1: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 2: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
 3: 00      0   0   0 -      0   0   0 [           0:           0 ] unused      
store:gwes:10519$ disklabel sd5
# /dev/rsd5c:
type: SCSI
disk: SCSI disk
label: SR RAID 1
duid: 3a724c18e7cf99de
flags:
bytes/sector: 512
sectors/track: 63
tracks/cylinder: 255
sectors/cylinder: 16065
cylinders: 729340
total sectors: 11716848576
boundstart: 0
boundend: 11716848576
drivedata: 0

16 partitions:
#                size           offset  fstype [fsize bsize   cpg]
  a:       5242892928              128  4.2BSD   8192 65536 52270 # /music
  c:      11716848576                0  unused                    
  d:       5452589440       5242893056  4.2BSD   8192 65536 52270 # /dwar
  e:       1021366080      10695482496  4.2BSD   4096 32768 26062 # /const
store:gwes:10520$ dumpfs -m sd5a
# newfs command for sd5a
newfs -O 2 -b 65536 -e 8192 -f 8192 -g 20000000 -h 64 -m 5 -o time -s 5242892928 sd5a
store:gwes:10521$ dumpfs -m sd5d
# newfs command for sd5d
newfs -O 2 -b 65536 -e 8192 -f 8192 -g 20000000 -h 64 -m 5 -o time -s 5452589440 sd5d
store:gwes:10522$ dumpfs -m sd5e
# newfs command for sd5e
newfs -O 1 -b 32768 -e 8192 -f 4096 -g 40000 -h 64 -m 5 -o time -s 1021366080 sd5e
store:gwes:10523$ obj/scan_ffs -s /dev/sd5c
ffs at 128 size 5242892928 (2.4T) mount /music time Tue Feb  5 12:38:31 2019
ffs at 5242893056 size 5452589440 (2.5T) mount /dwar time Wed Feb 13 03:58:03 2019
ffs at 10695482496 size 1021366080 (487G) mount /const time Tue Feb  5 12:38:31 2019
scan_ffs: read: Invalid argument
store:gwes:10524$

Index: scan_ffs.c
===================================================================
RCS file: /cvs/src/sbin/scan_ffs/scan_ffs.c,v
retrieving revision 1.21
diff -u -p -u -r1.21 scan_ffs.c
--- scan_ffs.c 23 Nov 2015 19:19:30 -0000 1.21
+++ scan_ffs.c 13 Feb 2019 09:01:07 -0000
@@ -25,6 +25,7 @@
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <sys/param.h>
 #include <sys/types.h>
 #include <sys/fcntl.h>
 #include <ufs/ffs/fs.h>
@@ -44,19 +45,27 @@
 #define FLAG_SMART 2
 #define FLAG_LABELS 4
 
+#define is_ufs2(fs) ((fs)->fs_magic == FS_UFS2_MAGIC)
+
+#define x_strof(x) #x
+#define s_strof(y) x_strof(y)
+#define S_MAXMNTLEN s_strof(MAXMNTLEN)
+
 static void usage(void);
+static void ffs1_compat_read(struct fs *, daddr_t);
+static int is_sblock(const struct fs *);
 
 static int
 ufsscan(int fd, daddr_t beg, daddr_t end, int flags)
 {
- static char lastmount[MAXMNTLEN];
  static u_int8_t buf[SBSIZE * SBCOUNT];
  struct fs *sb;
- daddr_t blk, lastblk;
+ daddr_t blk;
  int n;
-
- lastblk = -1;
- memset(lastmount, 0, MAXMNTLEN);
+ daddr_t blkno;
+ daddr_t filesys_base; /* in DEV_BSIZE blocks */
+ daddr_t filesys_size; /* in DEV_BSIZE blocks */
+ char hsizebuf[FMT_SCALED_STRSIZE + 1];
 
  for (blk = beg; blk <= ((end<0)?blk:end); blk += (SBCOUNT*SBSIZE/512)){
  memset(buf, 0, SBSIZE * SBCOUNT);
@@ -66,53 +75,47 @@ ufsscan(int fd, daddr_t beg, daddr_t end
  err(1, "read");
 
  for (n = 0; n < (SBSIZE * SBCOUNT); n += 512){
+
+ blkno = blk + n / 512 ;
  sb = (struct fs*)(&buf[n]);
- if (sb->fs_magic == FS_MAGIC) {
+ if (sb->fs_magic == FS_UFS1_MAGIC ||
+    sb->fs_magic == FS_UFS2_MAGIC) {
+ ffs1_compat_read(sb, blkno);
  if (flags & FLAG_VERBOSE)
- printf("block %lld id %x,%x size %d\n",
-    (long long)(blk + (n/512)),
+ printf("block %lld id %x,%x size %lld frag %d bsz %d\n",
+    blkno,
     sb->fs_id[0], sb->fs_id[1],
-    sb->fs_ffs1_size);
-
- if (((blk+(n/512)) - lastblk) == (SBSIZE/512)) {
+    sb->fs_size, sb->fs_frag, sb->fs_bsize);
+ if (is_sblock(sb)) {
+ filesys_base = blkno -
+    (is_ufs2(sb) ? SBLOCK_UFS2 : SBLOCK_UFS1) /
+ DEV_BSIZE;
+ filesys_size = ((off_t)sb->fs_size *
+    sb->fs_fsize / DEV_BSIZE);
  if (flags & FLAG_LABELS ) {
- printf("X: %lld %lld 4.2BSD %d %d %d # %s\n",
-    ((off_t)sb->fs_ffs1_size *
-    sb->fs_fsize / 512),
-    (long long)(blk + (n/512) -
-    (2*SBSIZE/512)),
+ printf("X: %lld %lld 4.2BSD %d %d %d # "
+    "%." S_MAXMNTLEN "s\n",
+    filesys_size,
+    filesys_base,
     sb->fs_fsize, sb->fs_bsize,
-    sb->fs_cpg, lastmount);
+    sb->fs_cpg, sb->fs_fsmnt);
  } else {
  /* XXX 2038 */
- time_t t = sb->fs_ffs1_time;
-
- printf("ffs at %lld size %lld "
-    "mount %s time %s",
-    (long long)(blk+(n/512) -
-    (2*SBSIZE/512)),
-    (long long)(off_t)sb->fs_ffs1_size *
-    sb->fs_fsize,
-    lastmount, ctime(&t));
+ time_t t = sb->fs_time;
+ fmt_scaled(filesys_size * DEV_BSIZE, hsizebuf);
+ printf("ffs at %lld size %lld (%s) "
+    "mount %." S_MAXMNTLEN "s time %s",
+    filesys_base,
+    filesys_size, hsizebuf,
+    sb->fs_fsmnt, ctime(&t));
  }
 
  if (flags & FLAG_SMART) {
- off_t size = (off_t)sb->fs_ffs1_size *
-    sb->fs_fsize;
-
- if ((n + size) < (SBSIZE * SBCOUNT))
- n += size;
- else {
- blk += (size/512 -
-    (SBCOUNT*SBCOUNT));
- break;
- }
+ blk = filesys_base + filesys_size -
+    (SBCOUNT*SBSIZE/512);
+ break;
  }
  }
-
- /* Update last potential FS SBs seen */
- lastblk = blk + (n/512);
- memcpy(lastmount, sb->fs_fsmnt, MAXMNTLEN);
  }
  }
  }
@@ -180,4 +183,52 @@ main(int argc, char *argv[])
  err(1, "pledge");
 
  return (ufsscan(fd, beg, end, flags));
+}
+
+/*
+ * Auxiliary function for reading FFS1 super blocks.
+ * from ufs_vfsops.c
+ */
+void
+ffs1_compat_read(struct fs *fs, int64_t sbloc)
+{
+ if (fs->fs_magic == FS_UFS2_MAGIC)
+ return; /* UFS2 */
+ fs->fs_flags = fs->fs_ffs1_flags;
+ fs->fs_sblockloc = sbloc;
+ fs->fs_maxbsize = fs->fs_bsize;
+ fs->fs_time = fs->fs_ffs1_time;
+ fs->fs_size = fs->fs_ffs1_size;
+ fs->fs_dsize = fs->fs_ffs1_dsize;
+ fs->fs_csaddr = fs->fs_ffs1_csaddr;
+ fs->fs_cstotal.cs_ndir = fs->fs_ffs1_cstotal.cs_ndir;
+ fs->fs_cstotal.cs_nbfree = fs->fs_ffs1_cstotal.cs_nbfree;
+ fs->fs_cstotal.cs_nifree = fs->fs_ffs1_cstotal.cs_nifree;
+ fs->fs_cstotal.cs_nffree = fs->fs_ffs1_cstotal.cs_nffree;
+}
+
+#define IS_POWER_OF_2(x) (((x) & -(x)) == (x))
+
+/*
+ * compromise validation of superblock contents
+ */
+
+static int
+is_sblock(const struct fs *fs)
+{
+ switch (fs->fs_frag) {
+ case 1:
+ case 2:
+ case 4:
+ case 8:
+ break;
+ default:
+ return(0);
+ }
+ if (fs->fs_bsize > MAXBSIZE || fs->fs_bsize < MINBSIZE ||
+    ! IS_POWER_OF_2(fs->fs_bsize))
+ return(0);
+ if (fs->fs_fsize * fs->fs_frag != fs->fs_bsize)
+ return(0);
+ return(1);
 }