Skip to content
50 changes: 40 additions & 10 deletions Doc/library/os.rst
Original file line number Diff line number Diff line change
Expand Up @@ -574,10 +574,13 @@ process and user.
the groups of which the specified username is a member, plus the specified
group id.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.
Comment thread
sabamdarif marked this conversation as resolved.

.. versionadded:: 3.2

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: putenv(key, value, /)

Expand Down Expand Up @@ -610,21 +613,30 @@ process and user.

Set the current process's effective group id.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: seteuid(euid, /)

Set the current process's effective user id.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: setgid(gid, /)

Set the current process' group id.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: setgroups(groups, /)
Expand Down Expand Up @@ -718,32 +730,44 @@ process and user.

Set the current process's real and effective group ids.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: setresgid(rgid, egid, sgid, /)

Set the current process's real, effective, and saved group ids.

.. availability:: Unix, not WASI, not Android, not macOS, not iOS.
.. availability:: Unix, not WASI, not macOS, not iOS.

.. versionadded:: 3.2

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: setresuid(ruid, euid, suid, /)

Set the current process's real, effective, and saved user ids.

.. availability:: Unix, not WASI, not Android, not macOS, not iOS.
.. availability:: Unix, not WASI, not macOS, not iOS.

.. versionadded:: 3.2

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: setreuid(ruid, euid, /)

Set the current process's real and effective user ids.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: getsid(pid, /)
Expand All @@ -766,7 +790,10 @@ process and user.

Set the current process's user id.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.16
Support for Android now exists.


.. placed in this section since it relates to errno.... a little weak
Expand Down Expand Up @@ -2324,11 +2351,14 @@ features:

Change the root directory of the current process to *path*.

.. availability:: Unix, not WASI, not Android.
.. availability:: Unix, not WASI.

.. versionchanged:: 3.6
Accepts a :term:`path-like object`.

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: fchdir(fd)

Expand Down
5 changes: 4 additions & 1 deletion Doc/library/socket.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1372,10 +1372,13 @@ The :mod:`!socket` module also offers various network-related services:

.. audit-event:: socket.sethostname name socket.sethostname

.. availability:: Unix, not Android.
.. availability:: Unix.

.. versionadded:: 3.3

.. versionchanged:: 3.16
Support for Android now exists.


.. function:: if_nameindex()

Expand Down
17 changes: 17 additions & 0 deletions Doc/whatsnew/3.16.rst
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,14 @@ os
process via a pidfd. Available on Linux 5.6+.
(Contributed by Maurycy Pawłowski-Wieroński in :gh:`149464`.)

* The following functions are now available on Android:
:func:`os.chroot`, :func:`os.initgroups`, :func:`os.setegid`,
:func:`os.seteuid`, :func:`os.setgid`, :func:`os.setregid`,
:func:`os.setresgid`, :func:`os.setresuid`, :func:`os.setreuid`,
and :func:`os.setuid`. Calling them without sufficient privileges
now raises :exc:`PermissionError` instead of the functions being unavailable.
(Contributed by Md Arif in :gh:`152936`.)


pydoc
-----
Expand Down Expand Up @@ -482,6 +490,15 @@ shlex
(Contributed by Jay Berry in :gh:`148846`.)


socket
------

* The :func:`socket.sethostname` function is now available on Android.
Calling it without sufficient privileges now raises :exc:`PermissionError`
instead of the function being unavailable.
(Contributed by Md Arif in :gh:`152936`.)


sqlite3
-------

Expand Down
8 changes: 8 additions & 0 deletions Lib/test/test_os/test_posix.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,10 @@ def test_getresgid(self):
@unittest.skipUnless(hasattr(posix, 'setresuid'),
'test needs posix.setresuid()')
def test_setresuid(self):
# Android blocks this function for non-root users regardless of the arguments.
if support.is_android and os.getuid() != 0:
self.assertRaises(PermissionError, posix.setresuid, -1, -1, -1)
return
current_user_ids = posix.getresuid()
self.assertIsNone(posix.setresuid(*current_user_ids))
# -1 means don't change that value.
Expand All @@ -124,6 +128,10 @@ def test_setresuid_exception(self):
@unittest.skipUnless(hasattr(posix, 'setresgid'),
'test needs posix.setresgid()')
def test_setresgid(self):
# Android blocks this function for non-root users regardless of the arguments.
if support.is_android and os.getuid() != 0:
self.assertRaises(PermissionError, posix.setresgid, -1, -1, -1)
return
current_group_ids = posix.getresgid()
self.assertIsNone(posix.setresgid(*current_group_ids))
# -1 means don't change that value.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
:func:`os.chroot`, :func:`os.initgroups`, :func:`os.setegid`,
:func:`os.seteuid`, :func:`os.setgid`, :func:`os.setregid`,
:func:`os.setresgid`, :func:`os.setresuid`, :func:`os.setreuid`,
:func:`os.setuid`, and :func:`socket.sethostname` are now available on
Android. Calling them without sufficient privileges now raises
:exc:`PermissionError` instead of the functions being unavailable.
80 changes: 80 additions & 0 deletions Modules/posixmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -4399,6 +4399,14 @@ static PyObject *
os_chroot_impl(PyObject *module, path_t *path)
/*[clinic end generated code: output=de80befc763a4475 input=14822965652c3dc3]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return path_error(path);
}
#endif
int res;
Py_BEGIN_ALLOW_THREADS
res = chroot(path->narrow);
Expand Down Expand Up @@ -9875,6 +9883,14 @@ os_initgroups_impl(PyObject *module, PyObject *oname, gid_t gid)
/*[clinic end generated code: output=59341244521a9e3f input=7e4514dff4526a95]*/
#endif
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
const char *username = PyBytes_AS_STRING(oname);

if (initgroups(username, gid) == -1)
Expand Down Expand Up @@ -10301,6 +10317,14 @@ static PyObject *
os_setuid_impl(PyObject *module, uid_t uid)
/*[clinic end generated code: output=a0a41fd0d1ec555f input=c921a3285aa22256]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setuid(uid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand All @@ -10322,6 +10346,14 @@ static PyObject *
os_seteuid_impl(PyObject *module, uid_t euid)
/*[clinic end generated code: output=102e3ad98361519a input=ba93d927e4781aa9]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (seteuid(euid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand All @@ -10343,6 +10375,14 @@ static PyObject *
os_setegid_impl(PyObject *module, gid_t egid)
/*[clinic end generated code: output=4e4b825a6a10258d input=4080526d0ccd6ce3]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setegid(egid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand All @@ -10365,6 +10405,14 @@ static PyObject *
os_setreuid_impl(PyObject *module, uid_t ruid, uid_t euid)
/*[clinic end generated code: output=62d991210006530a input=0ca8978de663880c]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setreuid(ruid, euid) < 0) {
return posix_error();
} else {
Expand All @@ -10389,6 +10437,14 @@ static PyObject *
os_setregid_impl(PyObject *module, gid_t rgid, gid_t egid)
/*[clinic end generated code: output=aa803835cf5342f3 input=c59499f72846db78]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setregid(rgid, egid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand All @@ -10409,6 +10465,14 @@ static PyObject *
os_setgid_impl(PyObject *module, gid_t gid)
/*[clinic end generated code: output=bdccd7403f6ad8c3 input=27d30c4059045dc6]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setgid(gid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand Down Expand Up @@ -15506,6 +15570,14 @@ static PyObject *
os_setresuid_impl(PyObject *module, uid_t ruid, uid_t euid, uid_t suid)
/*[clinic end generated code: output=834a641e15373e97 input=9e33cb79a82792f3]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setresuid(ruid, euid, suid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand All @@ -15529,6 +15601,14 @@ static PyObject *
os_setresgid_impl(PyObject *module, gid_t rgid, gid_t egid, gid_t sgid)
/*[clinic end generated code: output=6aa402f3d2e514a9 input=33e9e0785ef426b1]*/
{
#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return posix_error();
}
#endif
if (setresgid(rgid, egid, sgid) < 0)
return posix_error();
Py_RETURN_NONE;
Expand Down
9 changes: 9 additions & 0 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -5988,6 +5988,15 @@ _socket_sethostname(PyObject *module, PyObject *hnobj)
Py_buffer buf;
int res, flag = 0;

#ifdef __ANDROID__
// On Android, calling this function as a non-root user leads to a process crash
// rather than returning a permission error.
if (getuid() != 0) {
errno = EPERM;
return set_error();
}
#endif

#if defined(_AIX) || (defined(__sun) && defined(__SVR4) && Py_SUNOS_VERSION <= 510)
/* issue #18259, sethostname is not declared in any useful header file on AIX
* the same is true for Solaris 10 */
Expand Down
7 changes: 1 addition & 6 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

7 changes: 1 addition & 6 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -5492,14 +5492,9 @@ else
fi

if test "$ac_sys_system" = "Linux-android"; then
# When these functions are used in an unprivileged process, they crash rather
# than returning an error.
blocked_funcs="chroot initgroups setegid seteuid setgid sethostname
setregid setresgid setresuid setreuid setuid"

# These functions are unimplemented and always return an error
# (https://android.googlesource.com/platform/system/sepolicy/+/refs/heads/android13-release/public/domain.te#1044)
blocked_funcs="$blocked_funcs sem_open sem_unlink"
blocked_funcs="sem_open sem_unlink"

# Before API level 23, when fchmodat is called with the unimplemented flag
# AT_SYMLINK_NOFOLLOW, instead of returning ENOTSUP as it should, it actually
Expand Down
Loading