git: 66c61a685c73 - stable/14 - Fix LOCAL_PEERCRED in 32-bit compat mode

Alan Somers <[email protected]>
Newsgroups gmane.os.freebsd.devel.cvs.src
Message-ID <6a72a154.3bfc9.3afb1532__34789.1088154697$1785897330$gmane$org@gitrepo.freebsd.org>
The branch stable/14 has been updated by asomers:

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

commit 66c61a685c73aacf92aa0ecdadeff5f38332d669
Author:     Alan Somers <[email protected]>
AuthorDate: 2026-04-27 23:46:53 +0000
Commit:     Alan Somers <[email protected]>
CommitDate: 2026-08-05 02:23:12 +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
    Reviewed by:    emaste
    Differential Revision: https://reviews.freebsd.org/D56675
    
    (cherry picked from commit 1d24638d3e8875e4b99a4b5e39f4241e37221b3d)
    
    linuxulator: fix SO_PEERCRED emulation after 1d24638d3e8
    
    For Linux binaries, sopt->sopt_td may be null.  And there's also no
    need to check it, since struct l_ucred has the same layout on 32-bit
    systems as on 64-bit ones.
    
    PR:             295333
    Reported by:    Miguel Gomes <[email protected]>
    Fixes:          1d24638d3e8 ("Fix LOCAL_PEERCRED in 32-bit compat mode")
    Reviewed by:    emaste
    Differential Revision: https://reviews.freebsd.org/D57032
    
    (cherry picked from commit 4cee16d471d47f4673e4d2c66f7a96d4e6d86ee9)
---
 sys/kern/uipc_usrreq.c | 23 +++++++++++++++++++++--
 sys/sys/ucred.h        | 11 +++++++++++
 2 files changed, 32 insertions(+), 2 deletions(-)

diff --git a/sys/kern/uipc_usrreq.c b/sys/kern/uipc_usrreq.c
index 4df36221bc6a..c78b63005ca5 100644
--- a/sys/kern/uipc_usrreq.c
+++ b/sys/kern/uipc_usrreq.c
@@ -84,6 +84,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>
@@ -1785,8 +1786,26 @@ 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 (sopt->sopt_td &&
+			    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 d8b999e27db7..da72901a5b63 100644
--- a/sys/sys/ucred.h
+++ b/sys/sys/ucred.h
@@ -183,6 +183,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. */
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.