git: 8099a354469a - main - libkvm: Fix kvm_getloadavg() on modern kernel vmcores

From: John Baldwin <jhb_at_FreeBSD.org>
Date: Tue, 07 Dec 2021 23:38:41 UTC
The branch main has been updated by jhb:

URL: https://cgit.FreeBSD.org/src/commit/?id=8099a354469a012512d9850302edaa0e27c75fd7

commit 8099a354469a012512d9850302edaa0e27c75fd7
Author:     Michał Górny <mgorny@gentoo.org>
AuthorDate: 2021-11-07 21:11:52 +0000
Commit:     John Baldwin <jhb@FreeBSD.org>
CommitDate: 2021-12-07 23:36:34 +0000

    libkvm: Fix kvm_getloadavg() on modern kernel vmcores
    
    Fix kvm_getloadavg() to work correctly on vmcores for modern kernel
    versions.  The kernels no longer include the `_fscale` symbol causing
    the kvm_nlist() invocation to fail.  The code seemed to already assume
    that `_fscale` could be missing but the early kvm_nlist() result check
    has caused the function to fail if any symbol were missing.  Modify
    it to only treat `_averunnable` as obligatory, and handle missing
    `_fscale` gracefully.
    
    Sponsored by:   The FreeBSD Foundation
    Differential Revision:  https://reviews.freebsd.org/D32884
---
 lib/libkvm/kvm_getloadavg.c | 9 ++++-----
 1 file changed, 4 insertions(+), 5 deletions(-)

diff --git a/lib/libkvm/kvm_getloadavg.c b/lib/libkvm/kvm_getloadavg.c
index 0f2a5f69bcf0..f94b1d844663 100644
--- a/lib/libkvm/kvm_getloadavg.c
+++ b/lib/libkvm/kvm_getloadavg.c
@@ -62,7 +62,6 @@ int
 kvm_getloadavg(kvm_t *kd, double loadavg[], int nelem)
 {
 	struct loadavg loadinfo;
-	struct nlist *p;
 	int fscale, i;
 
 	if (ISALIVE(kd))
@@ -74,10 +73,9 @@ kvm_getloadavg(kvm_t *kd, double loadavg[], int nelem)
 		return (-1);
 	}
 
-	if (kvm_nlist(kd, nl) != 0) {
-		for (p = nl; p->n_type != 0; ++p);
+	if (kvm_nlist(kd, nl) != 0 && nl[X_AVERUNNABLE].n_type == 0) {
 		_kvm_err(kd, kd->program,
-		    "%s: no such symbol", p->n_name);
+		    "%s: no such symbol", nl[X_AVERUNNABLE].n_name);
 		return (-1);
 	}
 
@@ -92,7 +90,8 @@ kvm_getloadavg(kvm_t *kd, double loadavg[], int nelem)
 	 * Old kernels have fscale separately; if not found assume
 	 * running new format.
 	 */
-	if (!KREAD(kd, nl[X_FSCALE].n_value, &fscale))
+	if (nl[X_FSCALE].n_type != 0 &&
+	    !KREAD(kd, nl[X_FSCALE].n_value, &fscale))
 		loadinfo.fscale = fscale;
 
 	nelem = MIN(nelem, (int)(sizeof(loadinfo.ldavg) / sizeof(fixpt_t)));