The branch main has been updated by brooks:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=ac5a19ec6989675c8ec6c3ca245dba243d1a6416

commit ac5a19ec6989675c8ec6c3ca245dba243d1a6416
Author:     Brooks Davis <[email protected]>
AuthorDate: 2026-01-23 10:35:32 +0000
Commit:     Brooks Davis <[email protected]>
CommitDate: 2026-01-23 10:35:32 +0000

    rpc/xdr.h: make xdrproc_t always take two arguments
    
    The type of xdrproc_t is clearly defined in the comments as a function
    with two arguments, an XDR * and a void * (sometimes spelled caddr_t).
    It was initialy defined as:
    
            typedef bool_t (*xdrproc_t)();
    
    At some point people started giving it a non-empty argument list.
    Unfortunatly, there has been widespread disagreement about how arguments
    are passed.  There seems to have been a widespread view that it should
    be allowed to pass three argument function pointer to xdrproc_t.  Most
    notable is xdr_string which takes a maximum length parameter. This lead
    to all sorts of prototypes (all of which have been present in the
    FreeBSD source tree):
    
    FreeBSD userspace (nominally from tirpc, but seemingly local):
            typedef bool_t (*xdrproc_t)(XDR *, ...);
    FreeBSD kernel, glibc:
            typedef bool_t (*xdrproc_t)(XDR *, void *, ...);
    rcp/xdr.h with _KERNEL defined (not used?):
            typedef bool_t (*xdrproc_t)(XDR *, void *, u_int);
    gssrpc (in krb5) and Linux kernel:
            typedef bool_t (*xdrproc_t)(XDR *, void *);
    
    For two argument functions on current ABIs, these all equivalent as
    these arguments are passed in registers regardless of decleration and
    definition, but we end up with two problems:
    
       - xdr_free((xdrproc_t)xdr_string, ...) calls xdr_string with no third
         argument and (at least on FreeBSD) may fail to free memory if the
         string is shorter than the value lying around in the third argument
         register.  There are no instance of this in tree, but I found some
         with Debian code search, in particular in OpenAFS.
    
       - Under CheriABI, variadic arguments are passed in a separate,
         bounded array so theses prototypes aren't equilvalent to the
         non-variadic calling convention of the functions.
    
    The reality is that that xdr_string should not be cast to xdrproc_t and
    xdr_wrapstring should be used instead so we do not need to support this
    case.  Instances of the former behavior are now extremely rare.
    
    With this change we bring FreeBSD in line with gssrpc and the Linux
    Kernel.  Warnings about casts should now be correct and should be fixed.
    
    Bump __FreeBSD_version as some software required adaptation if it is
    declaring functions to cast to xdrproc_t.  Update OpenZFS's workaround
    of this historic mess accordingly.
    
    Effort:         CHERI upstreaming
    Sponsored by:   Innovate UK
    
    Reviewed by:    kib
    Differential Revision:  https://reviews.freebsd.org/D54824
---
 include/rpc/xdr.h                          | 9 +--------
 lib/libc/rpc/rpc.3                         | 4 ++--
 sys/contrib/openzfs/module/nvpair/nvpair.c | 3 ++-
 sys/rpc/xdr.h                              | 9 +--------
 sys/sys/param.h                            | 2 +-
 5 files changed, 7 insertions(+), 20 deletions(-)

diff --git a/include/rpc/xdr.h b/include/rpc/xdr.h
index ecf10e1659e4..4c75bcc5bbf7 100644
--- a/include/rpc/xdr.h
+++ b/include/rpc/xdr.h
@@ -129,14 +129,7 @@ typedef struct XDR {
  * to be decoded.  If this pointer is 0, then the type routines should
  * allocate dynamic storage of the appropriate size and return it.
  */
-#ifdef _KERNEL
-typedef        bool_t (*xdrproc_t)(XDR *, void *, u_int);
-#else
-/*
- * XXX can't actually prototype it, because some take three args!!!
- */
-typedef        bool_t (*xdrproc_t)(XDR *, ...);
-#endif
+typedef        bool_t (*xdrproc_t)(XDR *, void *);
 
 /*
  * Operations defined on a XDR handle
diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3
index 12d19df117ad..7ae3ec5c5aeb 100644
--- a/lib/libc/rpc/rpc.3
+++ b/lib/libc/rpc/rpc.3
@@ -254,9 +254,9 @@ enum xdr_op {
  * structure of the data type to be decoded.  If this points to 0,
  * then the type routines should allocate dynamic storage of the
  * appropriate size and return it.
- * bool_t  (*xdrproc_t)(XDR *, caddr_t *);
+ * bool_t  (*xdrproc_t)(XDR *, void *);
  */
-typedef  bool_t (*xdrproc_t)();
+typedef  bool_t (*xdrproc_t)(XDR *, void *);
 
 /*
  * The XDR handle.
diff --git a/sys/contrib/openzfs/module/nvpair/nvpair.c 
b/sys/contrib/openzfs/module/nvpair/nvpair.c
index eb8c14b4a783..cb3a024ec95c 100644
--- a/sys/contrib/openzfs/module/nvpair/nvpair.c
+++ b/sys/contrib/openzfs/module/nvpair/nvpair.c
@@ -3246,7 +3246,8 @@ nvs_xdr_nvl_fini(nvstream_t *nvs)
  * xdrproc_t-compatible callbacks for xdr_array()
  */
 
-#if defined(_KERNEL) && defined(__linux__) /* Linux kernel */
+#if (defined(__FreeBSD_version) && __FreeBSD_version >= 1600010) || \
+    defined(_KERNEL) && defined(__linux__) /* Linux kernel */
 
 #define        NVS_BUILD_XDRPROC_T(type)               \
 static bool_t                                  \
diff --git a/sys/rpc/xdr.h b/sys/rpc/xdr.h
index 4307b5101477..b3eafcb864b2 100644
--- a/sys/rpc/xdr.h
+++ b/sys/rpc/xdr.h
@@ -133,14 +133,7 @@ typedef struct XDR {
  * to be decoded.  If this pointer is 0, then the type routines should
  * allocate dynamic storage of the appropriate size and return it.
  */
-#ifdef _KERNEL
-typedef        bool_t (*xdrproc_t)(XDR *, void *, ...);
-#else
-/*
- * XXX can't actually prototype it, because some take three args!!!
- */
-typedef        bool_t (*xdrproc_t)(XDR *, ...);
-#endif
+typedef        bool_t (*xdrproc_t)(XDR *, void *);
 
 /*
  * Operations defined on a XDR handle
diff --git a/sys/sys/param.h b/sys/sys/param.h
index a5dd31519ea5..410d18b53df6 100644
--- a/sys/sys/param.h
+++ b/sys/sys/param.h
@@ -74,7 +74,7 @@
  * cannot include sys/param.h and should only be updated here.
  */
 #undef __FreeBSD_version
-#define __FreeBSD_version 1600009
+#define __FreeBSD_version 1600010
 
 /*
  * __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,

Reply via email to