I first discovered this by running dovecot2 from pkgsrc, and got the
following errors:

dovecot: imap-login: Error: fd_send(imap, 20) failed: Invalid argument

After some discussion on IRC, we came to the conclusion that something
isn't right with the CMSG macros on 64-bit systems.

Venkatesh Srinivas wrote a test program that I've attached to this email
that prints "hello" on 32-bit, and loops forever on 64-bit.

--Peter
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <errno.h>

main(argc, argv)
        int argc;
        char **argv;
{
        int i;
        int j[2];

        socketpair(AF_UNIX, SOCK_STREAM, 0, j);

        i = fork();
        if (i == 0) {
                close(0);
                close(1);
                close(2);

                int mysecretfd = recvfd(j[0]);
                write(mysecretfd, "hello\n", 7);
        } else {
                sendfd(j[1], 1);

                pause();
        }

}

int
sendfd(int s, int fd)
{
        char buf[1];
        struct iovec iov;
        struct msghdr msg;
        struct cmsghdr *cmsg;
        int n;
        char cms[CMSG_SPACE(sizeof(int))];
        
        buf[0] = 0;
        iov.iov_base = buf;
        iov.iov_len = 1;

        memset(&msg, 0, sizeof msg);
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;
        msg.msg_control = (caddr_t)cms;
        msg.msg_controllen = CMSG_LEN(sizeof(int));

        cmsg = CMSG_FIRSTHDR(&msg);
        cmsg->cmsg_len = CMSG_LEN(sizeof(int));
        cmsg->cmsg_level = SOL_SOCKET;
        cmsg->cmsg_type = SCM_RIGHTS;
        memmove(CMSG_DATA(cmsg), &fd, sizeof(int));

        if((n=sendmsg(s, &msg, 0)) != iov.iov_len)
                return -1;
        return 0;
}

int
recvfd(int s)
{
        int n;
        int fd;
        char buf[1];
        struct iovec iov;
        struct msghdr msg;
        struct cmsghdr *cmsg;
        char cms[CMSG_SPACE(sizeof(int))];

        iov.iov_base = buf;
        iov.iov_len = 1;

        memset(&msg, 0, sizeof msg);
        msg.msg_name = 0;
        msg.msg_namelen = 0;
        msg.msg_iov = &iov;
        msg.msg_iovlen = 1;

        msg.msg_control = (caddr_t)cms;
        msg.msg_controllen = sizeof cms;

        if((n=recvmsg(s, &msg, 0)) < 0)
                return -1;
        if(n == 0){
                return -1;
        }
        cmsg = CMSG_FIRSTHDR(&msg);
        memmove(&fd, CMSG_DATA(cmsg), sizeof(int));
        return fd;
}

Attachment: pgpRTUqB5dWGi.pgp
Description: PGP signature

  • FD passing on 64-bit is h... Peter Avalos

Reply via email to