1
0
mirror of https://git.FreeBSD.org/src.git synced 2024-12-25 11:37:56 +00:00

Fix issues with TCP_CONGESTION handling after r294540:

o Return back the buf[TCP_CA_NAME_MAX] for TCP_CONGESTION,
  for TCP_CCALGOOPT use dynamically allocated *pbuf.
o For SOPT_SET TCP_CONGESTION do NULL terminating of string
  taking from userland.
o For SOPT_SET TCP_CONGESTION do the search for the algorithm
  keeping the inpcb lock.
o For SOPT_GET TCP_CONGESTION first strlcpy() the name
  holding the inpcb lock into temporary buffer, then copyout.

Together with:	lstewart
This commit is contained in:
Gleb Smirnoff 2016-01-27 07:34:00 +00:00
parent 669414e4fb
commit af6fef3abb
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=294902

View File

@ -1479,7 +1479,8 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
u_int ui; u_int ui;
struct tcp_info ti; struct tcp_info ti;
struct cc_algo *algo; struct cc_algo *algo;
char *buf; char *pbuf, buf[TCP_CA_NAME_MAX];
size_t len;
/* /*
* For TCP_CCALGOOPT forward the control to CC module, for both * For TCP_CCALGOOPT forward the control to CC module, for both
@ -1488,22 +1489,22 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
switch (sopt->sopt_name) { switch (sopt->sopt_name) {
case TCP_CCALGOOPT: case TCP_CCALGOOPT:
INP_WUNLOCK(inp); INP_WUNLOCK(inp);
buf = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK | M_ZERO); pbuf = malloc(sopt->sopt_valsize, M_TEMP, M_WAITOK | M_ZERO);
error = sooptcopyin(sopt, buf, sopt->sopt_valsize, error = sooptcopyin(sopt, pbuf, sopt->sopt_valsize,
sopt->sopt_valsize); sopt->sopt_valsize);
if (error) { if (error) {
free(buf, M_TEMP); free(pbuf, M_TEMP);
return (error); return (error);
} }
INP_WLOCK_RECHECK(inp); INP_WLOCK_RECHECK(inp);
if (CC_ALGO(tp)->ctl_output != NULL) if (CC_ALGO(tp)->ctl_output != NULL)
error = CC_ALGO(tp)->ctl_output(tp->ccv, sopt, buf); error = CC_ALGO(tp)->ctl_output(tp->ccv, sopt, pbuf);
else else
error = ENOENT; error = ENOENT;
INP_WUNLOCK(inp); INP_WUNLOCK(inp);
if (error == 0 && sopt->sopt_dir == SOPT_GET) if (error == 0 && sopt->sopt_dir == SOPT_GET)
error = sooptcopyout(sopt, buf, sopt->sopt_valsize); error = sooptcopyout(sopt, pbuf, sopt->sopt_valsize);
free(buf, M_TEMP); free(pbuf, M_TEMP);
return (error); return (error);
} }
@ -1600,24 +1601,22 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
case TCP_CONGESTION: case TCP_CONGESTION:
INP_WUNLOCK(inp); INP_WUNLOCK(inp);
buf = malloc(TCP_CA_NAME_MAX, M_TEMP, M_WAITOK|M_ZERO); error = sooptcopyin(sopt, buf, TCP_CA_NAME_MAX - 1, 1);
error = sooptcopyin(sopt, buf, TCP_CA_NAME_MAX, 1); if (error)
if (error) {
free(buf, M_TEMP);
break; break;
} buf[sopt->sopt_valsize] = '\0';
INP_WLOCK_RECHECK(inp);
CC_LIST_RLOCK(); CC_LIST_RLOCK();
STAILQ_FOREACH(algo, &cc_list, entries) STAILQ_FOREACH(algo, &cc_list, entries)
if (strncmp(buf, algo->name, if (strncmp(buf, algo->name,
TCP_CA_NAME_MAX) == 0) TCP_CA_NAME_MAX) == 0)
break; break;
CC_LIST_RUNLOCK(); CC_LIST_RUNLOCK();
free(buf, M_TEMP);
if (algo == NULL) { if (algo == NULL) {
INP_WUNLOCK(inp);
error = EINVAL; error = EINVAL;
break; break;
} }
INP_WLOCK_RECHECK(inp);
/* /*
* We hold a write lock over the tcb so it's safe to * We hold a write lock over the tcb so it's safe to
* do these things without ordering concerns. * do these things without ordering concerns.
@ -1786,9 +1785,9 @@ tcp_default_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp
error = sooptcopyout(sopt, &ti, sizeof ti); error = sooptcopyout(sopt, &ti, sizeof ti);
break; break;
case TCP_CONGESTION: case TCP_CONGESTION:
len = strlcpy(buf, CC_ALGO(tp)->name, TCP_CA_NAME_MAX);
INP_WUNLOCK(inp); INP_WUNLOCK(inp);
error = sooptcopyout(sopt, CC_ALGO(tp)->name, error = sooptcopyout(sopt, buf, len + 1);
TCP_CA_NAME_MAX);
break; break;
case TCP_KEEPIDLE: case TCP_KEEPIDLE:
case TCP_KEEPINTVL: case TCP_KEEPINTVL: