Keep package directories accessible under restrictive build umasks
Release / release (push) Successful in 1m14s
Release / release (push) Successful in 1m14s
This commit is contained in:
@@ -21,6 +21,7 @@ backfill releases from before this changelog.
|
|||||||
- Preserve historical selections and store-fault messages through graph refresh and resize.
|
- Preserve historical selections and store-fault messages through graph refresh and resize.
|
||||||
- Show hourly drill-down results without overwriting them with a loading placeholder.
|
- Show hourly drill-down results without overwriting them with a loading placeholder.
|
||||||
- Keep known unallocated daily volume visible across coverage gaps, and distinguish missing hourly evidence from zero on small terminals.
|
- Keep known unallocated daily volume visible across coverage gaps, and distinguish missing hourly evidence from zero on small terminals.
|
||||||
|
- Stage package directories with consistent public permissions, avoiding openSUSE RPM conflicts and inaccessible runtime paths when built with a restrictive umask.
|
||||||
|
|
||||||
## [0.4.0] - 2026-09-18
|
## [0.4.0] - 2026-09-18
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,10 @@
|
|||||||
# /usr/lib/tmpfiles.d/fenris.conf
|
# /usr/lib/tmpfiles.d/fenris.conf
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
|
# Package directories must be traversable by every runtime user and agree
|
||||||
|
# with distribution-owned directories, regardless of the builder's umask.
|
||||||
|
umask 022
|
||||||
|
|
||||||
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
STAGE_DIR="${REPO_ROOT}/build/stage"
|
STAGE_DIR="${REPO_ROOT}/build/stage"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,43 @@
|
|||||||
|
"""Package directory permissions must not inherit a builder's private umask."""
|
||||||
|
import os
|
||||||
|
import shutil
|
||||||
|
import subprocess
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("mask", ["077", "022"])
|
||||||
|
def test_stage_is_publicly_traversable_under_any_builder_umask(tmp_path, mask):
|
||||||
|
root = Path(__file__).resolve().parent.parent
|
||||||
|
for directory in ("packaging", "scripts", "src", "units", "polkit"):
|
||||||
|
shutil.copytree(root / directory, tmp_path / directory,
|
||||||
|
ignore=shutil.ignore_patterns("__pycache__", "*.egg-info"))
|
||||||
|
for filename in ("LICENSE", "requirements.txt"):
|
||||||
|
shutil.copy(root / filename, tmp_path / filename)
|
||||||
|
(tmp_path / "dist").mkdir()
|
||||||
|
(tmp_path / "dist/fenris-9.9.9-py3-none-any.whl").touch()
|
||||||
|
bin_dir = tmp_path / "bin"
|
||||||
|
bin_dir.mkdir()
|
||||||
|
# Avoid downloading dependencies: emulate pip's target output while
|
||||||
|
# exercising the real staging script and its package directory layout.
|
||||||
|
pip_stub = bin_dir / "python3"
|
||||||
|
pip_stub.write_text(
|
||||||
|
f"#!{sys.executable}\n"
|
||||||
|
"import sys\nfrom pathlib import Path\n"
|
||||||
|
"target = Path(sys.argv[sys.argv.index('--target') + 1]) / 'fenris'\n"
|
||||||
|
"target.mkdir(parents=True)\n"
|
||||||
|
"(target / '__init__.py').write_text('')\n"
|
||||||
|
)
|
||||||
|
pip_stub.chmod(0o755)
|
||||||
|
subprocess.run(
|
||||||
|
["bash", "-c", f"umask {mask}; exec bash packaging/stage.sh 9.9.9"],
|
||||||
|
cwd=tmp_path, env={**os.environ, "PATH": str(bin_dir) + os.pathsep + os.environ["PATH"]},
|
||||||
|
check=True, capture_output=True, text=True,
|
||||||
|
)
|
||||||
|
stage = tmp_path / "build/stage"
|
||||||
|
for directory in (stage, *(p for p in stage.rglob("*") if p.is_dir())):
|
||||||
|
assert directory.stat().st_mode & 0o777 == 0o755, directory
|
||||||
|
assert (stage / "usr/bin/fenris").stat().st_mode & 0o777 == 0o755
|
||||||
|
assert (stage / "opt/fenris/vendor/fenris/__init__.py").stat().st_mode & 0o444 == 0o444
|
||||||
Reference in New Issue
Block a user