aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndy Whitcroft <apw@canonical.com>2017-03-22 07:29:31 +0000
committerEcco Park <eccopark@google.com>2017-03-24 10:00:57 -0700
commit416bf43a812994600f0f0d4dbfbff878fdd31c67 (patch)
treea426b5309b0a7f3e14b22847927e75761d854370
parent64033a604fcd23b3baa055a7d6e88c9c70dfed98 (diff)
xfrm_user: validate XFRM_MSG_NEWAE XFRMA_REPLAY_ESN_VAL replay_windowandroid-7.1.2_r0.12
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 <apw@canonical.com> Reviewed-by: Tyler Hicks <tyhicks@canonical.com> Reviewed-by: John Johansen <john.johansen@canonical.com> Reviewed-by: Kees Cook <keescook@chromium.org> Change-Id: I50d2766ab19fb182a5e75adf9e46ff043f2d99ea
-rw-r--r--net/xfrm/xfrm_user.c9
1 files changed, 8 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index e812e988c111..b8170ae1461e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -386,7 +386,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;