summaryrefslogtreecommitdiff
path: root/lib/config
diff options
context:
space:
mode:
authorDavid Teigland <teigland@redhat.com>2021-06-29 12:40:03 -0500
committerDavid Teigland <teigland@redhat.com>2021-07-06 10:10:23 -0500
commitb876dbfc245b8fe0a4c433b39d214652455c3f9e (patch)
tree25b2ececc0695db6010572f54447b8fa8f627078 /lib/config
parente035e323508383fdcd9df0ef036d276a9c9909ab (diff)
downloadlvm2-b876dbfc245b8fe0a4c433b39d214652455c3f9e.tar.gz
scan: move metadata vgname check
There have been two separate checks for metadata validity: first that the metadata text begins with a valid VG name, and second the checksum of the metadata text. These happen in different places, which means there have been two separate error paths for invalid metadata. This also causes large metadata to be read in multiple parts, the first part is read just to check the vgname, and then remaining parts are read later when the full metadata is needed. This patch moves the vg name verification so it's done just before the checksum verification, which results in a single error path for invalid metadata, and causes the entire metadata to be read together rather that in parts from different parts of the code.
Diffstat (limited to 'lib/config')
-rw-r--r--lib/config/config.c25
1 files changed, 24 insertions, 1 deletions
diff --git a/lib/config/config.c b/lib/config/config.c
index 485063a3d..25a87c983 100644
--- a/lib/config/config.c
+++ b/lib/config/config.c
@@ -501,6 +501,9 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
checksum_fn_t checksum_fn, uint32_t checksum,
int checksum_only, int no_dup_node_check)
{
+ char namebuf[NAME_LEN + 1] __attribute__((aligned(8)));
+ int namelen = 0;
+ int bad_name = 0;
char *fb, *fe;
int r = 0;
int sz, use_plain_read = 1;
@@ -548,6 +551,23 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
fb = buf;
+ if (!(dev->flags & DEV_REGULAR)) {
+ memcpy(namebuf, buf, NAME_LEN);
+
+ while (namebuf[namelen] && !isspace(namebuf[namelen]) && namebuf[namelen] != '{' && namelen < (NAME_LEN - 1))
+ namelen++;
+ namebuf[namelen] = '\0';
+
+ /*
+ * Check that the text metadata begins with a valid name.
+ */
+ if (!validate_name(namebuf)) {
+ log_warn("WARNING: Metadata location on %s at offset %llu begins with invalid name.",
+ dev_name(dev), (unsigned long long)offset);
+ bad_name = 1;
+ }
+ }
+
/*
* The checksum passed in is the checksum from the mda_header
* preceding this metadata. They should always match.
@@ -557,10 +577,13 @@ int config_file_read_fd(struct dm_config_tree *cft, struct device *dev, dev_io_r
if (checksum_fn && checksum !=
(checksum_fn(checksum_fn(INITIAL_CRC, (const uint8_t *)fb, size),
(const uint8_t *)(fb + size), size2))) {
- log_error("%s: Checksum error at offset %" PRIu64, dev_name(dev), (uint64_t) offset);
+ log_warn("WARNING: Checksum error on %s at offset %llu.", dev_name(dev), (unsigned long long)offset);
goto out;
}
+ if (bad_name)
+ goto out;
+
if (!checksum_only) {
fe = fb + size + size2;
if (no_dup_node_check) {