From f37a5a2543e4c7227f2f238cafdaf45cb657c552 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=8E=E9=80=9A=E6=B4=B2?= Date: Fri, 11 Sep 2026 23:38:10 +0800 Subject: [PATCH] OpenBSD: removes kvm dep --- CMakeLists.txt | 1 - src/common/impl/FFPlatform_unix.c | 63 ++++++++++++++---------- src/common/impl/processing_linux.c | 35 ++++++------- src/detection/displayserver/linux/wmde.c | 39 +++++++++------ src/detection/lm/lm_linux.c | 33 ++++++++----- src/detection/processes/processes_obsd.c | 24 ++++----- src/detection/top/top_obsd.c | 45 +++++++++-------- 7 files changed, 132 insertions(+), 108 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 5d52ecd8e..3fa14120b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1930,7 +1930,6 @@ elseif(FreeBSD) elseif(OpenBSD) target_link_libraries(libfastfetch PRIVATE "m" - PRIVATE "kvm" PRIVATE "sndio" PRIVATE "util" ) diff --git a/src/common/impl/FFPlatform_unix.c b/src/common/impl/FFPlatform_unix.c index 92f0e8634..2c0ab9db3 100644 --- a/src/common/impl/FFPlatform_unix.c +++ b/src/common/impl/FFPlatform_unix.c @@ -4,6 +4,7 @@ #include "common/strutil.h" #include "common/io.h" #include "common/path.h" +#include "common/mallocHelper.h" #include #include @@ -19,7 +20,6 @@ #elif defined(__OpenBSD__) #include #include - #include #include "common/path.h" #elif defined(__HAIKU__) #include @@ -68,13 +68,14 @@ static void getExePath(FFPlatform* platform) { // Current implementation uses argv[0], which can be easily spoofed. // See #2195 size_t exePathLen = 0; - kvm_t* kd = kvm_openfiles(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - if (kd) { - int kpCount; - struct kinfo_proc* kp = kvm_getprocs(kd, KERN_PROC_PID, (pid_t) platform->pid, sizeof(*kp), &kpCount); - if (kp && kpCount == 1) { - char** argv = kvm_getargv(kd, kp, 0); - if (argv && argv[0]) { + { + char argvBuf[ARG_MAX]; + size_t argvSize = sizeof(argvBuf); + int argvMib[] = { CTL_KERN, KERN_PROC_ARGS, (pid_t) platform->pid, KERN_PROC_ARGV }; + if (sysctl(argvMib, ARRAY_SIZE(argvMib), argvBuf, &argvSize, nullptr, 0) == 0) { + // The buffer is filled with an array of char pointers followed by the strings themselves + char** argv = (char**) argvBuf; + if (argv[0] && (char*) argv[0] >= argvBuf && (char*) argv[0] < argvBuf + argvSize) { char* arg0 = argv[0]; if (arg0[0]) { if (strchr(arg0, '/') != nullptr) // likely a path (absolute or relative) @@ -97,25 +98,38 @@ static void getExePath(FFPlatform* platform) { if (exePathLen > 0) { struct stat st; if (stat(exePath, &st) == 0 && S_ISREG(st.st_mode)) { - int cntp; - struct kinfo_file* kf = kvm_getfiles(kd, KERN_FILE_BYPID, (pid_t) platform->pid, sizeof(*kf), &cntp); - if (kf) { - int i; - for (i = 0; i < cntp; i++) { - if (kf[i].fd_fd == KERN_FILE_TEXT) { - // KERN_FILE_TEXT is the executable file, not a shared library, and should be unique in the list. - if (st.st_dev != (dev_t) kf[i].va_fsid || st.st_ino != (ino_t) kf[i].va_fileid) { - i = -1; + // Replicate kvm_getfiles()'s live path: {CTL_KERN, KERN_FILE, KERN_FILE_BYPID, pid, esize, count} + int fileMib[6] = { CTL_KERN, KERN_FILE, KERN_FILE_BYPID, (pid_t) platform->pid, (int) sizeof(struct kinfo_file), 0 }; + size_t fileSize = 0; + if (sysctl(fileMib, ARRAY_SIZE(fileMib), nullptr, &fileSize, nullptr, 0) == 0) { + fileSize += fileSize / 8; // add ~10% + FF_AUTO_FREE struct kinfo_file* kf = (struct kinfo_file*) malloc(fileSize); + if (kf) { + int rv; + do { + fileMib[5] = (int) (fileSize / sizeof(struct kinfo_file)); + rv = sysctl(fileMib, ARRAY_SIZE(fileMib), kf, &fileSize, nullptr, 0); + } while (rv == -1 && errno == ENOMEM); + + if (rv == 0) { + int cntp = (int) (fileSize / sizeof(struct kinfo_file)); + int i; + for (i = 0; i < cntp; i++) { + if (kf[i].fd_fd == KERN_FILE_TEXT) { + // KERN_FILE_TEXT is the executable file, not a shared library, and should be unique in the list. + if (st.st_dev != (dev_t) kf[i].va_fsid || st.st_ino != (ino_t) kf[i].va_fileid) { + i = -1; + } + break; + } + } + if (i < 0) { + exePathLen = 0; } - break; } + // If we can't get the list of open files, we can't verify that the file is actually the executable + // Assume it is } - if (i < 0) { - exePathLen = 0; - } - } else { - // If we can't get the list of open files, we can't verify that the file is actually the executable - // Assume it is } } else { exePathLen = 0; @@ -124,7 +138,6 @@ static void getExePath(FFPlatform* platform) { } } } - kvm_close(kd); } #elif defined(__sun) ssize_t exePathLen = readlink("/proc/self/path/a.out", exePath, sizeof(exePath) - 1); diff --git a/src/common/impl/processing_linux.c b/src/common/impl/processing_linux.c index e43aff2b9..5783f880f 100644 --- a/src/common/impl/processing_linux.c +++ b/src/common/impl/processing_linux.c @@ -28,7 +28,6 @@ #elif defined(__OpenBSD__) #include #include - #include #elif defined(__NetBSD__) #include #include @@ -423,12 +422,13 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons #elif defined(__OpenBSD__) - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - int count = 0; - const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count); - if (proc) { - char** argv = kvm_getargv(kd, proc, 0); - if (argv) { + char argvBuf[ARG_MAX]; + size_t argvSize = sizeof(argvBuf); + int argvMib[] = { CTL_KERN, KERN_PROC_ARGS, pid, KERN_PROC_ARGV }; + if (sysctl(argvMib, ARRAY_SIZE(argvMib), argvBuf, &argvSize, nullptr, 0) == 0) { + // The buffer is filled with an array of char pointers followed by the strings themselves + char** argv = (char**) argvBuf; + if (argv[0] && (char*) argv[0] >= argvBuf && (char*) argv[0] < argvBuf + argvSize) { const char* arg0 = argv[0]; if (arg0[0] == '-') { arg0++; @@ -436,7 +436,6 @@ void ffProcessGetInfoLinux(pid_t pid, FFstrbuf* processName, FFstrbuf* exe, cons ffStrbufSetS(exe, arg0); } } - kvm_close(kd); #elif defined(__HAIKU__) @@ -633,21 +632,19 @@ const char* ffProcessGetBasicInfoLinux(pid_t pid, FFstrbuf* name, pid_t* ppid, i #elif defined(__OpenBSD__) - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - int count = 0; - const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_PID, pid, sizeof(struct kinfo_proc), &count); - if (proc) { - ffStrbufSetS(name, proc->p_comm); + struct kinfo_proc proc; + size_t size = sizeof(proc); + int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PID, pid, (int) sizeof(struct kinfo_proc), 1 }; + if (sysctl(mib, ARRAY_SIZE(mib), &proc, &size, nullptr, 0) == 0) { + ffStrbufSetS(name, proc.p_comm); if (ppid) { - *ppid = proc->p_ppid; + *ppid = proc.p_ppid; } if (tty) { - *tty = (int) proc->p_tdev; + *tty = (int) proc.p_tdev; } - } - kvm_close(kd); - if (!proc) { - return "kvm_getprocs() failed"; + } else { + return "sysctl(KERN_PROC_PID) failed"; } #elif defined(__HAIKU__) diff --git a/src/detection/displayserver/linux/wmde.c b/src/detection/displayserver/linux/wmde.c index 6984d1d0c..984bdbeda 100644 --- a/src/detection/displayserver/linux/wmde.c +++ b/src/detection/displayserver/linux/wmde.c @@ -16,7 +16,6 @@ #elif __OpenBSD__ #include #include - #include #elif __sun #include #elif __NetBSD__ @@ -311,25 +310,33 @@ static const char* getFromProcesses(FFDisplayServerResult* result) { } } #elif __OpenBSD__ - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - int count = 0; - const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, (int) userId, sizeof(*proc), &count); - if (proc) { - for (int i = 0; i < count; ++i) { - if (result->dePrettyName.length == 0) { - applyPrettyNameIfDE(result, proc[i].p_comm); - } + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, (int) userId, (int) sizeof(struct kinfo_proc), 0 }; + size_t length = 0; - if (result->wmPrettyName.length == 0) { - applyNameIfWM(result, proc[i].p_comm); - } + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, nullptr) failed"; + } - if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) { - break; - } + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + request[5] = (int) (length / sizeof(struct kinfo_proc)); // count must be non-zero for data fetch + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; + } + + int count = (int) (length / sizeof(struct kinfo_proc)); + for (int i = 0; i < count; ++i) { + if (result->dePrettyName.length == 0) { + applyPrettyNameIfDE(result, procs[i].p_comm); + } + + if (result->wmPrettyName.length == 0) { + applyNameIfWM(result, procs[i].p_comm); + } + + if (result->dePrettyName.length > 0 && result->wmPrettyName.length > 0) { + break; } } - kvm_close(kd); #elif __sun FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if (procdir == nullptr) { diff --git a/src/detection/lm/lm_linux.c b/src/detection/lm/lm_linux.c index e4f18c19e..2abfab97a 100644 --- a/src/detection/lm/lm_linux.c +++ b/src/detection/lm/lm_linux.c @@ -18,7 +18,6 @@ #elif __OpenBSD__ #include #include - #include #elif __sun #include #elif __NetBSD__ @@ -55,7 +54,7 @@ static const char* getSshdVersion(FFstrbuf* version) { #ifdef FF_HAVE_ZLIB #include "common/library.h" #include "common/path.h" - + #include #include @@ -274,19 +273,27 @@ const char* detectByProcesses(FFLMResult* result) { } } #elif __OpenBSD__ - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - int count = 0; - const struct kinfo_proc* proc = kvm_getprocs(kd, KERN_PROC_UID, 0, sizeof(*proc), &count); - if (proc) { - for (int i = 0; i < count; ++i) { - const char* lm = testLms(proc[i].p_comm); - if (lm) { - ffStrbufSetStatic(&result->service, lm); - break; - } + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_UID, 0, (int) sizeof(struct kinfo_proc), 0 }; + size_t length = 0; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, nullptr) failed"; + } + + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + request[5] = (int) (length / sizeof(struct kinfo_proc)); // count must be non-zero for data fetch + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_UID}, procs) failed"; + } + + int count = (int) (length / sizeof(struct kinfo_proc)); + for (int i = 0; i < count; ++i) { + const char* lm = testLms(procs[i].p_comm); + if (lm) { + ffStrbufSetStatic(&result->service, lm); + break; } } - kvm_close(kd); #elif __sun FF_AUTO_CLOSE_DIR DIR* procdir = opendir("/proc"); if (procdir == nullptr) { diff --git a/src/detection/processes/processes_obsd.c b/src/detection/processes/processes_obsd.c index 8c50065a0..e07d45b1b 100644 --- a/src/detection/processes/processes_obsd.c +++ b/src/detection/processes/processes_obsd.c @@ -4,25 +4,22 @@ #include #include -#include const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResult* result) { - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - if (!kd) { - return "kvm_open() failed"; + int request[] = { CTL_KERN, KERN_PROC, (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, 0, (int) sizeof(struct kinfo_proc), 0 }; + size_t length = 0; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}, nullptr) failed"; } - int count = 0; - // KERN_PROC_ALL returns all user-level processes - // KERN_PROC_KTHREAD returns all processes, including user-level processes (despite the name) - const struct kinfo_proc* procs = kvm_getprocs(kd, - (options->countKprocs ? KERN_PROC_KTHREAD : KERN_PROC_ALL) | KERN_PROC_SHOW_THREADS, - 0, sizeof(struct kinfo_proc), &count); - if (!procs) { - kvm_close(kd); - return "kvm_getprocs() failed"; + FF_AUTO_FREE struct kinfo_proc* procs = (struct kinfo_proc*) malloc(length); + request[5] = (int) (length / sizeof(struct kinfo_proc)); // count must be non-zero for data fetch + if (sysctl(request, ARRAY_SIZE(request), procs, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}, procs) failed"; } + int count = (int) (length / sizeof(struct kinfo_proc)); for (int i = 0; i < count; ++i) { const struct kinfo_proc* proc = &procs[i]; @@ -32,6 +29,5 @@ const char* ffDetectProcesses(const FFProcessesOptions* options, FFProcessesResu } } - kvm_close(kd); return nullptr; } diff --git a/src/detection/top/top_obsd.c b/src/detection/top/top_obsd.c index 365ecfe7f..6c56ea549 100644 --- a/src/detection/top/top_obsd.c +++ b/src/detection/top/top_obsd.c @@ -1,24 +1,26 @@ #include "top.h" +#include "common/mallocHelper.h" + #include #include // DEV_BSIZE #include -#include const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { - kvm_t* kd = kvm_open(nullptr, nullptr, nullptr, KVM_NO_FILES, nullptr); - if (!kd) { - return "kvm_open() failed"; + int request[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL, 0, (int) sizeof(struct kinfo_proc), 0 }; + size_t length = 0; + + if (sysctl(request, ARRAY_SIZE(request), nullptr, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}, nullptr) failed"; } - int count = 0; - // KERN_PROC_ALL returns all user-level processes, excluding kernel processes and threads - const struct kinfo_proc* processes = kvm_getprocs(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc), &count); - if (!processes) { - kvm_close(kd); - return "kvm_getprocs() failed"; + FF_AUTO_FREE struct kinfo_proc* processes = (struct kinfo_proc*) malloc(length); + request[5] = (int) (length / sizeof(struct kinfo_proc)); // count must be non-zero for data fetch + if (sysctl(request, ARRAY_SIZE(request), processes, &length, nullptr, 0) != 0) { + return "sysctl({CTL_KERN, KERN_PROC, KERN_PROC_ALL}, processes) failed"; } + int count = (int) (length / sizeof(struct kinfo_proc)); const uint32_t pageSize = instance.state.platform.sysinfo.pageSize; for (int i = 0; i < count; ++i) { @@ -41,21 +43,24 @@ const char* ffTopGetProcessSnapshot(FFlist* snapshots, FFTopTypes showTypes) { } if (showTypes & FF_TOP_TYPE_THREADS) { - int threadCount = 0; - const struct kinfo_proc* threads = kvm_getprocs(kd, - KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, sizeof(struct kinfo_proc), &threadCount); - if (threads) { - for (uint32_t i = 0; i < snapshots->length; ++i) { - FFTopProcessSnapshot* item = FF_LIST_GET(FFTopProcessSnapshot, *snapshots, i); - for (int j = 0; j < threadCount; ++j) { - if (threads[j].p_pid == (pid_t) item->pid && threads[j].p_tid != -1) { - ++item->threads; + int threadRequest[] = { CTL_KERN, KERN_PROC, KERN_PROC_ALL | KERN_PROC_SHOW_THREADS, 0, (int) sizeof(struct kinfo_proc), 0 }; + size_t threadLength = 0; + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), nullptr, &threadLength, nullptr, 0) == 0 && threadLength > 0) { + FF_AUTO_FREE struct kinfo_proc* threads = (struct kinfo_proc*) malloc(threadLength); + threadRequest[5] = (int) (threadLength / sizeof(struct kinfo_proc)); // count must be non-zero for data fetch + if (sysctl(threadRequest, ARRAY_SIZE(threadRequest), threads, &threadLength, nullptr, 0) == 0) { + int threadCount = (int) (threadLength / sizeof(struct kinfo_proc)); + for (uint32_t i = 0; i < snapshots->length; ++i) { + FFTopProcessSnapshot* item = FF_LIST_GET(FFTopProcessSnapshot, *snapshots, i); + for (int j = 0; j < threadCount; ++j) { + if (threads[j].p_pid == (pid_t) item->pid && threads[j].p_tid != -1) { + ++item->threads; + } } } } } } - kvm_close(kd); return nullptr; }