Subject: bug in passing file descriptors

From: Steve Rago <[email-masked]>
Date: Mon, 7 Oct 2013 14:27:55 -0400

Sending this to a larger group at mtk's suggestion.

I recently found a bug with passing file descriptors over Unix domain sockets.  The attached program illustrates the 
problem.  I believe the source of the problem is in net/core/scm.c.  In put_cmsg(), cmlen is calculated as 
CMSG_SPACE(len) for the purposes of setting msg_controllen, but it probably should be CMSG_LEN(len), at least in this 
particular case (I didn't investigate other use cases).  On a 32-bit platform, a long is a 4-byte quantity and the file 
descriptor is already aligned to a 4-byte quantity by placing it after the cmsghdr structure.  On a 64-byte platform, 
however, a long is an 8-byte quantity, and CMSG_SPACE() assumes that len is aligned on an 8-byte boundary, which isn't a 
requirement for passing file descriptors (which are 4-byte quantities; see scm_fp_copy() to verify).  Anyway, the end 
result is that recvmsg(2) returns with msg_controllen 4 bytes larger than it should be on a 64-bit platform.  The 
attached program prints out a warning message when this happens.

I've tried this on kernels as old as 2.6.18, so it appears this bug has been around for a while.  I originally found it 
on a 3.2.0 kernel.  Michael verified it still exists on a 3.11 kernel.

Let me know if you need any more information

Steve Rago
[email-masked]