termux / proot

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

mprotect errors when running cool-retro-term #161

Closed ghost closed 3 years ago

ghost commented 3 years ago

Problem description When i try to run cool-retro-term in Arch Linux proot, it gives problems related to mprotect() system call error and some other Qt applications as well

Screenshot_2021-06-04-12-06-06-27_8659c1e795b4b4239e38d87c88c077b3.jpg

Steps to reproduce

  1. Install Arch Linux proot environment
  2. Do pacman -S cool-retro-term
  3. Run cool-retro-term

Expected behavior It should run with a terminal-retro style

Additional information This also happens in Ubuntu 20.04 as well when Installing cool-retro-term, but it seems this is some sort of Qt-related issue spitting out mprotect permission denied errors, not sure if this is Android specific,

termux-info output:

Application version:
0.113
Packages CPU architecture:
aarch64
Subscribed repositories:
# sources.list
deb https://packages.termux.org/apt/termux-main/ stable main
# game-repo (sources.list.d/game.list)
deb https://packages.termux.org/apt/termux-games games stable
# science-repo (sources.list.d/science.list)
deb https://packages.termux.org/apt/termux-science science stable
# unstable-repo (sources.list.d/unstable.list)
deb https://packages.termux.org/apt/termux-unstable unstable main
# x11-repo (sources.list.d/x11.list)
deb https://packages.termux.org/apt/termux-x11 x11 main
# sources.list.d/pointless.list
deb https://its-pointless.github.io/files/24 termux extras
Updatable packages:
All packages up to date
Android version:
10
Kernel build information:
Linux localhost 4.14.117-perf+ #2 SMP PREEMPT Thu Apr 15 23:25:42 CST 2021 aarch64 Android
Device manufacturer:
OPPO
Device model:
CPH1933

Not sure if this is Android-specific or proot-specific bug, but any answers is appreciated! thanks

ghost commented 3 years ago

This has something to do with Android, apparently mprotect and shared memory has issues with it, so apparently it is no-fix. closing this issue

michalbednarski commented 3 years ago

Sorry, I've had this issue analysed then forgot about it

Qt uses memfd_create() in order to create named memory allocation, however on Android such mapping cannot be made executable. When memfd_create() fails it'll fall back to using anonymous mapping.

Qt already handles this case when targeting Android (building QML application into .apk, but in this case we have Qt built for non-Android Linux) https://code.woboq.org/qt5/qtdeclarative/src/3rdparty/masm/wtf/OSAllocatorPosix.cpp.html#48

Probably could be fixed by intercepting memfd_create() and failing it (if name matches one of those Qt uses for executable code)

ghost commented 3 years ago

alright. i'mma reopening this issue

michalbednarski commented 3 years ago

So I've committed fix for mprotect failure, however at least on my device it looks like cool-retro-term still doesn't start shell, although it does render screen.

You can check fix so far by building proot from source

I'll yet have to still look at remaining issues

ghost commented 3 years ago

Hi @michalbednarski I compiled proot from source then installed it somehow it still spits out same mprotect errors although i tested on Ubuntu 20.04 this time (i'm on android 11 now)

am i missing something? i even tried to replace proot binary completly but still doesn't work somehow

ghost commented 3 years ago

actually that works on Debian sid (bullseye) and Arch Linux but not Ubuntu 20.04

Screenshot_2021-07-29-17-56-14-26_86e29ab1b9fd3f2a477a649413bc8db4.jpg

i had no idea why it didn't work on ubuntu 20.04 but atleast it works tho

ghost commented 3 years ago

Is that fixed yet?

ghost commented 3 years ago

Ubuntu 20.04 works with cool-retro-term

Screenshot_2021-07-30-09-28-37-05_00dcaf2fcbe692c602a0957f19a66664.jpg

instead of maybe denying memfd_create for specific call for qt (maybe for different versions of qt), probably i guess it can be denied in entirely?

diff --git a/src/syscall/enter.c b/src/syscall/enter.c
index f936d4d..8d79643 100644
--- a/src/syscall/enter.c
+++ b/src/syscall/enter.c
@@ -612,9 +612,7 @@ int translate_syscall_enter(Tracee *tracee)
            }
            /* If this memfd is one of those used by Qt/QML for executable code,
             * deny memfd_create() call and let Qt fall back to anonymous mmap.  */
-           if (0 == strcmp(memfd_name, "JITCode:QtQml")) {
-               status = -EACCES;
-           }
+           status = -EACCES;
            break;
        }
    }

apparently it is differing on different versions of qt, one in Debian sid/arch works but not Ubuntu 20.04 (which it may have different versions of qt)

michalbednarski commented 3 years ago

With further testing of cool-retro-term I've found additional issues:

Since Qt writes QSettings .ini files through open(O_TMPFILE) + linkat("/proc/self/fd/..."), after first when creating settings database through QtQuick.LocalStorage (cool-retro-term side source) (Qt side source), .sqlite file is created but no corresponding .ini file, so after first run following runs won't spawn shell.

I'm not sure about denying open(O_TMPFILE), while that would be easiest fix I think that could break other apps.

Following could be worked around by manually creating needed .ini file after first run

echo -e '[General]\nDescription=StorageDatabase\nDriver=QSQLITE\nEstimatedSize=100000\nName=coolretroterm1\nVersion=1.0' > ~/.local/share/cool-retro-term/QML/OfflineStorage/Databases/27e743fe85b8912a46804fed99e8a9ab.ini

(Otherwise terminal will be nonfunctional, same happens on desktop when .sqlite file is present but .ini file is missing, alternatively remove .sqlite file)

(Hash in file name is md5("coolretroterm1"))


Second issue is that when running proot without seccomp acceleration (either due to PROOT_NO_SECCOMP=1 PROOT_ASSUME_NEW_SECCOMP=1 proot run or due to debugger being attached inside proot), PRoots handle_statx_syscall is called twice per tracee syscall, once from syscall exit handler and second time due to SIGSYS. When doing statx(fd, "", AT_EMPTY_PATH, ...), first execution succeeds and set x0 register to 0 to mark success, then next invocation will see fd argument in x0 being set to zero add will stat wrong file (In this case /dev/null, providing stx_size=0 and making QSettings skip reading file.


Third is that when touching terminal in XServer XSDL, cool-retro-term crashes with stack overflow, though haven't debugged this one yet as so far I've had tested with Qt built without XInput support.

ghost commented 3 years ago

XServer XSDL problem Touching terminal and it crash

ghost commented 3 years ago

It seems everything is working now

Screenshot_2021-08-16-15-06-17-32_86e29ab1b9fd3f2a477a649413bc8db4.jpg

cool-retro-term seems to work as intended and fixed issues regarding shell isn't starting

i guess this applies to all qt applications as well

michalbednarski commented 3 years ago

Fixed version (mprotect and linkat issue) is now available in Termux apt repo