| From foo@baz Sun Nov 22 12:00:04 PM CET 2020 |
| From: Paul Moore <paul@paul-moore.com> |
| Date: Sun, 8 Nov 2020 09:08:26 -0500 |
| Subject: netlabel: fix our progress tracking in netlbl_unlabel_staticlist() |
| |
| From: Paul Moore <paul@paul-moore.com> |
| |
| [ Upstream commit 866358ec331f8faa394995fb4b511af1db0247c8 ] |
| |
| The current NetLabel code doesn't correctly keep track of the netlink |
| dump state in some cases, in particular when multiple interfaces with |
| large configurations are loaded. The problem manifests itself by not |
| reporting the full configuration to userspace, even though it is |
| loaded and active in the kernel. This patch fixes this by ensuring |
| that the dump state is properly reset when necessary inside the |
| netlbl_unlabel_staticlist() function. |
| |
| Fixes: 8cc44579d1bd ("NetLabel: Introduce static network labels for unlabeled connections") |
| Signed-off-by: Paul Moore <paul@paul-moore.com> |
| Link: https://lore.kernel.org/r/160484450633.3752.16512718263560813473.stgit@sifl |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| net/netlabel/netlabel_unlabeled.c | 17 ++++++++++++----- |
| 1 file changed, 12 insertions(+), 5 deletions(-) |
| |
| --- a/net/netlabel/netlabel_unlabeled.c |
| +++ b/net/netlabel/netlabel_unlabeled.c |
| @@ -1179,12 +1179,13 @@ static int netlbl_unlabel_staticlist(str |
| struct netlbl_unlhsh_walk_arg cb_arg; |
| u32 skip_bkt = cb->args[0]; |
| u32 skip_chain = cb->args[1]; |
| - u32 iter_bkt; |
| - u32 iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0; |
| + u32 skip_addr4 = cb->args[2]; |
| + u32 iter_bkt, iter_chain, iter_addr4 = 0, iter_addr6 = 0; |
| struct netlbl_unlhsh_iface *iface; |
| struct list_head *iter_list; |
| struct netlbl_af4list *addr4; |
| #if IS_ENABLED(CONFIG_IPV6) |
| + u32 skip_addr6 = cb->args[3]; |
| struct netlbl_af6list *addr6; |
| #endif |
| |
| @@ -1195,7 +1196,7 @@ static int netlbl_unlabel_staticlist(str |
| rcu_read_lock(); |
| for (iter_bkt = skip_bkt; |
| iter_bkt < rcu_dereference(netlbl_unlhsh)->size; |
| - iter_bkt++, iter_chain = 0, iter_addr4 = 0, iter_addr6 = 0) { |
| + iter_bkt++) { |
| iter_list = &rcu_dereference(netlbl_unlhsh)->tbl[iter_bkt]; |
| list_for_each_entry_rcu(iface, iter_list, list) { |
| if (!iface->valid || |
| @@ -1203,7 +1204,7 @@ static int netlbl_unlabel_staticlist(str |
| continue; |
| netlbl_af4list_foreach_rcu(addr4, |
| &iface->addr4_list) { |
| - if (iter_addr4++ < cb->args[2]) |
| + if (iter_addr4++ < skip_addr4) |
| continue; |
| if (netlbl_unlabel_staticlist_gen( |
| NLBL_UNLABEL_C_STATICLIST, |
| @@ -1216,10 +1217,12 @@ static int netlbl_unlabel_staticlist(str |
| goto unlabel_staticlist_return; |
| } |
| } |
| + iter_addr4 = 0; |
| + skip_addr4 = 0; |
| #if IS_ENABLED(CONFIG_IPV6) |
| netlbl_af6list_foreach_rcu(addr6, |
| &iface->addr6_list) { |
| - if (iter_addr6++ < cb->args[3]) |
| + if (iter_addr6++ < skip_addr6) |
| continue; |
| if (netlbl_unlabel_staticlist_gen( |
| NLBL_UNLABEL_C_STATICLIST, |
| @@ -1232,8 +1235,12 @@ static int netlbl_unlabel_staticlist(str |
| goto unlabel_staticlist_return; |
| } |
| } |
| + iter_addr6 = 0; |
| + skip_addr6 = 0; |
| #endif /* IPv6 */ |
| } |
| + iter_chain = 0; |
| + skip_chain = 0; |
| } |
| |
| unlabel_staticlist_return: |