.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-only |
---|
1 | 2 | /* |
---|
2 | 3 | * Pluggable TCP congestion control support and newReno |
---|
3 | 4 | * congestion control. |
---|
.. | .. |
---|
20 | 21 | static LIST_HEAD(tcp_cong_list); |
---|
21 | 22 | |
---|
22 | 23 | /* Simple linear search, don't expect many entries! */ |
---|
23 | | -static struct tcp_congestion_ops *tcp_ca_find(const char *name) |
---|
| 24 | +struct tcp_congestion_ops *tcp_ca_find(const char *name) |
---|
24 | 25 | { |
---|
25 | 26 | struct tcp_congestion_ops *e; |
---|
26 | 27 | |
---|
.. | .. |
---|
161 | 162 | |
---|
162 | 163 | rcu_read_lock(); |
---|
163 | 164 | ca = rcu_dereference(net->ipv4.tcp_congestion_control); |
---|
164 | | - if (unlikely(!try_module_get(ca->owner))) |
---|
| 165 | + if (unlikely(!bpf_try_module_get(ca, ca->owner))) |
---|
165 | 166 | ca = &tcp_reno; |
---|
166 | 167 | icsk->icsk_ca_ops = ca; |
---|
167 | 168 | rcu_read_unlock(); |
---|
.. | .. |
---|
175 | 176 | |
---|
176 | 177 | void tcp_init_congestion_control(struct sock *sk) |
---|
177 | 178 | { |
---|
178 | | - const struct inet_connection_sock *icsk = inet_csk(sk); |
---|
| 179 | + struct inet_connection_sock *icsk = inet_csk(sk); |
---|
179 | 180 | |
---|
180 | 181 | tcp_sk(sk)->prior_ssthresh = 0; |
---|
181 | 182 | if (icsk->icsk_ca_ops->init) |
---|
.. | .. |
---|
184 | 185 | INET_ECN_xmit(sk); |
---|
185 | 186 | else |
---|
186 | 187 | INET_ECN_dontxmit(sk); |
---|
| 188 | + icsk->icsk_ca_initialized = 1; |
---|
187 | 189 | } |
---|
188 | 190 | |
---|
189 | 191 | static void tcp_reinit_congestion_control(struct sock *sk, |
---|
.. | .. |
---|
212 | 214 | |
---|
213 | 215 | if (icsk->icsk_ca_ops->release) |
---|
214 | 216 | icsk->icsk_ca_ops->release(sk); |
---|
215 | | - module_put(icsk->icsk_ca_ops->owner); |
---|
| 217 | + bpf_module_put(icsk->icsk_ca_ops, icsk->icsk_ca_ops->owner); |
---|
216 | 218 | } |
---|
217 | 219 | |
---|
218 | 220 | /* Used by sysctl to change default congestion control */ |
---|
.. | .. |
---|
226 | 228 | ca = tcp_ca_find_autoload(net, name); |
---|
227 | 229 | if (!ca) { |
---|
228 | 230 | ret = -ENOENT; |
---|
229 | | - } else if (!try_module_get(ca->owner)) { |
---|
| 231 | + } else if (!bpf_try_module_get(ca, ca->owner)) { |
---|
230 | 232 | ret = -EBUSY; |
---|
231 | 233 | } else if (!net_eq(net, &init_net) && |
---|
232 | 234 | !(ca->flags & TCP_CONG_NON_RESTRICTED)) { |
---|
.. | .. |
---|
235 | 237 | } else { |
---|
236 | 238 | prev = xchg(&net->ipv4.tcp_congestion_control, ca); |
---|
237 | 239 | if (prev) |
---|
238 | | - module_put(prev->owner); |
---|
| 240 | + bpf_module_put(prev, prev->owner); |
---|
239 | 241 | |
---|
240 | 242 | ca->flags |= TCP_CONG_NON_RESTRICTED; |
---|
241 | 243 | ret = 0; |
---|
.. | .. |
---|
264 | 266 | offs += snprintf(buf + offs, maxlen - offs, |
---|
265 | 267 | "%s%s", |
---|
266 | 268 | offs == 0 ? "" : " ", ca->name); |
---|
| 269 | + |
---|
| 270 | + if (WARN_ON_ONCE(offs >= maxlen)) |
---|
| 271 | + break; |
---|
267 | 272 | } |
---|
268 | 273 | rcu_read_unlock(); |
---|
269 | 274 | } |
---|
.. | .. |
---|
293 | 298 | offs += snprintf(buf + offs, maxlen - offs, |
---|
294 | 299 | "%s%s", |
---|
295 | 300 | offs == 0 ? "" : " ", ca->name); |
---|
| 301 | + |
---|
| 302 | + if (WARN_ON_ONCE(offs >= maxlen)) |
---|
| 303 | + break; |
---|
296 | 304 | } |
---|
297 | 305 | rcu_read_unlock(); |
---|
298 | 306 | } |
---|
.. | .. |
---|
342 | 350 | * already initialized. |
---|
343 | 351 | */ |
---|
344 | 352 | int tcp_set_congestion_control(struct sock *sk, const char *name, bool load, |
---|
345 | | - bool reinit, bool cap_net_admin) |
---|
| 353 | + bool cap_net_admin) |
---|
346 | 354 | { |
---|
347 | 355 | struct inet_connection_sock *icsk = inet_csk(sk); |
---|
348 | 356 | const struct tcp_congestion_ops *ca; |
---|
.. | .. |
---|
363 | 371 | goto out; |
---|
364 | 372 | } |
---|
365 | 373 | |
---|
366 | | - if (!ca) { |
---|
| 374 | + if (!ca) |
---|
367 | 375 | err = -ENOENT; |
---|
368 | | - } else if (!load) { |
---|
369 | | - const struct tcp_congestion_ops *old_ca = icsk->icsk_ca_ops; |
---|
370 | | - |
---|
371 | | - if (try_module_get(ca->owner)) { |
---|
372 | | - if (reinit) { |
---|
373 | | - tcp_reinit_congestion_control(sk, ca); |
---|
374 | | - } else { |
---|
375 | | - icsk->icsk_ca_ops = ca; |
---|
376 | | - module_put(old_ca->owner); |
---|
377 | | - } |
---|
378 | | - } else { |
---|
379 | | - err = -EBUSY; |
---|
380 | | - } |
---|
381 | | - } else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || cap_net_admin)) { |
---|
| 376 | + else if (!((ca->flags & TCP_CONG_NON_RESTRICTED) || cap_net_admin)) |
---|
382 | 377 | err = -EPERM; |
---|
383 | | - } else if (!try_module_get(ca->owner)) { |
---|
| 378 | + else if (!bpf_try_module_get(ca, ca->owner)) |
---|
384 | 379 | err = -EBUSY; |
---|
385 | | - } else { |
---|
| 380 | + else |
---|
386 | 381 | tcp_reinit_congestion_control(sk, ca); |
---|
387 | | - } |
---|
388 | 382 | out: |
---|
389 | 383 | rcu_read_unlock(); |
---|
390 | 384 | return err; |
---|