The branch main has been updated by asomers:

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

commit 1d24638d3e8875e4b99a4b5e39f4241e37221b3d
Author:     Alan Somers <[email protected]>
AuthorDate: 2026-04-27 23:46:53 +0000
Commit:     Alan Somers <[email protected]>
CommitDate: 2026-05-07 20:52:35 +0000

    Fix LOCAL_PEERCRED in 32-bit compat mode
    
    Previously the cr_pid field would be incorrectly copied to userland, due
    to a size mismatch between the structure as defined in 32-bit vs 64-bit
    builds.  Fix it by converting the structure before copying it to
    userland.
    
    PR:             294833
    Sponsored by:   ConnectWise
    MFC after:      1 week
    Reviewed by:    emaste
    Differential Revision: https://reviews.freebsd.org/D56675
---
 sys/kern/uipc_usrreq.c | 21 +++++++++++++++++++--
 sys/sys/ucred.h        | 11 +++++++++++
 2 files changed, 30 insertions(+), 2 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 8ff9822ee9eb..2508f7edd1c5 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -83,6 +83,7 @@
 #include <sys/socketvar.h>
 #include <sys/signalvar.h>
 #include <sys/stat.h>
+#include <sys/sysent.h>
 #include <sys/sx.h>
 #include <sys/sysctl.h>
 #include <sys/systm.h>
@@ -2752,8 +2753,24 @@ uipc_ctloutput(struct socket *so, struct sockopt *sopt)
                                        error = EINVAL;
                        }
                        UNP_PCB_UNLOCK(unp);
-                       if (error == 0)
-                               error = sooptcopyout(sopt, &xu, sizeof(xu));
+                       if (error != 0)
+                               break;
+#ifdef COMPAT_FREEBSD32
+                       if (SV_PROC_FLAG(sopt->sopt_td->td_proc, SV_ILP32)) {
+                               struct xucred32 xu32 = {};
+                               int i;
+
+                               xu32.cr_version = xu.cr_version;
+                               xu32.cr_uid = xu.cr_uid;
+                               xu32.cr_ngroups = xu.cr_ngroups;
+                               for (i = 0; i < XU_NGROUPS; i++)
+                                       xu32.cr_groups[i] = xu.cr_groups[i];
+                               xu32.cr_pid = xu.cr_pid;
+                               error = sooptcopyout(sopt, &xu32, sizeof(xu32));
+                               break;
+                       }
+#endif
+                       error = sooptcopyout(sopt, &xu, sizeof(xu));
                        break;
 
                case LOCAL_CREDS:
diff --git a/sys/sys/ucred.h b/sys/sys/ucred.h
index ba241cf9ff3a..4bf48a5e4b87 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -193,6 +193,17 @@ struct setcred32 {
        uint32_t sc_label;              /* struct mac32 [*] */
 };
 
+#ifdef COMPAT_FREEBSD32
+/* 32-bit compatible version of xucred */
+struct xucred32 {
+       u_int   cr_version;             /* structure layout version */
+       uid_t   cr_uid;                 /* effective user id */
+       short   cr_ngroups;             /* number of groups (incl. cr_gid). */
+       gid_t   cr_groups[XU_NGROUPS];  /* groups */
+       pid_t   cr_pid;
+};
+#endif
+
 struct thread;
 
 /* Common native and 32-bit compatibility entry point. */

Reply via email to