Synopsis: Insufficient msg_controllen checking for sendmsg(2)
NetBSD versions: NetBSD-current (NetBSD 1.5A to July 1, 2001)
Thanks to: Jaromir Dolecek and Matt Thomas
Reported in NetBSD Security Advisory: NetBSD-SA2001-011


Index: sys/kern/uipc_syscalls.c
===================================================================
RCS file: /cvsroot/syssrc/sys/kern/uipc_syscalls.c,v
retrieving revision 1.63
retrieving revision 1.64
diff -p -p -c -r1.63 -r1.64
*** sys/kern/uipc_syscalls.c    2001/06/25 20:46:13     1.63
--- sys/kern/uipc_syscalls.c    2001/07/01 20:42:48     1.64
*************** sys_getpeername(struct proc *p, void *v,
*** 1068,1074 ****
  * XXX arguments in mbufs, and this could go away.
  */
 int
! sockargs(struct mbuf **mp, const void *buf, int buflen, int type)
 {
       struct sockaddr *sa;
       struct mbuf     *m;
--- 1068,1074 ----
  * XXX arguments in mbufs, and this could go away.
  */
 int
! sockargs(struct mbuf **mp, const void *buf, size_t buflen, int type)
 {
       struct sockaddr *sa;
       struct mbuf     *m;
*************** sockargs(struct mbuf **mp, const void *b
*** 1076,1089 ****

       /*
        * We can't allow socket names > UCHAR_MAX in length, since that
!        * will overflow sa_len.
        */
!       if (type == MT_SONAME && (u_int)buflen > UCHAR_MAX)
               return (EINVAL);

       /* Allocate an mbuf to hold the arguments. */
       m = m_get(M_WAIT, type);
!       if ((u_int)buflen > MLEN) {
               /*
                * Won't fit into a regular mbuf, so we allocate just
                * enough external storage to hold the argument.
--- 1076,1090 ----

       /*
        * We can't allow socket names > UCHAR_MAX in length, since that
!        * will overflow sa_len.  Control data more than a page size in
!        * length is just too much.
        */
!       if (buflen > (type == MT_SONAME ? UCHAR_MAX : PAGE_SIZE))
               return (EINVAL);

       /* Allocate an mbuf to hold the arguments. */
       m = m_get(M_WAIT, type);
!       if (buflen > MLEN) {
               /*
                * Won't fit into a regular mbuf, so we allocate just
                * enough external storage to hold the argument.
*************** sockargs(struct mbuf **mp, const void *b
*** 1091,1097 ****
               MEXTMALLOC(m, buflen, M_WAITOK);
       }
       m->m_len = buflen;
!       error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
       if (error) {
               (void) m_free(m);
               return (error);
--- 1092,1098 ----
               MEXTMALLOC(m, buflen, M_WAITOK);
       }
       m->m_len = buflen;
!       error = copyin(buf, mtod(m, caddr_t), buflen);
       if (error) {
               (void) m_free(m);
               return (error);