From: Greg Kroah-Hartman Date: Tue, 9 Oct 2012 13:31:01 +0000 (-0700) Subject: 3.5-stable patches X-Git-Tag: v3.0.46~34 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=529dd632fea4cf9b6100585a0b4a04bde9e237c7;p=thirdparty%2Fkernel%2Fstable-queue.git 3.5-stable patches added patches: xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch --- diff --git a/queue-3.5/series b/queue-3.5/series index 0f4bdfbdeec..28e7a329255 100644 --- a/queue-3.5/series +++ b/queue-3.5/series @@ -74,3 +74,4 @@ ext4-move_extent-code-cleanup.patch ext4-online-defrag-is-not-supported-for-journaled-files.patch ext4-always-set-i_op-in-ext4_mknod.patch ext4-fix-fdatasync-for-files-with-only-i_size-changes.patch +xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch diff --git a/queue-3.5/xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch b/queue-3.5/xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch new file mode 100644 index 00000000000..ea5d2cbb58a --- /dev/null +++ b/queue-3.5/xfrm_user-ensure-user-supplied-esn-replay-window-is-valid.patch @@ -0,0 +1,137 @@ +From ecd7918745234e423dd87fcc0c077da557909720 Mon Sep 17 00:00:00 2001 +From: Mathias Krause +Date: Thu, 20 Sep 2012 10:01:49 +0000 +Subject: xfrm_user: ensure user supplied esn replay window is valid + +From: Mathias Krause + +commit ecd7918745234e423dd87fcc0c077da557909720 upstream. + +The current code fails to ensure that the netlink message actually +contains as many bytes as the header indicates. If a user creates a new +state or updates an existing one but does not supply the bytes for the +whole ESN replay window, the kernel copies random heap bytes into the +replay bitmap, the ones happen to follow the XFRMA_REPLAY_ESN_VAL +netlink attribute. This leads to following issues: + +1. The replay window has random bits set confusing the replay handling + code later on. + +2. A malicious user could use this flaw to leak up to ~3.5kB of heap + memory when she has access to the XFRM netlink interface (requires + CAP_NET_ADMIN). + +Known users of the ESN replay window are strongSwan and Steffen's +iproute2 patch (). The latter +uses the interface with a bitmap supplied while the former does not. +strongSwan is therefore prone to run into issue 1. + +To fix both issues without breaking existing userland allow using the +XFRMA_REPLAY_ESN_VAL netlink attribute with either an empty bitmap or a +fully specified one. For the former case we initialize the in-kernel +bitmap with zero, for the latter we copy the user supplied bitmap. For +state updates the full bitmap must be supplied. + +To prevent overflows in the bitmap length calculation the maximum size +of bmp_len is limited to 128 by this patch -- resulting in a maximum +replay window of 4096 packets. This should be sufficient for all real +life scenarios (RFC 4303 recommends a default replay window size of 64). + +Signed-off-by: Mathias Krause +Cc: Steffen Klassert +Cc: Martin Willi +Cc: Ben Hutchings +Signed-off-by: David S. Miller +Signed-off-by: Greg Kroah-Hartman + +--- + include/linux/xfrm.h | 2 ++ + net/xfrm/xfrm_user.c | 31 +++++++++++++++++++++++++------ + 2 files changed, 27 insertions(+), 6 deletions(-) + +--- a/include/linux/xfrm.h ++++ b/include/linux/xfrm.h +@@ -84,6 +84,8 @@ struct xfrm_replay_state { + __u32 bitmap; + }; + ++#define XFRMA_REPLAY_ESN_MAX 4096 ++ + struct xfrm_replay_state_esn { + unsigned int bmp_len; + __u32 oseq; +--- a/net/xfrm/xfrm_user.c ++++ b/net/xfrm/xfrm_user.c +@@ -123,9 +123,21 @@ static inline int verify_replay(struct x + struct nlattr **attrs) + { + struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL]; ++ struct xfrm_replay_state_esn *rs; + +- if ((p->flags & XFRM_STATE_ESN) && !rt) +- return -EINVAL; ++ if (p->flags & XFRM_STATE_ESN) { ++ if (!rt) ++ return -EINVAL; ++ ++ rs = nla_data(rt); ++ ++ if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8) ++ return -EINVAL; ++ ++ if (nla_len(rt) < xfrm_replay_state_esn_len(rs) && ++ nla_len(rt) != sizeof(*rs)) ++ return -EINVAL; ++ } + + if (!rt) + return 0; +@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len + struct nlattr *rp) + { + struct xfrm_replay_state_esn *up; ++ int ulen; + + if (!replay_esn || !rp) + return 0; + + up = nla_data(rp); ++ ulen = xfrm_replay_state_esn_len(up); + +- if (xfrm_replay_state_esn_len(replay_esn) != +- xfrm_replay_state_esn_len(up)) ++ if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen) + return -EINVAL; + + return 0; +@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(s + struct nlattr *rta) + { + struct xfrm_replay_state_esn *p, *pp, *up; ++ int klen, ulen; + + if (!rta) + return 0; + + up = nla_data(rta); ++ klen = xfrm_replay_state_esn_len(up); ++ ulen = nla_len(rta) >= klen ? klen : sizeof(*up); + +- p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); ++ p = kzalloc(klen, GFP_KERNEL); + if (!p) + return -ENOMEM; + +- pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL); ++ pp = kzalloc(klen, GFP_KERNEL); + if (!pp) { + kfree(p); + return -ENOMEM; + } + ++ memcpy(p, up, ulen); ++ memcpy(pp, up, ulen); ++ + *replay_esn = p; + *preplay_esn = pp; +