Skip to content

Commit

Permalink
Use sysctl for *BSD
Browse files Browse the repository at this point in the history
  • Loading branch information
ricardobranco777 committed Feb 10, 2024
1 parent 8626958 commit 8c351bc
Show file tree
Hide file tree
Showing 5 changed files with 186 additions and 90 deletions.
10 changes: 6 additions & 4 deletions bsd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
7 changes: 7 additions & 0 deletions bsd/extern.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

void free_argv(char **);
char **kinfo_getargv(pid_t pid);

#ifdef __NetBSD__
struct kinfo_proc *kinfo_getallproc(int *);
#endif
63 changes: 63 additions & 0 deletions bsd/kinfo_getallproc.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <stdlib.h>

#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);
}
84 changes: 84 additions & 0 deletions bsd/kinfo_getargv.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
#include <sys/cdefs.h>
#include <sys/param.h>
#include <sys/sysctl.h>
#include <sys/proc.h>
#include <stdlib.h>
#include <string.h>

#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);
}
112 changes: 26 additions & 86 deletions bsd/restartable.c
Original file line number Diff line number Diff line change
Expand Up @@ -26,43 +26,41 @@
* SUCH DAMAGE.
*/

#ifdef __NetBSD__
/* struct kinfo_proc */
#define _KMEMUSER
#endif

#include <sys/types.h>
#include <sys/param.h>
#if defined(__FreeBSD__)
#include <sys/queue.h>
#include <sys/socket.h>
#include <sys/sysctl.h>
#include <sys/user.h>
#include <libprocstat.h>
#include <libutil.h>
#elif defined(__NetBSD__)
#include <sys/param.h>
#include <sys/sysctl.h>
#include <util.h>
#include <kvm.h>
#endif

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <err.h>
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
#include <vis.h>


#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
#define ki_ppid p_ppid
#define ki_ruid p_ruid
#endif

#include "extern.h"

static int verbose = 0;

/* Avoid ANSI terminal injection from processes that overwrite their argv */
Expand All @@ -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");
Expand All @@ -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__)
Expand All @@ -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;
}

Expand Down

0 comments on commit 8c351bc

Please sign in to comment.