diff options
author | Johan Hedberg <johan.hedberg@intel.com> | 2014-11-12 15:22:21 -0500 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2014-11-13 01:49:09 -0500 |
commit | abe84903a8efc6b83fa92161429e0e3a28bde15c (patch) | |
tree | 3b1b90b1c170c41bbd6fcdae92e8726024c37ade /net | |
parent | 24ccb9f4f7a3a5a867bbc880019cdb4b41176b63 (diff) |
Bluetooth: Use proper nesting annotation for l2cap_chan lock
By default lockdep considers all L2CAP channels equal. This would mean
that we get warnings if a channel is locked when another one's lock is
tried to be acquired in the same thread. This kind of inter-channel
locking dependencies exist in the form of parent-child channels as well
as any channel wishing to elevate the security by requesting procedures
on the SMP channel.
To eliminate the chance for these lockdep warnings we introduce a
nesting level for each channel and use that when acquiring the channel
lock. For now there exists the earlier mentioned three identified
categories: SMP, "normal" channels and parent channels (i.e. those in
BT_LISTEN state). The nesting level is defined as atomic_t since we need
access to it before the lock is actually acquired.
Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net')
-rw-r--r-- | net/bluetooth/l2cap_sock.c | 9 | ||||
-rw-r--r-- | net/bluetooth/smp.c | 10 |
2 files changed, 19 insertions, 0 deletions
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index ad1cf82fee02..f1a51564b8fd 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c | |||
@@ -285,6 +285,12 @@ static int l2cap_sock_listen(struct socket *sock, int backlog) | |||
285 | sk->sk_max_ack_backlog = backlog; | 285 | sk->sk_max_ack_backlog = backlog; |
286 | sk->sk_ack_backlog = 0; | 286 | sk->sk_ack_backlog = 0; |
287 | 287 | ||
288 | /* Listening channels need to use nested locking in order not to | ||
289 | * cause lockdep warnings when the created child channels end up | ||
290 | * being locked in the same thread as the parent channel. | ||
291 | */ | ||
292 | atomic_set(&chan->nesting, L2CAP_NESTING_PARENT); | ||
293 | |||
288 | chan->state = BT_LISTEN; | 294 | chan->state = BT_LISTEN; |
289 | sk->sk_state = BT_LISTEN; | 295 | sk->sk_state = BT_LISTEN; |
290 | 296 | ||
@@ -1497,6 +1503,9 @@ static void l2cap_sock_init(struct sock *sk, struct sock *parent) | |||
1497 | l2cap_chan_set_defaults(chan); | 1503 | l2cap_chan_set_defaults(chan); |
1498 | } | 1504 | } |
1499 | 1505 | ||
1506 | /* Set default lock nesting level */ | ||
1507 | atomic_set(&chan->nesting, L2CAP_NESTING_NORMAL); | ||
1508 | |||
1500 | /* Default config options */ | 1509 | /* Default config options */ |
1501 | chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; | 1510 | chan->flush_to = L2CAP_DEFAULT_FLUSH_TO; |
1502 | 1511 | ||
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 3d38553eb526..3b63c7f09dd5 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c | |||
@@ -1658,6 +1658,13 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan) | |||
1658 | chan->omtu = pchan->omtu; | 1658 | chan->omtu = pchan->omtu; |
1659 | chan->mode = pchan->mode; | 1659 | chan->mode = pchan->mode; |
1660 | 1660 | ||
1661 | /* Other L2CAP channels may request SMP routines in order to | ||
1662 | * change the security level. This means that the SMP channel | ||
1663 | * lock must be considered in its own category to avoid lockdep | ||
1664 | * warnings. | ||
1665 | */ | ||
1666 | atomic_set(&chan->nesting, L2CAP_NESTING_SMP); | ||
1667 | |||
1661 | BT_DBG("created chan %p", chan); | 1668 | BT_DBG("created chan %p", chan); |
1662 | 1669 | ||
1663 | return chan; | 1670 | return chan; |
@@ -1715,6 +1722,9 @@ int smp_register(struct hci_dev *hdev) | |||
1715 | chan->imtu = L2CAP_DEFAULT_MTU; | 1722 | chan->imtu = L2CAP_DEFAULT_MTU; |
1716 | chan->ops = &smp_root_chan_ops; | 1723 | chan->ops = &smp_root_chan_ops; |
1717 | 1724 | ||
1725 | /* Set correct nesting level for a parent/listening channel */ | ||
1726 | atomic_set(&chan->nesting, L2CAP_NESTING_PARENT); | ||
1727 | |||
1718 | hdev->smp_data = chan; | 1728 | hdev->smp_data = chan; |
1719 | 1729 | ||
1720 | return 0; | 1730 | return 0; |