56 lines
2.5 KiB
Python
56 lines
2.5 KiB
Python
from __future__ import annotations
|
|
|
|
import os
|
|
import fcntl
|
|
import struct
|
|
import sys
|
|
|
|
import pytest
|
|
|
|
from tht.workspace_writer_lock import WorkspaceWriterConflict, verify_workspace_writer_fds
|
|
|
|
|
|
def test_verifier_rejects_missing_capability():
|
|
with pytest.raises(WorkspaceWriterConflict): verify_workspace_writer_fds(env={})
|
|
|
|
def test_verifier_checks_fd_identity(tmp_path):
|
|
root=tmp_path / "root"; root.mkdir(mode=0o700); writer=root / "writer.lock"; writer.touch(mode=0o600)
|
|
r=os.open(root, os.O_RDONLY); w=os.open(writer, os.O_RDWR)
|
|
try:
|
|
fcntl.flock(w, fcntl.LOCK_EX | fcntl.LOCK_NB)
|
|
if hasattr(fcntl, "F_OFD_SETLK") and sys.platform.startswith("linux"):
|
|
fcntl.fcntl(w, fcntl.F_OFD_SETLK, struct.pack("hhqqi", fcntl.F_WRLCK, os.SEEK_SET, 0, 0, 0))
|
|
st=os.fstat(r); env={"THOTH_WORKSPACE_ID":"abc-workspace", "THOTH_WORKSPACE_REVISION":"a"*40, "THOTH_WORKSPACE_DEVICE":str(st.st_dev), "THOTH_WORKSPACE_INODE":str(st.st_ino)}
|
|
cap=verify_workspace_writer_fds(writer_fd=w, root_fd=r, env=env)
|
|
assert cap.inode == st.st_ino
|
|
finally: os.close(w); os.close(r)
|
|
|
|
|
|
def test_verifier_rejects_unrelated_lock(tmp_path):
|
|
root = tmp_path / "root"; other = tmp_path / "other"
|
|
root.mkdir(mode=0o700); other.mkdir(mode=0o700)
|
|
expected = root / "writer.lock"; forged = other / "forged.lock"
|
|
expected.touch(mode=0o600); forged.touch(mode=0o600)
|
|
root_fd = os.open(root, os.O_RDONLY); forged_fd = os.open(forged, os.O_RDWR)
|
|
try:
|
|
st = os.fstat(root_fd)
|
|
env = {"THOTH_WORKSPACE_ID": "abc-workspace", "THOTH_WORKSPACE_REVISION": "a" * 40, "THOTH_WORKSPACE_DEVICE": str(st.st_dev), "THOTH_WORKSPACE_INODE": str(st.st_ino)}
|
|
with pytest.raises(WorkspaceWriterConflict):
|
|
verify_workspace_writer_fds(writer_fd=forged_fd, root_fd=root_fd, env=env)
|
|
finally:
|
|
os.close(forged_fd); os.close(root_fd)
|
|
|
|
|
|
def test_verifier_rejects_independently_opened_unlocked_writer_fd(tmp_path):
|
|
root = tmp_path / "root"; root.mkdir(mode=0o700)
|
|
writer = root / "writer.lock"; writer.touch(mode=0o600)
|
|
root_fd = os.open(root, os.O_RDONLY)
|
|
writer_fd = os.open(writer, os.O_RDWR)
|
|
try:
|
|
st = os.fstat(root_fd)
|
|
env = {"THOTH_WORKSPACE_ID": "abc-workspace", "THOTH_WORKSPACE_REVISION": "a" * 40, "THOTH_WORKSPACE_DEVICE": str(st.st_dev), "THOTH_WORKSPACE_INODE": str(st.st_ino)}
|
|
with pytest.raises(WorkspaceWriterConflict):
|
|
verify_workspace_writer_fds(writer_fd=writer_fd, root_fd=root_fd, env=env)
|
|
finally:
|
|
os.close(writer_fd); os.close(root_fd)
|