summaryrefslogtreecommitdiff
path: root/sys/netbt/rfcomm_upper.c
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2009-11-21 13:05:33 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2009-11-21 13:05:33 +0000
commit9495e9003ab6bf557833fa1b2641293d748bcd9a (patch)
tree815ae731d25a84f7109a260d17e54c18273ae869 /sys/netbt/rfcomm_upper.c
parentcb9e8f5ce6398bbf3a336d8b9169f5222ed6501c (diff)
User triggerable KASSERT()s and NULL dereferences in netbt setsockopt()s,
found by Clement LECIGNE, localhost DoS everywhere. Also, don't leak the mbuf when the wrong level is used. ok claudio@, "just commit" deraadt@
Diffstat (limited to 'sys/netbt/rfcomm_upper.c')
-rw-r--r--sys/netbt/rfcomm_upper.c45
1 files changed, 27 insertions, 18 deletions
diff --git a/sys/netbt/rfcomm_upper.c b/sys/netbt/rfcomm_upper.c
index b6b95feba5b..19635350362 100644
--- a/sys/netbt/rfcomm_upper.c
+++ b/sys/netbt/rfcomm_upper.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: rfcomm_upper.c,v 1.6 2008/11/22 04:42:58 uwe Exp $ */
+/* $OpenBSD: rfcomm_upper.c,v 1.7 2009/11/21 13:05:32 guenther Exp $ */
/* $NetBSD: rfcomm_upper.c,v 1.11 2008/08/06 15:01:24 plunky Exp $ */
/*-
@@ -429,42 +429,51 @@ rfcomm_rcvd(struct rfcomm_dlc *dlc, size_t space)
}
/*
- * rfcomm_setopt(dlc, option, addr)
+ * rfcomm_setopt(dlc, option, m)
*
* set DLC options
*/
int
-rfcomm_setopt(struct rfcomm_dlc *dlc, int opt, void *addr)
+rfcomm_setopt(struct rfcomm_dlc *dlc, int opt, struct mbuf *m)
{
int mode, err = 0;
uint16_t mtu;
switch (opt) {
case SO_RFCOMM_MTU:
- mtu = *(uint16_t *)addr;
- if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
+ if (m == NULL || m->m_len != sizeof(uint16_t))
err = EINVAL;
- else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
- dlc->rd_mtu = mtu;
- else
- err = EBUSY;
+ else {
+ mtu = *mtod(m, uint16_t *);
+ if (mtu < RFCOMM_MTU_MIN || mtu > RFCOMM_MTU_MAX)
+ err = EINVAL;
+ else if (dlc->rd_state == RFCOMM_DLC_CLOSED)
+ dlc->rd_mtu = mtu;
+ else
+ err = EBUSY;
+ }
break;
case SO_RFCOMM_LM:
- mode = *(int *)addr;
- mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT | RFCOMM_LM_AUTH);
+ if (m == NULL || m->m_len != sizeof(int))
+ err = EINVAL;
+ else {
+ mode = *mtod(m, int *);
+ mode &= (RFCOMM_LM_SECURE | RFCOMM_LM_ENCRYPT |
+ RFCOMM_LM_AUTH);
- if (mode & RFCOMM_LM_SECURE)
- mode |= RFCOMM_LM_ENCRYPT;
+ if (mode & RFCOMM_LM_SECURE)
+ mode |= RFCOMM_LM_ENCRYPT;
- if (mode & RFCOMM_LM_ENCRYPT)
- mode |= RFCOMM_LM_AUTH;
+ if (mode & RFCOMM_LM_ENCRYPT)
+ mode |= RFCOMM_LM_AUTH;
- dlc->rd_mode = mode;
+ dlc->rd_mode = mode;
- if (dlc->rd_state == RFCOMM_DLC_OPEN)
- err = rfcomm_dlc_setmode(dlc);
+ if (dlc->rd_state == RFCOMM_DLC_OPEN)
+ err = rfcomm_dlc_setmode(dlc);
+ }
break;