summaryrefslogtreecommitdiff
path: root/include
diff options
context:
space:
mode:
authorPauli Virtanen <pav@iki.fi>2026-08-29 17:20:09 +0300
committerLuiz Augusto von Dentz <luiz.von.dentz@intel.com>2026-10-14 13:27:20 -0400
commitaba67d585b993a5a2d6c93181bd2ec50a25cf4c7 (patch)
tree1c8ea83983d93198f7f0050207da2a2e74bb6838 /include
parentb508a2a2d846ccc4c8f691e4e3dfca6f97dfe85a (diff)
downloadlinux-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.h9
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,