summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJoshua M. Clulow <josh@sysmgr.org>2020-08-05 22:20:29 -0700
committerJoshua M. Clulow <josh@sysmgr.org>2020-08-05 22:21:59 -0700
commitbe235d17490f6a5ad01c6a5319530fce66d88389 (patch)
tree432fc375e2b5d8df340e66b925f9fc9287bf05e4
parentbd05d33960c9701232eaa8bdb6a5ce585912ffc6 (diff)
downloadillumos-joyent-be235d17490f6a5ad01c6a5319530fce66d88389.tar.gz
12801 libdiskmgt leaks PROM device information handles like a sieve
Reviewed by: Garrett D'Amore <garrett@damore.org> Reviewed by: Robert Mustacchi <rm@fingolfin.org> Reviewed by: Yuri Pankov <yuripv@yuripv.dev> Approved by: Richard Lowe <richlowe@richlowe.net>
-rw-r--r--usr/src/lib/libdiskmgt/common/findevs.c30
1 files changed, 26 insertions, 4 deletions
diff --git a/usr/src/lib/libdiskmgt/common/findevs.c b/usr/src/lib/libdiskmgt/common/findevs.c
index 8114f31352..440d8585db 100644
--- a/usr/src/lib/libdiskmgt/common/findevs.c
+++ b/usr/src/lib/libdiskmgt/common/findevs.c
@@ -27,6 +27,7 @@
/*
* Copyright (c) 2011 by Delphix. All rights reserved.
* Copyright 2017 Nexenta Systems, Inc.
+ * Copyright 2020 Oxide Computer Company
*/
#include <fcntl.h>
@@ -149,8 +150,23 @@ findevs(struct search_args *args)
args->controller_listp = NULL;
args->disk_listp = NULL;
+ args->ph = DI_PROM_HANDLE_NIL;
+ args->handle = DI_LINK_NIL;
args->dev_walk_status = 0;
- args->handle = di_devlink_init(NULL, 0);
+
+ /*
+ * Create device information library handles, which must be destroyed
+ * before we return.
+ */
+ if ((args->ph = di_prom_init()) == DI_PROM_HANDLE_NIL ||
+ (args->handle = di_devlink_init(NULL, 0)) == DI_LINK_NIL) {
+ /*
+ * We could not open all of the handles we need, so clean up
+ * and report failure to the caller.
+ */
+ args->dev_walk_status = errno;
+ goto cleanup;
+ }
/*
* Have to make several passes at this with the new devfs caching.
@@ -158,7 +174,6 @@ findevs(struct search_args *args)
* devices.
*/
di_root = di_init("/", DINFOCACHE);
- args->ph = di_prom_init();
(void) di_walk_minor(di_root, NULL, 0, args, add_devs);
di_fini(di_root);
@@ -166,9 +181,16 @@ findevs(struct search_args *args)
(void) di_walk_minor(di_root, NULL, 0, args, add_devs);
di_fini(di_root);
- (void) di_devlink_fini(&(args->handle));
-
clean_paths(args);
+
+cleanup:
+ if (args->ph != DI_PROM_HANDLE_NIL) {
+ di_prom_fini(args->ph);
+ args->ph = DI_PROM_HANDLE_NIL;
+ }
+ if (args->handle != DI_LINK_NIL) {
+ (void) di_devlink_fini(&(args->handle));
+ }
}
/*