lkml.org 
[lkml]   [2019]   [Feb]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.18 087/108] xfrm: refine validation of template and selector families
    Date
    3.18-stable review patch.  If anyone has any objections, please let me know.

    ------------------

    From: Florian Westphal <fw@strlen.de>

    commit 35e6103861a3a970de6c84688c6e7a1f65b164ca upstream.

    The check assumes that in transport mode, the first templates family
    must match the address family of the policy selector.

    Syzkaller managed to build a template using MODE_ROUTEOPTIMIZATION,
    with ipv4-in-ipv6 chain, leading to following splat:

    BUG: KASAN: stack-out-of-bounds in xfrm_state_find+0x1db/0x1854
    Read of size 4 at addr ffff888063e57aa0 by task a.out/2050
    xfrm_state_find+0x1db/0x1854
    xfrm_tmpl_resolve+0x100/0x1d0
    xfrm_resolve_and_create_bundle+0x108/0x1000 [..]

    Problem is that addresses point into flowi4 struct, but xfrm_state_find
    treats them as being ipv6 because it uses templ->encap_family is used
    (AF_INET6 in case of reproducer) rather than family (AF_INET).

    This patch inverts the logic: Enforce 'template family must match
    selector' EXCEPT for tunnel and BEET mode.

    In BEET and Tunnel mode, xfrm_tmpl_resolve_one will have remote/local
    address pointers changed to point at the addresses found in the template,
    rather than the flowi ones, so no oob read will occur.

    Reported-by: 3ntr0py1337@gmail.com
    Reported-by: Daniel Borkmann <daniel@iogearbox.net>
    Signed-off-by: Florian Westphal <fw@strlen.de>
    Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

    ---
    net/xfrm/xfrm_user.c | 13 +++++++++----
    1 file changed, 9 insertions(+), 4 deletions(-)

    --- a/net/xfrm/xfrm_user.c
    +++ b/net/xfrm/xfrm_user.c
    @@ -1377,10 +1377,15 @@ static int validate_tmpl(int nr, struct
    if (!ut[i].family)
    ut[i].family = family;

    - if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
    - (ut[i].family != prev_family))
    - return -EINVAL;
    -
    + switch (ut[i].mode) {
    + case XFRM_MODE_TUNNEL:
    + case XFRM_MODE_BEET:
    + break;
    + default:
    + if (ut[i].family != prev_family)
    + return -EINVAL;
    + break;
    + }
    if (ut[i].mode >= XFRM_MODE_MAX)
    return -EINVAL;


    \
     
     \ /
      Last update: 2019-02-18 15:15    [W:4.237 / U:0.268 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site