net.ipv4.igmp_qrv only has a lower bound, but ip_mc_reset() stores it into the u8 in_device::mr_qrv, and the IGMPv3 retransmit counters filled from it (crcount, sf_crcount) are u8 as well. Anything above 255 silently wraps. With 256, mr_qrv becomes 0, every "in_dev->mr_qrv ?: sysctl_igmp_qrv" falls back to 256, which truncates to 0 again in crcount, and igmpv3_send_cr() never puts the state change records for the group into a report. The older version querier present timeout (mr_qrv * mr_qi + mr_qri) also collapses to just mr_qri. Unlike MLD there is no WARN_ON() here, the reports just go missing. Cap the sysctl at U8_MAX, the largest value mr_qrv can actually hold. Fixes: a9fe8e29945d ("ipv4: implement igmp_qrv sysctl to tune igmp robustness variable") Cc: stable@vger.kernel.org Signed-off-by: Jiayuan Chen --- net/ipv4/sysctl_net_ipv4.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index e3760daa3470..ef631a2759b0 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -33,6 +33,7 @@ static int ip_privileged_port_min; static int ip_privileged_port_max = 65535; static int ip_ttl_min = 1; static int ip_ttl_max = 255; +static int igmp_qrv_max __maybe_unused = U8_MAX; static int tcp_syn_retries_min = 1; static int tcp_syn_retries_max = MAX_TCP_SYNCNT; static int tcp_syn_linear_timeouts_max = MAX_TCP_SYNCNT; @@ -978,7 +979,8 @@ static const struct ctl_table ipv4_net_table[] = { .maxlen = sizeof(int), .mode = 0644, .proc_handler = proc_dointvec_minmax, - .extra1 = SYSCTL_ONE + .extra1 = SYSCTL_ONE, + .extra2 = &igmp_qrv_max, }, #endif { -- 2.43.0