diff options
| author | Peter Hurley <peter@hurleysoftware.com> | 2014-02-09 20:59:18 -0500 |
|---|---|---|
| committer | Marcel Holtmann <marcel@holtmann.org> | 2014-02-14 16:39:31 -0500 |
| commit | 033ace99c444daa4141b84419f670513ce637b77 (patch) | |
| tree | 6640d710788117d3dbf9c76dd15e870dddbddec5 /net/bluetooth/rfcomm | |
| parent | 7611fcedd6caae0586397508a2414788d87a231c (diff) | |
Bluetooth: Serialize RFCOMMCREATEDEV and RFCOMMRELEASEDEV ioctls
At least two different race conditions exist with multiple concurrent
RFCOMMCREATEDEV and RFCOMMRELEASEDEV ioctls:
* Multiple concurrent RFCOMMCREATEDEVs with RFCOMM_REUSE_DLC can
mistakenly share the same DLC.
* RFCOMMRELEASEDEV can destruct the rfcomm_dev still being
constructed by RFCOMMCREATEDEV.
Introduce rfcomm_ioctl_mutex to serialize these add/remove operations.
Signed-off-by: Peter Hurley <peter@hurleysoftware.com>
Tested-By: Alexander Holler <holler@ahsoftware.de>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Diffstat (limited to 'net/bluetooth/rfcomm')
| -rw-r--r-- | net/bluetooth/rfcomm/tty.c | 27 |
1 files changed, 25 insertions, 2 deletions
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c index 4a38b5454ab0..ef2769553dab 100644 --- a/net/bluetooth/rfcomm/tty.c +++ b/net/bluetooth/rfcomm/tty.c | |||
| @@ -40,6 +40,7 @@ | |||
| 40 | #define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */ | 40 | #define RFCOMM_TTY_MAJOR 216 /* device node major id of the usb/bluetooth.c driver */ |
| 41 | #define RFCOMM_TTY_MINOR 0 | 41 | #define RFCOMM_TTY_MINOR 0 |
| 42 | 42 | ||
| 43 | static DEFINE_MUTEX(rfcomm_ioctl_mutex); | ||
| 43 | static struct tty_driver *rfcomm_tty_driver; | 44 | static struct tty_driver *rfcomm_tty_driver; |
| 44 | 45 | ||
| 45 | struct rfcomm_dev { | 46 | struct rfcomm_dev { |
| @@ -373,7 +374,7 @@ static struct sk_buff *rfcomm_wmalloc(struct rfcomm_dev *dev, unsigned long size | |||
| 373 | 374 | ||
| 374 | #define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP)) | 375 | #define NOCAP_FLAGS ((1 << RFCOMM_REUSE_DLC) | (1 << RFCOMM_RELEASE_ONHUP)) |
| 375 | 376 | ||
| 376 | static int rfcomm_create_dev(struct sock *sk, void __user *arg) | 377 | static int __rfcomm_create_dev(struct sock *sk, void __user *arg) |
| 377 | { | 378 | { |
| 378 | struct rfcomm_dev_req req; | 379 | struct rfcomm_dev_req req; |
| 379 | struct rfcomm_dlc *dlc; | 380 | struct rfcomm_dlc *dlc; |
| @@ -423,7 +424,7 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg) | |||
| 423 | return id; | 424 | return id; |
| 424 | } | 425 | } |
| 425 | 426 | ||
| 426 | static int rfcomm_release_dev(void __user *arg) | 427 | static int __rfcomm_release_dev(void __user *arg) |
| 427 | { | 428 | { |
| 428 | struct rfcomm_dev_req req; | 429 | struct rfcomm_dev_req req; |
| 429 | struct rfcomm_dev *dev; | 430 | struct rfcomm_dev *dev; |
| @@ -466,6 +467,28 @@ static int rfcomm_release_dev(void __user *arg) | |||
| 466 | return 0; | 467 | return 0; |
| 467 | } | 468 | } |
| 468 | 469 | ||
| 470 | static int rfcomm_create_dev(struct sock *sk, void __user *arg) | ||
| 471 | { | ||
| 472 | int ret; | ||
| 473 | |||
| 474 | mutex_lock(&rfcomm_ioctl_mutex); | ||
| 475 | ret = __rfcomm_create_dev(sk, arg); | ||
| 476 | mutex_unlock(&rfcomm_ioctl_mutex); | ||
| 477 | |||
| 478 | return ret; | ||
| 479 | } | ||
| 480 | |||
| 481 | static int rfcomm_release_dev(void __user *arg) | ||
| 482 | { | ||
| 483 | int ret; | ||
| 484 | |||
| 485 | mutex_lock(&rfcomm_ioctl_mutex); | ||
| 486 | ret = __rfcomm_release_dev(arg); | ||
| 487 | mutex_unlock(&rfcomm_ioctl_mutex); | ||
| 488 | |||
| 489 | return ret; | ||
| 490 | } | ||
| 491 | |||
| 469 | static int rfcomm_get_dev_list(void __user *arg) | 492 | static int rfcomm_get_dev_list(void __user *arg) |
| 470 | { | 493 | { |
| 471 | struct rfcomm_dev *dev; | 494 | struct rfcomm_dev *dev; |
