Use an sbuf to generate the output of the net.inet.tcp.hostcache.list

sysctl to avoid a possible buffer overflow if the cache grows while the
text is being generated.

PR:		172675
MFC after:	2 weeks
This commit is contained in:
John Baldwin 2015-01-25 19:45:44 +00:00
parent 4fa545cb14
commit 002d455873

View File

@ -73,6 +73,7 @@ __FBSDID("$FreeBSD$");
#include <sys/lock.h> #include <sys/lock.h>
#include <sys/mutex.h> #include <sys/mutex.h>
#include <sys/malloc.h> #include <sys/malloc.h>
#include <sys/sbuf.h>
#include <sys/socket.h> #include <sys/socket.h>
#include <sys/socketvar.h> #include <sys/socketvar.h>
#include <sys/sysctl.h> #include <sys/sysctl.h>
@ -595,30 +596,27 @@ tcp_hc_update(struct in_conninfo *inc, struct hc_metrics_lite *hcml)
static int static int
sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS) sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
{ {
int bufsize;
int linesize = 128; int linesize = 128;
char *p, *buf; struct sbuf sb;
int len, i, error; int i, error;
struct hc_metrics *hc_entry; struct hc_metrics *hc_entry;
#ifdef INET6 #ifdef INET6
char ip6buf[INET6_ADDRSTRLEN]; char ip6buf[INET6_ADDRSTRLEN];
#endif #endif
bufsize = linesize * (V_tcp_hostcache.cache_count + 1); sbuf_new(&sb, NULL, linesize * (V_tcp_hostcache.cache_count + 1),
SBUF_FIXEDLEN);
p = buf = (char *)malloc(bufsize, M_TEMP, M_WAITOK|M_ZERO); sbuf_printf(&sb,
"\nIP address MTU SSTRESH RTT RTTVAR BANDWIDTH "
len = snprintf(p, linesize,
"\nIP address MTU SSTRESH RTT RTTVAR BANDWIDTH "
" CWND SENDPIPE RECVPIPE HITS UPD EXP\n"); " CWND SENDPIPE RECVPIPE HITS UPD EXP\n");
p += len;
#define msec(u) (((u) + 500) / 1000) #define msec(u) (((u) + 500) / 1000)
for (i = 0; i < V_tcp_hostcache.hashsize; i++) { for (i = 0; i < V_tcp_hostcache.hashsize; i++) {
THC_LOCK(&V_tcp_hostcache.hashbase[i].hch_mtx); THC_LOCK(&V_tcp_hostcache.hashbase[i].hch_mtx);
TAILQ_FOREACH(hc_entry, &V_tcp_hostcache.hashbase[i].hch_bucket, TAILQ_FOREACH(hc_entry, &V_tcp_hostcache.hashbase[i].hch_bucket,
rmx_q) { rmx_q) {
len = snprintf(p, linesize, sbuf_printf(&sb,
"%-15s %5lu %8lu %6lums %6lums %9lu %8lu %8lu %8lu " "%-15s %5lu %8lu %6lums %6lums %9lu %8lu %8lu %8lu "
"%4lu %4lu %4i\n", "%4lu %4lu %4i\n",
hc_entry->ip4.s_addr ? inet_ntoa(hc_entry->ip4) : hc_entry->ip4.s_addr ? inet_ntoa(hc_entry->ip4) :
@ -640,13 +638,13 @@ sysctl_tcp_hc_list(SYSCTL_HANDLER_ARGS)
hc_entry->rmx_hits, hc_entry->rmx_hits,
hc_entry->rmx_updates, hc_entry->rmx_updates,
hc_entry->rmx_expire); hc_entry->rmx_expire);
p += len;
} }
THC_UNLOCK(&V_tcp_hostcache.hashbase[i].hch_mtx); THC_UNLOCK(&V_tcp_hostcache.hashbase[i].hch_mtx);
} }
#undef msec #undef msec
error = SYSCTL_OUT(req, buf, p - buf); sbuf_finish(&sb);
free(buf, M_TEMP); error = SYSCTL_OUT(req, sbuf_data(&sb), sbuf_len(&sb));
sbuf_delete(&sb);
return(error); return(error);
} }