[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