You need to sign in or sign up before continuing.
提交 345cb673 编写于 作者: N Nikolay Aleksandrov 提交者: Jialin Zhang

net: bridge: mcast: add and enforce startup query interval minimum

mainline inclusion
from mainline-v5.16-rc8
commit f83a112b
category: bugfix
bugzilla: https://gitee.com/openeuler/kernel/issues/I6DKZJ
CVE: NA

Reference: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=f83a112bd91a494cdee671aec74e777470fb4a07

--------------------------------

As reported[1] if startup query interval is set too low in combination with
large number of startup queries and we have multiple bridges or even a
single bridge with multiple querier vlans configured we can crash the
machine. Add a 1 second minimum which must be enforced by overwriting the
value if set lower (i.e. without returning an error) to avoid breaking
user-space. If that happens a log message is emitted to let the admin know
that the startup interval has been set to the minimum. It doesn't make
sense to make the startup interval lower than the normal query interval
so use the same value of 1 second. The issue has been present since these
intervals could be user-controlled.

[1] https://lore.kernel.org/netdev/e8b9ce41-57b9-b6e2-a46a-ff9c791cf0ba@gmail.com/

Fixes: d902eee4 ("bridge: Add multicast count/interval sysfs entries")
Reported-by: NEric Dumazet <eric.dumazet@gmail.com>
Signed-off-by: NNikolay Aleksandrov <nikolay@nvidia.com>
Signed-off-by: NJakub Kicinski <kuba@kernel.org>

Conflicts:
	net/bridge/br_multicast.c
	net/bridge/br_netlink.c
	net/bridge/br_private.h
	net/bridge/br_sysfs_br.c
Signed-off-by: NZhengchao Shao <shaozhengchao@huawei.com>
Reviewed-by: NYue Haibing <yuehaibing@huawei.com>
Signed-off-by: NJialin Zhang <zhangjialin11@huawei.com>
上级 269e3b30
...@@ -3609,6 +3609,22 @@ int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val) ...@@ -3609,6 +3609,22 @@ int br_multicast_set_mld_version(struct net_bridge *br, unsigned long val)
} }
#endif #endif
void br_multicast_set_startup_query_intvl(struct net_bridge *br,
unsigned long val)
{
unsigned long intvl_jiffies = clock_t_to_jiffies(val);
if (intvl_jiffies < BR_MULTICAST_STARTUP_QUERY_INTVL_MIN) {
br_info(br,
"trying to set multicast startup query interval below minimum, setting to %lu (%ums)\n",
jiffies_to_clock_t(BR_MULTICAST_STARTUP_QUERY_INTVL_MIN),
jiffies_to_msecs(BR_MULTICAST_STARTUP_QUERY_INTVL_MIN));
intvl_jiffies = BR_MULTICAST_STARTUP_QUERY_INTVL_MIN;
}
br->multicast_startup_query_interval = intvl_jiffies;
}
/** /**
* br_multicast_list_adjacent - Returns snooped multicast addresses * br_multicast_list_adjacent - Returns snooped multicast addresses
* @dev: The bridge port adjacent to which to retrieve addresses * @dev: The bridge port adjacent to which to retrieve addresses
......
...@@ -1298,7 +1298,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[], ...@@ -1298,7 +1298,7 @@ static int br_changelink(struct net_device *brdev, struct nlattr *tb[],
if (data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) { if (data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]) {
u64 val = nla_get_u64(data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]); u64 val = nla_get_u64(data[IFLA_BR_MCAST_STARTUP_QUERY_INTVL]);
br->multicast_startup_query_interval = clock_t_to_jiffies(val); br_multicast_set_startup_query_intvl(br, val);
} }
if (data[IFLA_BR_MCAST_STATS_ENABLED]) { if (data[IFLA_BR_MCAST_STATS_ENABLED]) {
......
...@@ -28,6 +28,8 @@ ...@@ -28,6 +28,8 @@
#define BR_MAX_PORTS (1<<BR_PORT_BITS) #define BR_MAX_PORTS (1<<BR_PORT_BITS)
#define BR_MULTICAST_DEFAULT_HASH_MAX 4096 #define BR_MULTICAST_DEFAULT_HASH_MAX 4096
#define BR_MULTICAST_QUERY_INTVL_MIN msecs_to_jiffies(1000)
#define BR_MULTICAST_STARTUP_QUERY_INTVL_MIN BR_MULTICAST_QUERY_INTVL_MIN
#define BR_VERSION "2.3" #define BR_VERSION "2.3"
...@@ -1568,4 +1570,6 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br, ...@@ -1568,4 +1570,6 @@ void br_do_proxy_suppress_arp(struct sk_buff *skb, struct net_bridge *br,
void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br, void br_do_suppress_nd(struct sk_buff *skb, struct net_bridge *br,
u16 vid, struct net_bridge_port *p, struct nd_msg *msg); u16 vid, struct net_bridge_port *p, struct nd_msg *msg);
struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m); struct nd_msg *br_is_nd_neigh_msg(struct sk_buff *skb, struct nd_msg *m);
void br_multicast_set_startup_query_intvl(struct net_bridge *br,
unsigned long val);
#endif #endif
...@@ -640,7 +640,7 @@ static ssize_t multicast_startup_query_interval_show( ...@@ -640,7 +640,7 @@ static ssize_t multicast_startup_query_interval_show(
static int set_startup_query_interval(struct net_bridge *br, unsigned long val) static int set_startup_query_interval(struct net_bridge *br, unsigned long val)
{ {
br->multicast_startup_query_interval = clock_t_to_jiffies(val); br_multicast_set_startup_query_intvl(br, val);
return 0; return 0;
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册