gh-152936: Make privileged functions available on Android#152977
gh-152936: Make privileged functions available on Android#152977sabamdarif wants to merge 4 commits into
Conversation
|
Most changes to Python require a NEWS entry. Add one using the blurb_it web app or the blurb command-line tool. If this change has little impact on Python users, wait for a maintainer to apply the |
|
it's my first pr here so i don't know much about the NEWS entry, if it's not a problem can anyone tell me if i do need to add any NEWS entry ? |
Documentation build overview
60 files changed ·
|
thanks for the PR, as per my thought yes, this will need NEWS entry but you can wait for the review and then you can add NEWS entry ( to get 100 % sure 😀) |
|
i have another question for the Android test failure should i update the test_posix.py ? to do something like |
|
why did the Tests / Sanitizers / TSan (free-threading) (pull_request) failed i don't get it ? |
|
We can see that the cause of one of the test failures probably is that the Python test suite has interpreted the unblocking of cpython/Lib/test/test_os/test_posix.py Lines 99 to 105 in 0621639 I would say that yes, the test should probably be modified to check for Android platform, and in the case of Android platform, only test that function if the test is running as root user; however, what I find concerning is that the CI here only produced a failure for x86_64, and not for aarch64, even though in my own separate test, both x86_64 and aarch64 architectures of Android should be returning the same result from the same function:
I wonder if that suggests there is a deeper problem with the tests or an inconsistency somewhere in the test implementation between x86_64 and aarch64. |
|
@robertkirkman yes, let see what others are saying about this . I still didn't get any other comment from any of the core maintainers |
Ah I see, the aarch64 build does not run the test suite in CI, so if it did, it would also have that error. cpython/Platforms/Android/__main__.py Lines 844 to 852 in 881a13a It's possible in theory, in some projects, to implement testing aarch64 Android platform in CI, but in this case, based on my understanding of CPython and Android cumulatively so far, in order to implement that in CPython CI, one of the two following blockers would have to be overcome:
cpython/Platforms/Android/testbed/app/build.gradle.kts Lines 119 to 130 in 881a13a cpython/Platforms/Android/testbed/app/build.gradle.kts Lines 266 to 270 in 881a13a
both of these blockers arise because Google has never officially released any prebuilt Android NDK archives for the platform aarch64 GNU/Linux. If they do in the future some time, that would change. I don't know why the aarch64 macos runner that's currently used to build the aarch64 target Android testbed in CI isn't able to run the managed emulator (technically virtual machine), so I've just described this situation from the perspective I know, which is that of what would be required in the case of using entirely GNU/Linux runners for it. cpython/.github/workflows/build.yml Lines 337 to 349 in 881a13a it is understandable that all of this work is probably not worth it until there is a very important need to run the Android testbed for aarch64 in CI here. |
|
It would be very useful to run the tests on aarch64 on GitHub Actions, but the macOS runner is apparently already a virtual machine, so it can't run the emulator.
But the Android emulator isn't available for aarch64 Linux either. From this discussion, it sounds like it is possible to build it from source, but do you know of any downloadable build which is suitable for production use? |
mhsmith
left a comment
There was a problem hiding this comment.
can anyone tell me if i do need to add any NEWS entry ?
It's a change in behavior, so there should be a NEWS entry in the "Library" section. I think it's enough for it to list the functions and say that they are now available on Android. It doesn't need to go into details of exactly how this was done.
should i update the test_posix.py ? to do something like
if support.is_android and os.getuid() != 0:so it will not failed on PermissionError ? or should i need to update something on my patch so the existing test pass
On Linux, apparently the set...id functions all allow an unprivileged process to set any of the IDs to any of the saved, effective or real IDs (i.e. the values returned by getres...id), or in some cases, -1 to leave the ID unchanged. You should test whether this is true on Android as well, and if so, update the code to allow the function to run under those circumstances. Then the test will pass.
Those tests are unreliable; you can ignore them for now. |
yes, that's completely right; not only would an aarch64 build of the Android NDK probably be required, also an aarch64 build of the emulator would be, though the part of the emulator that I believe would need to be compiled is the part that is mostly formed from QEMU, and doesn't take as long to compile as the entire AVD image would take to build (which I think wouldn't be required), nor as long as the Android NDK would take to build. I agree, though, that both a custom emulator QEMU and a custom NDK are probably too complicated and involve too many unofficial steps for them to be worth using for CPython unless a pressing need for running the aarch64 Android tests in CI is found.
I am not sure exactly what the matrix of crashing vs not crashing looks like for this beyond "some of the functions here cause crashing when called as non-root user", but I can confirm that not all of the functions appear to be able to crash the program, only certain ones or combinations of arguments with certain ones, since I just now checked these several and saw these results, on Samsung Galaxy S8+ SM-G955F with Android 16: does not crash#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("%d\n", setresuid(-1, -1, -1));
}does not crash#include <stdio.h>
#include <unistd.h>
int main(void) {
uid_t r, e, s;
getresuid(&r, &e, &s);
printf("%d\n", setresuid(r, e, s));
}does not crash#include <stdio.h>
#include <unistd.h>
int main(void) {
printf("%d\n", setresuid(0, 0, 0));
}crashes with
|
|
I have just finished creating a custom ROM of the Android Studio Android Virtual Device Android Emulator that has the popular KernelSU implementation of root for Android preconfigured into it. For all non-root tests of this PR this is not important, but for anyone interested in testing the root-only functionality, expand to read further. more informationWhile it is not at all viable for CI anywhere since it is a custom ROM that takes many hours to compile, it might be useful if someone ever wants to manually test the root-only functionality of this PR, or the root-only functionality of the real-world reverse dependency of this PR (potential https://github.com/robertkirkman/kernelsu-goldfish-builder I made this because I was frustrated with the limited options available to most developers who don't have rooted Android for manual testing of root-only Android apps or code. It enables claims like "these functions don't crash the program if run as root user" to be validated objectively by outside testers. |
|
@robertkirkman can you test it https://github.com/sabamdarif/termux-packages/actions/runs/28925155859 and see if posix.setresuid(-1, -1, -1) works for you or not , i test tested it and it didn't actually crash , can you verify that ? |
|
Yes, for me that doesn't crash, when I test that build. |
|
@mhsmith FTR, once we are in the beta cycle, we can't introduce features anymore. Only bug fixes are considered backportable. |
picnixz
left a comment
There was a problem hiding this comment.
Please also add a What's New entry for Python 3.16.
I found the same thing when experimenting with ctypes on API level 36: >>> c = ctypes.CDLL(None, use_errno=True)
>>> c.setresuid(0, 0, 0)
-1
>>> os.strerror(ctypes.get_errno())
'Operation not permitted'On this emulator, when passing all arguments as 0, I can't see any logical reason for this difference, so I guess it may be an oversight which they'll fix in a future version of Android. In which case, it's probably still safer for us to keep the checks in all the functions. |
|
Based on the logcat message, the crash is evidently a deliberate security feature: This occurs even for calls which are supposed to be allowed in unprivileged processes, such as So I think we should disregard what I said before about checking the argument values, keep blocking all the functions when |

os.chroot,initgroups,setegid,seteuid,setgid.... are currently blocked on Android.
Because the underlying C functions crash the process when called by a non-root user on android, rather than returning an error.
So i added getuid() != 0 check (under
#ifdef __ANDROID__) before each call, so it will return PermissionError for non-root just like normal Unix