tcp: Handle stack switch while processing socket options
Handle the case where during socket option processing, the user switches a stack such that processing the stack specific socket option does not make sense anymore. Return an error in this case. MFC after: 1 week Reviewed by: markj Reported by: syzbot+a6e1d91f240ad5d72cd1@syzkaller.appspotmail.com Sponsored by: Netflix, Inc. Differential revision: https://reviews.freebsd.org/D30395
This commit is contained in:
parent
f784da883f
commit
8923ce6304
@ -518,6 +518,10 @@ static void
|
||||
bbr_log_pacing_delay_calc(struct tcp_bbr *bbr, uint16_t gain, uint32_t len,
|
||||
uint32_t cts, uint32_t usecs, uint64_t bw, uint32_t override, int mod);
|
||||
|
||||
static int
|
||||
bbr_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp,
|
||||
struct tcpcb *tp);
|
||||
|
||||
static inline uint8_t
|
||||
bbr_state_val(struct tcp_bbr *bbr)
|
||||
{
|
||||
@ -14197,6 +14201,33 @@ bbr_mtu_chg(struct tcpcb *tp)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
bbr_pru_options(struct tcpcb *tp, int flags)
|
||||
{
|
||||
if (flags & PRUS_OOB)
|
||||
return (EOPNOTSUPP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct tcp_function_block __tcp_bbr = {
|
||||
.tfb_tcp_block_name = __XSTRING(STACKNAME),
|
||||
.tfb_tcp_output = bbr_output,
|
||||
.tfb_do_queued_segments = ctf_do_queued_segments,
|
||||
.tfb_do_segment_nounlock = bbr_do_segment_nounlock,
|
||||
.tfb_tcp_do_segment = bbr_do_segment,
|
||||
.tfb_tcp_ctloutput = bbr_ctloutput,
|
||||
.tfb_tcp_fb_init = bbr_init,
|
||||
.tfb_tcp_fb_fini = bbr_fini,
|
||||
.tfb_tcp_timer_stop_all = bbr_stopall,
|
||||
.tfb_tcp_timer_activate = bbr_timer_activate,
|
||||
.tfb_tcp_timer_active = bbr_timer_active,
|
||||
.tfb_tcp_timer_stop = bbr_timer_stop,
|
||||
.tfb_tcp_rexmit_tmr = bbr_remxt_tmr,
|
||||
.tfb_tcp_handoff_ok = bbr_handoff_ok,
|
||||
.tfb_tcp_mtu_chg = bbr_mtu_chg,
|
||||
.tfb_pru_options = bbr_pru_options,
|
||||
};
|
||||
|
||||
/*
|
||||
* bbr_ctloutput() must drop the inpcb lock before performing copyin on
|
||||
* socket option arguments. When it re-acquires the lock after the copy, it
|
||||
@ -14269,6 +14300,10 @@ bbr_set_sockopt(struct socket *so, struct sockopt *sopt,
|
||||
return (ECONNRESET);
|
||||
}
|
||||
tp = intotcpcb(inp);
|
||||
if (tp->t_fb != &__tcp_bbr) {
|
||||
INP_WUNLOCK(inp);
|
||||
return (ENOPROTOOPT);
|
||||
}
|
||||
bbr = (struct tcp_bbr *)tp->t_fb_ptr;
|
||||
switch (sopt->sopt_name) {
|
||||
case TCP_BBR_PACE_PER_SEC:
|
||||
@ -14772,33 +14807,6 @@ bbr_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struct
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
bbr_pru_options(struct tcpcb *tp, int flags)
|
||||
{
|
||||
if (flags & PRUS_OOB)
|
||||
return (EOPNOTSUPP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
struct tcp_function_block __tcp_bbr = {
|
||||
.tfb_tcp_block_name = __XSTRING(STACKNAME),
|
||||
.tfb_tcp_output = bbr_output,
|
||||
.tfb_do_queued_segments = ctf_do_queued_segments,
|
||||
.tfb_do_segment_nounlock = bbr_do_segment_nounlock,
|
||||
.tfb_tcp_do_segment = bbr_do_segment,
|
||||
.tfb_tcp_ctloutput = bbr_ctloutput,
|
||||
.tfb_tcp_fb_init = bbr_init,
|
||||
.tfb_tcp_fb_fini = bbr_fini,
|
||||
.tfb_tcp_timer_stop_all = bbr_stopall,
|
||||
.tfb_tcp_timer_activate = bbr_timer_activate,
|
||||
.tfb_tcp_timer_active = bbr_timer_active,
|
||||
.tfb_tcp_timer_stop = bbr_timer_stop,
|
||||
.tfb_tcp_rexmit_tmr = bbr_remxt_tmr,
|
||||
.tfb_tcp_handoff_ok = bbr_handoff_ok,
|
||||
.tfb_tcp_mtu_chg = bbr_mtu_chg,
|
||||
.tfb_pru_options = bbr_pru_options,
|
||||
};
|
||||
|
||||
static const char *bbr_stack_names[] = {
|
||||
__XSTRING(STACKNAME),
|
||||
#ifdef STACKALIAS
|
||||
|
@ -19407,6 +19407,34 @@ rack_apply_deferred_options(struct tcp_rack *rack)
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
rack_pru_options(struct tcpcb *tp, int flags)
|
||||
{
|
||||
if (flags & PRUS_OOB)
|
||||
return (EOPNOTSUPP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct tcp_function_block __tcp_rack = {
|
||||
.tfb_tcp_block_name = __XSTRING(STACKNAME),
|
||||
.tfb_tcp_output = rack_output,
|
||||
.tfb_do_queued_segments = ctf_do_queued_segments,
|
||||
.tfb_do_segment_nounlock = rack_do_segment_nounlock,
|
||||
.tfb_tcp_do_segment = rack_do_segment,
|
||||
.tfb_tcp_ctloutput = rack_ctloutput,
|
||||
.tfb_tcp_fb_init = rack_init,
|
||||
.tfb_tcp_fb_fini = rack_fini,
|
||||
.tfb_tcp_timer_stop_all = rack_stopall,
|
||||
.tfb_tcp_timer_activate = rack_timer_activate,
|
||||
.tfb_tcp_timer_active = rack_timer_active,
|
||||
.tfb_tcp_timer_stop = rack_timer_stop,
|
||||
.tfb_tcp_rexmit_tmr = rack_remxt_tmr,
|
||||
.tfb_tcp_handoff_ok = rack_handoff_ok,
|
||||
.tfb_tcp_mtu_chg = rack_mtu_change,
|
||||
.tfb_pru_options = rack_pru_options,
|
||||
|
||||
};
|
||||
|
||||
/*
|
||||
* rack_ctloutput() must drop the inpcb lock before performing copyin on
|
||||
* socket option arguments. When it re-acquires the lock after the copy, it
|
||||
@ -19496,6 +19524,10 @@ rack_set_sockopt(struct socket *so, struct sockopt *sopt,
|
||||
INP_WUNLOCK(inp);
|
||||
return (ECONNRESET);
|
||||
}
|
||||
if (tp->t_fb != &__tcp_rack) {
|
||||
INP_WUNLOCK(inp);
|
||||
return (ENOPROTOOPT);
|
||||
}
|
||||
if (rack->defer_options && (rack->gp_ready == 0) &&
|
||||
(sopt->sopt_name != TCP_DEFER_OPTIONS) &&
|
||||
(sopt->sopt_name != TCP_RACK_PACING_BETA) &&
|
||||
@ -19832,34 +19864,6 @@ rack_ctloutput(struct socket *so, struct sockopt *sopt, struct inpcb *inp, struc
|
||||
return (error);
|
||||
}
|
||||
|
||||
static int
|
||||
rack_pru_options(struct tcpcb *tp, int flags)
|
||||
{
|
||||
if (flags & PRUS_OOB)
|
||||
return (EOPNOTSUPP);
|
||||
return (0);
|
||||
}
|
||||
|
||||
static struct tcp_function_block __tcp_rack = {
|
||||
.tfb_tcp_block_name = __XSTRING(STACKNAME),
|
||||
.tfb_tcp_output = rack_output,
|
||||
.tfb_do_queued_segments = ctf_do_queued_segments,
|
||||
.tfb_do_segment_nounlock = rack_do_segment_nounlock,
|
||||
.tfb_tcp_do_segment = rack_do_segment,
|
||||
.tfb_tcp_ctloutput = rack_ctloutput,
|
||||
.tfb_tcp_fb_init = rack_init,
|
||||
.tfb_tcp_fb_fini = rack_fini,
|
||||
.tfb_tcp_timer_stop_all = rack_stopall,
|
||||
.tfb_tcp_timer_activate = rack_timer_activate,
|
||||
.tfb_tcp_timer_active = rack_timer_active,
|
||||
.tfb_tcp_timer_stop = rack_timer_stop,
|
||||
.tfb_tcp_rexmit_tmr = rack_remxt_tmr,
|
||||
.tfb_tcp_handoff_ok = rack_handoff_ok,
|
||||
.tfb_tcp_mtu_chg = rack_mtu_change,
|
||||
.tfb_pru_options = rack_pru_options,
|
||||
|
||||
};
|
||||
|
||||
static const char *rack_stack_names[] = {
|
||||
__XSTRING(STACKNAME),
|
||||
#ifdef STACKALIAS
|
||||
|
Loading…
Reference in New Issue
Block a user