Hi,
I've compiled setcap and getcap for Android and tried to assign cap_net_bind_service capability to sshd, so I can get it running on port 22 instead of 8022.
The capability gets set and hence it should work as I am running kernel that supports capabilities. However after restarting the sshd process it fails to run without any error message - obviously it won't boot because of the port change (I've tried ports 22, 555). It will start just fine when I return to Port 8022 in sshd_config. I also tried this with SELinux in Permissive mode just in case.
__So the setcap and getcap utils are working just fine, but the kernel is ignoring set capabilities.__ Any ideas?
$ wget https://www.kernel.org/pub/linux/libs/security/linux-privs/libcap2/libcap-2.25.tar.gz
$ tar xvfz libcap-2.25.tar.gz
$ cd libcap-2.25
$ sudo apt-get update
$ sudo apt-get install build-essential
$ sed -i.bak "s/DYNAMIC.*/DYNAMIC := no/" Make.Rules
$ make
# setenforce 0
# chmod +x getcap
# chmod +x setcap
$ mv getcap ../usr/bin
$ mv setcap ../usr/bin
# /data/data/com.termux/files/usr/bin/setcap cap_net_bind_service=+ep /data/data/com.termux/files/usr/bin/sshd
$ getcap /data/data/com.termux/files/usr/bin/sshd
/data/data/com.termux/files/usr/bin/sshd = cap_net_bind_service+ep
$ echo Port 22 >> ../usr/etc/ssh/sshd_config
$ sshd
You didn't mention but ... do you have "root"?
Even on Linux you can only bind to ports # < 1024 if you are root.
@sessyargc yes, the phone is rooted.
@vovcacik I suspect that this is by design.
You are not trying to run those executables in root terminal, are you? Linux capabilities (and suid-bit) do not have effect when interacted with by ordinary Android apps, because Android JVM process (zygote) uses PR_SET_NO_NEW_PRIVS prctl flag to disable them before running any app code (see man prctl). This means, that ordinary processes (such as Termux UID) can not elevate themselves by using execve (neither with suid, nor with file-caps or SELinux file attributes).
This is the same reason, why rooting Android devices has become a lot harder around KitKat — you can no longer use suid su binary to trivially escape sandbox. Modern Android su binaries are actually non-suid client executables, that connect to separate daemon (google for "daemon-su"), running in background since early boot. Soon after system boot most processes castrate themselves with PR_SET_NO_NEW_PRIVS, so they and their children no longer can escalate privileges.
@Alexander-- that sounds very possible. And I am not running the sshd executable as root, instead I am trying to setcap it (which did require root access).
@vovcacik if you already have root, you are better off just starting non-root su shell with Termux UID. This way you will be able to use Termux normally, but without PR_SET_NO_NEW_PRIVS, seccomp and other similar restrictions, — as explained above, su processes are specifically started in way, that escapes those restrictions. You will be able to view full contents of /proc, use strace and take advantage of file capabilities without switching to UID 0.
If you have rooted device, there is no reason not to do so.
@Alexander-- I think I need to clarify.
The phone is rooted and I used su to set capabilities with setcap on sshd executable. And it worked fine. However I am executing the sshd from Termux shell - which as you say is not subject of Android restrictions (e.g. PR_SET_NO_NEW_PRIVS) and thus the set capabilities should have effect, but they don't.
I've used the debug tool capsh and getpcaps to show what is the problem here. I used the standard Termux shell without root.
-bash-4.4$ getcap `which sshd`
/data/data/com.termux/files/usr/bin/sshd = cap_net_bind_service+ep
-bash-4.4$ ./capsh --supports=cap_net_bind_service && echo supported || echo unsupported
supported
-bash-4.4$ sshd
-bash-4.4$ ps
PID USER TIME COMMAND
6078 u0_a83 0:00 /data/data/com.termux/files/usr/bin/bash -l
12811 u0_a83 0:00 /data/data/com.termux/files/usr/bin/sshd -R
12812 u0_a83 0:00 -bash
12843 u0_a83 0:00 sshd
12851 u0_a83 0:00 ps
-bash-4.4$ ./getpcaps 12843
Capabilities for `12843': =
-bash-4.4$
getcap returns expected capability cap_net_bind_service+ep, so setcap and getcap work finecapsh can test if particular capability is supported, and it reports cap_net_bind_service is supportedsshd from unprivileged shellgetpcaps should return capabilities set on a process, but as you can see it is emptysshd was configured for port 8022 in this session, if it was set to port 22 it would failed to runAlso
-bash-4.4$ ./capsh --caps=cap_net_bind_service+ep
Unable to set capabilities [--caps=cap_net_bind_service+ep]
@vovcacik I believe, that I understood you perfectly.
As I said, try to use su to switch to Termux user:
````
File: /data/data/com.termux/
Size: 4096 Blocks: 8 IO Block: 4096 directory
Device: 10300h/66304d Inode: 621526 Links: 5
Access: (0751/drwxr-x--x) Uid: (10146/ u0_a146) Gid: (10146/ u0_a146)
Access: 2017-09-08 17:05:27.000000000
Modify: 2017-09-08 17:10:32.000000000
Change: 2017-09-08 17:10:32.000000000
````
^ Note the value of "Uid" column: 10146
su to switch to that UID:````
$ id
uid=10146(u0_a146) gid=10146(u0_a146) context=u:r:untrusted_app:s0
````
File capabilities should work in that shell.
This is what I've got:
-bash-4.4$ stat /data/data/com.termux/
File: /data/data/com.termux/
Size: 4096 Blocks: 16 IO Block: 4096 directory
Device: b31ch/45852d Inode: 245769 Links: 6
Access: (0700/drwx------) Uid: (10083/ u0_a83) Gid: (10083/ u0_a83)
Access: 2017-07-23 17:09:53.215999793 +0200
Modify: 2017-09-02 14:39:49.684999997 +0200
Change: 2017-09-02 14:39:49.684999997 +0200
Birth: -
-bash-4.4$ su -cn u:r:untrusted_app:s0 -- 10083
bacon:/data/data/com.termux/files/home $ ../usr/bin/getcap ../usr/bin/sshd
../usr/bin/sshd = cap_net_bind_service+ep
bacon:/data/data/com.termux/files/home $ ./capsh --supports=cap_net_bind_service && echo supported || echo unsupported
supported
bacon:/data/data/com.termux/files/home $ ./capsh --caps=cap_net_bind_service+ep
Unable to set capabilities [--caps=cap_net_bind_service+ep]
bacon:/data/data/com.termux/files/home $ id
uid=10083(u0_a83) gid=10083(u0_a83) groups=10083(u0_a83) context=u:r:supersu:s0
sshd since it reports missing library, but the ./capsh --caps=cap_net_bind_service+ep should be enough to test capabilitiesAll the binaries I compiled to run capabilities are static. Is it possible linux is missing a library and hence can't detect capabilities set on files?
@vovcacik
Is it possible linux is missing a library and hence can't detect capabilities set on files?
This can not happen, — file capabilities are kernel feature
I haven't really tried sshd since it reports missing library
My bad, I have forgotten, that su resets environment variables. It is likely failing because su has cleared LD_LIBRARY_PATH.
Try to use su --preserve-environment -cn u:r:untrusted_app:s0 -- 10083. Don't bother with capsh, just run the actual binaries with capabilities to test.
I'm closing this as it doesn't seem to be something that the Termux app can solve.
Most helpful comment
I'm closing this as it doesn't seem to be something that the Termux app can solve.