[Bug 3639] server thread aborts during client login after receiving SSH2_MSG_KEXINIT due to ssh_sandbox_violation
bugzilla-daemon at mindrot.org
bugzilla-daemon at mindrot.org
Sun Dec 31 13:57:45 AEDT 2023
https://bugzilla.mindrot.org/show_bug.cgi?id=3639
--- Comment #29 from JM <jtm.moon.forum.user+mindrot at gmail.com> ---
> Also, if you can catch the sandbox-violation in gdb, getting a disassembly of
> instructions around the violation would be instructive.
tl;dr reviewing disassembly of a `getpid` call that violates the
sandbox shows
value `20` is the SYSCALL value used.
That SYSCALL value is also in a `SC_ALLOW` BPF filter.
### DEBUG SESSION ###
#### Debug Steps ####
1. modify `Makefile` to build with debugging symbols:
CFLAGS=-DDSANDBOX_SECCOMP_FILTER_DEBUG -ggdb -O0 ...
LDFLAGS=-ggdb -O0 ...
2. In `sandbox-seccomp-filter.c`
a. before the call to `prctl(PR_SET_SECCOMP, ...)`, I added a
`sleep(20)` and print `getpid()`
https://github.com/openssh/openssh-portable/blob/V_9_2_P1/sandbox-seccomp-filter.c#L438
This prints the child process PID, and allows time to manually
attach the `gdb` to the new child process.
b. Then added call to `raise(SIGINT)` so gdb will break just before
`prctl(PR_SET_SECCOMP, ...)`.
c. After the call to `prctl(PR_SET_SECCOMP, ...)` I added a call to
`getpid()`
https://github.com/openssh/openssh-portable/blob/V_9_2_P1/sandbox-seccomp-filter.c#L445
which will predictably invoke the sandbox violation.
3. run the `sshd` program
a. modify `sshd_config` to use port 55522
b. build and run
(set -eux; make clean; make sshd; "$(realpath .)/sshd" -ddd
-f ./sshd_config)
6. run the client ssh to invoke the error
ssh -v root at localhost -p 55522
7. when the `sshd` process sleeps for 20, attach `gdb`
gdb "--se=$(realpath ./sshd)" --pid=12345
8. in `gdb`
a. `continue`
it will break at `getpid` just after the `prctl` call
b. `stepi` into the call to `getpid`
See code in file `bpf-filters-dumped.txt`
#### Debug Result ####
Here is that run of `gdb` controlling the child process.
The child process terminates with `SIGSYS, Bad system call` after call
to `getpid`
when `getpid` is called *after* the sandbox filters are set by call
`prctl(PR_SET_SECCOMP, ...)`
https://github.com/openssh/openssh-portable/blob/V_9_2_P1/sandbox-seccomp-filter.c#L439
$ gdb "--se=$(realpath ./sshd)" --pid=16588
...
(gdb) step
Single stepping until exit from function raise,
which has no line number information.
ssh_sandbox_child (box=0x1506010) at sandbox-seccomp-filter.c:648
648 if (prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER,
&preauth_program) == -1) {
(gdb) step
654 else if (nnp_failed) {
(gdb) step
662 pid_t pid_2 = getpid();
(gdb) stepi
0x008d62e4 in getpid at plt ()
(gdb) stepi
0x008d62e8 in getpid at plt ()
(gdb) stepi
0x008d62ec in getpid at plt ()
(gdb) stepi
0xf7c04800 in getpid () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) stepi
0xf7c04804 in getpid () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) disassemble
Dump of assembler code for function getpid:
0xf7c04800 <+0>: push {r7} ; (str r7, [sp,
#-4]!)
=> 0xf7c04804 <+4>: mov r7, #20
0xf7c04808 <+8>: svc 0x00000000
0xf7c0480c <+12>: pop {r7} ; (ldr r7, [sp],
#4)
0xf7c04810 <+16>: bx lr
End of assembler dump.
(gdb) stepi
0xf7c04808 in getpid () from /lib/arm-linux-gnueabihf/libc.so.6
(gdb) disassemble
Dump of assembler code for function getpid:
0xf7c04800 <+0>: push {r7} ; (str r7, [sp,
#-4]!)
0xf7c04804 <+4>: mov r7, #20
=> 0xf7c04808 <+8>: svc 0x00000000
0xf7c0480c <+12>: pop {r7} ; (ldr r7, [sp],
#4)
0xf7c04810 <+16>: bx lr
End of assembler dump.
(gdb) stepi
Program terminated with signal SIGSYS, Bad system call.
The program no longer exists.
See file `gdb-output.txt` for the full output.
### DUMP OF BPF FILTERS ###
Before the call to `prctl(PR_SET_SECCOMP, ...)`, I added a print of
`__NR_getpid`
https://github.com/openssh/openssh-portable/blob/V_9_2_P1/sandbox-seccomp-filter.c#L438
#ifdef __NR_getpgid
debug3("SC_ALLOW(__NR_getpgid=%d),", __NR_getpgid);
#endif
That code snippet is taken from the creation of the BPF filter defined
at compile-time.
https://github.com/openssh/openssh-portable/blob/V_9_2_P1/sandbox-seccomp-filter.c#L229
This prints `__NR_getpid=20` which means it is defined and BPF allowed.
debug3: SC_ALLOW(__NR_getpid=20), [preauth]
See file `bpf-filters-dumped.txt`.
--
You are receiving this mail because:
You are watching the assignee of the bug.
You are watching someone on the CC list of the bug.
More information about the openssh-bugs
mailing list