lkml.org 
[lkml]   [2017]   [Aug]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.4 78/91] xfrm: Dont use sk_family for socket policy lookups
    Date
    4.4-stable review patch.  If anyone has any objections, please let me know.

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

    From: Steffen Klassert <steffen.klassert@secunet.com>

    commit 4c86d77743a54fb2d8a4d18a037a074c892bb3be upstream.

    On IPv4-mapped IPv6 addresses sk_family is AF_INET6,
    but the flow informations are created based on AF_INET.
    So the routing set up 'struct flowi4' but we try to
    access 'struct flowi6' what leads to an out of bounds
    access. Fix this by using the family we get with the
    dst_entry, like we do it for the standard policy lookup.

    Reported-by: Dmitry Vyukov <dvyukov@google.com>
    Tested-by: Dmitry Vyukov <dvyukov@google.com>
    Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

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

    --- a/net/xfrm/xfrm_policy.c
    +++ b/net/xfrm/xfrm_policy.c
    @@ -1216,7 +1216,7 @@ static inline int policy_to_flow_dir(int
    }

    static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
    - const struct flowi *fl)
    + const struct flowi *fl, u16 family)
    {
    struct xfrm_policy *pol;
    struct net *net = sock_net(sk);
    @@ -1225,8 +1225,7 @@ static struct xfrm_policy *xfrm_sk_polic
    read_lock_bh(&net->xfrm.xfrm_policy_lock);
    pol = rcu_dereference(sk->sk_policy[dir]);
    if (pol != NULL) {
    - bool match = xfrm_selector_match(&pol->selector, fl,
    - sk->sk_family);
    + bool match = xfrm_selector_match(&pol->selector, fl, family);
    int err = 0;

    if (match) {
    @@ -2174,7 +2173,7 @@ struct dst_entry *xfrm_lookup(struct net
    sk = sk_const_to_full_sk(sk);
    if (sk && sk->sk_policy[XFRM_POLICY_OUT]) {
    num_pols = 1;
    - pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl);
    + pols[0] = xfrm_sk_policy_lookup(sk, XFRM_POLICY_OUT, fl, family);
    err = xfrm_expand_policies(fl, family, pols,
    &num_pols, &num_xfrms);
    if (err < 0)
    @@ -2453,7 +2452,7 @@ int __xfrm_policy_check(struct sock *sk,
    pol = NULL;
    sk = sk_to_full_sk(sk);
    if (sk && sk->sk_policy[dir]) {
    - pol = xfrm_sk_policy_lookup(sk, dir, &fl);
    + pol = xfrm_sk_policy_lookup(sk, dir, &fl, family);
    if (IS_ERR(pol)) {
    XFRM_INC_STATS(net, LINUX_MIB_XFRMINPOLERROR);
    return 0;

    \
     
     \ /
      Last update: 2017-08-05 01:43    [W:4.173 / U:0.028 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site