| From foo@baz Mon Mar 27 18:18:08 CEST 2017 |
| From: Stanislaw Gruszka <sgruszka@redhat.com> |
| Date: Wed, 22 Mar 2017 16:08:33 +0100 |
| Subject: genetlink: fix counting regression on ctrl_dumpfamily() |
| |
| From: Stanislaw Gruszka <sgruszka@redhat.com> |
| |
| |
| [ Upstream commit 1d2a6a5e4bf2921531071fcff8538623dce74efa ] |
| |
| Commit 2ae0f17df1cd ("genetlink: use idr to track families") replaced |
| |
| if (++n < fams_to_skip) |
| continue; |
| into: |
| |
| if (n++ < fams_to_skip) |
| continue; |
| |
| This subtle change cause that on retry ctrl_dumpfamily() call we omit |
| one family that failed to do ctrl_fill_info() on previous call, because |
| cb->args[0] = n number counts also family that failed to do |
| ctrl_fill_info(). |
| |
| Patch fixes the problem and avoid confusion in the future just decrease |
| n counter when ctrl_fill_info() fail. |
| |
| User visible problem caused by this bug is failure to get access to |
| some genetlink family i.e. nl80211. However problem is reproducible |
| only if number of registered genetlink families is big enough to |
| cause second call of ctrl_dumpfamily(). |
| |
| Cc: Xose Vazquez Perez <xose.vazquez@gmail.com> |
| Cc: Larry Finger <Larry.Finger@lwfinger.net> |
| Cc: Johannes Berg <johannes@sipsolutions.net> |
| Fixes: 2ae0f17df1cd ("genetlink: use idr to track families") |
| Signed-off-by: Stanislaw Gruszka <sgruszka@redhat.com> |
| Acked-by: Johannes Berg <johannes@sipsolutions.net> |
| Signed-off-by: David S. Miller <davem@davemloft.net> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/netlink/genetlink.c | 4 +++- |
| 1 file changed, 3 insertions(+), 1 deletion(-) |
| |
| --- a/net/netlink/genetlink.c |
| +++ b/net/netlink/genetlink.c |
| @@ -783,8 +783,10 @@ static int ctrl_dumpfamily(struct sk_buf |
| |
| if (ctrl_fill_info(rt, NETLINK_CB(cb->skb).portid, |
| cb->nlh->nlmsg_seq, NLM_F_MULTI, |
| - skb, CTRL_CMD_NEWFAMILY) < 0) |
| + skb, CTRL_CMD_NEWFAMILY) < 0) { |
| + n--; |
| break; |
| + } |
| } |
| |
| cb->args[0] = n; |