Subject: Difference between sys_recvmsg and netbsd32_recvmsg
To: NetBSD Kernel <tech-kern@NetBSD.org>
From: Markus Mayer <mmayer@redback.com>
List: tech-kern
Date: 05/31/2007 13:46:01
We noticed a difference between sys_recvmsg() in kern/uipc_syscalls.c 
and netbsd32_recvmsg() in compat/netbsd32/netbsd32_socket.c. We noticed 
this in NetBSD 3.0, but it looks like NetBSD-current still has the same 
difference.

It seems to be causing problems for the 32 bit TFTP server running under 
a 64 bit kernel (using a 64 bit TFTP server *might* be an option, but 
that would be a work-around).

sys_recvmsg() checks if msg_iovlen is greater than 0, but doesn't issue 
an error if it's not and continues right on.

	if ((unsigned int)msg.msg_iovlen > UIO_SMALLIOV) {
		if ((unsigned int)msg.msg_iovlen > IOV_MAX)
			return (EMSGSIZE);
		iov = malloc(sizeof(struct iovec) * msg.msg_iovlen,
		    M_IOV, M_WAITOK);
	} else
		iov = aiov;
	if ((unsigned int)msg.msg_iovlen > 0) {
		error = copyin((caddr_t)msg.msg_iov, (caddr_t)iov,
		    (size_t)(msg.msg_iovlen * sizeof(struct iovec)));
		if (error)
			goto done;
	}

netbsd32_recvmsg() does that check as well, but issues an EMSGSIZE if 
msg_iovlen happens to be 0.

	if ((u_int)msg.msg_iovlen > UIO_SMALLIOV) {
		if ((u_int)msg.msg_iovlen > IOV_MAX)
			return (EMSGSIZE);
		MALLOC(iov, struct iovec *,
		    sizeof(struct iovec) * (u_int)msg.msg_iovlen, M_IOV,
		    M_WAITOK);
	} else if ((u_int)msg.msg_iovlen > 0)
		iov = aiov;
	else
		return (EMSGSIZE);

I thinking the two functions should behave more alike. Can't 
netbsd32_recvmsg() just skip over the netbsd32_to_iovecin() call like 
sys_recvmsg() skips over copyin() if msg.msg_iovlen == 0 and keep going 
otherwise?

Thanks,
-Markus

-- 
Markus Mayer
Redback Networks Inc.
(604) 629-7251