Repository navigation
posixpath.realpath('secretlink') raises #118447
Description
Activity
- addedtype-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error
on Apr 30, 2024 Setting permissions on a symlink is a BSD (including macOS) feature. Linux doesn't allow it. Testing this should be limited to platforms with
os.chmod in os.supports_follow_symlinks.Reacted by Nice ZombiesUpon closer inspection, this is a bug in coreutils:
wannes@Stefans-iMac dirs % sudo ls -l secret-recursive-symlink l--------- 1 wannes staff 40 Jun 30 2023 secret-recursive-symlink -> /Users/wannes/path-picker/link-test/dirs wannes@Stefans-iMac dirs % sudo realpath secret-recursive-symlink/.. /Users/wannes/path-picker/link-test wannes@Stefans-iMac dirs % grealpath -m secret-recursive-symlink/.. /Users/wannes/path-picker/link-test/dirs
I wouldn't expect
os.path.realpath(..., strict=False)to raiseOSError, no matter what coreutils does!That's probably a reason which this is not part of POSIX... I expected you needed permission to follow it, not to determine the real location.
Return the canonical path of the specified filename, eliminating any symbolic links encountered in the path.
We can't eliminate this symlink, because we don't know where it points to,
which we need to know for determining the parent directory. Also, coreutils doesn't even raise an error in strict mode:wannes@Stefans-iMac ~ % ln -s . src wannes@Stefans-iMac ~ % grealpath -e src/.. /Users wannes@Stefans-iMac ~ % chmod -h 000 src wannes@Stefans-iMac ~ % grealpath -e src/.. /Users/wannes
Raising an error here will lead to the fewest bugs.On macOS and NetBSD,
fcntl()supportsF_GETPATH. In that case, you could try to open "secret-symlink" and query the resolved path, e.g.target = os.fsdecode(fcntl.fcntl(fd, fcntl.F_GETPATH, bytes(1024))). You may have to revisit the design offcntl.fcntl()to make it use an internal buffer bigger than 1024 bytes, though I think that's currently the maximum path length supported by macOS.Reacted by Nice ZombiesThat works:
>>> import fcntl >>> import os >>> os.symlink('.', 'src') >>> os.chmod('src', 0o000, follow_symlinks=False) >>> os.readlink('src') Traceback (most recent call last): File "<stdin>", line 1, in <module> PermissionError: [Errno 13] Permission denied: 'src' >>> fd = os.open('src', os.O_RDONLY) >>> os.fsdecode(fcntl.fcntl(fd, fcntl.F_GETPATH, bytes(1024))).rstrip('\x00') '/Users/wannes'
But I think it might be cleaner to fix this in readlink...
But it doesn't work for broken symlinks:
>>> import fcntl >>> import os >>> open('tmp', 'w', encoding='utf-8') <_io.TextIOWrapper name='tmp' mode='w' encoding='utf-8'> >>> os.symlink('tmp', 'dst') >>> os.unlink('tmp') >>> os.chmod('dst', 0o000, follow_symlinks=False) >>> os.readlink('dst') Traceback (most recent call last): File "<stdin>", line 1, in <module> PermissionError: [Errno 13] Permission denied: 'dst' >>> fd = os.open('dst', os.O_RDONLY) Traceback (most recent call last): File "<stdin>", line 1, in <module> FileNotFoundError: [Errno 2] No such file or directory: 'dst'
- added a commit that references this issue
on May 18, 2024 - added 5 commits that reference this issue
on May 18, 2024 With the FreeBSD test failures fixed, we can close this.
Bug report
Bug description:
GNU coreutils
realpath -mdoesn't raise an error for secret symlinks (no read permission):But
posixpath.realpath()does:CPython versions tested on:
3.12
Operating systems tested on:
macOS
Linked PRs
os.path.realpath()#118489os.path.realpath()(GH-118489) #119163