git: c596dc64da6d - main - net/ucx: Improve FreeBSD ucx_vfs support

Laurent Chardon <[email protected]> Thu, 06 Aug 2026 11:21:08 +0000
Newsgroups gmane.os.freebsd.devel.cvs.ports
Message-ID <6a746e24.30923.15bff24e__27563.9246728801$1786015308$gmane$org@gitrepo.freebsd.org>
The branch main has been updated by laurent:

URL: https://cgit.FreeBSD.org/ports/commit/?id=c596dc64da6d3142ba5c9a6ea1fdbebc4e9bf3e1

commit c596dc64da6d3142ba5c9a6ea1fdbebc4e9bf3e1
Author:     GenericRikka <[email protected]>
AuthorDate: 2026-08-06 11:09:06 +0000
Commit:     Laurent Chardon <[email protected]>
CommitDate: 2026-08-06 11:19:32 +0000

    net/ucx: Improve FreeBSD ucx_vfs support
    
    - replace Linux-specific fusermount3 with mount_fusefs/umount
    - use FreeBSD-compatible FUSE capability detection
    - fix UNIX socket ancillary data handling for SCM_RIGHTS and peer
      credentials on FreeBSD
    
    This allows ucx_vfs to start and communicate correctly on FreeBSD.
    
    PR:             297093
    Reported-by:    Laurent Chardon <[email protected]>
    Reviewed by:    thierry (mentor)
    Approved by:    thierry (mentor)
---
 net/ucx/Makefile                                 |   4 +-
 net/ucx/files/patch-src_tools_vfs_vfs__daemon.h  |  17 +++
 net/ucx/files/patch-src_tools_vfs_vfs__main.c    |  75 ++++++++++
 net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c | 178 ++++++++++++++++++-----
 net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.h |  14 ++
 5 files changed, 245 insertions(+), 43 deletions(-)

diff --git a/net/ucx/Makefile b/net/ucx/Makefile
index 6c67495d9c7e..e1b35a6a76ec 100644
--- a/net/ucx/Makefile
+++ b/net/ucx/Makefile
@@ -1,6 +1,6 @@
 PORTNAME=		ucx
 DISTVERSION=		1.20.1
-PORTREVISION=		3
+PORTREVISION=		4
 CATEGORIES=		net
 MASTER_SITES=		https://github.com/openucx/ucx/releases/download/v${DISTVERSION}/
 
@@ -59,8 +59,6 @@ UMAD_CONFIGURE_OFF=	--with-mad=no
 post-patch:
 	${REINPLACE_CMD} 's|^examplesdir = $$(pkgdatadir)/examples$$|examplesdir = ${EXAMPLESDIR}|' \
 		${WRKSRC}/examples/Makefile.am
-	${REINPLACE_CMD} 's|/run/user|/var/run/user|' \
-		${WRKSRC}/src/ucs/vfs/sock/vfs_sock.h
 
 post-install:
 	${MV} ${STAGEDIR}${ETCDIR}/ucx.conf ${STAGEDIR}${ETCDIR}/ucx.conf.sample
diff --git a/net/ucx/files/patch-src_tools_vfs_vfs__daemon.h b/net/ucx/files/patch-src_tools_vfs_vfs__daemon.h
new file mode 100644
index 000000000000..eb7b0ef92f9a
--- /dev/null
+++ b/net/ucx/files/patch-src_tools_vfs_vfs__daemon.h
@@ -0,0 +1,17 @@
+--- src/tools/vfs/vfs_daemon.h.orig	2026-08-01 18:29:37 UTC
++++ src/tools/vfs/vfs_daemon.h
+@@ -17,7 +17,13 @@
+ 
+ 
+ #define VFS_DEFAULT_MOUNTPOINT_DIR "/tmp/ucx"
+-#define VFS_FUSE_MOUNT_PROG        "fusermount3"
++#ifdef __FreeBSD__
++#  define VFS_FUSE_MOUNT_PROG   "/sbin/mount_fusefs"
++#  define VFS_FUSE_UNMOUNT_PROG "/sbin/umount"
++#else
++#  define VFS_FUSE_MOUNT_PROG   "fusermount3"
++#  define VFS_FUSE_UNMOUNT_PROG "fusermount3"
++#endif
+ 
+ 
+ enum {
diff --git a/net/ucx/files/patch-src_tools_vfs_vfs__main.c b/net/ucx/files/patch-src_tools_vfs_vfs__main.c
new file mode 100644
index 000000000000..1af1720cf5be
--- /dev/null
+++ b/net/ucx/files/patch-src_tools_vfs_vfs__main.c
@@ -0,0 +1,75 @@
+--- src/tools/vfs/vfs_main.c.orig	2026-08-04 01:14:50 UTC
++++ src/tools/vfs/vfs_main.c
+@@ -37,7 +37,7 @@ static struct sockaddr_un g_sockaddr;
+ static struct sockaddr_un g_sockaddr;
+ 
+ 
+-static int vfs_run_fusermount(char **extra_argv)
++static int vfs_run_fusermount(const char *program, char **extra_argv, int add_quiet_option)
+ {
+     char command[128];
+     pid_t child_pid;
+@@ -48,8 +48,8 @@ static int vfs_run_fusermount(char **extra_argv)
+     int i, argc;
+ 
+     argc         = 0;
+-    argv[argc++] = VFS_FUSE_MOUNT_PROG;
+-    if (!g_opts.verbose) {
++    argv[argc++] = (char*)program;
++    if (add_quiet_option && !g_opts.verbose) {
+         argv[argc++] = "-q";
+     }
+     while (*extra_argv != NULL) {
+@@ -223,7 +223,11 @@ int vfs_unmount(int pid)
+ int vfs_unmount(int pid)
+ {
+     char *mountpoint;
++#ifdef __FreeBSD__
++    char *argv[2];
++#else
+     char *argv[5];
++#endif
+     int ret;
+ 
+     /* Unmount FUSE file system */
+@@ -233,12 +237,19 @@ int vfs_unmount(int pid)
+         goto out;
+     }
+ 
++#ifdef __FreeBSD__
++    argv[0] = mountpoint;
++    argv[1] = NULL;
++
++    ret = vfs_run_fusermount(VFS_FUSE_UNMOUNT_PROG, argv, 0);
++#else
+     argv[0] = "-u";
+     argv[1] = "-z";
+     argv[2] = "--";
+     argv[3] = mountpoint;
+     argv[4] = NULL;
+-    ret     = vfs_run_fusermount(argv);
++    ret     = vfs_run_fusermount(VFS_FUSE_UNMOUNT_PROG, argv, 1);
++#endif
+     if (ret < 0) {
+         goto out_free_mountpoint;
+     }
+@@ -505,8 +516,18 @@ static int vfs_test_fuse()
+ 
+ static int vfs_test_fuse()
+ {
++#ifdef __FreeBSD__
++    if (access(VFS_FUSE_MOUNT_PROG, X_OK) < 0) {
++        vfs_error("cannot execute '%s': %m", VFS_FUSE_MOUNT_PROG);
++        return -errno;
++    }
++
++    return 0;
++#else
+     char *argv[] = {"-V", NULL};
+-    return vfs_run_fusermount(argv);
++
++    return vfs_run_fusermount(VFS_FUSE_MOUNT_PROG, argv, 0);
++#endif
+ }
+ 
+ int main(int argc, char **argv)
diff --git a/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c
index 03e48c699cb6..f4f945f79f4d 100644
--- a/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c
+++ b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.c
@@ -1,6 +1,12 @@
---- src/ucs/vfs/sock/vfs_sock.c.orig	2026-02-04 09:52:46 UTC
+--- src/ucs/vfs/sock/vfs_sock.c.orig	2026-08-04 01:14:50 UTC
 +++ src/ucs/vfs/sock/vfs_sock.c
-@@ -24,6 +24,9 @@
+@@ -19,11 +19,15 @@
+ #include <sys/stat.h>
+ #include <string.h>
+ #include <assert.h>
++#include <stdlib.h>
+ #include <unistd.h>
+ #include <stdio.h>
  #include <errno.h>
  #include <pwd.h>
  #include <libgen.h>
@@ -10,71 +16,163 @@
  
  
  typedef struct {
-@@ -76,7 +79,13 @@ int ucs_vfs_sock_setopt_passcred(int sockfd)
+@@ -33,8 +37,29 @@ void ucs_vfs_sock_get_address(struct sockaddr_un *un_a
+ 
+ void ucs_vfs_sock_get_address(struct sockaddr_un *un_addr)
+ {
++#ifdef __FreeBSD__
++    const char *xdg_runtime_dir;
++    int ret;
++#endif
+     memset(un_addr, 0, sizeof(*un_addr));
+     un_addr->sun_family = AF_UNIX;
++#ifdef __FreeBSD__
++    /*
++     * Preserve an explicit UCX_VFS_SOCK_PATH override. When the default
++     * remains selected, prefer the runtime directory provided by the
++     * user's login session.
++     */
++    xdg_runtime_dir = getenv("XDG_RUNTIME_DIR");
++    if ((xdg_runtime_dir != NULL) && (xdg_runtime_dir[0] != '\0') &&
++        !strcmp(ucs_global_opts.vfs_sock_path,
++                UCX_VFS_SOCK_DEFAULT_PATH)) {
++        ret = snprintf(un_addr->sun_path, sizeof(un_addr->sun_path),
++                       "%s/ucx/vfs.sock", xdg_runtime_dir);
++        if ((ret >= 0) && ((size_t)ret < sizeof(un_addr->sun_path))) {
++            return;
++        }
++    }
++#endif
+     ucs_fill_filename_template(ucs_global_opts.vfs_sock_path, un_addr->sun_path,
+                                sizeof(un_addr->sun_path));
+ }
+@@ -43,6 +68,7 @@ int ucs_vfs_sock_mkdir(const char *sock_path, ucs_log_
+ {
+     const char *dirname;
+     char *sock_path_dir;
++    struct stat st;
+     int ret;
+     ucs_status_t status;
+ 
+@@ -57,8 +83,22 @@ int ucs_vfs_sock_mkdir(const char *sock_path, ucs_log_
+     ret = mkdir(dirname, S_IRWXU);
+     if (ret < 0) {
+         if (errno == EEXIST) {
+-            /* Directory already exists */
+-            ret = 0;
++            if (lstat(dirname, &st) < 0) {
++                ret = -errno;
++                ucs_log(log_level, "failed to stat directory '%s': %m",
++                        dirname);
++            } else if (!S_ISDIR(st.st_mode) ||
++                       (st.st_uid != geteuid()) ||
++                       ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)) {
++                ret = -EPERM;
++                ucs_log(log_level,
++                        "unsafe VFS socket directory '%s': "
++                        "expected a directory owned by uid %u without "
++                        "group or world write permissions",
++                        dirname, (unsigned)geteuid());
++            } else {
++                ret = 0;
++            }
+         } else {
+             ucs_log(log_level, "failed to create directory '%s': %m",
+                     sock_path_dir);
+@@ -73,6 +113,7 @@ int ucs_vfs_sock_setopt_passcred(int sockfd)
+ 
+ int ucs_vfs_sock_setopt_passcred(int sockfd)
+ {
++#if defined(__linux__)
      int optval, ret;
  
      optval = 1;
-+#if defined(__linux__)
-     ret = setsockopt(sockfd, SOL_SOCKET, SO_PASSCRED, &optval, sizeof(optval));
-+#elif defined(__FreeBSD__)
-+    ret = setsockopt(sockfd, SOL_LOCAL, LOCAL_CREDS, &optval, sizeof(optval));
-+#else
-+    ret = 0; /* no-op on other platforms for now */
-+#endif
+@@ -80,6 +121,11 @@ int ucs_vfs_sock_setopt_passcred(int sockfd)
      if (ret < 0) {
          return -errno;
      }
-@@ -106,6 +115,8 @@ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_m
++#else
++    /* FreeBSD retrieves credentials from connected local sockets using
++     * LOCAL_PEERCRED. Other platforms are currently a no-op. */
++    (void)sockfd;
++#endif
  
-     memset(cbuf, 0, sizeof(cbuf));
-     memset(&msgh, 0, sizeof(msgh));
-+    msgh.msg_control    = cbuf;
-+    msgh.msg_controllen = sizeof(cbuf);
-     msg.action      = vfs_msg->action;
-     iov.iov_base    = &msg;
-     iov.iov_len     = sizeof(msg);
-@@ -114,8 +125,6 @@ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_m
+     return 0;
+ }
+@@ -97,7 +143,7 @@ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_m
  
-     if (vfs_msg->action == UCS_VFS_SOCK_ACTION_MOUNT_REPLY) {
-         /* send file descriptor */
--        msgh.msg_control    = cbuf;
--        msgh.msg_controllen = sizeof(cbuf);
-         cmsgp               = CMSG_FIRSTHDR(&msgh);
-         cmsgp->cmsg_level   = SOL_SOCKET;
-         cmsgp->cmsg_len     = CMSG_LEN(sizeof(vfs_msg->fd));
-@@ -132,7 +141,11 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
+ int ucs_vfs_sock_send(int sockfd, const ucs_vfs_sock_message_t *vfs_msg)
+ {
+-    char cbuf[CMSG_SPACE(sizeof(*vfs_msg))] UCS_V_ALIGNED(sizeof(size_t));
++    char cbuf[CMSG_SPACE(sizeof(vfs_msg->fd))] UCS_V_ALIGNED(sizeof(size_t));
+     struct cmsghdr *cmsgp;
+     struct msghdr msgh;
+     ucs_vfs_msg_t msg;
+@@ -132,7 +178,12 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
  int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message_t *vfs_msg)
  {
      char cbuf[CMSG_SPACE(sizeof(*vfs_msg))] UCS_V_ALIGNED(sizeof(size_t));
-+#if defined(__FreeBSD__)
-+    const struct cmsgcred *cred;
-+#else
++#if defined(__linux__)
      const struct ucred *cred;
++#elif defined(__FreeBSD__)
++    struct xucred cred;
++    socklen_t cred_len;
 +#endif
      struct cmsghdr *cmsgp;
      struct msghdr msgh;
      ucs_vfs_msg_t msg;
-@@ -178,12 +191,30 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
+@@ -163,27 +214,54 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
+ 
+     vfs_msg->action = msg.action;
+ 
+-    cmsgp = CMSG_FIRSTHDR(&msgh);
+-    if ((cmsgp == NULL) || (cmsgp->cmsg_level != SOL_SOCKET)) {
+-        return -EINVAL;
+-    }
+-
+     if (msg.action == UCS_VFS_SOCK_ACTION_MOUNT_REPLY) {
+         /* expect file descriptor */
+-        if ((cmsgp->cmsg_type != SCM_RIGHTS) ||
++        cmsgp = CMSG_FIRSTHDR(&msgh);
++        if ((cmsgp == NULL) ||
++            (cmsgp->cmsg_level != SOL_SOCKET) ||
++            (cmsgp->cmsg_type != SCM_RIGHTS) ||
+             (cmsgp->cmsg_len != CMSG_LEN(sizeof(vfs_msg->fd)))) {
+             return -EINVAL;
+         }
+ 
          memcpy(&vfs_msg->fd, CMSG_DATA(cmsgp), sizeof(vfs_msg->fd));
      } else {
-         /* expect credentials */
+-        /* expect credentials */
++        /* expect peer credentials */
 +#if defined(__FreeBSD__)
-+        if ((cmsgp->cmsg_level != SOL_SOCKET) ||
-+            (cmsgp->cmsg_type  != SCM_CREDS) ||
-+            (cmsgp->cmsg_len   != CMSG_LEN(sizeof(*cred)))) {
-+            return -EINVAL;
++        cred_len = sizeof(cred);
++        if (getsockopt(sockfd, SOL_LOCAL, LOCAL_PEERCRED, &cred,
++                       &cred_len) < 0) {
++            return -errno;
 +        }
 +
-+        cred = (const struct cmsgcred*)CMSG_DATA(cmsgp);
++        if ((cred_len != sizeof(cred)) ||
++            (cred.cr_version != XUCRED_VERSION)) {
++            return -EINVAL;
++        }
 +
-+        if ((cred->cmcred_euid != geteuid()) || (cred->cmcred_gid != getegid())) {
++        if ((cred.cr_uid != geteuid()) ||
++            (cred.cr_ngroups < 1) ||
++            (cred.cr_groups[0] != getegid())) {
 +            return -EPERM;
 +        }
 +
 +        if (msg.action == UCS_VFS_SOCK_ACTION_MOUNT) {
-+            vfs_msg->pid = cred->cmcred_pid;
++            vfs_msg->pid = cred.cr_pid;
 +        }
 +#else
++        cmsgp = CMSG_FIRSTHDR(&msgh);
++        if ((cmsgp == NULL) ||
++            (cmsgp->cmsg_level != SOL_SOCKET)) {
++            return -EINVAL;
++        }
++
          if ((cmsgp->cmsg_type != SCM_CREDENTIALS) ||
 -            (cmsgp->cmsg_len != CMSG_LEN(sizeof(*cred)))) {
 +            (cmsgp->cmsg_len  != CMSG_LEN(sizeof(*cred)))) {
@@ -86,7 +184,7 @@
          if ((cred->uid != getuid()) || (cred->gid != getgid())) {
              return -EPERM;
          }
-@@ -191,6 +222,7 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
+@@ -191,6 +269,7 @@ int ucs_vfs_sock_recv(int sockfd, ucs_vfs_sock_message
          if (msg.action == UCS_VFS_SOCK_ACTION_MOUNT) {
              vfs_msg->pid = cred->pid;
          }
diff --git a/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.h b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.h
new file mode 100644
index 000000000000..443c2bbc6489
--- /dev/null
+++ b/net/ucx/files/patch-src_ucs_vfs_sock_vfs__sock.h
@@ -0,0 +1,14 @@
+--- src/ucs/vfs/sock/vfs_sock.h.orig	2026-08-04 15:13:35 UTC
++++ src/ucs/vfs/sock/vfs_sock.h
+@@ -15,7 +15,11 @@
+ /* This header file defines socket operations for communicating between UCS
+  * library and VFS daemon */
+ 
++#ifdef __FreeBSD__
++#define UCX_VFS_SOCK_DEFAULT_PATH "/tmp/ucx-%i/vfs.sock"
++#else
+ #define UCX_VFS_SOCK_DEFAULT_PATH "/run/user/%i/ucx/vfs.sock"
++#endif
+ 
+ 
+ /**