lkml.org 
[lkml]   [2019]   [Jan]   [11]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 3.18 08/47] ax25: fix a use-after-free in ax25_fillin_cb()
    Date
    3.18-stable review patch.  If anyone has any objections, please let me know.

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

    From: Cong Wang <xiyou.wangcong@gmail.com>

    [ Upstream commit c433570458e49bccea5c551df628d058b3526289 ]

    There are multiple issues here:

    1. After freeing dev->ax25_ptr, we need to set it to NULL otherwise
    we may use a dangling pointer.

    2. There is a race between ax25_setsockopt() and device notifier as
    reported by syzbot. Close it by holding RTNL lock.

    3. We need to test if dev->ax25_ptr is NULL before using it.

    Reported-and-tested-by: syzbot+ae6bb869cbed29b29040@syzkaller.appspotmail.com
    Signed-off-by: Cong Wang <xiyou.wangcong@gmail.com>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/ax25/af_ax25.c | 11 +++++++++--
    net/ax25/ax25_dev.c | 2 ++
    2 files changed, 11 insertions(+), 2 deletions(-)

    --- a/net/ax25/af_ax25.c
    +++ b/net/ax25/af_ax25.c
    @@ -655,15 +655,22 @@ static int ax25_setsockopt(struct socket
    break;
    }

    - dev = dev_get_by_name(&init_net, devname);
    + rtnl_lock();
    + dev = __dev_get_by_name(&init_net, devname);
    if (!dev) {
    + rtnl_unlock();
    res = -ENODEV;
    break;
    }

    ax25->ax25_dev = ax25_dev_ax25dev(dev);
    + if (!ax25->ax25_dev) {
    + rtnl_unlock();
    + res = -ENODEV;
    + break;
    + }
    ax25_fillin_cb(ax25, ax25->ax25_dev);
    - dev_put(dev);
    + rtnl_unlock();
    break;

    default:
    --- a/net/ax25/ax25_dev.c
    +++ b/net/ax25/ax25_dev.c
    @@ -116,6 +116,7 @@ void ax25_dev_device_down(struct net_dev
    if ((s = ax25_dev_list) == ax25_dev) {
    ax25_dev_list = s->next;
    spin_unlock_bh(&ax25_dev_lock);
    + dev->ax25_ptr = NULL;
    dev_put(dev);
    kfree(ax25_dev);
    return;
    @@ -125,6 +126,7 @@ void ax25_dev_device_down(struct net_dev
    if (s->next == ax25_dev) {
    s->next = ax25_dev->next;
    spin_unlock_bh(&ax25_dev_lock);
    + dev->ax25_ptr = NULL;
    dev_put(dev);
    kfree(ax25_dev);
    return;

    \
     
     \ /
      Last update: 2019-01-11 16:14    [W:2.376 / U:0.468 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site