Handle OSError / Filesystem corruptions (#4127)

* Handle OSError / Filesystem corruptions

* Fix tests
This commit is contained in:
Pascal Vizeli
2023-02-28 19:57:05 +01:00
committed by GitHub
parent 440379680e
commit 692d34a13c
4 changed files with 21 additions and 9 deletions

View File

@@ -69,6 +69,7 @@ class IssueType(str, Enum):
CORRUPT_DOCKER = "corrupt_docker" CORRUPT_DOCKER = "corrupt_docker"
CORRUPT_REPOSITORY = "corrupt_repository" CORRUPT_REPOSITORY = "corrupt_repository"
CORRUPT_FILESYSTEM = "corrupt_filesystem"
DNS_LOOP = "dns_loop" DNS_LOOP = "dns_loop"
DNS_SERVER_FAILED = "dns_server_failed" DNS_SERVER_FAILED = "dns_server_failed"
DNS_SERVER_IPV6_ERROR = "dns_server_ipv6_error" DNS_SERVER_IPV6_ERROR = "dns_server_ipv6_error"

View File

@@ -6,7 +6,7 @@ from ...const import CoreState
from ...coresys import CoreSys from ...coresys import CoreSys
from ...exceptions import CodeNotaryError, CodeNotaryUntrusted from ...exceptions import CodeNotaryError, CodeNotaryUntrusted
from ...utils.codenotary import calc_checksum_path_sourcecode from ...utils.codenotary import calc_checksum_path_sourcecode
from ..const import UnsupportedReason from ..const import ContextType, IssueType, UnsupportedReason
from .base import EvaluateBase from .base import EvaluateBase
_SUPERVISOR_SOURCE = Path("/usr/src/supervisor/supervisor") _SUPERVISOR_SOURCE = Path("/usr/src/supervisor/supervisor")
@@ -36,17 +36,25 @@ class EvaluateSourceMods(EvaluateBase):
"""Return a list of valid states when this evaluation can run.""" """Return a list of valid states when this evaluation can run."""
return [CoreState.RUNNING] return [CoreState.RUNNING]
async def evaluate(self) -> None: async def evaluate(self) -> bool:
"""Run evaluation.""" """Run evaluation."""
if not self.sys_security.content_trust: if not self.sys_security.content_trust:
_LOGGER.warning("Disabled content-trust, skipping evaluation") _LOGGER.warning("Disabled content-trust, skipping evaluation")
return return False
# Calculate sume of the sourcecode # Calculate sume of the sourcecode
checksum = await self.sys_run_in_executor( try:
calc_checksum_path_sourcecode, _SUPERVISOR_SOURCE checksum = await self.sys_run_in_executor(
) calc_checksum_path_sourcecode, _SUPERVISOR_SOURCE
)
except OSError as err:
self.sys_resolution.create_issue(
IssueType.CORRUPT_FILESYSTEM, ContextType.SYSTEM
)
_LOGGER.error("Can't calculate checksum of source code: %s", err)
return False
# Validate checksum
try: try:
await self.sys_security.verify_own_content(checksum) await self.sys_security.verify_own_content(checksum)
except CodeNotaryUntrusted: except CodeNotaryUntrusted:

View File

@@ -36,7 +36,10 @@ def calc_checksum(data: str | bytes) -> str:
def calc_checksum_path_sourcecode(folder: Path) -> str: def calc_checksum_path_sourcecode(folder: Path) -> str:
"""Calculate checksum for a path source code.""" """Calculate checksum for a path source code.
Need catch OSError.
"""
return dirhash(folder.as_posix(), "sha256", match=["*.py"]) return dirhash(folder.as_posix(), "sha256", match=["*.py"])

View File

@@ -13,9 +13,9 @@ async def test_evaluate_system_error(coresys: CoreSys, capture_exception: Mock):
with patch( with patch(
"supervisor.resolution.evaluations.source_mods.calc_checksum_path_sourcecode", "supervisor.resolution.evaluations.source_mods.calc_checksum_path_sourcecode",
side_effect=OSError, side_effect=RuntimeError,
): ):
await coresys.resolution.evaluate.evaluate_system() await coresys.resolution.evaluate.evaluate_system()
capture_exception.assert_called_once() capture_exception.assert_called_once()
assert check_exception_chain(capture_exception.call_args[0][0], OSError) assert check_exception_chain(capture_exception.call_args[0][0], RuntimeError)