Control messages may be lost in some cases: if copyout() fails, or if
the receiving process does not supply sufficient buffer space. In the
process of externalizing these control messages, their data may now
reference kernel resources; if these references cannot be transferred to
the recipient, they must be properly disposed of. This occurs
specifically when transmitting SCM_RIGHTS messages over a unix socket,
and results in a file descriptor leak when the control message mbuf
chain is freed.
Fix the problem using a new function, m_dispose_extcontrolm(), which is
responsible for releasing any resources contained in an externalized
control message. Such messages are stored in mbufs with a distinguished
type; once the resources are disposed, the type changes back to
MT_CONTROL. Right now, the only source of MT_EXTCONTROL messages will
use a separate mbuf for each control message, but
m_dispose_extcontrolm() attempts to handle multiple control messages in
a single mbuf.
If an externalized message would be truncated part way through, drop the
whole message. This makes disposal much simpler and follows NetBSD's
behaviour. I can't see any reason to try a partial copy as we do today,
and it would be tricky to support that.
Also fix a related bug in kern_recvit(): if truncation happens at an
mbuf boundary, we were failing to set MSG_CTRUNC.