termux / proot

An chroot-like implementation using ptrace.
https://wiki.termux.com/wiki/PRoot
Other
762 stars 160 forks source link

proot can't start ssh-agent #62

Closed arno01 closed 5 years ago

arno01 commented 5 years ago

Command Output

$ proot ssh-agent
proot warning: ptrace(PEEKDATA): Input/output error
proot warning: ptrace(PEEKDATA): Input/output error
proot warning: ptrace(PEEKDATA): Input/output error
proot warning: ptrace(PEEKDATA): Input/output error
PRNG is not seeded

with strace:

$ proot strace -e connect ssh-agent 
proot info: pid 1383: terminated with signal 9
connect(3, 0x7ffdac3df850, 19proot warning: ptrace(PEEKDATA): Input/output error
)          = -1 EFAULT (Bad address)
connect(3, 0x7ffdac3df850, 15proot warning: ptrace(PEEKDATA): Input/output error
)          = -1 EFAULT (Bad address)
connect(3, 0x7ffdac3df850, 15proot warning: ptrace(PEEKDATA): Input/output error
)          = -1 EFAULT (Bad address)
connect(3, 0x7ffdac3df850, 14proot warning: ptrace(PEEKDATA): Input/output error
)          = -1 EFAULT (Bad address)
PRNG is not seeded
+++ exited with 255 +++

Specifications

Extra

On Android Pie (Linux 4.9.112, Samsung):

$ proot ssh-agent
mkdtemp: private socket dir: Bad address

with strace:

$ proot strace -e mkdirat ssh-agent 
proot warning: ptrace request 'PTRACE_???' not supported yet
--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPC, si_addr=0x714b509cd0} ---
mkdirat(AT_FDCWD, 0x3000050298, 0700)   = -1 EFAULT (Bad address)
mkdtemp: private socket dir: Bad address
+++ exited with 1 +++

I've also opened it here https://github.com/proot-me/proot/issues/173

michalbednarski commented 5 years ago

It appears to be issue with process setting itself to be undumpable. It can be worked around with following LD_PRELOAD (but note that this workaround should be probably put in proot)

#define prctl prctl_from_header
#define _GNU_SOURCE
#include <sys/prctl.h>
#include <dlfcn.h>
#undef prctl

int prctl(int option, unsigned long arg2, unsigned long arg3,
         unsigned long arg4, unsigned long arg5)
{
    if (option == PR_SET_DUMPABLE) {
        return 0;
    }
    int (*real_prctl)(int, unsigned long, unsigned long, unsigned long, unsigned long);
    real_prctl = dlsym(RTLD_NEXT, "prctl");
    return real_prctl(option, arg2, arg3, arg4, arg5);
}

gcc forcedumpable.c -o forcedumpable.so -shared -ldl
LD_PRELOAD=`pwd`/forcedumpable.so ./proot ssh-agent
arno01 commented 5 years ago

@michalbednarski thank you, it does work! :-)

Do you know by chance why proot does not return the terminal prompt back?

$ LD_PRELOAD=`pwd`/forcedumpable.so proot ssh-agent
SSH_AUTH_SOCK=/data/data/com.termux/files/usr/tmp/ssh-ly8djYKpp36p/agent.25762; export SSH_AUTH_SOCK;
SSH_AGENT_PID=25763; export SSH_AGENT_PID;
echo Agent pid 25763;
(I'd expect proot to give the $ prompt back at this moment, but it does not)

Edit oh, that should not be a big issue, since I do not need to run it directly as proot ssh-agent anyway. It's rather proot <flags> bash -l, and then just ssh-agent.

michalbednarski commented 5 years ago

Thats by design as proot doesn't go into background (which is expected as it is usually used for interactive shell) and then stays alive as long as any process is traced.

Note that you can start proot in background when launching it from shell (proot ... &)

arno01 commented 5 years ago

Yeah, it all makes sense. Thanks for the explanation, Michal!

michalbednarski commented 5 years ago

Filtering of PR_SET_DUMPABLE is now done on proot side. Workaround should no longer be needed.