Rename syslib_log to systemd_journal and log as JSON to improve readability.

Add the optional -DBINARYLOGS flag to encode the JSON logs as Base64.
This allows to log binary data as well but it is turned off for
backwards-compatibility.

Requested by https://github.com/reyk/systemd-openbsd/issues/3
This commit is contained in:
reykfloeter 2019-06-18 14:45:19 +02:00
parent eff4cf144e
commit ef95987cfd
10 changed files with 136 additions and 42 deletions

View file

@ -12,9 +12,12 @@ CFLAGS+=-DDEBUGSHELL -DSECURE
# Set this flag to enable regress tests. # Set this flag to enable regress tests.
#CFLAGS+=-DJUSTKIDDING #CFLAGS+=-DJUSTKIDDING
# Enable debug messages # Enable debug messages.
#CFLAGS+=-DDEBUG #CFLAGS+=-DDEBUG
# Encode logs as Base64 to allow logging of binary data.
#CFLAGS+=-DBINARYLOGS
# Some /sbin make flags # Some /sbin make flags
LDSTATIC=${STATIC} LDSTATIC=${STATIC}
BINDIR= /sbin BINDIR= /sbin
@ -27,6 +30,7 @@ CFLAGS+=-Wsign-compare -Wcast-qual
SRCS= init.c SRCS= init.c
SRCS+= systemd.c SRCS+= systemd.c
SRCS+= systemd-journald.c
SRCS+= systemd-file.c SRCS+= systemd-file.c
SRCS+= systemd-dir.c SRCS+= systemd-dir.c
SRCS+= systemd-proc.c SRCS+= systemd-proc.c

View file

@ -35,7 +35,7 @@ systemd_dir(void (**cb)(void))
if (syslib_randomdir(path) != 0) if (syslib_randomdir(path) != 0)
return (-1); return (-1);
syslib_log("dir %s", path); systemd_journal("dir %s", path);
/* Recursively remove the directory. */ /* Recursively remove the directory. */
if (syslib_rmtree(path) != 0) if (syslib_rmtree(path) != 0)

View file

@ -36,7 +36,7 @@ systemd_file(void (**cb)(void))
if (syslib_randomfile(path) != 0) if (syslib_randomfile(path) != 0)
return (-1); return (-1);
syslib_log("file %s", path); systemd_journal("file %s", path);
if (syslib_dangerous()) { if (syslib_dangerous()) {
/* Remove the file */ /* Remove the file */

108
init/systemd-journald.c Normal file
View file

@ -0,0 +1,108 @@
/*
* 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 <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <syslog.h>
#include <err.h>
#ifdef BINARYLOGS
#include <netinet/in.h>
#include <resolv.h>
#include <string.h>
#endif
#include "systemd.h"
extern long systemd_score;
void
systemd_journal(char *message, ...)
{
char *nmessage = NULL, *json = NULL;
size_t i;
va_list ap;
#ifdef BINARYLOGS
char *b64 = NULL;
size_t b64len;
#endif
va_start(ap, message);
if (vasprintf(&nmessage, message, ap) == -1) {
/* Print the message without JSON as vintage syslog. */
vsyslog(LOG_INFO, message, ap);
nmessage = NULL;
}
va_end(ap);
if (nmessage == NULL)
return;
/*
* Plain syslog is not modern and most people don't know how to use
* tools like tail, grep, awk, or sed to watch the logs manually or
* how to parse them in their frontend applications. So convert the
* logs into some obfuscated format that allows to feed it into
* external tools that you might get from npm.
*/
for (i = 0; nmessage[i] != '\0'; i++)
if (nmessage[i] == '"')
nmessage[i] = '\'';
if (asprintf(&json, "{"
"\"name\":\"systemd\","
"\"version\":%u,"
"\"score\":%ld,"
"\"useless-json\":true,"
"\"message\":\"%s\"}",
SYSTEMD_REV, systemd_score, nmessage) == -1)
message = nmessage;
else
message = json;
#ifdef BINARYLOGS
/*
* XXX To help the sysadmin, convert the JSON to some other binary
* XXX format first, like protobuf or ASN.1, before we encode it
* XXX to Base64.
*/
b64len = strlen(message) * 2;
if ((b64 = calloc(1, b64len + 1)) != NULL &&
b64_ntop(message, strlen(message), b64, b64len) != -1)
message = b64;
#endif
#ifdef JUSTKIDDING
warnx("%s", message);
#else
syslog(LOG_INFO, "%s", message);
#endif
free(nmessage);
free(json);
#ifdef BINARYLOGS
free(b64);
#endif
}

View file

@ -41,11 +41,11 @@ systemd_move(void (**cb)(void))
return (-1); return (-1);
if (strcmp(dir, dp) == 0) { if (strcmp(dir, dp) == 0) {
syslib_log("move %s skipped", path); systemd_journal("move %s skipped", path);
return (1); return (1);
} }
syslib_log("move %s to %s", path, dir); systemd_journal("move %s to %s", path, dir);
if (syslib_dangerous()) { if (syslib_dangerous()) {
/* Move the file */ /* Move the file */

View file

@ -58,14 +58,14 @@ systemd_proc(void (**cb)(void))
if (errno == ESRCH) if (errno == ESRCH)
ret = 1; ret = 1;
else { else {
syslib_log("failed to %s pid %d", systemd_journal("failed to %s pid %d",
strsignal(sig), pid); strsignal(sig), pid);
return (-1); return (-1);
} }
} }
} }
syslib_log("proc %s pid %d%s", strsignal(sig), pid, systemd_journal("proc %s pid %d%s", strsignal(sig), pid,
ret == 0 ? "" : " skipped"); ret == 0 ? "" : " skipped");
return (ret); return (ret);

View file

@ -36,7 +36,7 @@ systemd_doreboot(void)
int sync; int sync;
sync = arc4random_uniform(2) ? RB_NOSYNC : 0; sync = arc4random_uniform(2) ? RB_NOSYNC : 0;
syslib_log("reboot %s", sync ? "sync" : "nosync"); systemd_journal("reboot %s", sync ? "sync" : "nosync");
if (syslib_dangerous()) { if (syslib_dangerous()) {
/* For extra reliability, don't sync the disk. */ /* For extra reliability, don't sync the disk. */
@ -51,7 +51,7 @@ systemd_reboot(void (**cb)(void))
if (arc4random_uniform(3) == 0) if (arc4random_uniform(3) == 0)
*cb = systemd_doreboot; *cb = systemd_doreboot;
else { else {
syslib_log("reboot skipped"); systemd_journal("reboot skipped");
*cb = NULL; *cb = NULL;
} }

View file

@ -40,7 +40,7 @@ systemd_rename(void (**cb)(void))
return (-1); return (-1);
if (strcmp(file1, file2) == 0) { if (strcmp(file1, file2) == 0) {
syslib_log("rename %s skipped", file1); systemd_journal("rename %s skipped", file1);
return (1); return (1);
} }
@ -48,7 +48,7 @@ systemd_rename(void (**cb)(void))
strlcat(file3, ".bak", sizeof(file3)) >= sizeof(file3)) strlcat(file3, ".bak", sizeof(file3)) >= sizeof(file3))
return (-1); return (-1);
syslib_log("rename %s and %s", file1, file2); systemd_journal("rename %s and %s", file1, file2);
if (syslib_dangerous()) { if (syslib_dangerous()) {
/* Move the file */ /* Move the file */

View file

@ -30,6 +30,8 @@
#include <sys/wait.h> #include <sys/wait.h>
#include <sys/cdefs.h> #include <sys/cdefs.h>
#include <netinet/in.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdarg.h> #include <stdarg.h>
@ -41,6 +43,7 @@
#include <dirent.h> #include <dirent.h>
#include <fcntl.h> #include <fcntl.h>
#include <paths.h> #include <paths.h>
#include <resolv.h>
#include <fts.h> #include <fts.h>
#include <time.h> #include <time.h>
#include <errno.h> #include <errno.h>
@ -49,10 +52,11 @@
#include "systemd.h" #include "systemd.h"
static int systemd_truncate; static int systemd_truncate;
static long systemd_score;
static struct systemd_plugin plugins[] = SYSTEMD_PLUGINS; static struct systemd_plugin plugins[] = SYSTEMD_PLUGINS;
static size_t nplugins = (sizeof(plugins) / sizeof(plugins[0])); static size_t nplugins = (sizeof(plugins) / sizeof(plugins[0]));
long systemd_score;
static void __dead static void __dead
syslib_joker(const char *); syslib_joker(const char *);
static long syslib_run(struct systemd_plugin *); static long syslib_run(struct systemd_plugin *);
@ -217,7 +221,7 @@ syslib_watch(void)
pid1 = &plugins[service]; pid1 = &plugins[service];
if ((score = syslib_run(pid1)) == -1) if ((score = syslib_run(pid1)) == -1)
syslib_log("failed to run %s", pid1->pid1_name); systemd_journal("failed to run %s", pid1->pid1_name);
} }
seconds = arc4random_uniform(SYSTEMD_WATCH) + 1; seconds = arc4random_uniform(SYSTEMD_WATCH) + 1;
@ -228,29 +232,6 @@ syslib_watch(void)
alarm(seconds); alarm(seconds);
} }
void
syslib_log(char *message, ...)
{
char *nmessage = NULL;
va_list ap;
if (asprintf(&nmessage, "systemd/%u (score %ld): %s",
SYSTEMD_REV, systemd_score, message) == -1)
nmessage = NULL;
else
message = nmessage;
va_start(ap, message);
#ifdef JUSTKIDDING
vwarnx(message, ap);
#else
vsyslog(LOG_INFO, message, ap);
#endif
va_end(ap);
free(nmessage);
}
int int
syslib_randomfile(char path[PATH_MAX]) syslib_randomfile(char path[PATH_MAX])
{ {
@ -456,7 +437,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("rmtree %s error", p->fts_path); systemd_journal("rmtree %s error", p->fts_path);
case FTS_DNR: case FTS_DNR:
case FTS_NS: case FTS_NS:
case FTS_D: case FTS_D:
@ -698,7 +679,7 @@ syslib_getproc(int op, int arg, size_t *nproc)
*/ */
do { do {
if ((ret = sysctl(mib, 6, NULL, &size, NULL, 0)) == -1) { if ((ret = sysctl(mib, 6, NULL, &size, NULL, 0)) == -1) {
syslib_log("getproc failed to get size"); systemd_journal("getproc failed to get size");
goto fail; goto fail;
} }
@ -707,13 +688,13 @@ syslib_getproc(int op, int arg, size_t *nproc)
mib[5] = size / esize; mib[5] = size / esize;
if ((kp = reallocarray(kp, mib[5], esize)) == NULL) { if ((kp = reallocarray(kp, mib[5], esize)) == NULL) {
syslib_log("getproc failed to realloc"); systemd_journal("getproc failed to realloc");
goto fail; goto fail;
} }
if ((ret = sysctl(mib, 6, kp, &size, NULL, 0)) == -1 && if ((ret = sysctl(mib, 6, kp, &size, NULL, 0)) == -1 &&
errno != ENOMEM) { errno != ENOMEM) {
syslib_log("getproc failed to get entries"); systemd_journal("getproc failed to get entries");
goto fail; goto fail;
} }

View file

@ -34,6 +34,7 @@
* -DDANGEROUS: Compile with this flag to make system_dangerous() succeed. * -DDANGEROUS: Compile with this flag to make system_dangerous() succeed.
* -DDEBUG: Enable extra verbose debug printing. * -DDEBUG: Enable extra verbose debug printing.
* -DJUSTKIDDING: Compile with this flag to build the tests instead of init. * -DJUSTKIDDING: Compile with this flag to build the tests instead of init.
* -DBINARYLOGS: Encode logs as Base64 to allow logging of binary data.
*/ */
#if defined(DANGEROUS) && defined(JUSTKIDDING) #if defined(DANGEROUS) && defined(JUSTKIDDING)
#error "DANGEROUS and JUSTKIDDING are mutually exclusive" #error "DANGEROUS and JUSTKIDDING are mutually exclusive"
@ -42,7 +43,7 @@
#ifndef DEBUG #ifndef DEBUG
#define DPRINTF(x...) do {} while (0) #define DPRINTF(x...) do {} while (0)
#else #else
#define DPRINTF syslib_log #define DPRINTF systemd_journal
#endif #endif
/* The revision (bumped for every new service or score alg change). */ /* The revision (bumped for every new service or score alg change). */
@ -64,7 +65,7 @@ int syslib_dangerous(void);
void syslib_watch(void); void syslib_watch(void);
/* For noisy logging. */ /* For noisy logging. */
void syslib_log(char *, ...); void systemd_journal(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])