Repository navigation
libc, rtld: translate osreldate to a FreeBSD version for ABI checks - #644
Conversation
The kernel reports __MidnightBSD_version (402005) as its osreldate, but every caller of __getosreldate() compares the result with FreeBSD version thresholds: INO64_FIRST, CLOSE_RANGE_OSREL, GETRANDOM_FIRST, P_OSREL_MAP_GUARD, P_OSREL_WRFSBASE, P_OSREL_TIDPID, and the __realpathat check. All of them failed on every architecture, so libc always used the freebsd11 stat and dirent compat syscalls (32-bit inode numbers), and close_range, getrandom, __realpathat, MAP_GUARD, WRFSBASE and CPU_WHICH_TIDPID were never used. Add __osrel_to_freebsd(), which maps a MidnightBSD version to the __FreeBSD_version of the tree it was built from (taken from the history of sys/sys/param.h, using the lowest value when a MidnightBSD version spanned several), and apply it in libc's __getosreldate() and in rtld's override and aux vector handling. Values of 700000 and up are already FreeBSD versions and pass through unchanged. getosreldate(3) still returns the MidnightBSD version. On amd64, ls -ld / goes from 19 compat11 syscalls to none, and rtld now maps objects with MAP_GUARD. See issue #641. AI-Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Lucas Holt <[email protected]>
Reviewer's GuideAPIDeclare the private osreldate translation interface for libc and rtld callers.
Uses of the APITranslate aux-vector and sysctl osreldate values in libc and rtld before ABI threshold checks use them.
ImplementationImplement the MidnightBSD-to-FreeBSD release mapping and pass-through rules that underpin internal ABI checks.
ConfigurationBuild the shared translation implementation into libc and rtld, and compile it into the focused ATF test.
TestsExercise translation pass-throughs, mapping boundaries, current-release behavior, and the running kernel's ino64 threshold.
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
There was a problem hiding this comment.
Hey - I've found 3 issues
Prompt for AI Agents
Please address the comments from this code review:
## Individual Comments
### Comment 1
<location path="lib/libc/gen/__osrel_freebsd.c" line_range="61" />
<code_context>
+ * version (for example, a jail created with a FreeBSD osreldate) and is
+ * returned unchanged.
+ */
+#define OSREL_FREEBSD_MIN 700000
+
+int
</code_context>
<issue_to_address>
**Older FreeBSD jails get newer ABI paths**
When a jail uses a FreeBSD 4–6 `osreldate` in the overlapping 400001–699999 range, `__osrel_to_freebsd()` treats the value as a MidnightBSD release and maps it to a newer FreeBSD ABI level, so libc and rtld select paths the jail’s configured ABI does not permit.
Distinguish pre-FreeBSD-7 osreldates from MidnightBSD release values before applying the mapping table.
Also at `lib/libc/gen/__osrel_freebsd.c:68-73`.
</issue_to_address>
### Comment 2
<location path="lib/libc/gen/__getosreldate.c" line_range="62" />
<code_context>
+ osrel = 0;
+ error = _elf_aux_info(AT_OSRELDATE, &osrel, sizeof(osrel));
+ if (error == 0 && osrel != 0) {
+ osreldate = __osrel_to_freebsd(osrel);
return (osreldate);
+ }
</code_context>
<issue_to_address>
**Jail changes leave stale ABI version**
When a process first initializes either cache in one prison and then attaches to a prison with a different `osreldate`, the cached translated release remains the value from the original prison, so libc and rtld keep selecting ABI paths for that prison after the process moves to another one, rather than using the new prison’s `kern.osreldate`.
Re-read and translate the current prison’s release when prison context can change, or invalidate these caches when the process changes prisons.
Also at `libexec/rtld-elf/rtld.c:2427`.
</issue_to_address>
### Comment 3
<location path="lib/libc/gen/__osrel_freebsd.c" line_range="48-53" />
<code_context>
+ int mnbsd;
+ int fbsd;
+} osrel_map[] = {
+ { 400001, 1305500 }, /* 4.0 */
+ { 301006, 1204500 }, /* 3.1 */
+ { 300003, 1203507 }, /* 3.0 */
+ { 200000, 1103507 }, /* 2.0 */
+ { 100001, 1004501 }, /* 1.0 */
+};
+
+/*
</code_context>
<issue_to_address>
**Release mapping lacks regression tests**
The new release mapping changes which ABI paths libc and rtld select, but no repository test covers its version boundaries or translated result. The boundary harness mentioned in the description is not part of the tree, so later mapping regressions can pass the checked-in test suite unnoticed.
Add checked-in regression tests for the translation boundaries and the libc/rtld paths that consume the translated value.
</issue_to_address>Add osrel_freebsd_test, which builds the private translation into an ATF test and checks pass-through values, every table boundary, the current release, and that the running kernel's osreldate translates to at least INO64_FIRST. Explain why values below 700000 are always treated as MidnightBSD versions even though FreeBSD 4-6 used the same range: only MidnightBSD userland calls this, and a FreeBSD 4-6 jail runs its own libc and rtld. AI-Assisted-by: Claude Opus 5.5 Co-Authored-By: Claude Opus 5.5 <[email protected]> Signed-off-by: Lucas Holt <[email protected]>
|
Claude finished @laffer1's task in 22s —— View job Review of PR #644I read the full diff ( Correctness
Sourcery's comments
Minor, non-blocking
Process notes
Overall the change is sound and ready from my side, pending a real buildworld on other architectures (including i386/lib32) as the PR itself notes. |
Fixes the userland half of #641.
Problem
The kernel reports
__MidnightBSD_version(402005) askern.osreldateand inAT_OSRELDATE. Every caller of the private__getosreldate()compares that value against FreeBSD thresholds, so on every architecture they all conclude the kernel is older than FreeBSD 12:stat,lstat,fstat,fstatat,statfs,fstatfs,getfsstat,getdirentriesINO64_FIRST1200031freebsd11_*compat syscalls, with 32-bit inode numbersclosefromCLOSE_RANGE_OSRELclose_range(2)never usedrealpath__realpathat(2)never usedgetentropyGETRANDOM_FIRST1200061getrandom(2)sched_{get,set}affinityP_OSREL_TIDPID{,_13}CPU_WHICH_TIDPIDmap_objectP_OSREL_MAP_GUARDMAP_GUARDP_OSREL_WRFSBASEWRFSBASEpath never usedChange
lib/libc/gen/__osrel_freebsd.cprovides__osrel_to_freebsd(), which maps a MidnightBSD version to the__FreeBSD_versionof the tree it was built from:sys/sys/param.h.__MidnightBSD_versionmaps to the libc's__FreeBSD_version.__getosreldate()and rtld's override and aux-vector path now return the translated value. rtld builds the same file throughrtld-libc.getosreldate(3), which still returns the MidnightBSD version that mports and other software use.I checked that the current kernel has every gated feature: the ino64 syscalls,
close_range,__realpathat,getrandom,MAP_GUARD, the amd64 fs/gs basesysarchcalls, andCPU_WHICH_TIDPID.Testing (amd64, native)
ktrace ls -ld /with the system libc and rtld makes 19compat11syscalls. With the patched rtld (direct exec) and libc, thelsprocess makes 0. It uses nativefstat/fstatat/fstatfs/getdirentries, and rtld maps withMAP_GUARD.Notes for review
COMPAT_FREEBSD11in GENERIC for existing static binaries and old packages; riscv GENERIC gets it in riscv64: fix booting install media under EDK2 (QEMU virt) #642.p_osrel/p_fctl0always 0) is not addressed here.nitems().AI-Assisted-by: Claude Opus 5.5
🤖 Generated with Claude Code
Summary by Sourcery
Translate kernel release values for private ABI checks so libc and rtld can use the native kernel interfaces supported by MidnightBSD.
New Features:
Bug Fixes:
Enhancements:
Tests: