Commit 1f3a4519 authored by Tiwei Bie's avatar Tiwei Bie Committed by Michael S. Tsirkin
Browse files

vhost-user: support receiving file descriptors in slave_read

parent 703878e2
Loading
Loading
Loading
Loading
+40 −1
Original line number Diff line number Diff line
@@ -852,14 +852,44 @@ static void slave_read(void *opaque)
    VhostUserHeader hdr = { 0, };
    VhostUserPayload payload = { 0, };
    int size, ret = 0;
    struct iovec iov;
    struct msghdr msgh;
    int fd = -1;
    char control[CMSG_SPACE(sizeof(fd))];
    struct cmsghdr *cmsg;
    size_t fdsize;

    memset(&msgh, 0, sizeof(msgh));
    msgh.msg_iov = &iov;
    msgh.msg_iovlen = 1;
    msgh.msg_control = control;
    msgh.msg_controllen = sizeof(control);

    /* Read header */
    size = read(u->slave_fd, &hdr, VHOST_USER_HDR_SIZE);
    iov.iov_base = &hdr;
    iov.iov_len = VHOST_USER_HDR_SIZE;

    size = recvmsg(u->slave_fd, &msgh, 0);
    if (size != VHOST_USER_HDR_SIZE) {
        error_report("Failed to read from slave.");
        goto err;
    }

    if (msgh.msg_flags & MSG_CTRUNC) {
        error_report("Truncated message.");
        goto err;
    }

    for (cmsg = CMSG_FIRSTHDR(&msgh); cmsg != NULL;
         cmsg = CMSG_NXTHDR(&msgh, cmsg)) {
            if (cmsg->cmsg_level == SOL_SOCKET &&
                cmsg->cmsg_type == SCM_RIGHTS) {
                    fdsize = cmsg->cmsg_len - CMSG_LEN(0);
                    memcpy(&fd, CMSG_DATA(cmsg), fdsize);
                    break;
            }
    }

    if (hdr.size > VHOST_USER_PAYLOAD_SIZE) {
        error_report("Failed to read msg header."
                " Size %d exceeds the maximum %zu.", hdr.size,
@@ -883,9 +913,15 @@ static void slave_read(void *opaque)
        break;
    default:
        error_report("Received unexpected msg type.");
        if (fd != -1) {
            close(fd);
        }
        ret = -EINVAL;
    }

    /* Message handlers need to make sure that fd will be consumed. */
    fd = -1;

    /*
     * REPLY_ACK feature handling. Other reply types has to be managed
     * directly in their request handlers.
@@ -918,6 +954,9 @@ err:
    qemu_set_fd_handler(u->slave_fd, NULL, NULL, NULL);
    close(u->slave_fd);
    u->slave_fd = -1;
    if (fd != -1) {
        close(fd);
    }
    return;
}