Ejemplo n.º 1
0
void detect_linux_lvm(SECTION *section, int level)
{
  unsigned char *buf;
  char s[256];
  int minor_version, pv_number;
  u8 pe_size, pe_count, pe_start;

  if (get_buffer(section, 0, 1024, (void **)&buf) < 1024)
    return;

  /* signature */
  if (buf[0] != 'H' || buf[1] != 'M')
    return;
  /* helpful sanity check... */
  if (get_le_long(buf + 36) == 0 || get_le_long(buf + 40) == 0)
    return;

  minor_version = get_le_short(buf + 2);
  print_line(level, "Linux LVM1 volume, version %d%s",
             minor_version,
             (minor_version < 1 || minor_version > 2) ? " (unknown)" : "");

  /* volume group name */
  get_string(buf + 172, 128, s);
  print_line(level + 1, "Volume group name \"%s\"", s);

  /* "UUID" of this physical volume */
  format_uuid_lvm(buf + 0x2c, s);
  print_line(level + 1, "PV UUID %s", s);

  /* number of this physical volume */
  pv_number = get_le_long(buf + 432);
  print_line(level + 1, "PV number %d", pv_number);

  /* volume size */
  pe_size = get_le_long(buf + 452);
  pe_count = get_le_long(buf + 456);
  format_blocky_size(s, pe_count, pe_size * 512, "PEs", NULL);
  print_line(level + 1, "Useable size %s", s);

  /* get start of first PE */
  if (minor_version == 1) {
    /* minor format 1: first PE starts after the declared length of the PE tables */
    pe_start = get_le_long(buf + 36) + get_le_long(buf + 40);
  } else if (minor_version == 2) {
    /* minor format 2: a field in the header indicates this */
    pe_start = get_le_long(buf + 464) << 9;
  } else {
    /* unknown minor format */
    pe_start = 0;
  }

  /* try to detect from first PE */
  if (pe_start > 0) {
    analyze_recursive(section, level + 1,
                      pe_start, 0, 0);
    /* TODO: elaborate on this by reading the PE allocation map */
  }
}
Ejemplo n.º 2
0
void detect_reiser(SECTION *section, int level)
{
  unsigned char *buf;
  int i, at, newformat;
  int offsets[3] = { 8, 64, -1 };
  char s[256];
  u8 blockcount;
  u4 blocksize;

  for (i = 0; offsets[i] >= 0; i++) {
    at = offsets[i];
    if (get_buffer(section, at * 1024, 1024, (void **)&buf) < 1024)
      continue;

    /* check signature */
    if (memcmp(buf + 52, "ReIsErFs", 8) == 0) {
      print_line(level, "ReiserFS file system (old 3.5 format, standard journal, starts at %d KiB)", at);
      newformat = 0;
    } else if (memcmp(buf + 52, "ReIsEr2Fs", 9) == 0) {
      print_line(level, "ReiserFS file system (new 3.6 format, standard journal, starts at %d KiB)", at);
      newformat = 1;
    } else if (memcmp(buf + 52, "ReIsEr3Fs", 9) == 0) {
      newformat = get_le_short(buf + 72);
      if (newformat == 0) {
        print_line(level, "ReiserFS file system (old 3.5 format, non-standard journal, starts at %d KiB)", at);
      } else if (newformat == 2) {
        print_line(level, "ReiserFS file system (new 3.6 format, non-standard journal, starts at %d KiB)", at);
        newformat = 1;
      } else {
        print_line(level, "ReiserFS file system (v3 magic, but unknown version %d, starts at %d KiB)", newformat, at);
        continue;
      }
    } else
      continue;

    /* get data */
    blockcount = get_le_long(buf);
    blocksize = get_le_short(buf + 44);
    /* for new format only:
       hashtype = get_le_long(buf + 64);
    */

    /* get label */
    get_string(buf + 100, 16, s);
    if (s[0])
      print_line(level + 1, "Volume name \"%s\"", s);

    format_uuid(buf + 84, s);
    print_line(level + 1, "UUID %s", s);

    /* print size */
    format_blocky_size(s, blockcount, blocksize, "blocks", NULL);
    print_line(level + 1, "Volume size %s", s);

    /* TODO: print hash code */
  }
}
Ejemplo n.º 3
0
void detect_linux_raid(SECTION *section, int level)
{
  unsigned char *buf;
  u8 pos;
  int rlevel, nr_disks, raid_disks, spare;
  u1 uuid[16];
  char s[256];

  /* don't do this if:
   *  - the size is unknown (0)
   *  - the size is too small for the calculation
   *  - it is inefficient to read from the end of the source
   */
  if (section->size < 65536 || section->source->sequential)
    return;

  /* get RAID superblock from the end of the device */
  pos = (section->size & ~65535) - 65536;
  if (get_buffer(section, pos, 4096, (void **)&buf) < 4096)
    return;

  /* signature */
  if (get_le_long(buf) != 0xa92b4efc)
    return;

  print_line(level, "Linux RAID disk, version %lu.%lu.%lu",
             get_le_long(buf + 4), get_le_long(buf + 8),
             get_le_long(buf + 12));

  /* get some data */
  rlevel = (int)(long)get_le_long(buf + 28);   /* is signed, actually */
  nr_disks = get_le_long(buf + 36);
  raid_disks = get_le_long(buf + 40);
  spare = nr_disks - raid_disks;

  /* find the name for the personality in the table */
  if (rlevel < -4 || rlevel > 5 || levels[rlevel+4] == NULL) {
    print_line(level + 1, "Unknown RAID level %d using %d regular %d spare disks",
               rlevel, raid_disks, spare);
  } else {
    print_line(level + 1, "%s set using %d regular %d spare disks",
               levels[rlevel+4], raid_disks, spare);
  }

  /* get the UUID */
  memcpy(uuid, buf + 5*4, 4);
  memcpy(uuid + 4, buf + 13*4, 3*4);
  format_uuid(uuid, s);
  print_line(level + 1, "RAID set UUID %s", s);
}
Ejemplo n.º 4
0
static int validate_tag(unsigned char *buf, u4 sector)
{
  int cksum, i;

  /* tag checksum */
  cksum = 0;
  for (i = 0; i < 16; i++)
    if (i != 4)
      cksum += buf[i];
  if ((cksum & 0xFF) != buf[4])
    return 0;

  /* reserverd */
  if (buf[5] != 0)
    return 0;

  /* tag location */
  if (get_le_long(buf + 12) != sector)
    return 0;

  return 1;
}
Ejemplo n.º 5
0
void detect_linux_lvm2(SECTION *section, int level)
{
  unsigned char *buf;
  int at, i;
  char s[256];
  u8 labelsector;
  u4 labeloffset;
  u8 pvsize, mdoffset, mdsize;
  int mda_version;

  for (at = 0; at < 4; at++) {
    if (get_buffer(section, at * 512, 512, (void **)&buf) < 512)
      continue;

    /* check signature */
    if (memcmp(buf, "LABELONE", 8) != 0)
      continue;

    labelsector = get_le_quad(buf + 8);
    labeloffset = get_le_long(buf + 20);

    if (memcmp(buf + 24, "LVM2 001", 8) != 0) {
      get_string(buf + 24, 8, s);
      print_line(level, "LABELONE label at sector %d, unknown type \"%s\"",
                 at, s);
      return;
    }

    print_line(level, "Linux LVM2 volume, version 001");
    print_line(level + 1, "LABELONE label at sector %d",
               at);

    if (labeloffset >= 512 || labelsector > 256 ||
        labelsector != at) {
      print_line(level + 1, "LABELONE data inconsistent, aborting analysis");
      return;
    }

    /* "UUID" of this physical volume */
    format_uuid_lvm(buf + labeloffset, s);
    print_line(level + 1, "PV UUID %s", s);

    /* raw volume size */
    pvsize = get_le_quad(buf + labeloffset + 32);
    format_size_verbose(s, pvsize);
    print_line(level + 1, "Volume size %s", s);

    /* find first metadata area in list */
    mdoffset = 0;
    for (i = 0; i < 16; i++)
      if (get_le_quad(buf + labeloffset + 40 + i * 16) == 0) {
        i++;
        mdoffset = get_le_quad(buf + labeloffset + 40 + i * 16);
        mdsize = get_le_quad(buf + labeloffset + 40 + i * 16 + 8);
        break;
      }
    if (mdoffset == 0)
      return;

    if (get_buffer(section, mdoffset, mdsize, (void **)&buf) < mdsize)
      return;

    if (memcmp(buf + 4, " LVM2 x[5A%r0N*>", 16) != 0)
      return;
    mda_version = get_le_long(buf + 20);

    print_line(level + 1, "Meta-data version %d", mda_version);

    /* TODO: parse the metadata area (big task...) */

    return;
  }
}
Ejemplo n.º 6
0
void detect_ext234(SECTION *section, int level)
{
  unsigned char *buf;
  char s[256];
  int fslevel, is_journal, is_dev;
  u4 blocksize;
  u8 blockcount;

  if (get_buffer(section, 1024, 1024, (void **)&buf) < 1024)
    return;

  if (get_le_short(buf + 56) == 0xEF53) {
    fslevel = 2;
    is_journal = 0;
    is_dev = 0;
    /* Ext3/4 external journal: INCOMPAT feature JOURNAL_DEV */
    if (get_le_long(buf + 96) & 0x0008) {
      is_journal = 1;
      fslevel = 3;  /* at least ext3, ext2 has no journalling */
    }
    /* Ext3/4 COMPAT feature: HAS_JOURNAL */
    if (get_le_long(buf + 92) & 0x0004)
      fslevel = 3;
    /* Ext4 INCOMPAT features: EXTENTS, 64BIT, FLEX_BG */
    //if (get_le_long(buf + 96) & 0x02C0)
    //  fslevel = 4;
    /* Ext4 RO_COMPAT features: HUGE_FILE, GDT_CSUM, DIR_NLINK, EXTRA_ISIZE */
    if (get_le_long(buf + 100) & 0x0078)
      fslevel = 4;
    /* Ext4 sets min_extra_isize even on external journals */
    //if (get_le_short(buf + 348) >= 0x1c)
    //  fslevel = 4;
    /* Ext4dev TEST_FILESYS flag */
    //if (get_le_long(buf + 352) & 0x0004)
    //  is_dev = 1;

    print_line(level, "Ext%d%s %s", fslevel, is_dev ? "dev" : "",
               is_journal ? "external journal" : "file system");

    get_string(buf + 120, 16, s);
    if (s[0])
      print_line(level + 1, "Volume name \"%s\"", s);

    format_uuid(buf + 104, s);
    print_line(level + 1, "UUID %s", s);

    get_string(buf + 136, 64, s);
    if (s[0])
      print_line(level + 1, "Last mounted at \"%s\"", s);

    blocksize = 1024 << get_le_long(buf + 24);
    blockcount = get_le_long(buf + 4);
    format_blocky_size(s, blockcount, blocksize, "blocks", NULL);
    print_line(level + 1, "Volume size %s", s);

    /* 76 4 s_rev_level */
    /* 62 2 s_minor_rev_level */
    /* 72 4 s_creator_os */
    /* 92 3x4 s_feature_compat, s_feature_incompat, s_feature_ro_compat */
  }
}
Ejemplo n.º 7
0
static int probe_udf(SECTION *section, int level, int sector_size)
{
  unsigned char *buffer;

  u4 count, addr, sect;
  int seen_primary = 0;
  int seen_logical = 0;
  int i;
  char s[256];

  /* first read the Anchor Volume Descriptor Pointer @ sector 256 */
  if (get_buffer(section, 256 * sector_size, 512, (void **)&buffer) < 512)
    return 0;
  if (!validate_tag(buffer, 256))
    return 0;
  /* tag identifier */
  if (get_le_short(buffer) != 2)
    return 0;

  print_line(level, "UDF file system");
  print_line(level + 1, "Sector size %d bytes", sector_size);

  /* get the Volume Descriptor Area */
  count = get_le_long(buffer + 16) / sector_size;
  addr = get_le_long(buffer + 20);

  /* look for a Logical Volume Descriptor */
  for (i = 0; i < count; i++) {
    sect = addr + i;
    if (get_buffer(section, (u8)sect * sector_size, 512, (void **)&buffer) < 512)
      break;
    if (!validate_tag(buffer, sect))
      continue;

    /* switch by tag identifier */
    switch (get_le_short(buffer)) {
    case 1:   /* Primary Volume Descriptor */
      if (!seen_primary) {
	seen_primary = 1;

	if (buffer[24] == 8) {
	  get_string(buffer + 25, 30, s);
	  print_line(level+1, "Volume name \"%s\"", s);
	} else if (buffer[24] == 16) {
	  format_utf16_le(buffer + 25, 30, s);
	  print_line(level+1, "Volume name \"%s\"", s);
	} else {
	  print_line(level+1, "Volume name encoding not supported");
	}

      }
      break;

    case 6:   /* Logical Volume Descriptor */
      if (!seen_logical) {
	seen_logical = 1;

	if (memcmp(buffer + 216+1, "*OSTA UDF Compliant", 19) == 0) {
	  print_line(level+1, "UDF version %x.%02x",
		     (int)buffer[216+25], (int)buffer[216+24]);
	}

      }
      break;
    }
  }

  if (!seen_primary) {
    print_line(level + 1, "Primary Volume Descriptor missing");
  }

  return 1;  /* some problems */
}