From 32592d86dfad2781a260387082ccdf251bc45abd Mon Sep 17 00:00:00 2001 From: Eric van Gyzen Date: Tue, 4 Aug 2020 21:05:53 +0000 Subject: [PATCH] devinfo: fix memory leak on error paths Refactor to create devinfo_free_dev(). Call it to plug a memory leak on two error paths in devinfo_init_devices(). Reported by: Coverity MFC after: 2 weeks Sponsored by: Dell EMC Isilon --- lib/libdevinfo/devinfo.c | 32 +++++++++++++++++++++++--------- 1 file changed, 23 insertions(+), 9 deletions(-) diff --git a/lib/libdevinfo/devinfo.c b/lib/libdevinfo/devinfo.c index c4cd8d78ba94..581d3464cd0e 100644 --- a/lib/libdevinfo/devinfo.c +++ b/lib/libdevinfo/devinfo.c @@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$"); static int devinfo_init_devices(int generation); static int devinfo_init_resources(int generation); +static void devinfo_free_dev(struct devinfo_i_dev *dd); TAILQ_HEAD(,devinfo_i_dev) devinfo_dev; TAILQ_HEAD(,devinfo_i_rman) devinfo_rman; @@ -225,7 +226,7 @@ devinfo_init_devices(int generation) rlen, sizeof(udev)); return (EINVAL); } - if ((dd = malloc(sizeof(*dd))) == NULL) + if ((dd = calloc(1, sizeof(*dd))) == NULL) return(ENOMEM); dd->dd_dev.dd_handle = udev.dv_handle; dd->dd_dev.dd_parent = udev.dv_parent; @@ -242,10 +243,14 @@ devinfo_init_devices(int generation) dd->dd_location = NULL; #define UNPACK(x) \ dd->dd_dev.x = dd->x = strdup(walker); \ - if (dd->x == NULL) \ + if (dd->x == NULL) { \ + devinfo_free_dev(dd); \ return(ENOMEM); \ - if (walker + strnlen(walker, ep - walker) >= ep) \ + } \ + if (walker + strnlen(walker, ep - walker) >= ep) { \ + devinfo_free_dev(dd); \ return(EINVAL); \ + } \ walker += strlen(walker) + 1; UNPACK(dd_name); @@ -364,6 +369,20 @@ devinfo_init_resources(int generation) return(0); } +/* + * Free an individual dev. + */ +static void +devinfo_free_dev(struct devinfo_i_dev *dd) +{ + free(dd->dd_name); + free(dd->dd_desc); + free(dd->dd_drivername); + free(dd->dd_pnpinfo); + free(dd->dd_location); + free(dd); +} + /* * Free the list contents. */ @@ -376,12 +395,7 @@ devinfo_free(void) while ((dd = TAILQ_FIRST(&devinfo_dev)) != NULL) { TAILQ_REMOVE(&devinfo_dev, dd, dd_link); - free(dd->dd_name); - free(dd->dd_desc); - free(dd->dd_drivername); - free(dd->dd_pnpinfo); - free(dd->dd_location); - free(dd); + devinfo_free_dev(dd); } while ((dm = TAILQ_FIRST(&devinfo_rman)) != NULL) { TAILQ_REMOVE(&devinfo_rman, dm, dm_link);