diff options
| author | Pauli Virtanen <pav@iki.fi> | 2026-08-29 17:20:09 +0300 |
|---|---|---|
| committer | Luiz Augusto von Dentz <luiz.von.dentz@intel.com> | 2026-10-14 13:27:20 -0400 |
| commit | aba67d585b993a5a2d6c93181bd2ec50a25cf4c7 (patch) | |
| tree | 1c8ea83983d93198f7f0050207da2a2e74bb6838 /include | |
| parent | b508a2a2d846ccc4c8f691e4e3dfca6f97dfe85a (diff) | |
| download | linux-aba67d585b993a5a2d6c93181bd2ec50a25cf4c7.tar.gz linux-aba67d585b993a5a2d6c93181bd2ec50a25cf4c7.zip | |
Bluetooth: L2CAP: make concurrent l2cap_set_timer() refcounting safe
Since l2cap_set_timer() does not check return value of
schedule_delayed_work(), two concurrent calls may result to l2cap_chan
refcount leak.
Change the refcounting by using mod_delayed_work() and checking its
return value.
Code paths aside from l2cap_chan_busy() hold chan->lock, so this has
little correctness impact.
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
Diffstat (limited to 'include')
| -rw-r--r-- | include/net/bluetooth/l2cap.h | 9 |
1 files changed, 4 insertions, 5 deletions
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h index a991fc07515c..2315a3993c7b 100644 --- a/include/net/bluetooth/l2cap.h +++ b/include/net/bluetooth/l2cap.h @@ -847,12 +847,11 @@ static inline void l2cap_set_timer(struct l2cap_chan *chan, BT_DBG("chan %p state %s timeout %ld", chan, state_to_string(chan->state), timeout); - /* If delayed work cancelled do not hold(chan) - since it is already done with previous set_timer */ - if (!cancel_delayed_work(work)) - l2cap_chan_hold(chan); + l2cap_chan_hold(chan); - schedule_delayed_work(work, timeout); + /* put(chan) if timer was already queued so it already has a ref */ + if (mod_delayed_work(system_percpu_wq, work, timeout)) + l2cap_chan_put(chan); } static inline bool l2cap_clear_timer(struct l2cap_chan *chan, |
