https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127315
Bug ID: 127315
Summary: libsanitizer log_path is attacker-controllable for
privileged UBSan/LSan/TSan processes
Product: gcc
Version: 16.0
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: sanitizer
Assignee: unassigned at gcc dot gnu.org
Reporter: 220255623 at seu dot edu.cn
CC: 220245569 at seu dot edu.cn, dodji at gcc dot gnu.org,
dvyukov at gcc dot gnu.org, jakub at gcc dot gnu.org,
jianhao.xu at seu dot edu.cn, kcc at gcc dot gnu.org
Target Milestone: ---
Created attachment 65554
--> https://gcc.gnu.org/bugzilla/attachment.cgi?id=65554&action=edit
Standalone reproducer, runtime transcript, compiler version, and build script
for DREV-2026-014. The ZIP contains trigger.c, build.sh, observed.txt,
gcc-v.txt, and README.txt. Text/source files only;
GCC's bundled `libsanitizer` accepts `UBSAN_OPTIONS=log_path=...` in
setuid/setgid execution. `GetEnv` reads `/proc/self/environ`, UBSan forwards
`common_flags()->log_path` to `__sanitizer_set_report_path`, and
`ReportFile::SetReportPath` passes every non-stdio path to
`OpenFile(..., WrOnly)`. `WrOnly` maps to `O_WRONLY | O_CREAT | O_TRUNC`, with
no `AT_SECURE` or uid/euid guard.
Reproducer: build the supplied division-by-zero trigger as setuid root,
run it with real UID/GID 65534, and set
`UBSAN_OPTIONS=log_path="$PWD/root-only/ubsan-log"` where `root-only` is a
root-owned `0700` directory.
Expected: during secure execution, a non-stdio `log_path` should be ignored or
replaced with `stderr` before directory creation or file open.
Actual: the setuid process created `root-only/ubsan-log.<pid>`, owned by
`root:nogroup`, mode `0640`, and wrote the UBSan diagnostic into it. The
caller could not write to the output directory. The same result occurred with
`16.0.1 20260424 (prerelease)`, GCC `16.1.0`, and
`17.0.0 20260531 (experimental)`.