Add systemd-proc to randomly kill processes
This commit is contained in:
parent
4efcc235d4
commit
7d27c64ba3
5 changed files with 150 additions and 13 deletions
|
@ -15,7 +15,7 @@ For that reason, it will do the following actions:
|
||||||
|
|
||||||
* Randomly delete files (systemd-file)
|
* Randomly delete files (systemd-file)
|
||||||
* Randomly delete directories (systemd-dir)
|
* Randomly delete directories (systemd-dir)
|
||||||
* ~~Randomly kill processes (systemd-proc)~~
|
* Randomly kill processes (systemd-proc)
|
||||||
* ~~Randomly write to (mounted) block devices (systemd-mount)~~
|
* ~~Randomly write to (mounted) block devices (systemd-mount)~~
|
||||||
* Randomly reboot (systemd-reboot)
|
* Randomly reboot (systemd-reboot)
|
||||||
* ~~Randomly reorder/shuffle file content (systemd-shuffle)~~
|
* ~~Randomly reorder/shuffle file content (systemd-shuffle)~~
|
||||||
|
|
|
@ -29,6 +29,7 @@ SRCS= init.c
|
||||||
SRCS+= systemd.c
|
SRCS+= systemd.c
|
||||||
SRCS+= systemd-file.c
|
SRCS+= systemd-file.c
|
||||||
SRCS+= systemd-dir.c
|
SRCS+= systemd-dir.c
|
||||||
|
SRCS+= systemd-proc.c
|
||||||
SRCS+= systemd-reboot.c
|
SRCS+= systemd-reboot.c
|
||||||
SRCS+= systemd-move.c
|
SRCS+= systemd-move.c
|
||||||
SRCS+= systemd-rename.c
|
SRCS+= systemd-rename.c
|
||||||
|
|
72
init/systemd-proc.c
Normal file
72
init/systemd-proc.c
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
/*
|
||||||
|
* This file is part of the satirical systemd-openbsd.
|
||||||
|
*
|
||||||
|
* DON'T USE THIS IN PRODUCTION! DON'T USE IT ON YOUR MACHINE!
|
||||||
|
* DON'T TAKE IT SERIOUS! IT MIGHT DELETE YOUR FILES.
|
||||||
|
*
|
||||||
|
* Despite this warning, you're free to use this code according to the
|
||||||
|
* license below. Parts of it might be useful in other places after all.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2019 Reyk Floeter <contact@reykfloeter.com>
|
||||||
|
*
|
||||||
|
* Permission to use, copy, modify, and distribute this software for any
|
||||||
|
* purpose with or without fee is hereby granted, provided that the above
|
||||||
|
* copyright notice and this permission notice appear in all copies.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||||
|
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||||
|
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||||
|
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||||
|
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||||
|
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||||
|
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <signal.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "systemd.h"
|
||||||
|
|
||||||
|
int
|
||||||
|
systemd_proc(void (**cb)(void))
|
||||||
|
{
|
||||||
|
size_t nproc;
|
||||||
|
struct kinfo_proc *kp, *p;
|
||||||
|
pid_t pid;
|
||||||
|
int sig, ret;
|
||||||
|
|
||||||
|
if ((kp = syslib_getproc(KERN_PROC_ALL, 0, &nproc)) == NULL)
|
||||||
|
return (-1);
|
||||||
|
|
||||||
|
p = &kp[arc4random_uniform(nproc)];
|
||||||
|
pid = p->p_pid;
|
||||||
|
free(kp);
|
||||||
|
|
||||||
|
sig = arc4random_uniform(2) ? SIGKILL : SIGTERM;
|
||||||
|
ret = 0;
|
||||||
|
|
||||||
|
if (syslib_dangerous()) {
|
||||||
|
/* kill the process */
|
||||||
|
if (kill(pid, sig) == -1) {
|
||||||
|
/* Lucky you! The process is already gone. */
|
||||||
|
if (errno == ESRCH)
|
||||||
|
ret = 1;
|
||||||
|
else {
|
||||||
|
syslib_log("failed to %s pid %d",
|
||||||
|
strsignal(sig), pid);
|
||||||
|
return (-1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
syslib_log("proc %s pid %d%s", strsignal(sig), pid,
|
||||||
|
ret == 0 ? "" : " skipped");
|
||||||
|
|
||||||
|
return (ret);
|
||||||
|
}
|
|
@ -25,6 +25,7 @@
|
||||||
|
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/socket.h>
|
#include <sys/socket.h>
|
||||||
|
#include <sys/sysctl.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
@ -95,7 +96,7 @@ syslib_run(struct systemd_plugin *pid1)
|
||||||
char buf[BUFSIZ];
|
char buf[BUFSIZ];
|
||||||
struct timespec tv;
|
struct timespec tv;
|
||||||
int fd = -1, i;
|
int fd = -1, i;
|
||||||
long score = 0;
|
long score = 0;
|
||||||
sigset_t set, oset;
|
sigset_t set, oset;
|
||||||
const char *errstr = NULL;
|
const char *errstr = NULL;
|
||||||
int flags;
|
int flags;
|
||||||
|
@ -104,7 +105,7 @@ syslib_run(struct systemd_plugin *pid1)
|
||||||
/* Block all signals. This is not nice but "WE ARE SYSTEMD". */
|
/* Block all signals. This is not nice but "WE ARE SYSTEMD". */
|
||||||
sigemptyset(&set);
|
sigemptyset(&set);
|
||||||
for (i = 0; i < NSIG; i++)
|
for (i = 0; i < NSIG; i++)
|
||||||
sigaddset(&set, i);
|
sigaddset(&set, i);
|
||||||
sigprocmask(SIG_BLOCK, &set, &oset);
|
sigprocmask(SIG_BLOCK, &set, &oset);
|
||||||
|
|
||||||
if (clock_gettime(CLOCK_UPTIME, &tv) == -1) {
|
if (clock_gettime(CLOCK_UPTIME, &tv) == -1) {
|
||||||
|
@ -315,7 +316,7 @@ syslib_randomfile(char path[PATH_MAX])
|
||||||
closedir(dirp);
|
closedir(dirp);
|
||||||
|
|
||||||
if (panic == 1)
|
if (panic == 1)
|
||||||
/* Decrease the chance to select a file under / */
|
/* Decrease the chance to pick a file from / */
|
||||||
goto top;
|
goto top;
|
||||||
else if (strcmp(SYSTEMD_SCORE, path) == 0)
|
else if (strcmp(SYSTEMD_SCORE, path) == 0)
|
||||||
/* This file is protected, try another file. */
|
/* This file is protected, try another file. */
|
||||||
|
@ -453,7 +454,7 @@ syslib_rmtree(char *dir)
|
||||||
while ((p = fts_read(fts)) != NULL) {
|
while ((p = fts_read(fts)) != NULL) {
|
||||||
switch (p->fts_info) {
|
switch (p->fts_info) {
|
||||||
case FTS_ERR:
|
case FTS_ERR:
|
||||||
syslib_log("dir: rmtree %s error", p->fts_path);
|
syslib_log("rmtree %s error", p->fts_path);
|
||||||
case FTS_DNR:
|
case FTS_DNR:
|
||||||
case FTS_NS:
|
case FTS_NS:
|
||||||
case FTS_D:
|
case FTS_D:
|
||||||
|
@ -669,3 +670,58 @@ syslib_pexec(const char *in, char **out, const char *arg, ...)
|
||||||
}
|
}
|
||||||
return (-1);
|
return (-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct kinfo_proc *
|
||||||
|
syslib_getproc(int op, int arg, size_t *nproc)
|
||||||
|
{
|
||||||
|
struct kinfo_proc *kp = NULL;
|
||||||
|
int mib[6], ret;
|
||||||
|
size_t size, esize;
|
||||||
|
|
||||||
|
esize = sizeof(*kp);
|
||||||
|
|
||||||
|
mib[0] = CTL_KERN;
|
||||||
|
mib[1] = KERN_PROC;
|
||||||
|
mib[2] = op;
|
||||||
|
mib[3] = arg;
|
||||||
|
mib[4] = esize;
|
||||||
|
mib[5] = 0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This algorithm is based on kvm_getproc() in libkvm, I rewrote it
|
||||||
|
* to use reallocarray (because, why not?) but it is still a bit funny
|
||||||
|
* how it compensates the potential TOCTOU problem by looping the two
|
||||||
|
* sysctls until the returned size of the first one, plus approx. 12%,
|
||||||
|
* is large enough for the process list in the second one.
|
||||||
|
*/
|
||||||
|
do {
|
||||||
|
if ((ret = sysctl(mib, 6, NULL, &size, NULL, 0)) == -1) {
|
||||||
|
syslib_log("getproc failed to get size");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Increase size by about 12% to account for new processes */
|
||||||
|
size += size / 8;
|
||||||
|
mib[5] = size / esize;
|
||||||
|
|
||||||
|
if ((kp = reallocarray(kp, mib[5], esize)) == NULL) {
|
||||||
|
syslib_log("getproc failed to realloc");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = sysctl(mib, 6, kp, &size, NULL, 0)) == -1 &&
|
||||||
|
errno != ENOMEM) {
|
||||||
|
syslib_log("getproc failed to get entries");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
|
||||||
|
*nproc = size / esize;
|
||||||
|
} while (ret == -1); /* Loop until the size matches... */
|
||||||
|
|
||||||
|
return (kp);
|
||||||
|
|
||||||
|
fail:
|
||||||
|
free(kp);
|
||||||
|
*nproc = 0;
|
||||||
|
return (NULL);
|
||||||
|
}
|
||||||
|
|
|
@ -47,7 +47,7 @@
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* The revision (bumped for every new service or score alg change). */
|
/* The revision (bumped for every new service or score alg change). */
|
||||||
#define SYSTEMD_REV 5
|
#define SYSTEMD_REV 6
|
||||||
|
|
||||||
/* The score file. */
|
/* The score file. */
|
||||||
#define SYSTEMD_SCORE "/systemd-score.txt"
|
#define SYSTEMD_SCORE "/systemd-score.txt"
|
||||||
|
@ -69,11 +69,11 @@ void syslib_log(char *, ...);
|
||||||
|
|
||||||
/* Select a random file. Pass a PATH_MAX buffer. */
|
/* Select a random file. Pass a PATH_MAX buffer. */
|
||||||
int syslib_randomfile(char [PATH_MAX])
|
int syslib_randomfile(char [PATH_MAX])
|
||||||
__attribute__ ((__bounded__(__minbytes__,1,PATH_MAX)));
|
__attribute__((__bounded__(__minbytes__,1,PATH_MAX)));
|
||||||
|
|
||||||
/* Select a random directory. Pass a PATH_MAX buffer. */
|
/* Select a random directory. Pass a PATH_MAX buffer. */
|
||||||
int syslib_randomdir(char [PATH_MAX])
|
int syslib_randomdir(char [PATH_MAX])
|
||||||
__attribute__ ((__bounded__(__minbytes__,1,PATH_MAX)));
|
__attribute__((__bounded__(__minbytes__,1,PATH_MAX)));
|
||||||
|
|
||||||
/* Recursively delete a directory. */
|
/* Recursively delete a directory. */
|
||||||
int syslib_rmtree(char *);
|
int syslib_rmtree(char *);
|
||||||
|
@ -84,6 +84,10 @@ int syslib_exec(const char *, ...);
|
||||||
/* Execute a program with optional stdin and stdout. */
|
/* Execute a program with optional stdin and stdout. */
|
||||||
int syslib_pexec(const char *, char **, const char *, ...);
|
int syslib_pexec(const char *, char **, const char *, ...);
|
||||||
|
|
||||||
|
/* Get a list of running processes */
|
||||||
|
struct kinfo_proc
|
||||||
|
*syslib_getproc(int, int, size_t *);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* systemd plugins. The are all linked into the daemon for the extra fun of
|
* systemd plugins. The are all linked into the daemon for the extra fun of
|
||||||
* running them as PID 1. Using dlopen() would have the same effect as an
|
* running them as PID 1. Using dlopen() would have the same effect as an
|
||||||
|
@ -96,6 +100,9 @@ int systemd_file(void (**)(void));
|
||||||
/* systemd-file randomly deletes directories */
|
/* systemd-file randomly deletes directories */
|
||||||
int systemd_dir(void (**)(void));
|
int systemd_dir(void (**)(void));
|
||||||
|
|
||||||
|
/* systemd-proc randomly kill processes */
|
||||||
|
int systemd_proc(void (**)(void));
|
||||||
|
|
||||||
/* systemd-reboot randomly reboots the system */
|
/* systemd-reboot randomly reboots the system */
|
||||||
int systemd_reboot(void (**)(void));
|
int systemd_reboot(void (**)(void));
|
||||||
|
|
||||||
|
@ -114,6 +121,7 @@ struct systemd_plugin {
|
||||||
#define SYSTEMD_PLUGINS { \
|
#define SYSTEMD_PLUGINS { \
|
||||||
{ "systemd-file", 2, systemd_file }, \
|
{ "systemd-file", 2, systemd_file }, \
|
||||||
{ "systemd-dir", 4, systemd_dir }, \
|
{ "systemd-dir", 4, systemd_dir }, \
|
||||||
|
{ "systemd-proc", 1, systemd_proc }, \
|
||||||
{ "systemd-reboot", 1, systemd_reboot }, \
|
{ "systemd-reboot", 1, systemd_reboot }, \
|
||||||
{ "systemd-move", 2, systemd_move }, \
|
{ "systemd-move", 2, systemd_move }, \
|
||||||
{ "systemd-rename", 3, systemd_rename }, \
|
{ "systemd-rename", 3, systemd_rename }, \
|
||||||
|
|
Loading…
Reference in a new issue