Please check the video I recorded. Non-character keys are actually handled as expected, but immediate visual response only represents the related escape sequence - it's difficult, when not impossible, to take advantage of auto-completion, history and such. This happens in Termux with both su and tsu scripts and is keyboard-independent; root shells behave correctly in other terminal apps and over adb.
I'm using MAGISKSU binary from Magisk 15.3 on Oreo 8.0; my device is a Moto Z2 Force. Not sure if that was happening even on Nougat.
Same problem here. My device is Oneplus5T, with Oreo 8.0 + Magisk 15.3.
Well this one is due to all them SELinux changes Oreo introduced.
More specifically the culprit is this rule:
allowxperm untrusted_app untrusted_app_devpts:chr_file ioctl { 0x5401-0x5403 0x540b 0x540e-0x5411 0x5413-0x5414 0x5451 };
Well guess which ioctl gets called by Termux when dropping into a su shell?
0x5404
You can inject this rule to rectify the issue:
magiskpolicy --live "allowxperm untrusted_app untrusted_app_devpts chr_file ioctl 0x5404"
Also note that 0x5404 is the TCSETSF ioctl.
( Except apparently on the mips platform ).
Since Termux is a good citizen it doesn't use a lot of ioctls directly but go through termios.
And that's where you'll find the culprit.
If you have ndk-sysroot installed you can verify that by yourself:
/data/data/com.termux/files/usr/include/bits/termios_inlines.h:
__BIONIC_TERMIOS_INLINE int tcsetattr(int fd, int optional_actions, const struct termios* s) {
int cmd; switch (optional_actions) { case TCSANOW: cmd = TCSETS; break;
case TCSADRAIN: cmd = TCSETSW; break;
case TCSAFLUSH: cmd = TCSETSF; break;
default: errno = EINVAL; return -1;
}
return ioctl(fd, cmd, s);
}
@vczilla Nice description of the problem!
Well guess which ioctl gets called by Termux when dropping into a su shell?
0x5404
Is this call made by the Magisk binary, so a fix has to be applied there? Or is it anything Termux can do here?
Well spotted , I also think the problem comes from Magisk:
Basically when su gets called and marshalls its parameters and pts to the daemon it calls this function:
pump_stdin_async(ptmx);
Which in turn calls:
set_stdin_raw();
And in there you'll find this call:
tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios)
I think that's the offender.
Note that Magisk injects these rules:
// xperms
if (policydb->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) {
sepol_allowxperm("domain", "devpts", "chr_file", "0x5400-0x54FF");
if (sepol_exists("untrusted_app_25_devpts"))
sepol_allowxperm("domain", "untrusted_app_25_devpts", "chr_file", "0x5400-0x54FF");
}
The trouble is Termux runs in the untrusted_app context since it targets an API level>=26.
But yeah the fix is easy enough , so I guess I should probably open an issue on Magisk github.
@vczilla Thanks a lot for the nice investigation! Can you open an issue there and link to that issue from here? I'm closing this then, as it's nothing we can do from the Termux side.
Most helpful comment
Well this one is due to all them SELinux changes Oreo introduced.
More specifically the culprit is this rule:
Well guess which ioctl gets called by Termux when dropping into a su shell?
0x5404
You can inject this rule to rectify the issue: