lkml.org 
[lkml]   [2018]   [Sep]   [13]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.9 05/78] net: sched: Fix memory exposure from short TCA_U32_SEL
    Date
    4.9-stable review patch.  If anyone has any objections, please let me know.

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

    From: Kees Cook <keescook@chromium.org>

    [ Upstream commit 98c8f125fd8a6240ea343c1aa50a1be9047791b8 ]

    Via u32_change(), TCA_U32_SEL has an unspecified type in the netlink
    policy, so max length isn't enforced, only minimum. This means nkeys
    (from userspace) was being trusted without checking the actual size of
    nla_len(), which could lead to a memory over-read, and ultimately an
    exposure via a call to u32_dump(). Reachability is CAP_NET_ADMIN within
    a namespace.

    Reported-by: Al Viro <viro@zeniv.linux.org.uk>
    Cc: Jamal Hadi Salim <jhs@mojatatu.com>
    Cc: Cong Wang <xiyou.wangcong@gmail.com>
    Cc: Jiri Pirko <jiri@resnulli.us>
    Cc: "David S. Miller" <davem@davemloft.net>
    Cc: netdev@vger.kernel.org
    Signed-off-by: Kees Cook <keescook@chromium.org>
    Acked-by: Jamal Hadi Salim <jhs@mojatatu.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/sched/cls_u32.c | 8 ++++++--
    1 file changed, 6 insertions(+), 2 deletions(-)

    --- a/net/sched/cls_u32.c
    +++ b/net/sched/cls_u32.c
    @@ -851,6 +851,7 @@ static int u32_change(struct net *net, s
    struct nlattr *opt = tca[TCA_OPTIONS];
    struct nlattr *tb[TCA_U32_MAX + 1];
    u32 htid, flags = 0;
    + size_t sel_size;
    int err;
    #ifdef CONFIG_CLS_U32_PERF
    size_t size;
    @@ -967,8 +968,11 @@ static int u32_change(struct net *net, s
    return -EINVAL;

    s = nla_data(tb[TCA_U32_SEL]);
    + sel_size = sizeof(*s) + sizeof(*s->keys) * s->nkeys;
    + if (nla_len(tb[TCA_U32_SEL]) < sel_size)
    + return -EINVAL;

    - n = kzalloc(sizeof(*n) + s->nkeys*sizeof(struct tc_u32_key), GFP_KERNEL);
    + n = kzalloc(offsetof(typeof(*n), sel) + sel_size, GFP_KERNEL);
    if (n == NULL)
    return -ENOBUFS;

    @@ -981,7 +985,7 @@ static int u32_change(struct net *net, s
    }
    #endif

    - memcpy(&n->sel, s, sizeof(*s) + s->nkeys*sizeof(struct tc_u32_key));
    + memcpy(&n->sel, s, sel_size);
    RCU_INIT_POINTER(n->ht_up, ht);
    n->handle = handle;
    n->fshift = s->hmask ? ffs(ntohl(s->hmask)) - 1 : 0;

    \
     
     \ /
      Last update: 2018-09-13 16:19    [W:8.950 / U:0.296 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site