lkml.org 
[lkml]   [2021]   [Dec]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 4.19 31/38] usb: gadget: u_ether: fix race in setting MAC address in setup phase
    Date
    From: Marian Postevca <posteuca@mutex.one>

    commit 890d5b40908bfd1a79be018d2d297cf9df60f4ee upstream.

    When listening for notifications through netlink of a new interface being
    registered, sporadically, it is possible for the MAC to be read as zero.
    The zero MAC address lasts a short period of time and then switches to a
    valid random MAC address.

    This causes problems for netd in Android, which assumes that the interface
    is malfunctioning and will not use it.

    In the good case we get this log:
    InterfaceController::getCfg() ifName usb0
    hwAddr 92:a8:f0:73:79:5b ipv4Addr 0.0.0.0 flags 0x1002

    In the error case we get these logs:
    InterfaceController::getCfg() ifName usb0
    hwAddr 00:00:00:00:00:00 ipv4Addr 0.0.0.0 flags 0x1002

    netd : interfaceGetCfg("usb0")
    netd : interfaceSetCfg() -> ServiceSpecificException
    (99, "[Cannot assign requested address] : ioctl() failed")

    The reason for the issue is the order in which the interface is setup,
    it is first registered through register_netdev() and after the MAC
    address is set.

    Fixed by first setting the MAC address of the net_device and after that
    calling register_netdev().

    Fixes: bcd4a1c40bee885e ("usb: gadget: u_ether: construct with default values and add setters/getters")
    Cc: stable@vger.kernel.org
    Signed-off-by: Marian Postevca <posteuca@mutex.one>
    Link: https://lore.kernel.org/r/20211204214912.17627-1-posteuca@mutex.one
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/usb/gadget/function/u_ether.c | 15 +++++----------
    1 file changed, 5 insertions(+), 10 deletions(-)

    --- a/drivers/usb/gadget/function/u_ether.c
    +++ b/drivers/usb/gadget/function/u_ether.c
    @@ -860,19 +860,23 @@ int gether_register_netdev(struct net_de
    {
    struct eth_dev *dev;
    struct usb_gadget *g;
    - struct sockaddr sa;
    int status;

    if (!net->dev.parent)
    return -EINVAL;
    dev = netdev_priv(net);
    g = dev->gadget;
    +
    + memcpy(net->dev_addr, dev->dev_mac, ETH_ALEN);
    + net->addr_assign_type = NET_ADDR_RANDOM;
    +
    status = register_netdev(net);
    if (status < 0) {
    dev_dbg(&g->dev, "register_netdev failed, %d\n", status);
    return status;
    } else {
    INFO(dev, "HOST MAC %pM\n", dev->host_mac);
    + INFO(dev, "MAC %pM\n", dev->dev_mac);

    /* two kinds of host-initiated state changes:
    * - iff DATA transfer is active, carrier is "on"
    @@ -880,15 +884,6 @@ int gether_register_netdev(struct net_de
    */
    netif_carrier_off(net);
    }
    - sa.sa_family = net->type;
    - memcpy(sa.sa_data, dev->dev_mac, ETH_ALEN);
    - rtnl_lock();
    - status = dev_set_mac_address(net, &sa);
    - rtnl_unlock();
    - if (status)
    - pr_warn("cannot set self ethernet address: %d\n", status);
    - else
    - INFO(dev, "MAC %pM\n", dev->dev_mac);

    return status;
    }

    \
     
     \ /
      Last update: 2021-12-27 16:34    [W:4.088 / U:0.208 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site