Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
45f957af23 |
@@ -1,5 +1,20 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## v0.3.5 — 2026-07-13
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- `delete_snapshot_tree` swallowed the error from its recursive-delete fast path.
|
||||||
|
That failure is *usually* just "parent already gone" — stock's `finally` winning
|
||||||
|
the race once our mounts are released, which the by-name sweep then handles. But
|
||||||
|
if the cause were anything else, this was the only place it was visible, and it
|
||||||
|
went straight to `/dev/null`. It is now logged before falling through.
|
||||||
|
|
||||||
|
- Annotated the two remaining static-analysis findings as considered-and-accepted
|
||||||
|
rather than leaving them to be re-litigated: `subprocess` is always called in
|
||||||
|
list form (no shell, so ZFS dataset names cannot inject), and the partial
|
||||||
|
`systemctl` path is moot in a script that only runs as root.
|
||||||
|
|
||||||
## v0.3.4 — 2026-07-13
|
## v0.3.4 — 2026-07-13
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|||||||
+1
-1
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
VERSION="0.3.4"
|
VERSION="0.3.5"
|
||||||
|
|
||||||
# The directory containing install.sh is the permanent install location.
|
# The directory containing install.sh is the permanent install location.
|
||||||
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|||||||
+1
-1
@@ -32,7 +32,7 @@
|
|||||||
# Derive PATCH_DIR from this script's location (parent of the patch/ directory).
|
# Derive PATCH_DIR from this script's location (parent of the patch/ directory).
|
||||||
PATCH_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
PATCH_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||||
LOG="$PATCH_DIR/apply.log"
|
LOG="$PATCH_DIR/apply.log"
|
||||||
VERSION="0.3.4"
|
VERSION="0.3.5"
|
||||||
|
|
||||||
# Rotate log at 512 KB to avoid unbounded growth on a system volume.
|
# Rotate log at 512 KB to avoid unbounded growth on a system volume.
|
||||||
# Keep two prior generations (.1 and .2) so the last three boots are always available.
|
# Keep two prior generations (.1 and .2) so the last three boots are always available.
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ import subprocess
|
|||||||
import sys
|
import sys
|
||||||
import time
|
import time
|
||||||
|
|
||||||
__version__ = "0.3.4"
|
__version__ = "0.3.5"
|
||||||
|
|
||||||
_PATCH_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
_PATCH_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
_STATUS_FILE = os.path.join(_PATCH_DIR, "hook_status.json")
|
_STATUS_FILE = os.path.join(_PATCH_DIR, "hook_status.json")
|
||||||
@@ -95,8 +95,11 @@ def midclt_call(method, *args):
|
|||||||
def _middlewared_start_epoch():
|
def _middlewared_start_epoch():
|
||||||
"""Epoch timestamp of the running middlewared main process, or None."""
|
"""Epoch timestamp of the running middlewared main process, or None."""
|
||||||
try:
|
try:
|
||||||
|
# Partial path (S607) is fine here: this runs as root on TrueNAS, so an
|
||||||
|
# attacker who can poison PATH already has root. Hard-coding a path would
|
||||||
|
# be less portable (/bin vs /usr/bin) for no security gain.
|
||||||
pid = int(subprocess.run(
|
pid = int(subprocess.run(
|
||||||
["systemctl", "show", "--property=MainPID", "--value", "middlewared"],
|
["systemctl", "show", "--property=MainPID", "--value", "middlewared"], # noqa: S607
|
||||||
capture_output=True, text=True, timeout=10, check=True,
|
capture_output=True, text=True, timeout=10, check=True,
|
||||||
).stdout.strip())
|
).stdout.strip())
|
||||||
if pid <= 0:
|
if pid <= 0:
|
||||||
|
|||||||
@@ -279,7 +279,11 @@ def current_mounts_under(root, mounts_file="/proc/self/mounts"):
|
|||||||
|
|
||||||
|
|
||||||
def _run(cmd):
|
def _run(cmd):
|
||||||
return subprocess.run(cmd, capture_output=True, text=True, check=False)
|
# List form, never shell=True: `cmd` is built from our own mount plan, so ZFS
|
||||||
|
# dataset names cannot inject. Runs as root by definition (it mounts).
|
||||||
|
return subprocess.run( # noqa: S603
|
||||||
|
cmd, capture_output=True, text=True, check=False
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def apply_plan(mounts, runner=_run, isdir=os.path.isdir):
|
def apply_plan(mounts, runner=_run, isdir=os.path.isdir):
|
||||||
@@ -379,8 +383,16 @@ async def delete_snapshot_tree(middleware, snapshot, logger=None):
|
|||||||
try:
|
try:
|
||||||
await middleware.call("zfs.snapshot.delete", snapshot, {"recursive": True})
|
await middleware.call("zfs.snapshot.delete", snapshot, {"recursive": True})
|
||||||
return
|
return
|
||||||
except Exception: # noqa: BLE001 - fall through to the explicit sweep
|
except Exception as e: # noqa: BLE001 - fall through to the explicit sweep
|
||||||
pass
|
# Usually just "parent already gone" (stock's finally won the race once our
|
||||||
|
# mounts were released), which the sweep below handles. Log it rather than
|
||||||
|
# swallow it: if the real cause is something else, this is the only place
|
||||||
|
# it is visible -- the sweep would report a different, downstream failure.
|
||||||
|
if logger:
|
||||||
|
logger.debug(
|
||||||
|
"truecloud-patch: recursive delete of %s failed (%r); sweeping "
|
||||||
|
"the tree by name instead", snapshot, e,
|
||||||
|
)
|
||||||
|
|
||||||
# The parent may already be gone -- stock's `finally` can win the race once
|
# The parent may already be gone -- stock's `finally` can win the race once
|
||||||
# our mounts are released -- which fails the recursive delete while the
|
# our mounts are released -- which fails the recursive delete while the
|
||||||
|
|||||||
+1
-1
@@ -17,7 +17,7 @@
|
|||||||
# bash /mnt/tank/truenas-truecloud-patch/patch/apply.sh
|
# bash /mnt/tank/truenas-truecloud-patch/patch/apply.sh
|
||||||
# systemctl restart middlewared
|
# systemctl restart middlewared
|
||||||
|
|
||||||
VERSION="0.3.4"
|
VERSION="0.3.5"
|
||||||
|
|
||||||
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
set -euo pipefail
|
set -euo pipefail
|
||||||
|
|
||||||
VERSION="0.3.4"
|
VERSION="0.3.5"
|
||||||
|
|
||||||
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
PATCH_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
_HOOK_COMMENT='TrueCloud provider patch (S3/B2)'
|
_HOOK_COMMENT='TrueCloud provider patch (S3/B2)'
|
||||||
|
|||||||
Reference in New Issue
Block a user