Skip to content

Possible Buffer-Overflow when sending control messages with sendmmsg #2176

Open
@Jan561

Description

@Jan561
pub fn sendmmsg<'a, C, S>(
    // elided ...
    data: &'a mut MultiHeaders<S>,
    cmsgs: C,
) 
where
    C: AsRef<[ControlMessage<'a>]>,
{

    for mmsghdr in data.items.iter_mut().enumerate() {
        let p = &mut mmsghdr.msg_hdr;

        let mut pmhdr: *mut cmsghdr = unsafe { CMSG_FIRSTHDR(p) };
        for cmsg in cmsgs.as_ref() {
            assert_ne!(pmhdr, ptr::null_mut());

            // This is unsound: it relies on the caller having initialized the control
            // message buffer inside `data` with enough space for holding all
            // control messages inside `cmsgs`, i.e. having used the `cmsg_space!`
            // macro properly in conjunction with `MultiHeaders::preallocate`. Since
            // the macro, the constructor of `MultiHeaders` and this function are
            // all safe to call, unsafe code must not rely on this invariant to be
            // upheld by the caller.
            //
            // Even the above assertion won't catch this bug, as there might
            // be enough space left to send *a* control message, different from `cmsg`.
            //
            // Original comment:
            //
            // > Safe because we know that pmhdr is valid, and we initialized it with
            // > sufficient space

            unsafe { cmsg.encode_into(pmhdr) };

            pmhdr = unsafe { CMSG_NXTHDR(p, pmhdr) };
        }
    }

    // ...
}

The security impact of this issue is probably negligible, as

  • the control message buffer inside data must have a non-zero length and the majority of the users of this function just want to reduce the amount of syscalls and don't need control messages,
  • an attacker would have to be able to influence which control messages are being sent, which is a very odd and unlikely scenario, or the program must be buggy in first place and initialize the control message buffer too small.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions