Subject: Re: cleaning up the rest of dtom()
To: enami tsugutomo <enami@ba2.so-net.or.jp>
From: Jason Thorpe <thorpej@nas.nasa.gov>
List: tech-kern
Date: 06/25/1997 00:05:17
On 25 Jun 1997 07:53:59 +0900 
 enami tsugutomo <enami@ba2.so-net.or.jp> wrote:

 > Or is there any arch on which mbuf length is less than 128 byte?  Hmm,
 > or is there arch on which sizeof sockaddr_un becomes 108 byte by some
 > alignment matter...?

Ok... I took a look at this problem ...This should also deal with the
COMPAT_OLDSOCK case where the sockaddr can legitimately be larger than
an mbuf...

What do you think of the patch?

Jason R. Thorpe                                       thorpej@nas.nasa.gov
NASA Ames Research Center                               Home: 408.866.1912
NAS: M/S 258-6                                          Work: 415.604.0935
Moffett Field, CA 94035                                Pager: 415.428.6939

Index: uipc_syscalls.c
===================================================================
RCS file: /mastersrc/netbsd/src/sys/kern/uipc_syscalls.c,v
retrieving revision 1.1.1.6
diff -c -r1.1.1.6 uipc_syscalls.c
*** uipc_syscalls.c	1997/01/07 01:20:13	1.1.1.6
--- uipc_syscalls.c	1997/06/25 06:51:21
***************
*** 968,973 ****
--- 968,977 ----
  	return (error);
  }
  
+ /*
+  * XXX In a perfect world, we wouldn't pass around socket control
+  * XXX arguments in mbufs, and this could go away.
+  */
  int
  sockargs(mp, buf, buflen, type)
  	struct mbuf **mp;
***************
*** 978,992 ****
  	register struct mbuf *m;
  	int error;
  
! 	if ((u_int)buflen > MLEN) {
! #ifdef COMPAT_OLDSOCK
! 		if (type == MT_SONAME && (u_int)buflen <= 112)
! 			buflen = MLEN;		/* unix domain compat. hack */
! 		else
! #endif
! 		return (EINVAL);
! 	}
  	m = m_get(M_WAIT, type);
  	m->m_len = buflen;
  	error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
  	if (error) {
--- 982,1004 ----
  	register struct mbuf *m;
  	int error;
  
! 	/*
! 	 * Allocate an mbuf to hold the arguments.
! 	 *
! 	 * XXX We have to allow for one extra byte, so that
! 	 * we can ensure nul-termination of the pathname for
! 	 * unix domain sockets.
! 	 */
  	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.
+ 		 */
+ 		MEXTMALLOC(m, buflen + 1, M_WAITOK);
+ 		if ((m->m_flags & M_EXT) == 0)
+ 			return (ENOMEM);
+ 	}
  	m->m_len = buflen;
  	error = copyin(buf, mtod(m, caddr_t), (u_int)buflen);
  	if (error) {
Index: uipc_usrreq.c
===================================================================
RCS file: /mastersrc/netbsd/src/sys/kern/uipc_usrreq.c,v
retrieving revision 1.1.1.7
diff -c -r1.1.1.7 uipc_usrreq.c
*** uipc_usrreq.c	1997/06/24 21:51:44	1.1.1.7
--- uipc_usrreq.c	1997/06/25 06:58:37
***************
*** 419,435 ****
  	int error;
  	struct nameidata nd;
  
- 	if (nam->m_len > sizeof(struct sockaddr_un))
- 		return (EINVAL);
  	if (unp->unp_vnode != 0)
  		return (EINVAL);
  	NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
  	    sun->sun_path, p);
! 	if (nam->m_data + nam->m_len == &nam->m_dat[MLEN]) {	/* XXX */
! 		if (*(mtod(nam, caddr_t) + nam->m_len - 1) != 0)
! 			return (EINVAL);
! 	} else
! 		*(mtod(nam, caddr_t) + nam->m_len) = 0;
  /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
  	if ((error = namei(&nd)) != 0)
  		return (error);
--- 419,434 ----
  	int error;
  	struct nameidata nd;
  
  	if (unp->unp_vnode != 0)
  		return (EINVAL);
  	NDINIT(&nd, CREATE, FOLLOW | LOCKPARENT, UIO_SYSSPACE,
  	    sun->sun_path, p);
! 	/*
! 	 * Ensure that the pathname is nul-terminated.  An extra byte
! 	 * was set aside in sockargs() for this purpose.
! 	 */
! 	*(mtod(nam, caddr_t) + nam->m_len) = '\0';
! 
  /* SHOULD BE ABLE TO ADOPT EXISTING AND wakeup() ALA FIFO's */
  	if ((error = namei(&nd)) != 0)
  		return (error);