syslogd: fix memory leak in casper_ttymsg()

nvlist_take_string_array(9) takes ownership of the array and its
strings. casper_ttymsg() freed neither, leaking memory on every
F_CONSOLE and F_TTY message. On long-running systems with high
error-rate syslog traffic routed to /dev/console, syslogd.casper grew
to hundreds of MB.

Use nvlist_get_string_array(9) to borrow the array instead. Update
casper_wallmsg() similarly.

Approved by:    src (des)
Closes:         https://github.com/freebsd/freebsd-src/pull/2222
Fixes:          61a29eca55 ("syslogd: Log messages using libcasper")
MFC after:      3 days
MFC to:         stable/15
PR:             295488
Reported by:    Pat Maddox <pat@patmaddox.com>
Reviewed by:    markj
Tested by:      dch
This commit is contained in:
Pat Maddox
2026-05-22 21:45:30 +00:00
committed by Dave Cottlehuber
parent 22fa41b4e8
commit c783d7181d
+6 -8
View File
@@ -128,19 +128,19 @@ cap_ttymsg(cap_channel_t *chan, struct iovec *iov, int iovcnt,
int
casper_ttymsg(nvlist_t *nvlin, nvlist_t *nvlout)
{
char **nvlstrs;
const char * const *nvlstrs;
struct iovec *iov;
size_t iovcnt;
int tmout;
const char *line;
nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &iovcnt);
nvlstrs = nvlist_get_string_array(nvlin, "iov_strs", &iovcnt);
assert(iovcnt <= TTYMSG_IOV_MAX);
iov = calloc(iovcnt, sizeof(*iov));
if (iov == NULL)
err(EXIT_FAILURE, "calloc");
for (size_t i = 0; i < iovcnt; ++i) {
iov[i].iov_base = nvlstrs[i];
iov[i].iov_base = __DECONST(char *, nvlstrs[i]);
iov[i].iov_len = strlen(nvlstrs[i]);
}
line = nvlist_get_string(nvlin, "line");
@@ -187,25 +187,23 @@ int
casper_wallmsg(nvlist_t *nvlin)
{
const struct filed *f;
char **nvlstrs;
const char * const *nvlstrs;
struct iovec *iov;
size_t sz;
f = nvlist_get_binary(nvlin, "filed", &sz);
assert(sz == sizeof(*f));
nvlstrs = nvlist_take_string_array(nvlin, "iov_strs", &sz);
nvlstrs = nvlist_get_string_array(nvlin, "iov_strs", &sz);
assert(sz <= TTYMSG_IOV_MAX);
iov = calloc(sz, sizeof(*iov));
if (iov == NULL)
err(EXIT_FAILURE, "calloc");
for (size_t i = 0; i < sz; ++i) {
iov[i].iov_base = nvlstrs[i];
iov[i].iov_base = __DECONST(char *, nvlstrs[i]);
iov[i].iov_len = strlen(nvlstrs[i]);
}
wallmsg(f, iov, sz);
for (size_t i = 0; i < sz; ++i)
free(iov[i].iov_base);
free(iov);
return (0);
}