(root)/
util-linux-2.39/
libblkid/
src/
superblocks/
lvm.c
       1  /*
       2   * Copyright (C) 1999 by Andries Brouwer
       3   * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
       4   * Copyright (C) 2001 by Andreas Dilger
       5   * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
       6   * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
       7   * Copyright (C) 2012 Milan Broz <gmazyland@gmail.com>
       8   *
       9   * This file may be redistributed under the terms of the
      10   * GNU Lesser General Public License.
      11   */
      12  #include <stdio.h>
      13  #include <stdlib.h>
      14  #include <unistd.h>
      15  #include <string.h>
      16  #include <stdint.h>
      17  
      18  #include "superblocks.h"
      19  
      20  #define LVM1_ID_LEN 128
      21  #define LVM2_ID_LEN 32
      22  
      23  struct lvm2_pv_label_header {
      24  	/* label_header */
      25  	uint8_t		id[8];		/* LABELONE */
      26  	uint64_t	sector_xl;	/* Sector number of this label */
      27  	uint32_t	crc_xl;		/* From next field to end of sector */
      28  	uint32_t	offset_xl;	/* Offset from start of struct to contents */
      29  	uint8_t		type[8];	/* LVM2 001 */
      30  	/* pv_header */
      31  	uint8_t		pv_uuid[LVM2_ID_LEN];
      32  } __attribute__ ((packed));
      33  
      34  struct lvm1_pv_label_header {
      35  	uint8_t id[2];			/* HM */
      36  	uint16_t version;		/* version 1 or 2 */
      37  	uint32_t _notused[10];		/* lvm1 internals */
      38  	uint8_t pv_uuid[LVM1_ID_LEN];
      39  } __attribute__ ((packed));
      40  
      41  #define LVM2_LABEL_SIZE 512
      42  static unsigned int lvm2_calc_crc(const void *buf, unsigned int size)
      43  {
      44  	static const unsigned int crctab[] = {
      45  		0x00000000, 0x1db71064, 0x3b6e20c8, 0x26d930ac,
      46  		0x76dc4190, 0x6b6b51f4, 0x4db26158, 0x5005713c,
      47  		0xedb88320, 0xf00f9344, 0xd6d6a3e8, 0xcb61b38c,
      48  		0x9b64c2b0, 0x86d3d2d4, 0xa00ae278, 0xbdbdf21c
      49  	};
      50  	unsigned int i, crc = 0xf597a6cf;
      51  	const uint8_t *data = (const uint8_t *) buf;
      52  
      53  	for (i = 0; i < size; i++) {
      54  		crc ^= *data++;
      55  		crc = (crc >> 4) ^ crctab[crc & 0xf];
      56  		crc = (crc >> 4) ^ crctab[crc & 0xf];
      57  	}
      58  	return crc;
      59  }
      60  
      61  /* Length of real UUID is always LVM2_ID_LEN */
      62  static void format_lvm_uuid(char *dst_uuid, char *src_uuid)
      63  {
      64  	unsigned int i, b;
      65  
      66  	for (i = 0, b = 1; i < LVM2_ID_LEN; i++, b <<= 1) {
      67  		if (b & 0x4444440)
      68  			*dst_uuid++ = '-';
      69  		*dst_uuid++ = *src_uuid++;
      70  	}
      71  	*dst_uuid = '\0';
      72  }
      73  
      74  static int probe_lvm2(blkid_probe pr, const struct blkid_idmag *mag)
      75  {
      76  	int sector = mag->kboff << 1;
      77  	struct lvm2_pv_label_header *label;
      78  	char uuid[LVM2_ID_LEN + 7];
      79  	unsigned char *buf;
      80  
      81  	buf = blkid_probe_get_buffer(pr,
      82  			mag->kboff << 10,
      83  			512 + sizeof(struct lvm2_pv_label_header));
      84  	if (!buf)
      85  		return errno ? -errno : 1;
      86  
      87  	/* buf is at 0k or 1k offset; find label inside */
      88  	if (memcmp(buf, "LABELONE", 8) == 0) {
      89  		label = (struct lvm2_pv_label_header *) buf;
      90  	} else if (memcmp(buf + 512, "LABELONE", 8) == 0) {
      91  		label = (struct lvm2_pv_label_header *)(buf + 512);
      92  		sector++;
      93  	} else {
      94  		return 1;
      95  	}
      96  
      97  	if (le64_to_cpu(label->sector_xl) != (unsigned) sector)
      98  		return 1;
      99  
     100  	if (!blkid_probe_verify_csum(
     101  		pr, lvm2_calc_crc(
     102  			&label->offset_xl, LVM2_LABEL_SIZE -
     103  			((char *) &label->offset_xl - (char *) label)),
     104  			le32_to_cpu(label->crc_xl)))
     105  		return 1;
     106  
     107  	format_lvm_uuid(uuid, (char *) label->pv_uuid);
     108  	blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
     109  			"%s", uuid);
     110  
     111  	/* the mag->magic is the same string as label->type,
     112  	 * but zero terminated */
     113  	blkid_probe_set_version(pr, mag->magic);
     114  
     115  	/* LVM (pvcreate) wipes begin of the device -- let's remember this
     116  	 * to resolve conflicts between LVM and partition tables, ...
     117  	 */
     118  	blkid_probe_set_wiper(pr, 0, 8 * 1024);
     119  
     120  	return 0;
     121  }
     122  
     123  static int probe_lvm1(blkid_probe pr, const struct blkid_idmag *mag)
     124  {
     125  	struct lvm1_pv_label_header *label;
     126  	char uuid[LVM2_ID_LEN + 7];
     127  	unsigned int version;
     128  
     129  	label = blkid_probe_get_sb(pr, mag, struct lvm1_pv_label_header);
     130  	if (!label)
     131  		return errno ? -errno : 1;
     132  
     133  	version = le16_to_cpu(label->version);
     134  	if (version != 1 && version != 2)
     135  		return 1;
     136  
     137  	format_lvm_uuid(uuid, (char *) label->pv_uuid);
     138  	blkid_probe_sprintf_uuid(pr, label->pv_uuid, sizeof(label->pv_uuid),
     139  			"%s", uuid);
     140  
     141  	return 0;
     142  }
     143  
     144  struct verity_sb {
     145  	uint8_t  signature[8];	/* "verity\0\0" */
     146  	uint32_t version;	/* superblock version */
     147  	uint32_t hash_type;	/* 0 - Chrome OS, 1 - normal */
     148  	uint8_t  uuid[16];	/* UUID of hash device */
     149  	uint8_t  algorithm[32];/* hash algorithm name */
     150  	uint32_t data_block_size; /* data block in bytes */
     151  	uint32_t hash_block_size; /* hash block in bytes */
     152  	uint64_t data_blocks;	/* number of data blocks */
     153  	uint16_t salt_size;	/* salt size */
     154  	uint8_t  _pad1[6];
     155  	uint8_t  salt[256];	/* salt */
     156  	uint8_t  _pad2[168];
     157  } __attribute__((packed));
     158  
     159  static int probe_verity(blkid_probe pr, const struct blkid_idmag *mag)
     160  {
     161  	struct verity_sb *sb;
     162  	unsigned int version;
     163  
     164  	sb = blkid_probe_get_sb(pr, mag, struct verity_sb);
     165  	if (sb == NULL)
     166  		return errno ? -errno : 1;
     167  
     168  	version = le32_to_cpu(sb->version);
     169  	if (version != 1)
     170  		return 1;
     171  
     172  	blkid_probe_set_uuid(pr, sb->uuid);
     173  	blkid_probe_sprintf_version(pr, "%u", version);
     174  	return 0;
     175  }
     176  
     177  struct integrity_sb {
     178  	uint8_t  magic[8];
     179  	uint8_t  version;
     180  	int8_t   log2_interleave_sectors;
     181  	uint16_t integrity_tag_size;
     182  	uint32_t journal_sections;
     183  	uint64_t provided_data_sectors;
     184  	uint32_t flags;
     185  	uint8_t  log2_sectors_per_block;
     186  } __attribute__ ((packed));
     187  
     188  static int probe_integrity(blkid_probe pr, const struct blkid_idmag *mag)
     189  {
     190  	struct integrity_sb *sb;
     191  
     192  	sb = blkid_probe_get_sb(pr, mag, struct integrity_sb);
     193  	if (sb == NULL)
     194  		return errno ? -errno : 1;
     195  
     196  	if (!sb->version)
     197  		return 1;
     198  
     199  	blkid_probe_sprintf_version(pr, "%u", sb->version);
     200  	return 0;
     201  }
     202  
     203  /* NOTE: the original libblkid uses "lvm2pv" as a name */
     204  const struct blkid_idinfo lvm2_idinfo =
     205  {
     206  	.name		= "LVM2_member",
     207  	.usage		= BLKID_USAGE_RAID,
     208  	.probefunc	= probe_lvm2,
     209  	.magics		=
     210  	{
     211  		{ .magic = "LVM2 001", .len = 8, .sboff = 0x218 },
     212  		{ .magic = "LVM2 001", .len = 8, .sboff = 0x018 },
     213  		{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x018 },
     214  		{ .magic = "LVM2 001", .len = 8, .kboff = 1, .sboff = 0x218 },
     215  		{ NULL }
     216  	}
     217  };
     218  
     219  const struct blkid_idinfo lvm1_idinfo =
     220  {
     221  	.name		= "LVM1_member",
     222  	.usage		= BLKID_USAGE_RAID,
     223  	.probefunc	= probe_lvm1,
     224  	.magics		=
     225  	{
     226  		{ .magic = "HM", .len = 2 },
     227  		{ NULL }
     228  	}
     229  };
     230  
     231  const struct blkid_idinfo snapcow_idinfo =
     232  {
     233  	.name		= "DM_snapshot_cow",
     234  	.usage		= BLKID_USAGE_OTHER,
     235  	.magics		=
     236  	{
     237  		{ .magic = "SnAp", .len = 4 },
     238  		{ NULL }
     239  	}
     240  };
     241  
     242  const struct blkid_idinfo verity_hash_idinfo =
     243  {
     244  	.name		= "DM_verity_hash",
     245  	.usage		= BLKID_USAGE_CRYPTO,
     246  	.probefunc	= probe_verity,
     247  	.magics		=
     248  	{
     249  		{ .magic = "verity\0\0", .len = 8 },
     250  		{ NULL }
     251  	}
     252  };
     253  
     254  const struct blkid_idinfo integrity_idinfo =
     255  {
     256  	.name		= "DM_integrity",
     257  	.usage		= BLKID_USAGE_CRYPTO,
     258  	.probefunc	= probe_integrity,
     259  	.magics		=
     260  	{
     261  		{ .magic = "integrt\0", .len = 8 },
     262  		{ NULL }
     263  	}
     264  };