Message ID | tencent_DE4D2D0FE82F3CA9294AEEB3A949A44F6008@qq.com |
---|---|
State | Not Applicable |
Headers | show |
Series | netfilter: tproxy: Add RCU protection in nf_tproxy_laddr4 | expand |
On Wed, Sep 4, 2024 at 2:25 PM Jiawei Ye <jiawei.ye@foxmail.com> wrote: > > In the `nf_tproxy_laddr4` function, both the `__in_dev_get_rcu()` call > and the `in_dev_for_each_ifa_rcu()` macro are used to access > RCU-protected data structures. Previously, these accesses were not > enclosed within an RCU read-side critical section, which violates RCU > usage rules and can lead to race conditions, data inconsistencies, and > memory corruption issues. > > This possible bug was identified using a static analysis tool developed > by myself, specifically designed to detect RCU-related issues. > > To address this, `rcu_read_lock()` and `rcu_read_unlock()` are added > around the RCU-protected operations in the `nf_tproxy_laddr4` function by > acquiring the RCU read lock before calling `__in_dev_get_rcu()` and > iterating with `in_dev_for_each_ifa_rcu()`. This change prevents > potential RCU issues and adheres to proper RCU usage patterns. Please share with us the complete stack trace where you think rcu is not held, because your static tool is unknown to us. nf_tproxy_get_sock_v4() would have a similar issue.
Eric Dumazet <edumazet@google.com> wrote: > On Wed, Sep 4, 2024 at 2:25 PM Jiawei Ye <jiawei.ye@foxmail.com> wrote: > > > > In the `nf_tproxy_laddr4` function, both the `__in_dev_get_rcu()` call > > and the `in_dev_for_each_ifa_rcu()` macro are used to access > > RCU-protected data structures. Previously, these accesses were not > > enclosed within an RCU read-side critical section, which violates RCU > > usage rules and can lead to race conditions, data inconsistencies, and > > memory corruption issues. > > > > This possible bug was identified using a static analysis tool developed > > by myself, specifically designed to detect RCU-related issues. > > > > To address this, `rcu_read_lock()` and `rcu_read_unlock()` are added > > around the RCU-protected operations in the `nf_tproxy_laddr4` function by > > acquiring the RCU read lock before calling `__in_dev_get_rcu()` and > > iterating with `in_dev_for_each_ifa_rcu()`. This change prevents > > potential RCU issues and adheres to proper RCU usage patterns. > > Please share with us the complete stack trace where you think rcu is not held, > because your static tool is unknown to us. > > nf_tproxy_get_sock_v4() would have a similar issue. Right, all netfilter hooks assume rcu read lock is held. See nf_hook()/nf_hook_slow().
Hi Jiawei,
kernel test robot noticed the following build warnings:
[auto build test WARNING on netfilter-nf/main]
[also build test WARNING on linus/master v6.11-rc6 next-20240904]
[cannot apply to nf-next/master horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Jiawei-Ye/netfilter-tproxy-Add-RCU-protection-in-nf_tproxy_laddr4/20240904-202126
base: https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git main
patch link: https://lore.kernel.org/r/tencent_DE4D2D0FE82F3CA9294AEEB3A949A44F6008%40qq.com
patch subject: [PATCH] netfilter: tproxy: Add RCU protection in nf_tproxy_laddr4
config: arm-randconfig-001-20240905 (https://download.01.org/0day-ci/archive/20240905/202409051900.8A3Mf8i7-lkp@intel.com/config)
compiler: clang version 14.0.6 (https://github.com/llvm/llvm-project f28c006a5895fc0e329fe15fead81e37457cb1d1)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240905/202409051900.8A3Mf8i7-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409051900.8A3Mf8i7-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> net/ipv4/netfilter/nf_tproxy_ipv4.c:64:3: warning: misleading indentation; statement is not part of the previous 'if' [-Wmisleading-indentation]
return daddr;
^
net/ipv4/netfilter/nf_tproxy_ipv4.c:62:2: note: previous statement is here
if (!indev)
^
1 warning generated.
vim +/if +64 net/ipv4/netfilter/nf_tproxy_ipv4.c
45ca4e0cf2734f Máté Eckl 2018-06-01 49
45ca4e0cf2734f Máté Eckl 2018-06-01 50 __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
45ca4e0cf2734f Máté Eckl 2018-06-01 51 {
b8d19572367bb0 Florian Westphal 2019-05-31 52 const struct in_ifaddr *ifa;
45ca4e0cf2734f Máté Eckl 2018-06-01 53 struct in_device *indev;
45ca4e0cf2734f Máté Eckl 2018-06-01 54 __be32 laddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 55
45ca4e0cf2734f Máté Eckl 2018-06-01 56 if (user_laddr)
45ca4e0cf2734f Máté Eckl 2018-06-01 57 return user_laddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 58
45ca4e0cf2734f Máté Eckl 2018-06-01 59 laddr = 0;
2729675b33a93a Jiawei Ye 2024-09-04 60 rcu_read_lock();
45ca4e0cf2734f Máté Eckl 2018-06-01 61 indev = __in_dev_get_rcu(skb->dev);
21a673bddc8fd4 Florian Westphal 2024-05-13 62 if (!indev)
2729675b33a93a Jiawei Ye 2024-09-04 63 rcu_read_unlock();
21a673bddc8fd4 Florian Westphal 2024-05-13 @64 return daddr;
b8d19572367bb0 Florian Westphal 2019-05-31 65
b8d19572367bb0 Florian Westphal 2019-05-31 66 in_dev_for_each_ifa_rcu(ifa, indev) {
b8d19572367bb0 Florian Westphal 2019-05-31 67 if (ifa->ifa_flags & IFA_F_SECONDARY)
b8d19572367bb0 Florian Westphal 2019-05-31 68 continue;
b8d19572367bb0 Florian Westphal 2019-05-31 69
45ca4e0cf2734f Máté Eckl 2018-06-01 70 laddr = ifa->ifa_local;
45ca4e0cf2734f Máté Eckl 2018-06-01 71 break;
b8d19572367bb0 Florian Westphal 2019-05-31 72 }
2729675b33a93a Jiawei Ye 2024-09-04 73 rcu_read_unlock();
45ca4e0cf2734f Máté Eckl 2018-06-01 74
45ca4e0cf2734f Máté Eckl 2018-06-01 75 return laddr ? laddr : daddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 76 }
45ca4e0cf2734f Máté Eckl 2018-06-01 77 EXPORT_SYMBOL_GPL(nf_tproxy_laddr4);
45ca4e0cf2734f Máté Eckl 2018-06-01 78
Hi Jiawei,
kernel test robot noticed the following build warnings:
[auto build test WARNING on netfilter-nf/main]
[also build test WARNING on linus/master v6.11-rc6 next-20240905]
[cannot apply to nf-next/master horms-ipvs/master]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch#_base_tree_information]
url: https://github.com/intel-lab-lkp/linux/commits/Jiawei-Ye/netfilter-tproxy-Add-RCU-protection-in-nf_tproxy_laddr4/20240904-202126
base: https://git.kernel.org/pub/scm/linux/kernel/git/netfilter/nf.git main
patch link: https://lore.kernel.org/r/tencent_DE4D2D0FE82F3CA9294AEEB3A949A44F6008%40qq.com
patch subject: [PATCH] netfilter: tproxy: Add RCU protection in nf_tproxy_laddr4
config: m68k-allmodconfig (https://download.01.org/0day-ci/archive/20240905/202409052334.kT8sZWuh-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 14.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20240905/202409052334.kT8sZWuh-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202409052334.kT8sZWuh-lkp@intel.com/
All warnings (new ones prefixed by >>):
net/ipv4/netfilter/nf_tproxy_ipv4.c: In function 'nf_tproxy_laddr4':
>> net/ipv4/netfilter/nf_tproxy_ipv4.c:62:9: warning: this 'if' clause does not guard... [-Wmisleading-indentation]
62 | if (!indev)
| ^~
net/ipv4/netfilter/nf_tproxy_ipv4.c:64:17: note: ...this statement, but the latter is misleadingly indented as if it were guarded by the 'if'
64 | return daddr;
| ^~~~~~
vim +/if +62 net/ipv4/netfilter/nf_tproxy_ipv4.c
45ca4e0cf2734f Máté Eckl 2018-06-01 49
45ca4e0cf2734f Máté Eckl 2018-06-01 50 __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr)
45ca4e0cf2734f Máté Eckl 2018-06-01 51 {
b8d19572367bb0 Florian Westphal 2019-05-31 52 const struct in_ifaddr *ifa;
45ca4e0cf2734f Máté Eckl 2018-06-01 53 struct in_device *indev;
45ca4e0cf2734f Máté Eckl 2018-06-01 54 __be32 laddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 55
45ca4e0cf2734f Máté Eckl 2018-06-01 56 if (user_laddr)
45ca4e0cf2734f Máté Eckl 2018-06-01 57 return user_laddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 58
45ca4e0cf2734f Máté Eckl 2018-06-01 59 laddr = 0;
2729675b33a93a Jiawei Ye 2024-09-04 60 rcu_read_lock();
45ca4e0cf2734f Máté Eckl 2018-06-01 61 indev = __in_dev_get_rcu(skb->dev);
21a673bddc8fd4 Florian Westphal 2024-05-13 @62 if (!indev)
2729675b33a93a Jiawei Ye 2024-09-04 63 rcu_read_unlock();
21a673bddc8fd4 Florian Westphal 2024-05-13 64 return daddr;
b8d19572367bb0 Florian Westphal 2019-05-31 65
b8d19572367bb0 Florian Westphal 2019-05-31 66 in_dev_for_each_ifa_rcu(ifa, indev) {
b8d19572367bb0 Florian Westphal 2019-05-31 67 if (ifa->ifa_flags & IFA_F_SECONDARY)
b8d19572367bb0 Florian Westphal 2019-05-31 68 continue;
b8d19572367bb0 Florian Westphal 2019-05-31 69
45ca4e0cf2734f Máté Eckl 2018-06-01 70 laddr = ifa->ifa_local;
45ca4e0cf2734f Máté Eckl 2018-06-01 71 break;
b8d19572367bb0 Florian Westphal 2019-05-31 72 }
2729675b33a93a Jiawei Ye 2024-09-04 73 rcu_read_unlock();
45ca4e0cf2734f Máté Eckl 2018-06-01 74
45ca4e0cf2734f Máté Eckl 2018-06-01 75 return laddr ? laddr : daddr;
45ca4e0cf2734f Máté Eckl 2018-06-01 76 }
45ca4e0cf2734f Máté Eckl 2018-06-01 77 EXPORT_SYMBOL_GPL(nf_tproxy_laddr4);
45ca4e0cf2734f Máté Eckl 2018-06-01 78
diff --git a/net/ipv4/netfilter/nf_tproxy_ipv4.c b/net/ipv4/netfilter/nf_tproxy_ipv4.c index 73e66a088e25..51ff9c337e71 100644 --- a/net/ipv4/netfilter/nf_tproxy_ipv4.c +++ b/net/ipv4/netfilter/nf_tproxy_ipv4.c @@ -57,8 +57,10 @@ __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) return user_laddr; laddr = 0; + rcu_read_lock(); indev = __in_dev_get_rcu(skb->dev); if (!indev) + rcu_read_unlock(); return daddr; in_dev_for_each_ifa_rcu(ifa, indev) { @@ -68,6 +70,7 @@ __be32 nf_tproxy_laddr4(struct sk_buff *skb, __be32 user_laddr, __be32 daddr) laddr = ifa->ifa_local; break; } + rcu_read_unlock(); return laddr ? laddr : daddr; }
In the `nf_tproxy_laddr4` function, both the `__in_dev_get_rcu()` call and the `in_dev_for_each_ifa_rcu()` macro are used to access RCU-protected data structures. Previously, these accesses were not enclosed within an RCU read-side critical section, which violates RCU usage rules and can lead to race conditions, data inconsistencies, and memory corruption issues. This possible bug was identified using a static analysis tool developed by myself, specifically designed to detect RCU-related issues. To address this, `rcu_read_lock()` and `rcu_read_unlock()` are added around the RCU-protected operations in the `nf_tproxy_laddr4` function by acquiring the RCU read lock before calling `__in_dev_get_rcu()` and iterating with `in_dev_for_each_ifa_rcu()`. This change prevents potential RCU issues and adheres to proper RCU usage patterns. Fixes: b8d19572367b ("netfilter: use in_dev_for_each_ifa_rcu") Signed-off-by: Jiawei Ye <jiawei.ye@foxmail.com> --- net/ipv4/netfilter/nf_tproxy_ipv4.c | 3 +++ 1 file changed, 3 insertions(+)