summaryrefslogtreecommitdiff
path: root/sys/netbt/hci_socket.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/hci_socket.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/hci_socket.c')
-rw-r--r--sys/netbt/hci_socket.c43
1 files changed, 30 insertions, 13 deletions
diff --git a/sys/netbt/hci_socket.c b/sys/netbt/hci_socket.c
index ca5aa5f14a3..d9d161cd185 100644
--- a/sys/netbt/hci_socket.c
+++ b/sys/netbt/hci_socket.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: hci_socket.c,v 1.7 2008/11/22 04:42:58 uwe Exp $ */
+/* $OpenBSD: hci_socket.c,v 1.8 2009/11/21 13:05:32 guenther Exp $ */
/* $NetBSD: hci_socket.c,v 1.17 2008/08/06 15:01:24 plunky Exp $ */
/*-
@@ -755,10 +755,11 @@ hci_ctloutput(int req, struct socket *so, int level,
if (pcb == NULL)
return EINVAL;
- if (level != BTPROTO_HCI)
- return ENOPROTOOPT;
-
- switch(req) {
+ if (level != BTPROTO_HCI) {
+ err = EINVAL;
+ if (req == PRCO_SETOPT && *opt)
+ m_free(*opt);
+ } else switch(req) {
case PRCO_GETOPT:
m = m_get(M_WAIT, MT_SOOPTS);
switch (optname) {
@@ -793,20 +794,36 @@ hci_ctloutput(int req, struct socket *so, int level,
m = *opt;
if (m) switch (optname) {
case SO_HCI_EVT_FILTER: /* set event filter */
- m->m_len = min(m->m_len, sizeof(struct hci_filter));
- memcpy(&pcb->hp_efilter, mtod(m, void *), m->m_len);
+ if (m == NULL || m->m_len > sizeof(struct hci_filter))
+ err = EINVAL;
+ else {
+ memcpy(&pcb->hp_efilter, mtod(m, void *),
+ m->m_len);
+ memset((char *)&pcb->hp_efilter + m->m_len,
+ 0, sizeof(struct hci_filter) - m->m_len);
+ }
break;
case SO_HCI_PKT_FILTER: /* set packet filter */
- m->m_len = min(m->m_len, sizeof(struct hci_filter));
- memcpy(&pcb->hp_pfilter, mtod(m, void *), m->m_len);
+ if (m == NULL || m->m_len > sizeof(struct hci_filter))
+ err = EINVAL;
+ else {
+ memcpy(&pcb->hp_pfilter, mtod(m, void *),
+ m->m_len);
+ memset((char *)&pcb->hp_pfilter + m->m_len,
+ 0, sizeof(struct hci_filter) - m->m_len);
+ }
break;
case SO_HCI_DIRECTION: /* request direction ctl messages */
- if (*mtod(m, int *))
- pcb->hp_flags |= HCI_DIRECTION;
- else
- pcb->hp_flags &= ~HCI_DIRECTION;
+ if (m == NULL || m->m_len != sizeof(int))
+ err = EINVAL;
+ else {
+ if (*mtod(m, int *))
+ pcb->hp_flags |= HCI_DIRECTION;
+ else
+ pcb->hp_flags &= ~HCI_DIRECTION;
+ }
break;
default: