1
0
mirror of git://sourceware.org/git/lvm2.git synced 2025-02-17 17:57:56 +03:00

device_id: ensure pvid buffers are ID_LEN+1

A pvid string read from system.devices could be less
then ID_LEN since system.devices fields can be edited.
Ensure the pvid buffer is ID_LEN+1 even if the string
read from the file is shorter.
This commit is contained in:
David Teigland 2023-11-08 11:46:38 -06:00
parent de2b11f39a
commit 631b8edefb
3 changed files with 35 additions and 6 deletions

View File

@ -248,4 +248,6 @@ struct device_id_list *device_id_list_find_dev(struct dm_list *devices, struct d
int device_list_remove(struct dm_list *devices, struct device *dev);
struct device_list *device_list_find_dev(struct dm_list *devices, struct device *dev);
char *strdup_pvid(char *pvid);
#endif

View File

@ -51,6 +51,25 @@ static const char *_searched_file_dir = DEFAULT_RUN_DIR;
char devices_file_hostname_orig[PATH_MAX];
char devices_file_product_uuid_orig[PATH_MAX];
/*
* The input string pvid may be of any length, it's often
* read from system.devices, which can be edited.
* These pvid strings are often compared to pvids in the
* form char pvid[ID_LEN+1] using memcmp with ID_LEN.
*
* . ignore any pvid characters over ID_LEN
* . return a buffer is ID_LEN+1 in size, even
* if the pvid string is shorter.
*/
char *strdup_pvid(char *pvid)
{
char *buf;
if (!(buf = zalloc(ID_LEN + 1)))
return NULL;
strncpy(buf, pvid, ID_LEN);
return buf;
}
char *devices_file_version(void)
{
return _devices_file_version;
@ -1267,7 +1286,15 @@ int device_ids_read(struct cmd_context *cmd)
if (pvid) {
_copy_idline_str(pvid, buf, PATH_MAX);
if (buf[0] && (buf[0] != '.')) {
if (!(du->pvid = strdup(buf)))
/*
* Caution: pvids are usually stored as
* char pvid[ID_LEN+1], and use memcmp/memcpy
* with ID_LEN. So, strdup_pvid is used to
* ensure the buffer for du->pvid is ID_LEN+1.
* Then, memcmp/memcpy with ID_LEN will work,
* and printing du->pvid with %s will work.
*/
if (!(du->pvid = strdup_pvid(buf)))
line_error = 1;
}
}
@ -1881,7 +1908,7 @@ id_done:
du->idname = strdup(id->idname);
du->devname = strdup(dev_name(dev));
du->dev = dev;
du->pvid = strdup(pvid);
du->pvid = strdup_pvid(pvid);
dev_get_partition_number(dev, &du->part);
@ -2659,7 +2686,7 @@ void device_ids_validate(struct cmd_context *cmd, struct dm_list *scanned_devs,
dev_name(dev), dev->pvid);
log_warn("Device %s has PVID %s (devices file %s)",
dev_name(dev), dev->pvid, du->pvid ?: "none");
if (!(tmpdup = strdup(dev->pvid)))
if (!(tmpdup = strdup_pvid(dev->pvid)))
continue;
free(du->pvid);
du->pvid = tmpdup;
@ -3210,7 +3237,7 @@ void device_ids_check_serial(struct cmd_context *cmd, struct dm_list *scan_devs,
log_debug("Device %s with serial number %s has PVID %s (devices file %s)",
dev_name(dev), du->idname, dev->pvid, du->pvid ?: "none");
if (!(tmpdup = strdup(dev->pvid)))
if (!(tmpdup = strdup_pvid(dev->pvid)))
continue;
free(du->pvid);
du->pvid = tmpdup;
@ -3395,7 +3422,7 @@ void device_ids_search(struct cmd_context *cmd, struct dm_list *new_devs,
memcpy(dil->pvid, du->pvid, ID_LEN);
dm_list_add(&search_pvids, &dil->list);
search_pvids_count++;
search_pvids_hash = calc_crc(search_pvids_hash, (const uint8_t *)du->pvid, strlen(du->pvid));
search_pvids_hash = calc_crc(search_pvids_hash, (const uint8_t *)du->pvid, ID_LEN);
}
/* No unmatched PVIDs to search for, and no system id to update. */

View File

@ -190,7 +190,7 @@ static int _pvchange_single(struct cmd_context *cmd, struct volume_group *vg,
if (du) {
memcpy(pvid, &pv->id.uuid, ID_LEN);
free(du->pvid);
if (!(du->pvid = strdup(pvid)))
if (!(du->pvid = strdup_pvid(pvid)))
log_error("Failed to set pvid for devices file.");
if (!device_ids_write(cmd))
log_warn("Failed to update devices file.");