| From: Florian Westphal <fw@strlen.de> |
| Date: Mon, 12 Feb 2018 14:42:01 +0100 |
| Subject: xfrm_user: uncoditionally validate esn replay attribute struct |
| |
| commit d97ca5d714a5334aecadadf696875da40f1fbf3e upstream. |
| |
| The sanity test added in ecd7918745234 can be bypassed, validation |
| only occurs if XFRM_STATE_ESN flag is set, but rest of code doesn't care |
| and just checks if the attribute itself is present. |
| |
| So always validate. Alternative is to reject if we have the attribute |
| without the flag but that would change abi. |
| |
| Reported-by: syzbot+0ab777c27d2bb7588f73@syzkaller.appspotmail.com |
| Cc: Mathias Krause <minipli@googlemail.com> |
| Fixes: ecd7918745234 ("xfrm_user: ensure user supplied esn replay window is valid") |
| Fixes: d8647b79c3b7e ("xfrm: Add user interface for esn and big anti-replay windows") |
| Signed-off-by: Florian Westphal <fw@strlen.de> |
| Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com> |
| [bwh: Backported to 3.16: adjust context] |
| Signed-off-by: Ben Hutchings <ben@decadent.org.uk> |
| --- |
| net/xfrm/xfrm_user.c | 21 ++++++++------------- |
| 1 file changed, 8 insertions(+), 13 deletions(-) |
| |
| --- a/net/xfrm/xfrm_user.c |
| +++ b/net/xfrm/xfrm_user.c |
| @@ -120,22 +120,17 @@ static inline int verify_replay(struct x |
| struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; |
| struct xfrm_replay_state_esn *rs; |
| |
| - if (p->flags & XFRM_STATE_ESN) { |
| - if (!rt) |
| - return -EINVAL; |
| - |
| - rs = nla_data(rt); |
| + if (!rt) |
| + return (p->flags & XFRM_STATE_ESN) ? -EINVAL : 0; |
| |
| - if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) |
| - return -EINVAL; |
| + rs = nla_data(rt); |
| |
| - if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && |
| - nla_len(rt) != sizeof(*rs)) |
| - return -EINVAL; |
| - } |
| + if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) |
| + return -EINVAL; |
| |
| - if (!rt) |
| - return 0; |
| + if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && |
| + nla_len(rt) != sizeof(*rs)) |
| + return -EINVAL; |
| |
| /* As only ESP and AH support ESN feature. */ |
| if ((p->id.proto != IPPROTO_ESP) && (p->id.proto != IPPROTO_AH)) |