x86-64 client: hide the tracer only from tier0's status reads

Hiding it from the whole x86 web helper got it past tier0 (message loop,
BrowserCreated) but then Chromium trapped on the status descriptor it
opened itself, now a memfd copy - which is the other reason the shim
leaves the web helper alone. With BL_WEBHELPER_HIDE_TRACER=1 only opens
called from libtier0_s.so get the copy; Chromium's get procfs.
This commit is contained in:
The412Banner committed 2026-10-02 16:28:43 -04:00
1 parent b2e3a3a5ea
commit 131ba72ee5
3 files changed
+20 -13

No files matched your search

+2 -2
View File
@@ -483,12 +483,12 @@ static FILE *synthesize(const char *table) {
}
/* tracer.c */
int bl_status_without_tracer(const char *path, int flags) __attribute__((visibility("hidden")));
int bl_status_without_tracer(const char *path, int flags, const void *caller) __attribute__((visibility("hidden")));
static FILE *open_stream(const char *symbol, const char *path, const char *mode) {
typedef FILE *(*fopen_fn)(const char *, const char *);
int status = mode && mode[0] == 'r' && !strchr(mode, '+')
? bl_status_without_tracer(path, O_RDONLY | O_CLOEXEC) : -1;
? bl_status_without_tracer(path, O_RDONLY | O_CLOEXEC, NULL) : -1;
if (status >= 0) {
FILE *copy = fdopen(status, "r");
if (copy == NULL) close(status);
+3 -3
View File
@@ -33,7 +33,7 @@
#include <string.h>
#include <sys/types.h>
int bl_status_without_tracer(const char *path, int flags) __attribute__((visibility("hidden")));
int bl_status_without_tracer(const char *path, int flags, const void *caller) __attribute__((visibility("hidden")));
int bl_writable_retry(int dirfd, const char *path, int flags) __attribute__((visibility("hidden")));
static int retry_without_noatime(int fd, int flags) {
@@ -60,7 +60,7 @@ int open(const char *path, int flags, ...) {
errno = EACCES;
return -1;
}
if ((fd = bl_status_without_tracer(path, flags)) >= 0) return fd;
if ((fd = bl_status_without_tracer(path, flags, __builtin_return_address(0))) >= 0) return fd;
if (real_open == NULL) real_open = dlsym(RTLD_NEXT, "open");
if (real_open == NULL) {
errno = ENOSYS;
@@ -86,7 +86,7 @@ int openat(int dirfd, const char *path, int flags, ...) {
errno = EACCES;
return -1;
}
if ((fd = bl_status_without_tracer(path, flags)) >= 0) return fd;
if ((fd = bl_status_without_tracer(path, flags, __builtin_return_address(0))) >= 0) return fd;
if (real_openat == NULL) real_openat = dlsym(RTLD_NEXT, "openat");
if (real_openat == NULL) {
errno = ENOSYS;
+15 -8
View File
@@ -18,6 +18,7 @@
*/
#define _GNU_SOURCE
#include <ctype.h>
#include <dlfcn.h>
#include <errno.h>
#include <fcntl.h>
#include <stdlib.h>
@@ -48,14 +49,20 @@ static int is_status_path(const char *path) {
}
/* Chromium stands its hang watchdogs down when it sees a tracer, and the client's web helper does
* not come up within their patience here: it is left reading the truth. Not so for the x86-64
* client under FEX (BL_WEBHELPER_HIDE_TRACER=1, set by bannerlator-steam-x64): its tier0 breaks
* into the supposed debugger with int3 on the first failed assertion, and the web helper dies of
* SIGTRAP a second after it starts. */
static int is_web_helper(void) {
* not come up within their patience here: it is left reading the truth. Chromium also traps when a
* status descriptor it opened turns out not to be procfs. The x86-64 client under FEX
* (BL_WEBHELPER_HIDE_TRACER=1, set by bannerlator-steam-x64) still needs its tier0 told: tier0
* reads the status, sees the tracer, and breaks into the supposed debugger with int3 on the first
* failed assertion - the web helper died of SIGTRAP a second after it started. There tier0's own
* opens (by caller) get the copy and Chromium's the real file. */
static int is_web_helper(const void *caller) {
if (strcmp(program_invocation_short_name, "steamwebhelper") != 0) return 0;
const char *hide = getenv("BL_WEBHELPER_HIDE_TRACER");
return !(hide && hide[0] == '1');
Dl_info info;
if (hide && hide[0] == '1' && caller && dladdr(caller, &info) && info.dli_fname
&& strstr(info.dli_fname, "libtier0_s.so"))
return 0;
return 1;
}
static int write_all(int fd, const char *data, size_t len) {
@@ -71,13 +78,13 @@ static int write_all(int fd, const char *data, size_t len) {
/* The descriptor to hand back for a read-only open of a status file, or -1 with errno untouched
* when the path is something else or the copy cannot be made, and the real open should run. */
__attribute__((visibility("hidden"))) int bl_status_without_tracer(const char *path, int flags) {
__attribute__((visibility("hidden"))) int bl_status_without_tracer(const char *path, int flags, const void *caller) {
char text[STATUS_MAX];
size_t len = 0;
int saved = errno;
int out = -1;
if ((flags & O_ACCMODE) != O_RDONLY || !is_status_path(path) || is_web_helper()) return -1;
if ((flags & O_ACCMODE) != O_RDONLY || !is_status_path(path) || is_web_helper(caller)) return -1;
int in = (int)syscall(SYS_openat, AT_FDCWD, path, O_RDONLY | O_CLOEXEC);
if (in < 0) goto done;
for (;;) {