Bluetooth: Release rfcomm_dev only once
No logic prevents an rfcomm_dev from being released multiple times. For example, if the rfcomm_dev ref count is large due to pending tx, then multiple RFCOMMRELEASEDEV ioctls may mistakenly release the rfcomm_dev too many times. Note that concurrent ioctls are not required to create this condition. Introduce RFCOMM_DEV_RELEASED status bit which guarantees the rfcomm_dev can only be released once. NB: Since the flags are exported to userspace, introduce the status field to track state for which userspace should not be aware. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Tested-By: Alexander Holler <holler@ahsoftware.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
This commit is contained in:
parent
960603a54a
commit
1c64834e06
2 changed files with 14 additions and 3 deletions
|
@ -324,11 +324,15 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel,
|
|||
#define RFCOMMGETDEVINFO _IOR('R', 211, int)
|
||||
#define RFCOMMSTEALDLC _IOW('R', 220, int)
|
||||
|
||||
/* rfcomm_dev.flags bit definitions */
|
||||
#define RFCOMM_REUSE_DLC 0
|
||||
#define RFCOMM_RELEASE_ONHUP 1
|
||||
#define RFCOMM_HANGUP_NOW 2
|
||||
#define RFCOMM_TTY_ATTACHED 3
|
||||
#define RFCOMM_TTY_RELEASED 4
|
||||
#define RFCOMM_DEFUNCT_BIT4 4 /* don't reuse this bit - userspace visible */
|
||||
|
||||
/* rfcomm_dev.status bit definitions */
|
||||
#define RFCOMM_DEV_RELEASED 0
|
||||
|
||||
struct rfcomm_dev_req {
|
||||
s16 dev_id;
|
||||
|
|
|
@ -51,6 +51,8 @@ struct rfcomm_dev {
|
|||
unsigned long flags;
|
||||
int err;
|
||||
|
||||
unsigned long status; /* don't export to userspace */
|
||||
|
||||
bdaddr_t src;
|
||||
bdaddr_t dst;
|
||||
u8 channel;
|
||||
|
@ -423,6 +425,12 @@ static int rfcomm_release_dev(void __user *arg)
|
|||
return -EPERM;
|
||||
}
|
||||
|
||||
/* only release once */
|
||||
if (test_and_set_bit(RFCOMM_DEV_RELEASED, &dev->status)) {
|
||||
tty_port_put(&dev->port);
|
||||
return -EALREADY;
|
||||
}
|
||||
|
||||
if (req.flags & (1 << RFCOMM_HANGUP_NOW))
|
||||
rfcomm_dlc_close(dev->dlc, 0);
|
||||
|
||||
|
@ -433,8 +441,7 @@ static int rfcomm_release_dev(void __user *arg)
|
|||
tty_kref_put(tty);
|
||||
}
|
||||
|
||||
if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags) &&
|
||||
!test_and_set_bit(RFCOMM_TTY_RELEASED, &dev->flags))
|
||||
if (!test_bit(RFCOMM_RELEASE_ONHUP, &dev->flags))
|
||||
tty_port_put(&dev->port);
|
||||
|
||||
tty_port_put(&dev->port);
|
||||
|
|
Loading…
Reference in a new issue