lkml.org 
[lkml]   [2022]   [May]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.17 050/140] nfc: replace improper check device_is_registered() in netlink related functions
    Date
    From: Duoming Zhou <duoming@zju.edu.cn>

    commit da5c0f119203ad9728920456a0f52a6d850c01cd upstream.

    The device_is_registered() in nfc core is used to check whether
    nfc device is registered in netlink related functions such as
    nfc_fw_download(), nfc_dev_up() and so on. Although device_is_registered()
    is protected by device_lock, there is still a race condition between
    device_del() and device_is_registered(). The root cause is that
    kobject_del() in device_del() is not protected by device_lock.

    (cleanup task) | (netlink task)
    |
    nfc_unregister_device | nfc_fw_download
    device_del | device_lock
    ... | if (!device_is_registered)//(1)
    kobject_del//(2) | ...
    ... | device_unlock

    The device_is_registered() returns the value of state_in_sysfs and
    the state_in_sysfs is set to zero in kobject_del(). If we pass check in
    position (1), then set zero in position (2). As a result, the check
    in position (1) is useless.

    This patch uses bool variable instead of device_is_registered() to judge
    whether the nfc device is registered, which is well synchronized.

    Fixes: 3e256b8f8dfa ("NFC: add nfc subsystem core")
    Signed-off-by: Duoming Zhou <duoming@zju.edu.cn>
    Signed-off-by: David S. Miller <davem@davemloft.net>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    net/nfc/core.c | 29 ++++++++++++++---------------
    1 file changed, 14 insertions(+), 15 deletions(-)

    --- a/net/nfc/core.c
    +++ b/net/nfc/core.c
    @@ -38,7 +38,7 @@ int nfc_fw_download(struct nfc_dev *dev,

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -94,7 +94,7 @@ int nfc_dev_up(struct nfc_dev *dev)

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -142,7 +142,7 @@ int nfc_dev_down(struct nfc_dev *dev)

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -207,7 +207,7 @@ int nfc_start_poll(struct nfc_dev *dev,

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -246,7 +246,7 @@ int nfc_stop_poll(struct nfc_dev *dev)

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -291,7 +291,7 @@ int nfc_dep_link_up(struct nfc_dev *dev,

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -335,7 +335,7 @@ int nfc_dep_link_down(struct nfc_dev *de

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -401,7 +401,7 @@ int nfc_activate_target(struct nfc_dev *

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -448,7 +448,7 @@ int nfc_deactivate_target(struct nfc_dev

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -495,7 +495,7 @@ int nfc_data_exchange(struct nfc_dev *de

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    kfree_skb(skb);
    goto error;
    @@ -552,7 +552,7 @@ int nfc_enable_se(struct nfc_dev *dev, u

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -601,7 +601,7 @@ int nfc_disable_se(struct nfc_dev *dev,

    device_lock(&dev->dev);

    - if (!device_is_registered(&dev->dev)) {
    + if (dev->shutting_down) {
    rc = -ENODEV;
    goto error;
    }
    @@ -1134,6 +1134,7 @@ int nfc_register_device(struct nfc_dev *
    dev->rfkill = NULL;
    }
    }
    + dev->shutting_down = false;
    device_unlock(&dev->dev);

    rc = nfc_genl_device_added(dev);
    @@ -1166,12 +1167,10 @@ void nfc_unregister_device(struct nfc_de
    rfkill_unregister(dev->rfkill);
    rfkill_destroy(dev->rfkill);
    }
    + dev->shutting_down = true;
    device_unlock(&dev->dev);

    if (dev->ops->check_presence) {
    - device_lock(&dev->dev);
    - dev->shutting_down = true;
    - device_unlock(&dev->dev);
    del_timer_sync(&dev->check_pres_timer);
    cancel_work_sync(&dev->check_pres_work);
    }

    \
     
     \ /
      Last update: 2022-05-10 16:25    [W:4.386 / U:0.344 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site