Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

prevent log message truncation #6554

Merged
merged 5 commits into from
Jan 14, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 10 additions & 12 deletions src/broker/shutdown.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <flux/core.h>

#include "src/common/libutil/stdlog.h"
#include "src/common/libutil/errno_safe.h"

#include "shutdown.h"
#include "state_machine.h"
Expand Down Expand Up @@ -66,30 +67,27 @@ static int forward_logbuf (flux_t *h,
struct stdlog_header hdr;
const char *txt;
size_t txtlen;
char buf[FLUX_MAX_LOGBUF];
int len = strlen (stdlog);
char *buf;
int loglevel;
int rc;

if (flux_msg_unpack (request, "{s:i}", "loglevel", &loglevel) < 0)
loglevel = LOG_ERR;

if (stdlog_decode (stdlog,
strlen (stdlog),
&hdr,
NULL,
NULL,
&txt,
&txtlen) < 0
if (stdlog_decode (stdlog, len, &hdr, NULL, NULL, &txt, &txtlen) < 0
|| STDLOG_SEVERITY (hdr.pri) > loglevel
|| snprintf (buf,
sizeof (buf),
|| asprintf (&buf,
"%s.%s[%lu]: %.*s\n",
hdr.appname,
stdlog_severity_to_string (STDLOG_SEVERITY (hdr.pri)),
strtoul (hdr.hostname, NULL, 10),
(int)txtlen,
txt) >= sizeof (buf))
txt) < 0)
return 0;
return flux_respond_pack (h, request, "{s:s}", "log", buf);
rc = flux_respond_pack (h, request, "{s:s}", "log", buf);
ERRNO_SAFE_WRAP (free, buf);
return rc;
}

static void dmesg_continuation (flux_future_t *f, void *arg)
Expand Down
82 changes: 70 additions & 12 deletions src/common/libflux/flog.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@

#include "src/common/libutil/wallclock.h"
#include "src/common/libutil/stdlog.h"
#include "src/common/libutil/errno_safe.h"

#define FLUX_MAX_LOGBUF 2048

typedef struct {
char appname[STDLOG_MAX_APPNAME + 1];
Expand Down Expand Up @@ -111,6 +114,32 @@
return 0;
}

static int vlog_stderr (int level, const char *fmt, va_list ap)
{
char buf[FLUX_MAX_LOGBUF];
char *result = buf;
char *mbuf = NULL;
const char *lstr = stdlog_severity_to_string (LOG_PRI (level));
int rc;
va_list ap_copy;

/* Copy va_list ap in case it reused on truncation below:
*/
va_copy (ap_copy, ap);

if (vsnprintf (result, sizeof (buf), fmt, ap) >= sizeof (buf)) {
/* Message truncation occurred. Fall back to malloc. If that
* fails, just print the truncated message:
*/
if (vasprintf (&mbuf, fmt, ap_copy) == 0)
result = mbuf;

Check warning on line 135 in src/common/libflux/flog.c

View check run for this annotation

Codecov / codecov/patch

src/common/libflux/flog.c#L134-L135

Added lines #L134 - L135 were not covered by tests
}
rc = fprintf (stderr, "%s: %s\n", lstr, result);
va_end (ap_copy);
ERRNO_SAFE_WRAP (free, mbuf);
return rc < 0 ? -1 : 0;
}

int flux_vlog (flux_t *h, int level, const char *fmt, va_list ap)
{
logctx_t *ctx;
Expand All @@ -122,16 +151,12 @@
char hostname[STDLOG_MAX_HOSTNAME + 1];
struct stdlog_header hdr;
char *xtra = NULL;
char *mbuf = NULL;
char *result;
va_list ap_copy;

if (!h) {
char buf[FLUX_MAX_LOGBUF];
const char *lstr = stdlog_severity_to_string (LOG_PRI (level));

(void)vsnprintf (buf, sizeof (buf), fmt, ap);
if (fprintf (stderr, "%s: %s\n", lstr, buf) < 0)
return -1;
return 0;
}
if (!h)
return vlog_stderr (level, fmt, ap);

if (!(ctx = getctx (h))) {
errno = ENOMEM;
Expand All @@ -149,32 +174,65 @@
hdr.appname = ctx->appname;
hdr.procid = ctx->procid;

/* Copy va_list ap in case it reused on truncation below:
*/
va_copy (ap_copy, ap);

Comment on lines +177 to +180
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same comment here

n = stdlog_vencodef (ctx->buf,
sizeof (ctx->buf),
&hdr,
STDLOG_NILVALUE,
fmt,
ap);
result = ctx->buf;
len = n >= sizeof (ctx->buf) ? sizeof (ctx->buf) : n;

/* Unlikely: On overflow, try again with a buffer allocated on the heap.
* If this fails for any reason, fall back to truncated output.
*/
if (n >= sizeof (ctx->buf)) {
if ((mbuf = malloc (n + 1))) {
/* Note: `n` returned from stdlog_vencodef() may be > actual
* length because if there's truncation then this function cannot
* drop trailing \r, \n from the result. Therefore, ignore return
* of stdlog_vencodef() here (if malloc(3) succeeds) because it is
* known the result will fit in the allocated buffer, but the
* expected return value is not known.
*/
(void) stdlog_vencodef (mbuf,
n + 1,
&hdr,
STDLOG_NILVALUE,
fmt,
ap_copy);
result = mbuf;
len = n;
}
}

va_end (ap_copy);

/* If log message contains multiple lines, log the first
* line and save the rest.
*/
xtra = stdlog_split_message (ctx->buf, &len, "\r\n");
xtra = stdlog_split_message (result, &len, "\r\n");
if (ctx->cb) {
ctx->cb (ctx->buf, len, ctx->cb_arg);
ctx->cb (result, len, ctx->cb_arg);
} else {
if (log_rpc (h, ctx->buf, len) < 0)
if (log_rpc (h, result, len) < 0)
goto fatal;
}
/* If addition log lines were saved above, log them separately.
*/
if (xtra)
flux_log (h, level, "%s", xtra);
free (xtra);
free (mbuf);
errno = saved_errno;
return 0;
fatal:
free (xtra);
free (mbuf);

Check warning on line 235 in src/common/libflux/flog.c

View check run for this annotation

Codecov / codecov/patch

src/common/libflux/flog.c#L235

Added line #L235 was not covered by tests
return -1;
}

Expand Down
3 changes: 0 additions & 3 deletions src/common/libflux/flog.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@
extern "C" {
#endif


#define FLUX_MAX_LOGBUF 2048

typedef void (*flux_log_f)(const char *buf, int len, void *arg);

/* Set log appname for handle instance.
Expand Down
10 changes: 10 additions & 0 deletions src/common/libflux/test/log.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
int main (int argc, char *argv[])
{
flux_t *h;
char *s;
int truncation_size = 3073;

plan (NO_PLAN);

Expand All @@ -41,6 +43,14 @@ int main (int argc, char *argv[])
ok (flux_log (NULL, LOG_INFO, "# flux_t=NULL") == 0,
"flux_log h=NULL works");

if (!(s = calloc (1, truncation_size)))
BAIL_OUT ("Failed to allocate memory for truncation test");
memset (s, 'a', truncation_size - 2);

ok (flux_log (NULL, LOG_INFO, "# %s", s) == 0,
"flux_log h=NULL works with long message");

free (s);
test_server_stop (h);
flux_close (h);
done_testing();
Expand Down
7 changes: 7 additions & 0 deletions t/t0009-dmesg.t
Original file line number Diff line number Diff line change
Expand Up @@ -171,4 +171,11 @@ test_expect_success 'dmesg with invalid --color option fails' '
test_must_fail flux dmesg --color=foo
'

test_expect_success 'dmesg: long lines are not truncated' '
python3 -c "print(\"x\"*3000)" | flux logger --appname=truncate &&
result=$(flux dmesg | sed -n "/truncate/s/^.*: //p" | wc -c) &&
test_debug "echo logged 3001 characters, got $result" &&
test $result -eq 3001
'

test_done
Loading