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
This commit is contained in:
Eric van Gyzen 2020-08-04 21:05:53 +00:00
parent b64dca2b6f
commit 32592d86df

View File

@ -76,6 +76,7 @@ __FBSDID("$FreeBSD$");
static int devinfo_init_devices(int generation); static int devinfo_init_devices(int generation);
static int devinfo_init_resources(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_dev) devinfo_dev;
TAILQ_HEAD(,devinfo_i_rman) devinfo_rman; TAILQ_HEAD(,devinfo_i_rman) devinfo_rman;
@ -225,7 +226,7 @@ devinfo_init_devices(int generation)
rlen, sizeof(udev)); rlen, sizeof(udev));
return (EINVAL); return (EINVAL);
} }
if ((dd = malloc(sizeof(*dd))) == NULL) if ((dd = calloc(1, sizeof(*dd))) == NULL)
return(ENOMEM); return(ENOMEM);
dd->dd_dev.dd_handle = udev.dv_handle; dd->dd_dev.dd_handle = udev.dv_handle;
dd->dd_dev.dd_parent = udev.dv_parent; dd->dd_dev.dd_parent = udev.dv_parent;
@ -242,10 +243,14 @@ devinfo_init_devices(int generation)
dd->dd_location = NULL; dd->dd_location = NULL;
#define UNPACK(x) \ #define UNPACK(x) \
dd->dd_dev.x = dd->x = strdup(walker); \ dd->dd_dev.x = dd->x = strdup(walker); \
if (dd->x == NULL) \ if (dd->x == NULL) { \
devinfo_free_dev(dd); \
return(ENOMEM); \ return(ENOMEM); \
if (walker + strnlen(walker, ep - walker) >= ep) \ } \
if (walker + strnlen(walker, ep - walker) >= ep) { \
devinfo_free_dev(dd); \
return(EINVAL); \ return(EINVAL); \
} \
walker += strlen(walker) + 1; walker += strlen(walker) + 1;
UNPACK(dd_name); UNPACK(dd_name);
@ -364,6 +369,20 @@ devinfo_init_resources(int generation)
return(0); 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. * Free the list contents.
*/ */
@ -376,12 +395,7 @@ devinfo_free(void)
while ((dd = TAILQ_FIRST(&devinfo_dev)) != NULL) { while ((dd = TAILQ_FIRST(&devinfo_dev)) != NULL) {
TAILQ_REMOVE(&devinfo_dev, dd, dd_link); TAILQ_REMOVE(&devinfo_dev, dd, dd_link);
free(dd->dd_name); devinfo_free_dev(dd);
free(dd->dd_desc);
free(dd->dd_drivername);
free(dd->dd_pnpinfo);
free(dd->dd_location);
free(dd);
} }
while ((dm = TAILQ_FIRST(&devinfo_rman)) != NULL) { while ((dm = TAILQ_FIRST(&devinfo_rman)) != NULL) {
TAILQ_REMOVE(&devinfo_rman, dm, dm_link); TAILQ_REMOVE(&devinfo_rman, dm, dm_link);