diff options
author | Vegard Nossum <vegard.nossum@oracle.com> | 2016-07-05 04:18:08 -0400 |
---|---|---|
committer | Steffen Klassert <steffen.klassert@secunet.com> | 2016-07-18 03:37:02 -0400 |
commit | 1ba5bf993c6a3142e18e68ea6452b347f9cb5635 (patch) | |
tree | 50acfc1c0fc36a81964f600f505ec93be0e34f10 /net/xfrm | |
parent | 8e6ce7ebeb34f0992f56de078c3744fb383657fa (diff) |
xfrm: fix crash in XFRM_MSG_GETSA netlink handler
If we hit any of the error conditions inside xfrm_dump_sa(), then
xfrm_state_walk_init() never gets called. However, we still call
xfrm_state_walk_done() from xfrm_dump_sa_done(), which will crash
because the state walk was never initialized properly.
We can fix this by setting cb->args[0] only after we've processed the
first element and checking this before calling xfrm_state_walk_done().
Fixes: d3623099d3 ("ipsec: add support of limited SA dump")
Cc: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Cc: Steffen Klassert <steffen.klassert@secunet.com>
Signed-off-by: Vegard Nossum <vegard.nossum@oracle.com>
Acked-by: Nicolas Dichtel <nicolas.dichtel@6wind.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm')
-rw-r--r-- | net/xfrm/xfrm_user.c | 6 |
1 files changed, 3 insertions, 3 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c index d516845e16e3..4fb04ced5867 100644 --- a/net/xfrm/xfrm_user.c +++ b/net/xfrm/xfrm_user.c | |||
@@ -896,7 +896,8 @@ static int xfrm_dump_sa_done(struct netlink_callback *cb) | |||
896 | struct sock *sk = cb->skb->sk; | 896 | struct sock *sk = cb->skb->sk; |
897 | struct net *net = sock_net(sk); | 897 | struct net *net = sock_net(sk); |
898 | 898 | ||
899 | xfrm_state_walk_done(walk, net); | 899 | if (cb->args[0]) |
900 | xfrm_state_walk_done(walk, net); | ||
900 | return 0; | 901 | return 0; |
901 | } | 902 | } |
902 | 903 | ||
@@ -921,8 +922,6 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | |||
921 | u8 proto = 0; | 922 | u8 proto = 0; |
922 | int err; | 923 | int err; |
923 | 924 | ||
924 | cb->args[0] = 1; | ||
925 | |||
926 | err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX, | 925 | err = nlmsg_parse(cb->nlh, 0, attrs, XFRMA_MAX, |
927 | xfrma_policy); | 926 | xfrma_policy); |
928 | if (err < 0) | 927 | if (err < 0) |
@@ -939,6 +938,7 @@ static int xfrm_dump_sa(struct sk_buff *skb, struct netlink_callback *cb) | |||
939 | proto = nla_get_u8(attrs[XFRMA_PROTO]); | 938 | proto = nla_get_u8(attrs[XFRMA_PROTO]); |
940 | 939 | ||
941 | xfrm_state_walk_init(walk, proto, filter); | 940 | xfrm_state_walk_init(walk, proto, filter); |
941 | cb->args[0] = 1; | ||
942 | } | 942 | } |
943 | 943 | ||
944 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); | 944 | (void) xfrm_state_walk(net, walk, dump_one_state, &info); |