Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions src/borg/testsuite/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,34 @@ def is_root():
return os.getuid() == 0


@functools.lru_cache
def can_revoke_read_access():
"""Return True if taking away our own read permissions for a file really works.

Highly privileged users can read files no matter what the permissions say: root ignores
the permission bits, and on cygwin a user holding SeBackupPrivilege bypasses the ACL
checks (cygwin always opens files with FILE_OPEN_FOR_BACKUP_INTENT). Tests that need an
unreadable file must be skipped for such users.
"""
if is_win32:
# there, read access is revoked via a deny ACE (see the icacls calls in the tests)
# rather than via chmod, and such an ACE is honoured also for privileged users.
return True
with unopened_tempfile() as filepath:
with open(filepath, "wb") as fd:
fd.write(b"secret")
os.chmod(filepath, 0o000)
try:
with open(filepath, "rb") as fd:
fd.read(1)
except OSError:
return True # good, we can not read it any more.
else:
return False
finally:
os.chmod(filepath, 0o600) # make sure the tempfile can be cleaned up.


@functools.lru_cache
def are_symlinks_supported():
with unopened_tempfile() as filepath:
Expand Down
8 changes: 5 additions & 3 deletions src/borg/testsuite/archiver/create_cmd_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
is_utime_fully_supported,
is_birthtime_fully_supported,
same_ts_ns,
is_root,
can_revoke_read_access,
granularity_sleep,
)
from . import (
Expand Down Expand Up @@ -308,7 +308,7 @@ def test_create_erroneous_file(archivers, request):
assert "input/file3" in out


@pytest.mark.skipif(is_root(), reason="test must not be run as (fake)root")
@pytest.mark.skipif(not can_revoke_read_access(), reason="can not revoke our own read permissions")
def test_create_no_permission_file(archivers, request):
archiver = request.getfixturevalue(archivers)
file_path = os.path.join(archiver.input_path, "file")
Expand All @@ -317,7 +317,9 @@ def test_create_no_permission_file(archivers, request):
create_regular_file(archiver.input_path, file_path + "3", size=1000)
# revoke read permissions on file2 for everybody, including us:
if is_win32:
subprocess.run(["icacls.exe", file_path + "2", "/deny", "everyone:(R)"])
# "*S-1-1-0" is the well-known SID of the "Everyone" group. Using the SID instead of the
# group name keeps this working on non-English Windows installations.
subprocess.run(["icacls.exe", file_path + "2", "/deny", "*S-1-1-0:(R)"])
else:
# note: this will NOT take away read permissions for root
os.chmod(file_path + "2", 0o000)
Expand Down
Loading