| From foo@baz Sun Jun 17 12:07:33 CEST 2018 |
| From: Tung Nguyen <tung.q.nguyen@dektech.com.au> |
| Date: Tue, 17 Apr 2018 21:58:27 +0200 |
| Subject: tipc: fix infinite loop when dumping link monitor summary |
| |
| From: Tung Nguyen <tung.q.nguyen@dektech.com.au> |
| |
| [ Upstream commit 36a50a989ee8267588de520b8704b85f045a3220 ] |
| |
| 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> |
| Signed-off-by: Sasha Levin <alexander.levin@microsoft.com> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/tipc/monitor.c | 2 +- |
| net/tipc/node.c | 11 ++++------- |
| 2 files changed, 5 insertions(+), 8 deletions(-) |
| |
| --- a/net/tipc/monitor.c |
| +++ b/net/tipc/monitor.c |
| @@ -777,7 +777,7 @@ int __tipc_nl_add_monitor(struct net *ne |
| |
| ret = tipc_bearer_get_name(net, bearer_name, bearer_id); |
| if (ret || !mon) |
| - return -EINVAL; |
| + return 0; |
| |
| hdr = genlmsg_put(msg->skb, msg->portid, msg->seq, &tipc_genl_family, |
| NLM_F_MULTI, TIPC_NL_MON_GET); |
| --- a/net/tipc/node.c |
| +++ b/net/tipc/node.c |
| @@ -2145,8 +2145,8 @@ int tipc_nl_node_dump_monitor(struct sk_ |
| struct net *net = sock_net(skb->sk); |
| u32 prev_bearer = cb->args[0]; |
| struct tipc_nl_msg msg; |
| + int bearer_id; |
| int err; |
| - int i; |
| |
| if (prev_bearer == MAX_BEARERS) |
| return 0; |
| @@ -2156,16 +2156,13 @@ int tipc_nl_node_dump_monitor(struct sk_ |
| msg.seq = cb->nlh->nlmsg_seq; |
| |
| rtnl_lock(); |
| - for (i = prev_bearer; i < MAX_BEARERS; i++) { |
| - prev_bearer = i; |
| + for (bearer_id = prev_bearer; bearer_id < MAX_BEARERS; bearer_id++) { |
| err = __tipc_nl_add_monitor(net, &msg, prev_bearer); |
| if (err) |
| - goto out; |
| + break; |
| } |
| - |
| -out: |
| rtnl_unlock(); |
| - cb->args[0] = prev_bearer; |
| + cb->args[0] = bearer_id; |
| |
| return skb->len; |
| } |