From 2bab4a56f14b544ac6c680a7a8ef2acc6dde0b57 Mon Sep 17 00:00:00 2001 From: Kir Kolyshkin Date: Thu, 29 Jul 2021 14:28:18 -0700 Subject: [PATCH] libct/nsenter: fix logging race in nsexec As reported in issue 3119, there is a race in nsexec logging that can lead to garbled json received by log forwarder, which complains about it with a "failed to decode" error. This happens because dprintf (used since the very beginning of nsexec logging introduced in commit ba3cabf932943) relies on multiple write(2) calls, and with additional logging added by 64bb59f5920b15d a race is possible between runc init parent and its children. The fix is to prepare a string and write it using a single call to write(2). [v2: NULLify json on error from asprintf] Signed-off-by: Kir Kolyshkin --- libcontainer/nsenter/nsexec.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/libcontainer/nsenter/nsexec.c b/libcontainer/nsenter/nsexec.c index 49e8f54b6a4..ee7b75b1e5a 100644 --- a/libcontainer/nsenter/nsexec.c +++ b/libcontainer/nsenter/nsexec.c @@ -136,7 +136,7 @@ int setns(int fd, int nstype) static void write_log(const char *level, const char *format, ...) { - char *message = NULL, *stage = NULL; + char *message = NULL, *stage = NULL, *json = NULL; va_list args; int ret; @@ -158,11 +158,18 @@ static void write_log(const char *level, const char *format, ...) if (ret < 0) goto out; - dprintf(logfd, "{\"level\":\"%s\", \"msg\": \"%s[%d]: %s\"}\n", level, stage, getpid(), message); + ret = asprintf(&json, "{\"level\":\"%s\", \"msg\": \"%s[%d]: %s\"}\n", level, stage, getpid(), message); + if (ret < 0) { + json = NULL; + goto out; + } + + write(logfd, json, ret); out: free(message); free(stage); + free(json); } /* XXX: This is ugly. */