summaryrefslogtreecommitdiffstats
path: root/sys/netinet/cc/cc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/netinet/cc/cc.c')
-rw-r--r--sys/netinet/cc/cc.c25
1 files changed, 21 insertions, 4 deletions
diff --git a/sys/netinet/cc/cc.c b/sys/netinet/cc/cc.c
index f075327..cfcbfa6 100644
--- a/sys/netinet/cc/cc.c
+++ b/sys/netinet/cc/cc.c
@@ -128,20 +128,37 @@ cc_list_available(SYSCTL_HANDLER_ARGS)
{
struct cc_algo *algo;
struct sbuf *s;
- int err, first;
+ int err, first, nalgos;
- err = 0;
+ err = nalgos = 0;
first = 1;
- s = sbuf_new(NULL, NULL, TCP_CA_NAME_MAX, SBUF_AUTOEXTEND);
+
+ CC_LIST_RLOCK();
+ STAILQ_FOREACH(algo, &cc_list, entries) {
+ nalgos++;
+ }
+ CC_LIST_RUNLOCK();
+
+ s = sbuf_new(NULL, NULL, nalgos * TCP_CA_NAME_MAX, SBUF_FIXEDLEN);
if (s == NULL)
return (ENOMEM);
+ /*
+ * It is theoretically possible for the CC list to have grown in size
+ * since the call to sbuf_new() and therefore for the sbuf to be too
+ * small. If this were to happen (incredibly unlikely), the sbuf will
+ * reach an overflow condition, sbuf_printf() will return an error and
+ * the sysctl will fail gracefully.
+ */
CC_LIST_RLOCK();
STAILQ_FOREACH(algo, &cc_list, entries) {
err = sbuf_printf(s, first ? "%s" : ", %s", algo->name);
- if (err)
+ if (err) {
+ /* Sbuf overflow condition. */
+ err = EOVERFLOW;
break;
+ }
first = 0;
}
CC_LIST_RUNLOCK();
OpenPOWER on IntegriCloud