aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPeter Hurley <peter@hurleysoftware.com>2014-02-09 20:59:10 -0500
committerMarcel Holtmann <marcel@holtmann.org>2014-02-14 16:39:30 -0500
commitc10a848cea89a8f0418fa0efec33c4e8507aab4b (patch)
tree1c6eaf6a370f29ca4438bac6a8654c1fabbb1ae2
parentc949c224cfd7d5445ef947e8b93c0657323d5be5 (diff)
Bluetooth: Verify dlci not in use before rfcomm_dev create
Only one session/channel combination may be in use at any one time. However, the failure does not occur until the tty is opened (in rfcomm_dlc_open()). Because these settings are actually bound at rfcomm device creation (via RFCOMMCREATEDEV ioctl), validate and fail before creating the rfcomm tty device. Signed-off-by: Peter Hurley <peter@hurleysoftware.com> Tested-By: Alexander Holler <holler@ahsoftware.de> Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
-rw-r--r--include/net/bluetooth/rfcomm.h1
-rw-r--r--net/bluetooth/rfcomm/core.c26
-rw-r--r--net/bluetooth/rfcomm/tty.c8
3 files changed, 34 insertions, 1 deletions
diff --git a/include/net/bluetooth/rfcomm.h b/include/net/bluetooth/rfcomm.h
index 0d69936831fa..f8262a2783ec 100644
--- a/include/net/bluetooth/rfcomm.h
+++ b/include/net/bluetooth/rfcomm.h
@@ -241,6 +241,7 @@ int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb);
241int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig); 241int rfcomm_dlc_set_modem_status(struct rfcomm_dlc *d, u8 v24_sig);
242int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig); 242int rfcomm_dlc_get_modem_status(struct rfcomm_dlc *d, u8 *v24_sig);
243void rfcomm_dlc_accept(struct rfcomm_dlc *d); 243void rfcomm_dlc_accept(struct rfcomm_dlc *d);
244struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel);
244 245
245#define rfcomm_dlc_lock(d) spin_lock(&d->lock) 246#define rfcomm_dlc_lock(d) spin_lock(&d->lock)
246#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock) 247#define rfcomm_dlc_unlock(d) spin_unlock(&d->lock)
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index ba115d472f7b..b378bbb6f8a7 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -360,6 +360,11 @@ static struct rfcomm_dlc *rfcomm_dlc_get(struct rfcomm_session *s, u8 dlci)
360 return NULL; 360 return NULL;
361} 361}
362 362
363static int rfcomm_check_channel(u8 channel)
364{
365 return channel < 1 || channel > 30;
366}
367
363static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel) 368static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst, u8 channel)
364{ 369{
365 struct rfcomm_session *s; 370 struct rfcomm_session *s;
@@ -369,7 +374,7 @@ static int __rfcomm_dlc_open(struct rfcomm_dlc *d, bdaddr_t *src, bdaddr_t *dst,
369 BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d", 374 BT_DBG("dlc %p state %ld %pMR -> %pMR channel %d",
370 d, d->state, src, dst, channel); 375 d, d->state, src, dst, channel);
371 376
372 if (channel < 1 || channel > 30) 377 if (rfcomm_check_channel(channel))
373 return -EINVAL; 378 return -EINVAL;
374 379
375 if (d->state != BT_OPEN && d->state != BT_CLOSED) 380 if (d->state != BT_OPEN && d->state != BT_CLOSED)
@@ -514,6 +519,25 @@ no_session:
514 return r; 519 return r;
515} 520}
516 521
522struct rfcomm_dlc *rfcomm_dlc_exists(bdaddr_t *src, bdaddr_t *dst, u8 channel)
523{
524 struct rfcomm_session *s;
525 struct rfcomm_dlc *dlc = NULL;
526 u8 dlci;
527
528 if (rfcomm_check_channel(channel))
529 return ERR_PTR(-EINVAL);
530
531 rfcomm_lock();
532 s = rfcomm_session_get(src, dst);
533 if (s) {
534 dlci = __dlci(!s->initiator, channel);
535 dlc = rfcomm_dlc_get(s, dlci);
536 }
537 rfcomm_unlock();
538 return dlc;
539}
540
517int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb) 541int rfcomm_dlc_send(struct rfcomm_dlc *d, struct sk_buff *skb)
518{ 542{
519 int len = skb->len; 543 int len = skb->len;
diff --git a/net/bluetooth/rfcomm/tty.c b/net/bluetooth/rfcomm/tty.c
index 6ea08b05b53a..a58d693e1e61 100644
--- a/net/bluetooth/rfcomm/tty.c
+++ b/net/bluetooth/rfcomm/tty.c
@@ -385,6 +385,14 @@ static int rfcomm_create_dev(struct sock *sk, void __user *arg)
385 dlc = rfcomm_pi(sk)->dlc; 385 dlc = rfcomm_pi(sk)->dlc;
386 rfcomm_dlc_hold(dlc); 386 rfcomm_dlc_hold(dlc);
387 } else { 387 } else {
388 /* Validate the channel is unused */
389 dlc = rfcomm_dlc_exists(&req.src, &req.dst, req.channel);
390 if (IS_ERR(dlc))
391 return PTR_ERR(dlc);
392 else if (dlc) {
393 rfcomm_dlc_put(dlc);
394 return -EBUSY;
395 }
388 dlc = rfcomm_dlc_alloc(GFP_KERNEL); 396 dlc = rfcomm_dlc_alloc(GFP_KERNEL);
389 if (!dlc) 397 if (!dlc)
390 return -ENOMEM; 398 return -ENOMEM;