git: 3298d82ea340 - stable/15 - Fix LOCAL_PEERCRED in 32-bit compat mode
- Go to: [ bottom of page ] [ top of archives ] [ this month ]
Date: Wed, 13 May 2026 17:22:50 UTC
The branch stable/15 has been updated by asomers:
URL: https://cgit.FreeBSD.org/src/commit/?id=3298d82ea34059354dc1ff1a60d8b7d3e495c2cd
commit 3298d82ea34059354dc1ff1a60d8b7d3e495c2cd
Author: Alan Somers <asomers@FreeBSD.org>
AuthorDate: 2026-04-27 23:46:53 +0000
Commit: Alan Somers <asomers@FreeBSD.org>
CommitDate: 2026-05-13 16:54:53 +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)
---
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 44d0185e9d1c..8e8261c9644e 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>
@@ -2755,8 +2756,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. */