Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

tipc: fix infinite loop when dumping link monitor summary

When configuring the number of used bearers to MAX_BEARER and issuing
command "tipc link monitor summary", the command enters infinite loop
in user space.

This issue happens because function tipc_nl_node_dump_monitor() returns
the wrong 'prev_bearer' value when all potential monitors have been
scanned.

The correct behavior is to always try to scan all monitors until either
the netlink message is full, in which case we return the bearer identity
of the affected monitor, or we continue through the whole bearer array
until we can return MAX_BEARERS. This solution also caters for the case
where there may be gaps in the bearer array.

Signed-off-by: Tung Nguyen <tung.q.nguyen@dektech.com.au>
Signed-off-by: Jon Maloy <jon.maloy@ericsson.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Tung Nguyen and committed by
David S. Miller
36a50a98 be47e41d

+5 -8
+1 -1
net/tipc/monitor.c
··· 777 777 778 778 ret = tipc_bearer_get_name(net, bearer_name, bearer_id); 779 779 if (ret || !mon) 780 - return -EINVAL; 780 + return 0; 781 781 782 782 hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, 783 783 NLM_F_MULTI, TIPC_NL_MON_GET);
+4 -7
net/tipc/node.c
··· 2232 2232 struct net *net = sock_net(skb->sk); 2233 2233 u32 prev_bearer = cb->args[0]; 2234 2234 struct tipc_nl_msg msg; 2235 + int bearer_id; 2235 2236 int err; 2236 - int i; 2237 2237 2238 2238 if (prev_bearer == MAX_BEARERS) 2239 2239 return 0; ··· 2243 2243 msg.seq = cb->nlh->nlmsg_seq; 2244 2244 2245 2245 rtnl_lock(); 2246 - for (i = prev_bearer; i < MAX_BEARERS; i++) { 2247 - prev_bearer = i; 2246 + for (bearer_id = prev_bearer; bearer_id < MAX_BEARERS; bearer_id++) { 2248 2247 err = __tipc_nl_add_monitor(net, &msg, prev_bearer); 2249 2248 if (err) 2250 - goto out; 2249 + break; 2251 2250 } 2252 - 2253 - out: 2254 2251 rtnl_unlock(); 2255 - cb->args[0] = prev_bearer; 2252 + cb->args[0] = bearer_id; 2256 2253 2257 2254 return skb->len; 2258 2255 }