This commit is contained in:
Carlos Polop
2026-05-28 12:44:26 +02:00
parent 18ea88b35b
commit 195fc242ba
2 changed files with 53 additions and 2 deletions
@@ -70,6 +70,7 @@ except Exception:
cf31_run_python_probe() {
CF31_PY="$1"
CF31_TMP_PY=/tmp/cf31-probe-$$.py
trap 'rm -f "$CF31_TMP_PY"' EXIT HUP INT TERM
cat > "$CF31_TMP_PY" <<'PY'
import errno, os, signal, socket, struct, sys, tempfile, shutil
@@ -233,13 +234,19 @@ finally:
pass
PY
[ -s "$CF31_TMP_PY" ] || return 1
if [ ! -s "$CF31_TMP_PY" ]; then
rm -f "$CF31_TMP_PY"
return 1
fi
if command -v timeout >/dev/null 2>&1; then
timeout "$CF31_PY_TIMEOUT" "$CF31_PY" "$CF31_TMP_PY"
else
"$CF31_PY" "$CF31_TMP_PY"
fi
CF31_RC=$?
rm -f "$CF31_TMP_PY"
return "$CF31_RC"
}
checkCopyFail() {
@@ -397,4 +404,4 @@ checkCopyFail() {
echo "LIKELY VULNERABLE: $CF31_KERNEL_RELEASE is in the affected upstream range and AEAD user API appears $CF31_API." | sed -${E} "s,.*,${SED_RED_YELLOW},"
exit 2
)
}
}
+44
View File
@@ -1,5 +1,6 @@
import os
import re
import shlex
import stat
import subprocess
import tempfile
@@ -53,6 +54,49 @@ class LinpeasBuilderTests(unittest.TestCase):
self.assertNotIn("Checking for Copy Fail", content)
self.assertNotIn("checkCopyFail", content)
def test_copyfail_python_probe_removes_temp_script(self):
"""Regression: cf31_run_python_probe must remove its generated probe file."""
with tempfile.TemporaryDirectory() as tmpdir:
tmp_path = Path(tmpdir)
marker_path = tmp_path / "probe_path"
fake_python = tmp_path / "fake-python"
fake_python.write_text(
"#!/bin/sh\n"
"printf '%s\\n' \"$1\" > \"$CF31_PROBE_PATH_FILE\"\n"
"printf '%s\\n' probe-output\n"
"exit 2\n",
encoding="utf-8",
)
fake_python.chmod(0o755)
function_file = self.linpeas_dir / "builder" / "linpeas_parts" / "functions" / "checkCopyFail.sh"
script = "\n".join(
[
f". {shlex.quote(str(function_file))}",
"CF31_PY_TIMEOUT=5",
f"export CF31_PROBE_PATH_FILE={shlex.quote(str(marker_path))}",
f"CF31_MSG=$(cf31_run_python_probe {shlex.quote(str(fake_python))})",
"CF31_RC=$?",
f"CF31_PROBE_FILE=$(cat {shlex.quote(str(marker_path))})",
'printf "rc=%s\\n" "$CF31_RC"',
'printf "msg=%s\\n" "$CF31_MSG"',
'printf "path=%s\\n" "$CF31_PROBE_FILE"',
'if [ -e "$CF31_PROBE_FILE" ]; then echo "exists=yes"; else echo "exists=no"; fi',
]
)
result = subprocess.run(
["sh", "-c", script],
cwd=str(self.repo_root),
capture_output=True,
text=True,
)
self.assertEqual(result.returncode, 0, result.stderr)
self.assertIn("rc=2", result.stdout)
self.assertIn("msg=probe-output", result.stdout)
self.assertIn("exists=no", result.stdout)
def test_threads_flag_present_in_getopts(self):
"""Regression: -z must appear in the getopts string so it is actually parsed."""
with tempfile.TemporaryDirectory() as tmpdir: