net: ipv6: fix dst ref loop on input in rpl lwt
[ Upstream commit13e55fbaec] Prevent a dst ref loop on input in rpl_iptunnel. Fixes:a7a29f9c36("net: ipv6: add rpl sr tunnel") Cc: Alexander Aring <alex.aring@gmail.com> Cc: Ido Schimmel <idosch@nvidia.com> Reviewed-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Justin Iurman <justin.iurman@uliege.be> Signed-off-by: Paolo Abeni <pabeni@redhat.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
committed by
Greg Kroah-Hartman
parent
c0b11dc505
commit
2daabaa55c
+12
-2
@@ -259,10 +259,18 @@ static int rpl_input(struct sk_buff *skb)
|
||||
{
|
||||
struct dst_entry *orig_dst = skb_dst(skb);
|
||||
struct dst_entry *dst = NULL;
|
||||
struct lwtunnel_state *lwtst;
|
||||
struct rpl_lwt *rlwt;
|
||||
int err;
|
||||
|
||||
rlwt = rpl_lwt_lwtunnel(orig_dst->lwtstate);
|
||||
/* We cannot dereference "orig_dst" once ip6_route_input() or
|
||||
* skb_dst_drop() is called. However, in order to detect a dst loop, we
|
||||
* need the address of its lwtstate. So, save the address of lwtstate
|
||||
* now and use it later as a comparison.
|
||||
*/
|
||||
lwtst = orig_dst->lwtstate;
|
||||
|
||||
rlwt = rpl_lwt_lwtunnel(lwtst);
|
||||
|
||||
local_bh_disable();
|
||||
dst = dst_cache_get(&rlwt->cache);
|
||||
@@ -277,7 +285,9 @@ static int rpl_input(struct sk_buff *skb)
|
||||
if (!dst) {
|
||||
ip6_route_input(skb);
|
||||
dst = skb_dst(skb);
|
||||
if (!dst->error) {
|
||||
|
||||
/* cache only if we don't create a dst reference loop */
|
||||
if (!dst->error && lwtst != dst->lwtstate) {
|
||||
local_bh_disable();
|
||||
dst_cache_set_ip6(&rlwt->cache, dst,
|
||||
&ipv6_hdr(skb)->saddr);
|
||||
|
||||
Reference in New Issue
Block a user