Skip to content

Commit

Permalink
xfrm_user: validate XFRM_MSG_NEWAE XFRMA_REPLAY_ESN_VAL replay_window
Browse files Browse the repository at this point in the history
When a new xfrm state is created during an XFRM_MSG_NEWSA call we validate
the user supplied replay_esn to ensure that the size is valid and to ensure
that the replay_window size is within the allocated buffer.  However later
it is possible to update this replay_esn via a XFRM_MSG_NEWAE call.
There we again validate the size of the supplied buffer matches the
existing state and if so inject the contents.  We do not at this point
check that the replay_window is within the allocated memory.  This leads
to out-of-bounds reads and writes triggered by netlink packets.  This leads
to memory corruption and the potential for priviledge escalation.

We already attempt to validate the incoming replay information in
xfrm_new_ae() via xfrm_replay_verify_len().  This confirms that the
user is not trying to change the size of the replay state buffer which
includes the replay_esn.  It however does not check the replay_window
remains within that buffer.  Add validation of the contained replay_window.

Additionally Kees Cook has pointed out that xfrm_replay_state_esn_len()
is subject to wrapping issues.  To ensure we are correctly ensuring that
the two ESN structures are the same size compare both the overall size
as reported by xfrm_replay_state_esn_len() and the internal length are
the same.

CVE-2017-7184
ZDI-CAN-4586
Bug: 36565222
Signed-off-by: Andy Whitcroft <[email protected]>
Reviewed-by: Tyler Hicks <[email protected]>
Reviewed-by: John Johansen <[email protected]>
Reviewed-by: Kees Cook <[email protected]>
Change-Id: I50d2766ab19fb182a5e75adf9e46ff043f2d99ea
Signed-off-by: Francisco Franco <[email protected]>
  • Loading branch information
Andy Whitcroft authored and franciscofranco committed Dec 9, 2017
1 parent 4f4ee3e commit e13e4a8
Showing 1 changed file with 8 additions and 1 deletion.
9 changes: 8 additions & 1 deletion net/xfrm/xfrm_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,14 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
up = nla_data(rp);
ulen = xfrm_replay_state_esn_len(up);

if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
/* Check the overall length and the internal bitmap length to avoid
* potential overflow. */
if (nla_len(rp) < ulen ||
xfrm_replay_state_esn_len(replay_esn) != ulen ||
replay_esn->bmp_len != up->bmp_len)
return -EINVAL;

if (up->replay_window > up->bmp_len * sizeof(__u32) * 8)
return -EINVAL;

return 0;
Expand Down

0 comments on commit e13e4a8

Please sign in to comment.