Skip to content

Commit

Permalink
libct/nsenter: fix logging race in nsexec
Browse files Browse the repository at this point in the history
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 ba3cabf) relies on multiple write(2)
calls, and with additional logging added by 64bb59f 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 <kolyshkin@gmail.com>
  • Loading branch information
kolyshkin committed Aug 11, 2021
1 parent 16027b8 commit 2bab4a5
Showing 1 changed file with 9 additions and 2 deletions.
11 changes: 9 additions & 2 deletions libcontainer/nsenter/nsexec.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand All @@ -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. */
Expand Down

0 comments on commit 2bab4a5

Please sign in to comment.