-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Closed
Milestone
Description
In zfsonlinx, the libzfs zpool_find_vdev() function has the side-effect of overwriting the pool config associated with the pool handle. Found while integration zfs_mod.c from illumos.
code path of overwrite:
zpool_find_vdev()grabs config nvlist from pool handle and extracts vdev tree- calls into
vdev_to_nvlist_iter()with vdev tree, visiting each vdev - calls into
zfs_strcmp_pathname()with 'path' string value - calls
strtok()on above string and path value is overwritten
an easy way to reproduce is (see actual code below):
$ gcc -m64 -lzfs -lnvpair -I/usr/include/libzfs/ -I/usr/include/libspl zpool_find_vdev.c -o zpool_find_vdev
$ sudo ./zpool_find_vdev serenity
config vdev paths before:
vdev 01123202461778220001: /dev/disk/by-id/scsi-350000394a8caede4-part1
vdev 11514177655449603062: /dev/disk/by-id/scsi-350000394a8cb11f0-part1
vdev 01435883551868357921: /dev/disk/by-id/scsi-350000394a8cb4d8c-part1
vdev 07294385912884184264: /dev/disk/by-id/scsi-350000394a8ca4fc4-part1
vdev 03405823394303353173: /dev/disk/by-id/scsi-350000394a8cb3d64-part1
vdev 06846423427570562778: /dev/disk/by-id/scsi-350000394a8ca4fbc-part1
vdev 12727135398764565842: /dev/disk/by-id/scsi-350000394a8cb2d3c-part1
vdev 12336940145533931721: /dev/disk/by-id/scsi-350000394a8ca4fc0-part1
config vdev paths after:
vdev 01123202461778220001: /dev
vdev 11514177655449603062: /dev
vdev 01435883551868357921: /dev
vdev 07294385912884184264: /dev
vdev 03405823394303353173: /dev
vdev 06846423427570562778: /dev
vdev 12727135398764565842: /dev
vdev 12336940145533931721: /dev
stand-alone code that repoduces the problem:
#include <stdio.h>
#include <libzfs/libnvpair.h>
#include <libzfs/libzfs.h>
static void
print_vdev_paths(zpool_handle_t *zhp, nvlist_t *nvl)
{
char *path;
uint_t c, children;
nvlist_t **child;
uint64_t guid;
if (nvlist_lookup_nvlist_array(nvl, ZPOOL_CONFIG_CHILDREN,
&child, &children) == 0) {
for (c = 0; c < children; c++)
print_vdev_paths(zhp, child[c]);
return;
}
(void) nvlist_lookup_uint64(nvl, ZPOOL_CONFIG_GUID, &guid);
(void) nvlist_lookup_string(nvl, ZPOOL_CONFIG_PATH, &path);
if (guid && path)
(void) fprintf(stdout, "vdev %020llu: %s\n", guid, path);
}
int
main(int argc, char **argv)
{
libzfs_handle_t *zfshdl;
zpool_handle_t *zhp;
zfshdl = libzfs_init();
if ((zhp = zpool_open(zfshdl, argv[1])) != NULL) {
nvlist_t *config, *tree;
boolean_t tmp;
config = zpool_get_config(zhp, NULL);
(void) nvlist_lookup_nvlist(config, ZPOOL_CONFIG_VDEV_TREE, &tree);
(void) fprintf(stdout, "\nconfig vdev paths before:\n");
print_vdev_paths(zhp, tree);
(void) zpool_find_vdev(zhp, "anything", &tmp, &tmp, &tmp);
(void) fprintf(stdout, "\nconfig vdev paths after:\n");
print_vdev_paths(zhp, tree);
zpool_close(zhp);
}
libzfs_fini(zfshdl);
}
Metadata
Metadata
Assignees
Labels
No labels