How to hide TracerPID from a process

ltraceprocreverse-engineeringsqlserverstrace

I'm conjecturing SQL Server on Linux is checking /proc/self/status for TracerPID and then dying if it's not 0. I want to test that. Playing around, here is the strace,

... lots of stuff
openat(AT_FDCWD, "/proc/self/status", O_RDONLY) = 5
fstat(5, {st_mode=S_IFREG|0444, st_size=0, ...}) = 0
read(5, "Name:\tsqlservr\nUmask:\t0022\nState"..., 1024) = 1024
close(5)                                = 0
rt_sigprocmask(SIG_UNBLOCK, [ABRT], NULL, 8) = 0
rt_sigprocmask(SIG_BLOCK, ~[RTMIN RT_1], [], 8) = 0
getpid()                                = 28046
gettid()                                = 28046
tgkill(28046, 28046, SIGABRT)           = 0
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
--- SIGABRT {si_signo=SIGABRT, si_code=SI_TKILL, si_pid=28046, si_uid=999} ---
gettid()                                = 28046
write(2, "Dump collecting thread [28046] h"..., 59Dump collecting thread [28046] hit exception [6]. Exiting.
) = 59
exit_group(-1)                          = ?

The ltrace is even more damning, thankfully they're using strstr which makes it seem really likely my theory is correct.

strstr("PPid:\t28515\n", "TracerPid:")                                                                  = nil
__getdelim(0x7ffc0b7d2330, 0x7ffc0b7d2328, 10, 0x7f12f5811980)                                          = 17
strstr("TracerPid:\t28515\n", "TracerPid:")                                                             = "TracerPid:\t28515\n"
strtol(0x7f12f581840b, 0x7ffc0b7d2320, 10, 0)                                                           = 0x6f63
free(0x7f12f5818400)                                                                                    = <void>
fclose(0x7f12f5811980)                                                                                  = 0
abort( <no return ...>
--- SIGABRT (Aborted) ---
syscall(186, 6, 0, 0)                                                                                   = 0x6f64
fprintf(0x7f12f6ec4640, "Dump collecting thread [%d] hit "..., 28516, 6Dump collecting thread [28516] hit exception [6]. Exiting.
)                                = 59
fflush(0x7f12f6ec4640)                                                                                  = 0
exit(-1 <unfinished ...>

The last line on the file they check (with strstr) before they abort() is the line with TracerPid:, however with my /proc/self/status there are many lines after it.

In order of preference, I'd like /proc/self/status to report

...stuff...
TracerPid:  0
...stuff...

for this process. If that can't be achieved, I'd like it to report 0 for all processes.

Is it possible to create a wrapper that changes the value of TracerPID for /proc/self/status and then exec the argument given to it resulting in it not having access to TracerPID?

Best Answer

The only way I found to do this by patching the kernel. Though I think it may also be possible to hack this of thing with LD_PRELOAD, I'll check into later.

Related Question