diff options
author | Joshua M. Clulow <josh@sysmgr.org> | 2020-08-05 22:20:29 -0700 |
---|---|---|
committer | Joshua M. Clulow <josh@sysmgr.org> | 2020-08-05 22:21:59 -0700 |
commit | be235d17490f6a5ad01c6a5319530fce66d88389 (patch) | |
tree | 432fc375e2b5d8df340e66b925f9fc9287bf05e4 | |
parent | bd05d33960c9701232eaa8bdb6a5ce585912ffc6 (diff) | |
download | illumos-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.c | 30 |
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)); + } } /* |