diff --git a/WHATS_NEW b/WHATS_NEW index e06fcc2f3..24e28c716 100644 --- a/WHATS_NEW +++ b/WHATS_NEW @@ -1,5 +1,6 @@ Version 2.02.112 - ===================================== + Validate major and minor numbers stored in metadata. Use -fPIE when linking -pie executables. Enable cache segment type by default. Ensure only supported volume types are used with cache segments. diff --git a/lib/format_text/import_vsn1.c b/lib/format_text/import_vsn1.c index 174b3bf31..580349f29 100644 --- a/lib/format_text/import_vsn1.c +++ b/lib/format_text/import_vsn1.c @@ -635,7 +635,7 @@ static int _read_lvnames(struct format_instance *fid __attribute__((unused)), return 1; } -static int _read_lvsegs(struct format_instance *fid __attribute__((unused)), +static int _read_lvsegs(struct format_instance *fid, struct volume_group *vg, const struct dm_config_node *lvn, const struct dm_config_node *vgn __attribute__((unused)), struct dm_hash_table *pv_hash, @@ -668,20 +668,27 @@ static int _read_lvsegs(struct format_instance *fid __attribute__((unused)), return_0; lv->size = (uint64_t) lv->le_count * (uint64_t) vg->extent_size; - lv->minor = -1; - if ((lv->status & FIXED_MINOR) && - !_read_int32(lvn, "minor", &lv->minor)) { - log_error("Couldn't read minor number for logical " - "volume %s.", lv->name); - return 0; - } - lv->major = -1; - if ((lv->status & FIXED_MINOR) && - !_read_int32(lvn, "major", &lv->major)) { - log_error("Couldn't read major number for logical " - "volume %s.", lv->name); + + if (lv->status & FIXED_MINOR) { + if (!_read_int32(lvn, "minor", &lv->minor)) { + log_error("Couldn't read minor number for logical " + "volume %s.", lv->name); + return 0; + } + + if (!_read_int32(lvn, "major", &lv->major)) { + log_error("Couldn't read major number for logical " + "volume %s.", lv->name); + return 0; + } + + if (!validate_major_minor(vg->cmd, fid->fmt, lv->major, lv->minor)) { + log_error("Logical volume %s does not have a valid major, minor number.", + lv->name); + return 0; + } } return 1; diff --git a/lib/metadata/metadata-exported.h b/lib/metadata/metadata-exported.h index 935d3f710..aa0edcf6a 100644 --- a/lib/metadata/metadata-exported.h +++ b/lib/metadata/metadata-exported.h @@ -1136,6 +1136,9 @@ struct vgcreate_params { uint32_t vgmetadatacopies; }; +int validate_major_minor(const struct cmd_context *cmd, + const struct format_type *fmt, + int32_t major, int32_t minor); int vgcreate_params_validate(struct cmd_context *cmd, struct vgcreate_params *vp); diff --git a/lib/metadata/metadata.c b/lib/metadata/metadata.c index 2900ccc4c..08425639f 100644 --- a/lib/metadata/metadata.c +++ b/lib/metadata/metadata.c @@ -836,6 +836,49 @@ const char *strip_dir(const char *vg_name, const char *dev_dir) return vg_name; } +/* + * Validates major and minor numbers. + * On >2.4 kernel we only support dynamic major number. + */ +int validate_major_minor(const struct cmd_context *cmd, + const struct format_type *fmt, + int32_t major, int32_t minor) +{ + int r = 1; + + if (!strncmp(cmd->kernel_vsn, "2.4.", 4) || + (fmt->features & FMT_RESTRICTED_LVIDS)) { + if (major < 0 || major > 255) { + log_error("Major number %d outside range 0-255.", major); + r = 0; + } + if (minor < 0 || minor > 255) { + log_error("Minor number %d outside range 0-255.", minor); + r = 0; + } + } else { + /* 12 bits for major number */ + if ((major != -1) && + (major != cmd->dev_types->device_mapper_major)) { + /* User supplied some major number */ + if (major < 0 || major > 4095) { + log_error("Major number %d outside range 0-4095.", major); + r = 0; + } else + log_print_unless_silent("Ignoring supplied major %d number - " + "kernel assigns major numbers dynamically.", + major); + } + /* 20 bits for minor number */ + if (minor < 0 || minor > 1048575) { + log_error("Minor number %d outside range 0-1048575.", minor); + r = 0; + } + } + + return r; +} + /* * Validate parameters to vg_create() before calling. * FIXME: Move inside vg_create library function.