summaryrefslogtreecommitdiff
path: root/net
diff options
context:
space:
mode:
authorXiaodong Xu <stid.smth@gmail.com>2019-11-11 15:05:46 -0800
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2019-12-17 20:37:28 +0100
commit3bbb8eec91fe6939bce32c7658f5d8f4c0442659 (patch)
treec70f084547005b77285d19daab780207e1ccfd33 /net
parent7a9b522fa65d4a25754b3a4329f76d132ffab63d (diff)
xfrm: release device reference for invalid state
[ Upstream commit 4944a4b1077f74d89073624bd286219d2fcbfce3 ] An ESP packet could be decrypted in async mode if the input handler for this packet returns -EINPROGRESS in xfrm_input(). At this moment the device reference in skb is held. Later xfrm_input() will be invoked again to resume the processing. If the transform state is still valid it would continue to release the device reference and there won't be a problem; however if the transform state is not valid when async resumption happens, the packet will be dropped while the device reference is still being held. When the device is deleted for some reason and the reference to this device is not properly released, the kernel will keep logging like: unregister_netdevice: waiting for ppp2 to become free. Usage count = 1 The issue is observed when running IPsec traffic over a PPPoE device based on a bridge interface. By terminating the PPPoE connection on the server end for multiple times, the PPPoE device on the client side will eventually get stuck on the above warning message. This patch will check the async mode first and continue to release device reference in async resumption, before it is dropped due to invalid state. v2: Do not assign address family from outer_mode in the transform if the state is invalid v3: Release device reference in the error path instead of jumping to resume Fixes: 4ce3dbe397d7b ("xfrm: Fix xfrm_input() to verify state is valid when (encap_type < 0)") Signed-off-by: Xiaodong Xu <stid.smth@gmail.com> Reported-by: Bo Chen <chenborfc@163.com> Tested-by: Bo Chen <chenborfc@163.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
Diffstat (limited to 'net')
-rw-r--r--net/xfrm/xfrm_input.c3
1 files changed, 3 insertions, 0 deletions
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index fc0a9ce1be18..311597401b82 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -245,6 +245,9 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
else
XFRM_INC_STATS(net,
LINUX_MIB_XFRMINSTATEINVALID);
+
+ if (encap_type == -1)
+ dev_put(skb->dev);
goto drop;
}