From 8c351bc3f9c7249d356b29bd0828bfbb2b221d53 Mon Sep 17 00:00:00 2001 From: Ricardo Branco Date: Sat, 10 Feb 2024 00:17:47 +0100 Subject: [PATCH] Use sysctl for *BSD --- bsd/Makefile | 10 ++-- bsd/extern.h | 7 +++ bsd/kinfo_getallproc.c | 63 +++++++++++++++++++++++ bsd/kinfo_getargv.c | 84 +++++++++++++++++++++++++++++++ bsd/restartable.c | 112 ++++++++++------------------------------- 5 files changed, 186 insertions(+), 90 deletions(-) create mode 100644 bsd/extern.h create mode 100644 bsd/kinfo_getallproc.c create mode 100644 bsd/kinfo_getargv.c diff --git a/bsd/Makefile b/bsd/Makefile index eecc54d..7cb3172 100644 --- a/bsd/Makefile +++ b/bsd/Makefile @@ -3,10 +3,12 @@ OPSYS:sh = uname PROG= restartable WARNS= 3 CFLAGS+= -O2 -.if ${OPSYS} == "FreeBSD" -LDFLAGS= -lprocstat -.elif ${OPSYS} == "NetBSD" -LDFLAGS= -lkvm -lutil +LDFLAGS= -lutil +SRCS= restartable.c kinfo_getargv.c +HDRS= extern.h + +.if ${OPSYS} == "NetBSD" +SRCS+= kinfo_getallproc.c .endif MK_DEBUG_FILES= no diff --git a/bsd/extern.h b/bsd/extern.h new file mode 100644 index 0000000..c742b53 --- /dev/null +++ b/bsd/extern.h @@ -0,0 +1,7 @@ + +void free_argv(char **); +char **kinfo_getargv(pid_t pid); + +#ifdef __NetBSD__ +struct kinfo_proc *kinfo_getallproc(int *); +#endif diff --git a/bsd/kinfo_getallproc.c b/bsd/kinfo_getallproc.c new file mode 100644 index 0000000..8129608 --- /dev/null +++ b/bsd/kinfo_getallproc.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include +#include + +#if defined(__NetBSD__) +#define kinfo_proc kinfo_proc2 +#endif + +#include "extern.h" + +/* + * Sort processes by pid + */ +static int +kinfo_proc_compare(const void *a, const void *b) +{ + + return ((const struct kinfo_proc *)a)->p_pid - + ((const struct kinfo_proc *)b)->p_pid; +} + +static void +kinfo_proc_sort(struct kinfo_proc *kipp, int count) +{ + + qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); +} + +struct kinfo_proc * +kinfo_getallproc(int *cntp) +{ + struct kinfo_proc *kipp; + size_t len; + int mib[6]; + + mib[0] = CTL_KERN; + mib[1] = KERN_PROC2; + mib[2] = KERN_PROC_ALL; + mib[3] = 0; + mib[4] = sizeof(struct kinfo_proc2); + mib[5] = 0; + + len = 0; + if (sysctl(mib, 6, NULL, &len, NULL, 0) < 0) + return (NULL); + mib[5] = (int) (len / sizeof(struct kinfo_proc2)); + + kipp = malloc(len); + if (kipp == NULL) + return (NULL); + + if (sysctl(mib, 6, kipp, &len, NULL, 0) < 0) + goto bad; + *cntp = len / sizeof(*kipp); + kinfo_proc_sort(kipp, len / sizeof(*kipp)); + return (kipp); +bad: + *cntp = 0; + free(kipp); + return (NULL); +} diff --git a/bsd/kinfo_getargv.c b/bsd/kinfo_getargv.c new file mode 100644 index 0000000..091c87e --- /dev/null +++ b/bsd/kinfo_getargv.c @@ -0,0 +1,84 @@ +#include +#include +#include +#include +#include +#include + +#include "extern.h" + +static int +memnchr(const void *p, int c, size_t len) +{ + int n = 0; + + for (size_t i = 0; i < len; i++) + if (*((const unsigned char *)p + i) == c) + n++; + + return n; +} + +void +free_argv(char **argv) +{ + char **argvp = argv; + + while (*argvp != NULL) { + free(*argvp); + argvp++; + } + + free(argv); +} + +char ** +kinfo_getargv(pid_t pid) +{ + char *buf = NULL; + char **argv; + int mib[4]; + int i, argc; + size_t off = 0, len = ARG_MAX; + + buf = malloc(len); + if (buf == NULL) + return (NULL); + + mib[0] = CTL_KERN; +#if defined(__FreeBSD__) + mib[1] = KERN_PROC; + mib[2] = KERN_PROC_ARGS; + mib[3] = pid; +#elif defined(__NetBSD__) + mib[1] = KERN_PROC_ARGS; + mib[2] = pid; + mib[3] = KERN_PROC_ARGV; +#endif + + if (sysctl(mib, 4, buf, &len, NULL, 0) < 0) + goto bad; + buf[len] = '\0'; + + argc = memnchr(buf, '\0', len); + argv = malloc((argc + 1) * sizeof(char *)); + if (argv == NULL) + goto bad; + + for (i = 0; i < argc; i++) { + argv[i] = strdup(buf + off); + if (argv[i] == NULL) { + free_argv(argv); + goto bad; + } + off += strlen(argv[i]) + 1; + } + argv[argc] = NULL; + + free(buf); + return (argv); + +bad: + free(buf); + return (NULL); +} diff --git a/bsd/restartable.c b/bsd/restartable.c index 337c3b6..862c44b 100644 --- a/bsd/restartable.c +++ b/bsd/restartable.c @@ -26,36 +26,32 @@ * SUCH DAMAGE. */ +#ifdef __NetBSD__ +/* struct kinfo_proc */ +#define _KMEMUSER +#endif + #include -#include #if defined(__FreeBSD__) -#include -#include -#include #include -#include +#include #elif defined(__NetBSD__) +#include #include #include -#include #endif #include #include #include #include +#include #include #include #include - -#ifdef __FreeBSD__ -#define kvm_t struct procstat -#endif - -#ifdef __NetBSD__ +#if defined(__NetBSD__) #define kinfo_proc kinfo_proc2 -#define kvm_getargv kvm_getargv2 #define ki_comm p_comm #define ki_login p_login #define ki_pid p_pid @@ -63,6 +59,8 @@ #define ki_ruid p_ruid #endif +#include "extern.h" + static int verbose = 0; /* Avoid ANSI terminal injection from processes that overwrite their argv */ @@ -74,25 +72,17 @@ safe_arg(char *arg) { vis = malloc(PATH_MAX * 4 + 1); if (vis == NULL) err(1, "malloc"); - (void) strnvis(vis, PATH_MAX * 4 + 1, arg, VIS_TAB | VIS_NL | VIS_CSTYLE); + (void) strvis(vis, arg, VIS_TAB | VIS_NL | VIS_CSTYLE); return vis; } static void -print_argv(kvm_t *kd, struct kinfo_proc *kp) { -#if defined(__FreeBSD__) - char **argv = procstat_getargv(kd, kp, 0); -#elif defined(__NetBSD__) - char **argv = kvm_getargv(kd, kp, 0); -#endif +print_argv(pid_t pid) { + char **argv = kinfo_getargv(pid); if (argv == NULL) { -#if defined(__FreeBSD__) - warn("procstat_getargv(): %d", kp->ki_pid); -#elif defined(__NetBSD__) - warnx("kvm_getargv(): %d: %s", kp->ki_pid, kvm_geterr(kd)); -#endif + warn("%d: kinfo_getargv", pid); return; } printf("\t"); @@ -101,13 +91,11 @@ print_argv(kvm_t *kd, struct kinfo_proc *kp) { } while (*++argv); printf("\n"); -#ifdef __FreeBSD__ - procstat_freeargv(kd); -#endif + free_argv(argv); } static void -print_proc(kvm_t *kd, struct kinfo_proc *kp) { +print_proc(const struct kinfo_proc *kp) { #if defined(__FreeBSD__) int i, count; #elif defined(__NetBSD__) @@ -118,85 +106,37 @@ print_proc(kvm_t *kd, struct kinfo_proc *kp) { if (kp->ki_pid == 0) return; -#if defined(__FreeBSD__) - struct kinfo_vmentry *vmmap = procstat_getvmmap(kd, kp, &count); -#elif defined(__NetBSD__) struct kinfo_vmentry *vmmap = kinfo_getvmmap(kp->ki_pid, &count); - if (vmmap == NULL) - err(1, "kinfo_getvmmap(): %d", kp->ki_pid); -#endif + if (vmmap == NULL) { + if (errno != EPERM) + warn("kinfo_getvmmap(): %d", kp->ki_pid); + return; + } for (i = 0; i < count; i++) if (vmmap[i].kve_type == KVME_TYPE_VNODE && vmmap[i].kve_protection & KVME_PROT_EXEC && vmmap[i].kve_path[0] == '\0') { printf("%d\t%d\t%d\t%s\t%s\n", kp->ki_pid, kp->ki_ppid, kp->ki_ruid, kp->ki_login, kp->ki_comm); if (verbose) - print_argv(kd, kp); + print_argv(kp->ki_pid); break; } -#if defined(__FreeBSD__) - procstat_freevmmap(kd, vmmap); -#elif defined(__NetBSD__) free(vmmap); -#endif } -#ifdef __NetBSD__ -/* - * Sort processes by pid - */ -static int -kinfo_proc_compare(const void *a, const void *b) -{ - return ((const struct kinfo_proc2 *)a)->p_pid - ((const struct kinfo_proc2 *)b)->p_pid; -} - -static void -kinfo_proc_sort(struct kinfo_proc2 *kipp, int count) -{ - - qsort(kipp, count, sizeof(*kipp), kinfo_proc_compare); -} -#endif - static int print_all(void) { -#ifdef __NetBSD__ - char errbuf[_POSIX2_LINE_MAX]; -#endif struct kinfo_proc *procs; int count; - kvm_t *kd; -#if defined(__FreeBSD__) - /* Doesn't work if security.bsd.unprivileged_proc_debug=0 */ - kd = procstat_open_sysctl(); - if (kd == NULL) - err(1, "procstat_open_sysctl()"); - procs = procstat_getprocs(kd, KERN_PROC_PROC, 0, &count); + procs = kinfo_getallproc(&count); if (procs == NULL) - err(1, "procstat_getprocs()"); -#elif defined(__NetBSD__) - kd = kvm_openfiles(NULL, NULL, NULL, O_RDONLY, errbuf); - if (kd == NULL) - errx(1, "kvm_openfiles(): %s", errbuf); - - procs = kvm_getproc2(kd, KERN_PROC_ALL, 0, sizeof(struct kinfo_proc2), &count); - kinfo_proc_sort(procs, count / sizeof(*procs)); - if (procs == NULL) - err(1, "kvm_getproc2(): %s", kvm_geterr(kd)); -#endif + err(1, "kinfo_getallproc()"); for (int i = 0; i < count; i++) - print_proc(kd, &procs[i]); + print_proc(&procs[i]); -#if defined(__FreeBSD__) - procstat_freeprocs(kd, procs); - procstat_close(kd); -#elif defined(__NetBSD__) free(procs); - (void)kvm_close(kd); -#endif return 0; }