From e70531a9453473a01bf86e13aa8e54047ddac28c Mon Sep 17 00:00:00 2001 From: Jim Warner Date: Tue, 22 Nov 2016 10:10:10 -0500 Subject: [PATCH] library: protect against possible 'refcount' underflow In each module employing a priming read at 'new' time, should that read fail, a call to 'unref' will be made. However, there is a hidden dependency that these calls must never occur before the context 'refcount' was set due to the way an 'unref' conditional was constructed. So this commit just ensures that 'unref' will function as expected, even if called with a 'refcount' of zero. Signed-off-by: Jim Warner --- proc/diskstats.c | 4 ++-- proc/meminfo.c | 4 +++- proc/pids.c | 3 ++- proc/slabinfo.c | 4 ++-- proc/stat.c | 3 ++- proc/vmstat.c | 4 +++- 6 files changed, 14 insertions(+), 8 deletions(-) diff --git a/proc/diskstats.c b/proc/diskstats.c index 2aafa3d4..ff5fcddf 100644 --- a/proc/diskstats.c +++ b/proc/diskstats.c @@ -800,7 +800,8 @@ PROCPS_EXPORT int procps_diskstats_unref ( return -EINVAL; (*info)->refcount--; - if ((*info)->refcount == 0) { + + if ((*info)->refcount < 1) { if ((*info)->diskstats_fp) { fclose((*info)->diskstats_fp); (*info)->diskstats_fp = NULL; @@ -828,7 +829,6 @@ PROCPS_EXPORT int procps_diskstats_unref ( free(*info); *info = NULL; - return 0; } return (*info)->refcount; diff --git a/proc/meminfo.c b/proc/meminfo.c index 53d4e46f..549b0340 100644 --- a/proc/meminfo.c +++ b/proc/meminfo.c @@ -778,14 +778,16 @@ PROCPS_EXPORT int procps_meminfo_unref ( { if (info == NULL || *info == NULL) return -EINVAL; + (*info)->refcount--; - if ((*info)->refcount == 0) { + if ((*info)->refcount < 1) { if ((*info)->extents) meminfo_extents_free_all((*info)); if ((*info)->items) free((*info)->items); hdestroy_r(&(*info)->hashtab); + free(*info); *info = NULL; return 0; diff --git a/proc/pids.c b/proc/pids.c index 446add3f..1a0d0b3d 100644 --- a/proc/pids.c +++ b/proc/pids.c @@ -1180,7 +1180,8 @@ PROCPS_EXPORT int procps_pids_unref ( return -EINVAL; (*info)->refcount--; - if ((*info)->refcount == 0) { + + if ((*info)->refcount < 1) { #ifdef UNREF_RPTHASH pids_unref_rpthash(*info); #endif diff --git a/proc/slabinfo.c b/proc/slabinfo.c index 02f84280..97933128 100644 --- a/proc/slabinfo.c +++ b/proc/slabinfo.c @@ -843,7 +843,8 @@ PROCPS_EXPORT int procps_slabinfo_unref ( return -EINVAL; (*info)->refcount--; - if ((*info)->refcount == 0) { + + if ((*info)->refcount < 1) { if ((*info)->slabinfo_fp) { fclose((*info)->slabinfo_fp); (*info)->slabinfo_fp = NULL; @@ -867,7 +868,6 @@ PROCPS_EXPORT int procps_slabinfo_unref ( free(*info); *info = NULL; - return 0; } return (*info)->refcount; diff --git a/proc/stat.c b/proc/stat.c index 4d0989a5..9eccb133 100644 --- a/proc/stat.c +++ b/proc/stat.c @@ -901,9 +901,10 @@ PROCPS_EXPORT int procps_stat_unref ( { if (info == NULL || *info == NULL) return -EINVAL; + (*info)->refcount--; - if ((*info)->refcount == 0) { + if ((*info)->refcount < 1) { if ((*info)->cpus.anchor) free((*info)->cpus.anchor); if ((*info)->cpus.result.stacks) diff --git a/proc/vmstat.c b/proc/vmstat.c index 5cd49c3d..e012777b 100644 --- a/proc/vmstat.c +++ b/proc/vmstat.c @@ -1162,14 +1162,16 @@ PROCPS_EXPORT int procps_vmstat_unref ( { if (info == NULL || *info == NULL) return -EINVAL; + (*info)->refcount--; - if ((*info)->refcount == 0) { + if ((*info)->refcount < 1) { if ((*info)->extents) vmstat_extents_free_all((*info)); if ((*info)->items) free((*info)->items); hdestroy_r(&(*info)->hashtab); + free(*info); *info = NULL; return 0;