The inflight fd code is guarded by #ifdef MFD_ALLOW_SEALING, which only
tells us that the headers define the flag, not that memfd_create() is
available in the C library. There are environments where the flag is
defined but the link fails:

  ld: error: libvhost-user.a(libvhost-user.c.o): undefined symbol: memfd_create

Probe for memfd_create() with MFD_ALLOW_SEALING in the subproject's
meson.build, using the same test QEMU's top-level meson.build uses for
CONFIG_MEMFD, and guard the code with CONFIG_MEMFD instead.

When memfd is not available, VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD is
masked out as before, so the frontend never sends
VHOST_USER_GET_INFLIGHT_FD.

Signed-off-by: Tim Pambor <[email protected]>
---
 subprojects/libvhost-user/libvhost-user.c | 17 ++++++++---------
 subprojects/libvhost-user/meson.build     | 11 ++++++++++-
 2 files changed, 18 insertions(+), 10 deletions(-)

diff --git a/subprojects/libvhost-user/libvhost-user.c 
b/subprojects/libvhost-user/libvhost-user.c
index 7ce73fba19..32b7ae82ce 100644
--- a/subprojects/libvhost-user/libvhost-user.c
+++ b/subprojects/libvhost-user/libvhost-user.c
@@ -85,7 +85,7 @@ int eventfd_read(int fd, eventfd_t *value)
 }
 #endif
 
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
 #include <fcntl.h>
 
 #ifndef F_LINUX_SPECIFIC_BASE
@@ -1963,13 +1963,12 @@ vu_get_protocol_features_exec(VuDev *dev, VhostUserMsg 
*vmsg)
         features |= dev->iface->get_protocol_features(dev);
     }
 
-#ifndef MFD_ALLOW_SEALING
+#ifndef CONFIG_MEMFD
     /*
-     * If MFD_ALLOW_SEALING is not defined, we are not able to handle
-     * VHOST_USER_GET_INFLIGHT_FD messages, since we can't create a memfd.
-     * Those messages are used only if VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD
-     * is negotiated. A device implementation can enable it, so let's mask
-     * it to avoid a runtime panic.
+     * Without memfd we are not able to handle VHOST_USER_GET_INFLIGHT_FD
+     * messages. Those messages are used only if
+     * VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD is negotiated. A device
+     * implementation can enable it, so let's mask it to avoid a runtime panic.
      */
     features &= ~(1ULL << VHOST_USER_PROTOCOL_F_INFLIGHT_SHMFD);
 #endif
@@ -2164,7 +2163,7 @@ vu_inflight_queue_size(uint16_t queue_size)
            sizeof(uint16_t), INFLIGHT_ALIGNMENT);
 }
 
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
 static void *
 memfd_alloc(const char *name, size_t size, unsigned int flags, int *fd)
 {
@@ -2231,7 +2230,7 @@ vu_get_inflight_fd(VuDev *dev, VhostUserMsg *vmsg)
 
     mmap_size = vu_inflight_queue_size(queue_size) * num_queues;
 
-#ifdef MFD_ALLOW_SEALING
+#ifdef CONFIG_MEMFD
     addr = memfd_alloc("vhost-inflight", mmap_size,
                        F_SEAL_GROW | F_SEAL_SHRINK | F_SEAL_SEAL,
                        &fd);
diff --git a/subprojects/libvhost-user/meson.build 
b/subprojects/libvhost-user/meson.build
index a18014e7f2..aa5894a642 100644
--- a/subprojects/libvhost-user/meson.build
+++ b/subprojects/libvhost-user/meson.build
@@ -11,10 +11,19 @@ 
add_project_arguments(cc.get_supported_arguments('-Wsign-compare',
 threads = dependency('threads')
 glib = dependency('glib-2.0')
 
+vhost_user_flags = ['-D_GNU_SOURCE']
+
+if cc.links('''
+    #define _GNU_SOURCE
+    #include <sys/mman.h>
+    int main(void) { return memfd_create("foo", MFD_ALLOW_SEALING); }''')
+  vhost_user_flags += '-DCONFIG_MEMFD'
+endif
+
 vhost_user = static_library('vhost-user',
                             files('libvhost-user.c'),
                             dependencies: threads,
-                            c_args: '-D_GNU_SOURCE')
+                            c_args: vhost_user_flags)
 
 executable('link-test', files('link-test.c'),
            link_whole: vhost_user)

-- 
2.55.0


Reply via email to