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);
