Background ========== The LOCAL_PEERCRED sockopt is supposed to return the credentials of the process that owns the peer side of a connection-oriented unix domain socket. It returns the peer's UID, GID, supplementary group list (up to 16), and pid. Problem ======= When the sockopt is fetched by a 32-bit process running on a 64-bit kernel, the structure's size is defined differently for the process than it is for the kernel. The kernel fails to check that, and populates the structure as if it were the 64-bit version. The problem is the anonymous union in struct xucred that contains a pointer. The userspace process thinks that the union is 4 bytes large, but the kernel things that it's 8-bytes large. As a result, the kernel will always populate the cr_pid field with 0. Steps to Reproduce ================== Build and run the attached program on a 64-bit host: $ cc -m32 -o LOCAL_PEERCRED -Wall LOCAL_PEERCRED.c $ ./LOCAL_PEERCRED sizeof(struct xucred)=0x50 My pid = 0x192c cr_uid=1000 cr_gid=1000 cr_pid=0 0000: 0000 0000 03e8 0000 0008 0000 03e8 0000 0010: 0000 0000 0005 0000 000d 0000 002c 0000 0020: 0074 0000 01be 0000 03e8 0000 0000 0000 0030: 0000 0000 0000 0000 0000 0000 0000 0000 0040: 0000 0000 0000 0000 0000 0000 0000 0000 0050: 192c 0000 0000 0000 c952 2059 0001 0000 Note that the kernel returns the correct pid (0x192c), but it returns it at offset 0x50, which is beyond the end of the xucred struct.
Created attachment 270193 [details] testcase
A commit in branch main references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=1d24638d3e8875e4b99a4b5e39f4241e37221b3d commit 1d24638d3e8875e4b99a4b5e39f4241e37221b3d Author: Alan Somers <asomers@FreeBSD.org> AuthorDate: 2026-04-27 23:46:53 +0000 Commit: Alan Somers <asomers@FreeBSD.org> 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(-)
A commit in branch stable/15 references this bug: 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(-)
A commit in branch releng/15.1 references this bug: URL: https://cgit.FreeBSD.org/src/commit/?id=39fcfcc64bbae6ff8792c8598c6147e3c63b60c1 commit 39fcfcc64bbae6ff8792c8598c6147e3c63b60c1 Author: Alan Somers <asomers@FreeBSD.org> AuthorDate: 2026-04-27 23:46:53 +0000 Commit: Colin Percival <cperciva@FreeBSD.org> CommitDate: 2026-05-14 19:04:38 +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. Approved by: re (cperciva) PR: 294833 Sponsored by: ConnectWise Reviewed by: emaste Differential Revision: https://reviews.freebsd.org/D56675 (cherry picked from commit 1d24638d3e8875e4b99a4b5e39f4241e37221b3d) (cherry picked from commit 3298d82ea34059354dc1ff1a60d8b7d3e495c2cd) sys/kern/uipc_usrreq.c | 21 +++++++++++++++++++-- sys/sys/ucred.h | 11 +++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-)