From nobody Mon Feb 9 08:55:14 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) client-ip=205.139.110.120; envelope-from=libvir-list-bounces@redhat.com; helo=us-smtp-1.mimecast.com; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1579779846; cv=none; d=zohomail.com; s=zohoarc; b=ahGNgjhcmMj0g45tGA1D1WDuvWOEfjiaxJ6+6ip22xqcE3KyIzFi1HGiLxakqyxeJtkuQLduzXnb49ISBzFlnxuiJfWngUe7jodTvpOfQNYXkYrEYXEtlvEBawE9hnvcB4JH/OXqRen+gP5mIdbsvAlMiHflbi6hsGQlrWLMwIw= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1579779846; h=Content-Type:Content-Transfer-Encoding:Date:From:In-Reply-To:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:References:Sender:Subject:To; bh=6L62MJ1/1Bc9LxoUNjILbIC3nkIsMJvyxzz96rVMV0M=; b=GFsq3TG0lUKe3n/obg7sd+gMDRaAJN7Lpp7Jakr7nnJTR7iKk+tD5Qea1FQ7voD7Ule9d69VNsEReoKgXRhrAhN4QHkYFvKRoQdtiUryfFi79BSQvfqqLuxFATcMV3lwUUP3zzYuoiuFV13Azb3ZN7Earz8Vv3Zjdv8a3oR2Ptw= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of redhat.com designates 205.139.110.120 as permitted sender) smtp.mailfrom=libvir-list-bounces@redhat.com; dmarc=pass header.from= (p=none dis=none) header.from= Return-Path: Received: from us-smtp-1.mimecast.com (us-smtp-delivery-1.mimecast.com [205.139.110.120]) by mx.zohomail.com with SMTPS id 1579779846637407.6910006478789; Thu, 23 Jan 2020 03:44:06 -0800 (PST) Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-48-3MYtFdiDNeebq22wiSqwQg-1; Thu, 23 Jan 2020 06:44:03 -0500 Received: from smtp.corp.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.13]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 46054800D41; Thu, 23 Jan 2020 11:43:56 +0000 (UTC) Received: from colo-mx.corp.redhat.com (colo-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.20]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 1BE988CCD5; Thu, 23 Jan 2020 11:43:56 +0000 (UTC) Received: from lists01.pubmisc.prod.ext.phx2.redhat.com (lists01.pubmisc.prod.ext.phx2.redhat.com [10.5.19.33]) by colo-mx.corp.redhat.com (Postfix) with ESMTP id D09BE180887A; Thu, 23 Jan 2020 11:43:55 +0000 (UTC) Received: from smtp.corp.redhat.com (int-mx01.intmail.prod.int.phx2.redhat.com [10.5.11.11]) by lists01.pubmisc.prod.ext.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id 00NBhrDw025387 for ; Thu, 23 Jan 2020 06:43:53 -0500 Received: by smtp.corp.redhat.com (Postfix) id 2CD0685757; Thu, 23 Jan 2020 11:43:53 +0000 (UTC) Received: from domokun.gsslab.fab.redhat.com (unknown [10.33.8.110]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA8759CA3; Thu, 23 Jan 2020 11:43:51 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1579779845; h=from:from:sender:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references:list-id:list-help: list-unsubscribe:list-subscribe:list-post; bh=6L62MJ1/1Bc9LxoUNjILbIC3nkIsMJvyxzz96rVMV0M=; b=CXCjnr7Fo29+f40iwH9FEBziQliHUB3uvs5J7Ez0G6jRFZFMCU/cqwEuJNSSeICixH1Be/ Y4xXXN5SXuCS/JvxSZ52sMAu5vZS3f4w3Oc8fjhCivtHo9AP/XUUg9yNlRmMreaV8hbrWS +oZRTn5ptTQttrfS9GnoVNCz9+VIoSg= From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= To: libvir-list@redhat.com Subject: [libvirt PATCH 11/32] src: implement APIs for passing FDs over UNIX sockets Date: Thu, 23 Jan 2020 11:43:04 +0000 Message-Id: <20200123114325.3860881-12-berrange@redhat.com> In-Reply-To: <20200123114325.3860881-1-berrange@redhat.com> References: <20200123114325.3860881-1-berrange@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.11 X-loop: libvir-list@redhat.com X-BeenThere: libvir-list@redhat.com X-Mailman-Version: 2.1.12 Precedence: junk List-Id: Development discussions about the libvirt library & tools List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: libvir-list-bounces@redhat.com Errors-To: libvir-list-bounces@redhat.com X-Scanned-By: MIMEDefang 2.79 on 10.5.11.13 X-MC-Unique: 3MYtFdiDNeebq22wiSqwQg-1 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Transfer-Encoding: quoted-printable X-ZohoMail-DKIM: pass (identity @redhat.com) Content-Type: text/plain; charset="utf-8" This is a simplified variant of gnulib's passfd module without the portability code that we do not require. Signed-off-by: Daniel P. Berrang=C3=A9 Reviewed-by: Pavel Hrdina --- src/libvirt_private.syms | 5 ++ src/qemu/qemu_interface.c | 4 +- src/rpc/virnetsocket.c | 5 +- src/util/virfile.c | 5 +- src/util/virsocket.c | 142 +++++++++++++++++++++++++++++++++++++- src/util/virsocket.h | 3 + 6 files changed, 154 insertions(+), 10 deletions(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index fa046051a3..4fe93e785c 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -3004,6 +3004,11 @@ virSecretLookupFormatSecret; virSecretLookupParseSecret; =20 =20 +# util/virsocket.h +virSocketRecvFD; +virSocketSendFD; + + # util/virsocketaddr.h virSocketAddrBroadcast; virSocketAddrBroadcastByPrefix; diff --git a/src/qemu/qemu_interface.c b/src/qemu/qemu_interface.c index bb62b53c04..48bb0043fe 100644 --- a/src/qemu/qemu_interface.c +++ b/src/qemu/qemu_interface.c @@ -25,7 +25,6 @@ #include "domain_audit.h" #include "domain_nwfilter.h" #include "qemu_interface.h" -#include "passfd.h" #include "viralloc.h" #include "virlog.h" #include "virstring.h" @@ -34,6 +33,7 @@ #include "virnetdevmacvlan.h" #include "virnetdevbridge.h" #include "virnetdevvportprofile.h" +#include "virsocket.h" =20 #include #include @@ -347,7 +347,7 @@ qemuCreateInBridgePortWithHelper(virQEMUDriverConfigPtr= cfg, } =20 do { - *tapfd =3D recvfd(pair[0], 0); + *tapfd =3D virSocketRecvFD(pair[0], 0); } while (*tapfd < 0 && errno =3D=3D EINTR); =20 if (*tapfd < 0) { diff --git a/src/rpc/virnetsocket.c b/src/rpc/virnetsocket.c index 973827ebde..687099720f 100644 --- a/src/rpc/virnetsocket.c +++ b/src/rpc/virnetsocket.c @@ -56,7 +56,6 @@ #include "virprobe.h" #include "virprocess.h" #include "virstring.h" -#include "passfd.h" =20 #if WITH_SSH2 # include "virnetsshsession.h" @@ -2045,7 +2044,7 @@ int virNetSocketSendFD(virNetSocketPtr sock, int fd) virObjectLock(sock); PROBE(RPC_SOCKET_SEND_FD, "sock=3D%p fd=3D%d", sock, fd); - if (sendfd(sock->fd, fd) < 0) { + if (virSocketSendFD(sock->fd, fd) < 0) { if (errno =3D=3D EAGAIN) ret =3D 0; else @@ -2078,7 +2077,7 @@ int virNetSocketRecvFD(virNetSocketPtr sock, int *fd) } virObjectLock(sock); =20 - if ((*fd =3D recvfd(sock->fd, O_CLOEXEC)) < 0) { + if ((*fd =3D virSocketRecvFD(sock->fd, O_CLOEXEC)) < 0) { if (errno =3D=3D EAGAIN) ret =3D 0; else diff --git a/src/util/virfile.c b/src/util/virfile.c index b3a63fa2ea..51a0d40b50 100644 --- a/src/util/virfile.c +++ b/src/util/virfile.c @@ -25,7 +25,6 @@ #include #include "internal.h" =20 -#include #include #ifndef WIN32 # include @@ -2268,7 +2267,7 @@ virFileOpenForked(const char *path, int openflags, mo= de_t mode, } =20 do { - ret =3D sendfd(pair[1], fd); + ret =3D virSocketSendFD(pair[1], fd); } while (ret < 0 && errno =3D=3D EINTR); =20 if (ret < 0) { @@ -2302,7 +2301,7 @@ virFileOpenForked(const char *path, int openflags, mo= de_t mode, VIR_FORCE_CLOSE(pair[1]); =20 do { - fd =3D recvfd(pair[0], 0); + fd =3D virSocketRecvFD(pair[0], 0); } while (fd < 0 && errno =3D=3D EINTR); VIR_FORCE_CLOSE(pair[0]); /* NB: this preserves errno */ if (fd < 0) diff --git a/src/util/virsocket.c b/src/util/virsocket.c index 96b9ece2b7..0e3775ac44 100644 --- a/src/util/virsocket.c +++ b/src/util/virsocket.c @@ -19,10 +19,12 @@ #include =20 #include "virsocket.h" +#include "virutil.h" +#include "virfile.h" =20 -#ifdef WIN32 +#include =20 -# include +#ifdef WIN32 =20 # define FD2SK(fd) _get_osfhandle(fd) # define SK2FD(sk) (_open_osfhandle((intptr_t) (sk), O_RDWR | O_BINARY)) @@ -365,3 +367,139 @@ vir_socket(int domain, int type, int protocol) } =20 #endif /* WIN32 */ + +/* The code that uses CMSG_FIRSTHDR is enabled on + Linux, Mac OS X, FreeBSD, OpenBSD, NetBSD, AIX, OSF/1, Cygwin. + The code that uses HAVE_STRUCT_MSGHDR_MSG_ACCRIGHTS is enabled on + HP-UX, IRIX, Solaris. */ + +/* MSG_CMSG_CLOEXEC is defined only on Linux, as of 2011. */ +#ifndef MSG_CMSG_CLOEXEC +# define MSG_CMSG_CLOEXEC 0 +#endif + +#ifndef WIN32 +/* virSocketSendFD sends the file descriptor fd along the socket + to a process calling recvfd on the other end. + + Return 0 on success, or -1 with errno set in case of error. +*/ +int +virSocketSendFD(int sock, int fd) +{ + char byte =3D 0; + struct iovec iov; + struct msghdr msg; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(sizeof(fd))]; + + /* send at least one char */ + memset(&msg, 0, sizeof(msg)); + iov.iov_base =3D &byte; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_name =3D NULL; + msg.msg_namelen =3D 0; + + msg.msg_control =3D buf; + msg.msg_controllen =3D sizeof(buf); + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(fd)); + /* Initialize the payload: */ + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + msg.msg_controllen =3D cmsg->cmsg_len; + + if (sendmsg(sock, &msg, 0) !=3D iov.iov_len) + return -1; + return 0; +} +#else +int +virSocketSendFD(int sock G_GNUC_UNUSED, int fd G_GNUC_UNUSED) +{ + errno =3D ENOSYS; + return -1; +} +#endif + + +#ifndef WIN32 +/* virSocketRecvFD receives a file descriptor through the socket. + The flags are a bitmask, possibly including O_CLOEXEC (defined in ). + + Return the fd on success, or -1 with errno set in case of error. +*/ +int +virSocketRecvFD(int sock, int fdflags) +{ + char byte =3D 0; + struct iovec iov; + struct msghdr msg; + int fd =3D -1; + ssize_t len; + struct cmsghdr *cmsg; + char buf[CMSG_SPACE(sizeof(fd))]; + int fdflags_recvmsg =3D fdflags & O_CLOEXEC ? MSG_CMSG_CLOEXEC : 0; + + if ((fdflags & ~O_CLOEXEC) !=3D 0) { + errno =3D EINVAL; + return -1; + } + + /* send at least one char */ + memset(&msg, 0, sizeof(msg)); + iov.iov_base =3D &byte; + iov.iov_len =3D 1; + msg.msg_iov =3D &iov; + msg.msg_iovlen =3D 1; + msg.msg_name =3D NULL; + msg.msg_namelen =3D 0; + + msg.msg_control =3D buf; + msg.msg_controllen =3D sizeof(buf); + cmsg =3D CMSG_FIRSTHDR(&msg); + cmsg->cmsg_level =3D SOL_SOCKET; + cmsg->cmsg_type =3D SCM_RIGHTS; + cmsg->cmsg_len =3D CMSG_LEN(sizeof(fd)); + /* Initialize the payload: */ + memcpy(CMSG_DATA(cmsg), &fd, sizeof(fd)); + msg.msg_controllen =3D cmsg->cmsg_len; + + len =3D recvmsg(sock, &msg, fdflags_recvmsg); + if (len < 0) + return -1; + + cmsg =3D CMSG_FIRSTHDR(&msg); + /* be paranoiac */ + if (len =3D=3D 0 || cmsg =3D=3D NULL || cmsg->cmsg_len !=3D CMSG_LEN(s= izeof(fd)) + || cmsg->cmsg_level !=3D SOL_SOCKET || cmsg->cmsg_type !=3D SCM_RI= GHTS) { + /* fake errno: at end the file is not available */ + errno =3D len ? EACCES : ENOTCONN; + return -1; + } + + memcpy(&fd, CMSG_DATA(cmsg), sizeof(fd)); + + /* set close-on-exec flag */ + if (!MSG_CMSG_CLOEXEC && (fdflags & O_CLOEXEC)) { + if (virSetCloseExec(fd) < 0) { + int saved_errno =3D errno; + VIR_FORCE_CLOSE(fd); + errno =3D saved_errno; + return -1; + } + } + + return fd; +} +#else +int +virSocketRecvFD(int sock G_GNUC_UNUSED, int fdflags G_GNUC_UNUSED) +{ + errno =3D ENOSYS; + return -1; +} +#endif diff --git a/src/util/virsocket.h b/src/util/virsocket.h index 33f237886f..e1e7d08bb4 100644 --- a/src/util/virsocket.h +++ b/src/util/virsocket.h @@ -20,6 +20,9 @@ =20 #include "internal.h" =20 +int virSocketSendFD(int sock, int fd); +int virSocketRecvFD(int sock, int fdflags); + #ifdef WIN32 =20 # define WIN32_LEAN_AND_MEAN --=20 2.24.1