Message ID | 20201007231448.27346-4-pablo@netfilter.org |
---|---|
State | Accepted |
Delegated to: | Pablo Neira |
Headers | show |
Series | Add nf_tables ingress hook for the inet family | expand |
Hi Pablo, I love your patch! Yet something to improve: [auto build test ERROR on nf-next/master] url: https://github.com/0day-ci/linux/commits/Pablo-Neira-Ayuso/Add-nf_tables-ingress-hook-for-the-inet-family/20201008-071530 base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master config: x86_64-randconfig-s022-20201008 (attached as .config) compiler: gcc-9 (Debian 9.3.0-15) 9.3.0 reproduce: # apt-get install sparse # sparse version: v0.6.2-218-gc0e96d6d-dirty # https://github.com/0day-ci/linux/commit/4a788f545ac2e08b0c08658e156da55e2fce5ae6 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Pablo-Neira-Ayuso/Add-nf_tables-ingress-hook-for-the-inet-family/20201008-071530 git checkout 4a788f545ac2e08b0c08658e156da55e2fce5ae6 # save the attached .config to linux build tree make W=1 C=1 CF='-fdiagnostic-prefix -D__CHECK_ENDIAN__' ARCH=x86_64 If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All error/warnings (new ones prefixed by >>): net/netfilter/core.c: In function 'nf_hook_entry_head': >> net/netfilter/core.c:292:14: error: 'struct net_device' has no member named 'nf_hooks_ingress' 292 | return &dev->nf_hooks_ingress; | ^~ >> net/netfilter/core.c:288:12: warning: this statement may fall through [-Wimplicit-fallthrough=] 288 | if (!dev || dev_net(dev) != net) { | ~~~~~^~~~~~~~~~~~~~~~~~~~~~ net/netfilter/core.c:293:2: note: here 293 | case NFPROTO_IPV4: | ^~~~ At top level: net/netfilter/core.c:336:13: warning: 'nf_ingress_hook' defined but not used [-Wunused-function] 336 | static bool nf_ingress_hook(const struct nf_hook_ops *reg, int pf) | ^~~~~~~~~~~~~~~ vim +292 net/netfilter/core.c 265 266 static struct nf_hook_entries __rcu ** 267 nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, 268 struct net_device *dev) 269 { 270 switch (pf) { 271 case NFPROTO_NETDEV: 272 break; 273 #ifdef CONFIG_NETFILTER_FAMILY_ARP 274 case NFPROTO_ARP: 275 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= hooknum)) 276 return NULL; 277 return net->nf.hooks_arp + hooknum; 278 #endif 279 #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE 280 case NFPROTO_BRIDGE: 281 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= hooknum)) 282 return NULL; 283 return net->nf.hooks_bridge + hooknum; 284 #endif 285 case NFPROTO_INET: 286 if (WARN_ON_ONCE(hooknum != NF_INET_INGRESS)) 287 return NULL; > 288 if (!dev || dev_net(dev) != net) { 289 WARN_ON_ONCE(1); 290 return NULL; 291 } > 292 return &dev->nf_hooks_ingress; 293 case NFPROTO_IPV4: 294 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= hooknum)) 295 return NULL; 296 return net->nf.hooks_ipv4 + hooknum; 297 case NFPROTO_IPV6: 298 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= hooknum)) 299 return NULL; 300 return net->nf.hooks_ipv6 + hooknum; 301 #if IS_ENABLED(CONFIG_DECNET) 302 case NFPROTO_DECNET: 303 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= hooknum)) 304 return NULL; 305 return net->nf.hooks_decnet + hooknum; 306 #endif 307 default: 308 WARN_ON_ONCE(1); 309 return NULL; 310 } 311 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Hi Pablo, I love your patch! Yet something to improve: [auto build test ERROR on nf-next/master] url: https://github.com/0day-ci/linux/commits/Pablo-Neira-Ayuso/Add-nf_tables-ingress-hook-for-the-inet-family/20201008-071530 base: https://git.kernel.org/pub/scm/linux/kernel/git/pablo/nf-next.git master config: arm-randconfig-r033-20201008 (attached as .config) compiler: clang version 12.0.0 (https://github.com/llvm/llvm-project 8da0df3d6dcc0dd42740be60b0da4ec201190904) reproduce (this is a W=1 build): wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross chmod +x ~/bin/make.cross # install arm cross compiling tool for clang build # apt-get install binutils-arm-linux-gnueabi # https://github.com/0day-ci/linux/commit/4a788f545ac2e08b0c08658e156da55e2fce5ae6 git remote add linux-review https://github.com/0day-ci/linux git fetch --no-tags linux-review Pablo-Neira-Ayuso/Add-nf_tables-ingress-hook-for-the-inet-family/20201008-071530 git checkout 4a788f545ac2e08b0c08658e156da55e2fce5ae6 # save the attached .config to linux build tree COMPILER_INSTALL_PATH=$HOME/0day COMPILER=clang make.cross ARCH=arm If you fix the issue, kindly add following tag as appropriate Reported-by: kernel test robot <lkp@intel.com> All errors (new ones prefixed by >>): >> net/netfilter/core.c:292:16: error: no member named 'nf_hooks_ingress' in 'struct net_device' return &dev->nf_hooks_ingress; ~~~ ^ 1 error generated. vim +292 net/netfilter/core.c 265 266 static struct nf_hook_entries __rcu ** 267 nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, 268 struct net_device *dev) 269 { 270 switch (pf) { 271 case NFPROTO_NETDEV: 272 break; 273 #ifdef CONFIG_NETFILTER_FAMILY_ARP 274 case NFPROTO_ARP: 275 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_arp) <= hooknum)) 276 return NULL; 277 return net->nf.hooks_arp + hooknum; 278 #endif 279 #ifdef CONFIG_NETFILTER_FAMILY_BRIDGE 280 case NFPROTO_BRIDGE: 281 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_bridge) <= hooknum)) 282 return NULL; 283 return net->nf.hooks_bridge + hooknum; 284 #endif 285 case NFPROTO_INET: 286 if (WARN_ON_ONCE(hooknum != NF_INET_INGRESS)) 287 return NULL; 288 if (!dev || dev_net(dev) != net) { 289 WARN_ON_ONCE(1); 290 return NULL; 291 } > 292 return &dev->nf_hooks_ingress; 293 case NFPROTO_IPV4: 294 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= hooknum)) 295 return NULL; 296 return net->nf.hooks_ipv4 + hooknum; 297 case NFPROTO_IPV6: 298 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv6) <= hooknum)) 299 return NULL; 300 return net->nf.hooks_ipv6 + hooknum; 301 #if IS_ENABLED(CONFIG_DECNET) 302 case NFPROTO_DECNET: 303 if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_decnet) <= hooknum)) 304 return NULL; 305 return net->nf.hooks_decnet + hooknum; 306 #endif 307 default: 308 WARN_ON_ONCE(1); 309 return NULL; 310 } 311 --- 0-DAY CI Kernel Test Service, Intel Corporation https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff --git a/include/uapi/linux/netfilter.h b/include/uapi/linux/netfilter.h index ca9e63d6e0e4..6a6179af0d7c 100644 --- a/include/uapi/linux/netfilter.h +++ b/include/uapi/linux/netfilter.h @@ -45,6 +45,7 @@ enum nf_inet_hooks { NF_INET_FORWARD, NF_INET_LOCAL_OUT, NF_INET_POST_ROUTING, + NF_INET_INGRESS, NF_INET_NUMHOOKS }; diff --git a/net/netfilter/core.c b/net/netfilter/core.c index a7639501d78b..38feb1f0feda 100644 --- a/net/netfilter/core.c +++ b/net/netfilter/core.c @@ -282,6 +282,14 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, return NULL; return net->nf.hooks_bridge + hooknum; #endif + case NFPROTO_INET: + if (WARN_ON_ONCE(hooknum != NF_INET_INGRESS)) + return NULL; + if (!dev || dev_net(dev) != net) { + WARN_ON_ONCE(1); + return NULL; + } + return &dev->nf_hooks_ingress; case NFPROTO_IPV4: if (WARN_ON_ONCE(ARRAY_SIZE(net->nf.hooks_ipv4) <= hooknum)) return NULL; @@ -311,22 +319,56 @@ nf_hook_entry_head(struct net *net, int pf, unsigned int hooknum, return NULL; } +static int nf_ingress_check(struct net *net, const struct nf_hook_ops *reg, + int hooknum) +{ +#ifndef CONFIG_NETFILTER_INGRESS + if (reg->hooknum == hooknum) + return -EOPNOTSUPP; +#endif + if (reg->hooknum != hooknum || + !reg->dev || dev_net(reg->dev) != net) + return -EINVAL; + + return 0; +} + static bool nf_ingress_hook(const struct nf_hook_ops *reg, int pf) { - return pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS; + if ((pf == NFPROTO_NETDEV && reg->hooknum == NF_NETDEV_INGRESS) || + (pf == NFPROTO_INET && reg->hooknum == NF_INET_INGRESS)) + return true; + + return false; } static void nf_static_key_inc(const struct nf_hook_ops *reg, int pf) { #ifdef CONFIG_JUMP_LABEL - static_key_slow_inc(&nf_hooks_needed[pf][reg->hooknum]); + int hooknum; + + if (pf == NFPROTO_INET && reg->hooknum == NF_INET_INGRESS) { + pf = NFPROTO_NETDEV; + hooknum = NF_NETDEV_INGRESS; + } else { + hooknum = reg->hooknum; + } + static_key_slow_inc(&nf_hooks_needed[pf][hooknum]); #endif } static void nf_static_key_dec(const struct nf_hook_ops *reg, int pf) { #ifdef CONFIG_JUMP_LABEL - static_key_slow_dec(&nf_hooks_needed[pf][reg->hooknum]); + int hooknum; + + if (pf == NFPROTO_INET && reg->hooknum == NF_INET_INGRESS) { + pf = NFPROTO_NETDEV; + hooknum = NF_NETDEV_INGRESS; + } else { + hooknum = reg->hooknum; + } + static_key_slow_dec(&nf_hooks_needed[pf][hooknum]); #endif } @@ -335,15 +377,22 @@ static int __nf_register_net_hook(struct net *net, int pf, { struct nf_hook_entries *p, *new_hooks; struct nf_hook_entries __rcu **pp; + int err; - if (pf == NFPROTO_NETDEV) { -#ifndef CONFIG_NETFILTER_INGRESS - if (reg->hooknum == NF_NETDEV_INGRESS) - return -EOPNOTSUPP; -#endif - if (reg->hooknum != NF_NETDEV_INGRESS || - !reg->dev || dev_net(reg->dev) != net) - return -EINVAL; + switch (pf) { + case NFPROTO_NETDEV: + err = nf_ingress_check(net, reg, NF_NETDEV_INGRESS); + if (err < 0) + return err; + break; + case NFPROTO_INET: + if (reg->hooknum != NF_INET_INGRESS) + break; + + err = nf_ingress_check(net, reg, NF_INET_INGRESS); + if (err < 0) + return err; + break; } pp = nf_hook_entry_head(net, pf, reg->hooknum, reg->dev); @@ -441,8 +490,12 @@ static void __nf_unregister_net_hook(struct net *net, int pf, void nf_unregister_net_hook(struct net *net, const struct nf_hook_ops *reg) { if (reg->pf == NFPROTO_INET) { - __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); - __nf_unregister_net_hook(net, NFPROTO_IPV6, reg); + if (reg->hooknum == NF_INET_INGRESS) { + __nf_unregister_net_hook(net, NFPROTO_INET, reg); + } else { + __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); + __nf_unregister_net_hook(net, NFPROTO_IPV6, reg); + } } else { __nf_unregister_net_hook(net, reg->pf, reg); } @@ -467,14 +520,20 @@ int nf_register_net_hook(struct net *net, const struct nf_hook_ops *reg) int err; if (reg->pf == NFPROTO_INET) { - err = __nf_register_net_hook(net, NFPROTO_IPV4, reg); - if (err < 0) - return err; - - err = __nf_register_net_hook(net, NFPROTO_IPV6, reg); - if (err < 0) { - __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); - return err; + if (reg->hooknum == NF_INET_INGRESS) { + err = __nf_register_net_hook(net, NFPROTO_INET, reg); + if (err < 0) + return err; + } else { + err = __nf_register_net_hook(net, NFPROTO_IPV4, reg); + if (err < 0) + return err; + + err = __nf_register_net_hook(net, NFPROTO_IPV6, reg); + if (err < 0) { + __nf_unregister_net_hook(net, NFPROTO_IPV4, reg); + return err; + } } } else { err = __nf_register_net_hook(net, reg->pf, reg);
This patch adds the NF_INET_INGRESS pseudohook for the NFPROTO_INET family. This is a mapping this new hook to the existing NFPROTO_NETDEV and NF_NETDEV_INGRESS hook. The hook does not guarantee that packets are inet only, users must filter out non-ip traffic explicitly. This infrastructure makes it easier to support this new hook in nf_tables. Signed-off-by: Pablo Neira Ayuso <pablo@netfilter.org> --- include/uapi/linux/netfilter.h | 1 + net/netfilter/core.c | 101 ++++++++++++++++++++++++++------- 2 files changed, 81 insertions(+), 21 deletions(-)