-
-
Notifications
You must be signed in to change notification settings - Fork 30.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
os.getgrouplist() can fail on macOS if the user has more than 17 groups #84195
Comments
example: https://github.com/python/cpython/pull/19073/checks?check_run_id=519539592 I suggest to not to add information for os.getgrouplist |
or adding <OSError> might be great just like getpwuid |
These errors are really strange. Steve Dower: are you aware of anything recent change on the macOS job of Azure Pipelines / GH Actions. pythoninfo: platform.architecture: 64bit platform.platform: macOS-10.15.3-x86_64-i386-64bit
./python.exe -m test.pythoninfo
ERROR: collect_pwd() failed
Traceback (most recent call last):
File "/Users/runner/runners/2.165.2/work/cpython/cpython/Lib/test/pythoninfo.py", line 761, in collect_info
collect_func(info_add)
File "/Users/runner/runners/2.165.2/work/cpython/cpython/Lib/test/pythoninfo.py", line 336, in collect_pwd
groups = os.getgrouplist(entry.pw_name, entry.pw_gid)
OSError: [Errno 0] Error Collection failed: exit with error test_posix.test_getgrouplist() failed with: ====================================================================== Traceback (most recent call last):
File "/Users/runner/runners/2.165.2/work/cpython/cpython/Lib/test/test_posix.py", line 1028, in test_getgrouplist
self.assertIn(group, posix.getgrouplist(user, group))
OSError: [Errno 25] Inappropriate ioctl for device |
This error has to do with the number of groups a particular user is associated with. We’ve squashed similar bugs in the past but it looks like something has changed again in recent releases of macOS. It’s not Azure specific. |
tl; dr os.getgrouplist() is limited to 17 groups and fails with a random OSError if the request user has more groups. PR 19118 fix the issue. -- On macOS-10.15.1-x86_64-i386-64bit (python -m platform), os.getgrouplist() fails with my user name and group identifier: >>> os.getgrouplist('haypo', 20)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error Full example: macbook:master haypo$ ./python.exe
Python 3.9.0a4+ (heads/master:da2914d, Mar 20 2020, 09:45:36)
[Clang 11.0.0 (clang-1100.0.33.8)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import os, pwd
>>> entry=pwd.getpwuid(os.getuid())
>>> os.getgrouplist(entry.pw_name, entry.pw_gid)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
InterruptedError: [Errno 4] Interrupted system call
>>> os.getgrouplist(entry.pw_name, entry.pw_gid)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
OSError: [Errno 0] Error
>>> entry
pwd.struct_passwd(pw_name='haypo', pw_passwd='********', pw_uid=502, pw_gid=20, pw_gecos='Victor Stinner', pw_dir='/Users/haypo', pw_shell='/bin/bash') My user has the following groups: macbook:master haypo$ id My user has 18 groups. MAX_GROUPS=16, Python uses 1 + MAX_GROUPS. getgrouplist() manual page says: RETURN VALUES In short, getgrouplist() doesn't set errno on failure. |
Python 3.7 and 3.8 are also affected on macOS 10.15 (Catalina). |
Thanks for the PR, Victor, it does address the problem. I went back and explicitly tested on macOS 10.14 and 10.13 by creating some more groups and adding the user to them and the same failure occurred there so this is not just a 10.15 issue. Most likely this hasn't been an issue before is that 10.15 creates more groups for system services than the earlier versions did. So the PR should be updated to remove the 10.15 (and 10.5!) references. |
Aha, interesting. I updated my PR to remove mentions of the macOS version number. I just wrote "on macOS". Yeah, I wouldn't be surprised that the function always failed. -- I'm not sure that the Linux implementation is correct. It rely on errno, whereas Linux manual page of getgrouplist() doesn't say anything about errno being set on error. Moreover, on Linux, getgrouplist() can also fail with -1 if the group list is too small. In that case, ngroups is updated to the number of groups and so can be used to enlarge the list! |
test.pythoninfo of the macOS job on the PR: os.getgrouplist: 20, 0, 12, 61, 79, 80, 81, 98, 264, 399, 701, 33, 100, 204, 250, 395, 398, 400 So yeah, there are 18 groups ;-) |
I tested by manually initializing ngroups to a value way lower than MAX_GROUPS (65536 on my Fedora 31): os.getgrouplist() raises OSError() with a random errno, getgrouplist() doesn't set errno on failure. I wrote PR 19126 to fix the issue on all platforms. The glibc implementation is detected and used: use updated ngroups value (only if it's larger). |
Ned: so Linux was also impacted, but Linux only has an issue with more than 65536 groups :-D macOS MAX_GROUPS is now only 16 (Python uses MAX_GROUPS+1)! Maybe MAX_GROUPS was reduced recently. I'm not sure. Anyway, os.getgrouplist() does no longer depend on MAX_GROUPS hardcoded limit, but grow the group list dynamically. It should now work with any number of groups an all platforms (which provide the getgrouplist() function ;-)) on Python 3.7, 3.8 and master branches. Thanks Dong-hee Na for the bug report and your PR. |
Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.
Show more details
GitHub fields:
bugs.python.org fields:
The text was updated successfully, but these errors were encountered: