aboutsummaryrefslogtreecommitdiffstats
path: root/lib/libzutil
diff options
context:
space:
mode:
authorнаб <[email protected]>2021-05-22 17:19:14 +0200
committerBrian Behlendorf <[email protected]>2021-06-11 09:10:21 -0700
commitfeb04e66802ef96aa77951c43d4b632b376041ef (patch)
tree0d78f6283f001f8f66828bef33c9ace4185f7802 /lib/libzutil
parent64dfdaba372f07f91a6eab598b3480693b1d14c8 (diff)
Forbid basename(3) and dirname(3)
There are at least two interpretations of basename(3), in addition to both functions being allowed to /both/ return a static buffer (unsuitable in multi-threaded environments) /and/ raze the input (which encourages overallocations, at best) Reviewed-by: John Kennedy <[email protected]> Reviewed-by: Brian Behlendorf <[email protected]> Reviewed-by: Ryan Moeller <[email protected]> Signed-off-by: Ahelenia Ziemiańska <[email protected]> Closes #12105
Diffstat (limited to 'lib/libzutil')
-rw-r--r--lib/libzutil/zutil_import.c37
1 files changed, 27 insertions, 10 deletions
diff --git a/lib/libzutil/zutil_import.c b/lib/libzutil/zutil_import.c
index 871a75ab2..9bd12973f 100644
--- a/lib/libzutil/zutil_import.c
+++ b/lib/libzutil/zutil_import.c
@@ -154,6 +154,17 @@ zutil_strdup(libpc_handle_t *hdl, const char *str)
return (ret);
}
+static char *
+zutil_strndup(libpc_handle_t *hdl, const char *str, size_t n)
+{
+ char *ret;
+
+ if ((ret = strndup(str, n)) == NULL)
+ (void) zutil_no_memory(hdl);
+
+ return (ret);
+}
+
/*
* Intermediate structures used to gather configuration information.
*/
@@ -1272,20 +1283,22 @@ zpool_find_import_scan_path(libpc_handle_t *hdl, pthread_mutex_t *lock,
{
int error = 0;
char path[MAXPATHLEN];
- char *d, *b;
- char *dpath, *name;
+ char *d = NULL;
+ ssize_t dl;
+ const char *dpath, *name;
/*
- * Separate the directory part and last part of the
- * path. We do this so that we can get the realpath of
+ * Separate the directory and the basename.
+ * We do this so that we can get the realpath of
* the directory. We don't get the realpath on the
* whole path because if it's a symlink, we want the
* path of the symlink not where it points to.
*/
- d = zutil_strdup(hdl, dir);
- b = zutil_strdup(hdl, dir);
- dpath = dirname(d);
- name = basename(b);
+ name = zfs_basename(dir);
+ if ((dl = zfs_dirnamelen(dir)) == -1)
+ dpath = ".";
+ else
+ dpath = d = zutil_strndup(hdl, dir, dl);
if (realpath(dpath, path) == NULL) {
error = errno;
@@ -1303,7 +1316,6 @@ zpool_find_import_scan_path(libpc_handle_t *hdl, pthread_mutex_t *lock,
zpool_find_import_scan_add_slice(hdl, lock, cache, path, name, order);
out:
- free(b);
free(d);
return (error);
}
@@ -1506,6 +1518,7 @@ discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
avl_tree_t *cache, pthread_mutex_t *lock)
{
char *path = NULL;
+ ssize_t dl;
uint_t children;
nvlist_t **child;
@@ -1521,8 +1534,12 @@ discover_cached_paths(libpc_handle_t *hdl, nvlist_t *nv,
* our directory cache.
*/
if (nvlist_lookup_string(nv, ZPOOL_CONFIG_PATH, &path) == 0) {
+ if ((dl = zfs_dirnamelen(path)) == -1)
+ path = ".";
+ else
+ path[dl] = '\0';
return (zpool_find_import_scan_dir(hdl, lock, cache,
- dirname(path), 0));
+ path, 0));
}
return (0);
}