Skip to content

Commit

Permalink
Forward more messages on the sd-notify socket
Browse files Browse the repository at this point in the history
Several of the standard sd-notify messages are safe to use from a
container and are very useful. This commit cleans up the general
handling of notify messages and allows forwarding of:

 * READY=1
 * RELOADING=1
 * STOPPING=1
 * WATCHDOG=1
 * WATCHDOG=trigger
 * STATUS=...
 * ERRNO=...
 * BUSERROR=...
 * MONOTONIC_USEC...

See https://www.freedesktop.org/software/systemd/man/latest/sd_notify.html#Well-known%20assignments
for documentation of these.

Note: We don't allow unknown messages to be forewarded. For one, all
the file-descriptor based ones are currently unsupported (since the
forwarding doesn't handle fds), but also some options (current and
future) may be security sensitive.

fixes #461
fixes #311

Signed-off-by: Alexander Larsson <[email protected]>
  • Loading branch information
alexlarsson committed Dec 12, 2023
1 parent 57eedf0 commit 20ce441
Showing 1 changed file with 44 additions and 9 deletions.
53 changes: 44 additions & 9 deletions src/conn_sock.c
Original file line number Diff line number Diff line change
Expand Up @@ -432,17 +432,52 @@ static gboolean read_remote_sock(struct remote_sock_s *sock)
sock->off = 0;

if (SOCK_IS_NOTIFY(sock->sock_type)) {
/* Do what OCI runtime does - only pass READY=1 */
/* We pass a limited amount of safe messages here, as some existing or
future ones could be security sensitive */
const char *passon_line[] = {
"READY=1", "RELOADING=1", "STOPPING=1", "WATCHDOG=1", "WATCHDOG=trigger",
};
const char *passon_prefix[] = {
"STATUS=",
"ERRNO=",
"BUSERROR=",
"MONOTONIC_USEC=",
};
char **lines;

sock->buf[num_read] = '\0';
if (strstr(sock->buf, "READY=1")) {
strncpy(sock->buf, "READY=1", 8);
sock->remaining = 7;
} else if (strstr(sock->buf, "WATCHDOG=1")) {
strncpy(sock->buf, "WATCHDOG=1", 11);
sock->remaining = 10;
} else {
sock->remaining = 0;
lines = g_strsplit_set(sock->buf, "\n\r", -1);
sock->remaining = 0;

for (size_t i = 0; lines[i] != NULL; i++) {
const char *line = lines[i];
gboolean pass_line = FALSE;

for (size_t j = 0; j < G_N_ELEMENTS(passon_line); j++) {
if (strcmp(line, passon_line[j]) == 0) {
pass_line = TRUE;
break;
}
}

for (size_t j = 0; !pass_line && j < G_N_ELEMENTS(passon_prefix); j++) {
if (g_str_has_prefix(line, passon_prefix[j])) {
pass_line = TRUE;
break;
}
}

/* This will always fit in sock->buf as we only pass through exact
bytes from an existing sock->buf */
if (pass_line) {
if (sock->remaining > 0)
sock->buf[sock->remaining++] = '\n';

memcpy(sock->buf + sock->remaining, line, strlen(line));
sock->remaining += strlen(line);
}
}
g_strfreev(lines);
}

if (sock->remaining)
Expand Down

0 comments on commit 20ce441

Please sign in to comment.