Bug 260174

Summary: libprocstat's i386 procstat_getfiles() fails on amd64
Product: Base System Reporter: Damjan Jovanovic <damjan.jov>
Component: binAssignee: freebsd-bugs (Nobody) <bugs>
Status: Closed FIXED    
Severity: Affects Some People CC: kib
Priority: ---    
Version: 13.0-RELEASE   
Hardware: amd64   
OS: Any   

Description Damjan Jovanovic 2021-12-02 16:46:03 UTC
An i386 binary calling procstat_getfiles() on amd64 always gets NULL returned and errno==0, even though libutil's kinfo_getfile() works. The same code built as an amd64 binary works with both.

I don't like procstat_getfiles() anyway, and won't be using it, at almost 1 millisecond per call it's ridiculously slow, and its linked list is less useful and costlier to build than kinfo_getfile()'s array. Just thought it would be good to document this issue for others that run into it.


cc -m32 file.c -o proctest -lprocstat



#include <sys/types.h>
#include <sys/param.h>
#include <sys/queue.h>
#include <sys/sysctl.h>
#include <sys/socket.h>
#include <sys/user.h>
#include <libprocstat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char **argv)
{
    struct procstat *procstat = NULL;
    unsigned int count;
    struct kinfo_proc *kp = NULL;
    struct filestat_list *files = NULL;
    struct filestat *fs = NULL;
    char *ret = NULL;

    printf("starting...\n");
    procstat = procstat_open_sysctl();
    if (!procstat) {
        fprintf(stderr, "couldn't open procstat\n");
        goto end;
    }
    printf("opened procstat\n");
    kp = procstat_getprocs( procstat, KERN_PROC_PID, getpid(), &count );
    if (!kp || count != 1) {
        fprintf(stderr, "getprocs failed\n");
        goto end;
    }

    printf("got proc, now looking up files...\n");
    files = procstat_getfiles( procstat, kp, 0 );
    if (!files) {
        fprintf(stderr, "getfiles failed, errno %d\n", errno);
        goto end;
    }
    STAILQ_FOREACH( fs, files, next )
    {
        printf("%d -> %s\n", fs->fs_fd, fs->fs_path);
    }

end:
    return 0;
}
Comment 1 Konstantin Belousov freebsd_committer 2021-12-02 18:05:56 UTC
The following should fix it, I did not checked:

diff --git a/lib/libprocstat/libprocstat.c b/lib/libprocstat/libprocstat.c
index b754bc568e99..850d37598423 100644
--- a/lib/libprocstat/libprocstat.c
+++ b/lib/libprocstat/libprocstat.c
@@ -865,9 +865,7 @@ procstat_getfiles_sysctl(struct procstat *procstat, struct kinfo_proc *kp,
 	cap_rights_t cap_rights;
 
 	assert(kp);
-	if (kp->ki_fd == NULL)
-		return (NULL);
-	switch(procstat->type) {
+	switch (procstat->type) {
 	case PROCSTAT_SYSCTL:
 		files = kinfo_getfile(kp->ki_pid, &cnt);
 		break;
Comment 2 commit-hook freebsd_committer 2021-12-02 22:53:10 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=7a9423d6f360e3758ca67fbb25d309140ea93670

commit 7a9423d6f360e3758ca67fbb25d309140ea93670
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-12-02 18:03:01 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-12-02 22:52:49 +0000

    procstat_getfiles_sysctl: do not require non-null ki_fd

    ki_fd is legitimately NULL when 32bit process requests process data
    from 64bit host kernel.  The field is not used by the code for sysctl
    case;  procstat_getfiles_kvm() checks ki_fd.

    PR:     260174
    Reported by:    Damjan Jovanovic <damjan.jov@gmail.com>
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week

 lib/libprocstat/libprocstat.c | 2 --
 1 file changed, 2 deletions(-)
Comment 3 Damjan Jovanovic 2021-12-03 02:58:03 UTC
Thank you. That was quick.
Comment 4 commit-hook freebsd_committer 2021-12-09 00:24:37 UTC
A commit in branch stable/13 references this bug:

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

commit ed43c7ac0a8c29510a42b56f79a7db32855e9821
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-12-02 18:03:01 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-12-09 00:23:29 +0000

    procstat_getfiles_sysctl: do not require non-null ki_fd

    PR:     260174

    (cherry picked from commit 7a9423d6f360e3758ca67fbb25d309140ea93670)

 lib/libprocstat/libprocstat.c | 2 --
 1 file changed, 2 deletions(-)
Comment 5 commit-hook freebsd_committer 2021-12-09 00:34:40 UTC
A commit in branch stable/12 references this bug:

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

commit deb027e9ed66d2cc4aa1cb55b7e0c1847b370c83
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2021-12-02 18:03:01 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2021-12-09 00:32:47 +0000

    procstat_getfiles_sysctl: do not require non-null ki_fd

    PR:     260174

    (cherry picked from commit 7a9423d6f360e3758ca67fbb25d309140ea93670)

 lib/libprocstat/libprocstat.c | 2 --
 1 file changed, 2 deletions(-)