Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #!/usr/bin/env bash
- #
- # openvas-compile.sh
- #
- # Rebuilds the Kali/Debian package that provides ospd/ospd.py (the "ospd"
- # source package, binary python3-ospd) with the multiprocessing start-method
- # fix baked in, so the patch survives inside the installed package instead of
- # being applied to files on disk afterwards.
- #
- # It downloads the Debian source with apt, adds a quilt patch equivalent to
- # ospd-openvas v22.10.5 commit a99fe321:
- #
- # multiprocessing.set_start_method('fork', force=True)
- #
- # then builds a .deb with dpkg-buildpackage. It only compiles the package;
- # installing the resulting .deb is left to you.
- #
- # This is the "proper package" counterpart of openvas.sh (which live-patches
- # the installed files). Target platform: Kali Linux (Debian based).
- #
- # Usage: sudo ./openvas-compile.sh
- #
- set -euo pipefail
- RED=$'\e[31m'; GREEN=$'\e[32m'; YELLOW=$'\e[33m'; BOLD=$'\e[1m'; RESET=$'\e[0m'
- info() { printf '%s[*]%s %s\n' "$BOLD" "$RESET" "$*"; }
- ok() { printf '%s[+]%s %s\n' "$GREEN" "$RESET" "$*"; }
- warn() { printf '%s[!]%s %s\n' "$YELLOW" "$RESET" "$*"; }
- die() { printf '%s[x]%s %s\n' "$RED" "$RESET" "$*" >&2; exit 1; }
- # --- 1. Must run as root ----------------------------------------------------
- if [[ ${EUID:-$(id -u)} -ne 0 ]]; then
- die "Please run as root: sudo $0"
- fi
- # Building Debian packages as root is discouraged; allow it explicitly.
- export DEB_BUILD_OPTIONS="${DEB_BUILD_OPTIONS:-} nocheck"
- # --- 2. Install build tooling ----------------------------------------------
- info "Installing build tooling (devscripts, quilt, dpkg-dev, build-essential)..."
- export DEBIAN_FRONTEND=noninteractive
- apt-get update -qq
- apt-get install -y --no-install-recommends \
- devscripts build-essential dpkg-dev quilt fakeroot dh-python \
- >/dev/null || die "Failed to install build tooling."
- ok "Build tooling ready."
- # --- 3. Ensure a deb-src source is available -------------------------------
- if ! grep -Rqs '^\s*deb-src' /etc/apt/sources.list /etc/apt/sources.list.d/ 2>/dev/null \
- && ! grep -Rqs 'Types:.*deb-src' /etc/apt/sources.list.d/ 2>/dev/null; then
- warn "No deb-src entry found. Adding Kali source repository."
- cat >/etc/apt/sources.list.d/kali-src.list <<'EOF'
- deb-src http://http.kali.org/kali kali-rolling main contrib non-free non-free-firmware
- EOF
- apt-get update -qq || die "apt-get update failed after adding deb-src."
- ok "Kali deb-src repository added."
- fi
- # --- 4. Work out which source package actually ships ospd/ospd.py ----------
- # The installed file may be owned by a binary package (e.g. ospd-openvas)
- # whose Debian *source* de-vendors the module. So we build a candidate list
- # and pick the first source package whose tree really contains ospd/ospd.py.
- info "Locating the installed ospd module and its source package..."
- OSPD_PY="$(python3 - <<'PY' 2>/dev/null || true
- import importlib.util
- spec = importlib.util.find_spec("ospd.ospd")
- print(spec.origin if spec and spec.origin else "")
- PY
- )"
- if [[ -z "${OSPD_PY}" || ! -f "${OSPD_PY}" ]]; then
- for cand in \
- /usr/lib/python3/dist-packages/ospd/ospd.py \
- /usr/local/lib/python3*/dist-packages/ospd/ospd.py \
- /usr/lib/python3*/site-packages/ospd/ospd.py; do
- [[ -f "$cand" ]] && { OSPD_PY="$cand"; break; }
- done
- fi
- [[ -n "${OSPD_PY}" && -f "${OSPD_PY}" ]] \
- || die "ospd/ospd.py is not installed. Is ospd-openvas installed?"
- CANDIDATES=()
- BINPKG="$(dpkg -S "${OSPD_PY}" 2>/dev/null | cut -d: -f1 | tr ',' '\n' | head -n1)"
- if [[ -n "${BINPKG}" ]]; then
- SRC="$(dpkg-query -W -f='${source:Package}\n' "${BINPKG}" 2>/dev/null | head -n1)"
- [[ -n "${SRC}" ]] && CANDIDATES+=("${SRC}")
- fi
- # Debian de-vendors ospd into its own source package; try it explicitly too.
- CANDIDATES+=("ospd" "ospd-openvas")
- ok "ospd/ospd.py is provided by '${BINPKG:-unknown}'. Candidate sources: ${CANDIDATES[*]}"
- # --- 5. Prepare an isolated work directory ---------------------------------
- WORKDIR="$(mktemp -d /tmp/openvas-src-build.XXXXXX)"
- # _apt drops privileges when downloading; make the dir readable to it.
- chmod 755 "${WORKDIR}"
- trap 'info "Build artifacts left in: ${WORKDIR}"' EXIT
- info "Working directory: ${WORKDIR}"
- cd "${WORKDIR}"
- # --- 6. Download candidate sources until one contains ospd/ospd.py ----------
- PKG=""; SRCDIR=""; TARGET=""
- declare -A SEEN=()
- for cand in "${CANDIDATES[@]}"; do
- [[ -n "${SEEN[$cand]:-}" ]] && continue
- SEEN[$cand]=1
- info "Downloading source package '${cand}'..."
- if ! apt-get source -o APT::Sandbox::User=root "${cand}" 2>/dev/null; then
- warn "Could not fetch source for '${cand}'; skipping."
- continue
- fi
- d="$(find "${WORKDIR}" -maxdepth 1 -type d -name "${cand}-*" | head -n1)"
- [[ -n "$d" && -d "$d" ]] || continue
- t="$(cd "$d" && find . -type f -path '*/ospd/ospd.py' -printf '%P\n' 2>/dev/null | head -n1)"
- if [[ -n "$t" ]]; then
- PKG="${cand}"; SRCDIR="$d"; TARGET="$t"
- break
- fi
- warn "Source '${cand}' does not contain ospd/ospd.py."
- done
- [[ -n "${SRCDIR}" ]] \
- || die "None of the candidate source packages contain ospd/ospd.py: ${CANDIDATES[*]}"
- ok "Using source package '${PKG}' (${SRCDIR}), target: ${TARGET}"
- info "Installing build dependencies for ${PKG}..."
- apt-get build-dep -y "${PKG}" >/dev/null 2>&1 \
- || warn "apt-get build-dep reported issues; continuing."
- cd "${SRCDIR}"
- # --- 7. Skip if the upstream source already contains the fix ---------------
- if grep -Eq "set_start_method\(\s*['\"]fork['\"]" "${TARGET}"; then
- ok "Source already contains the fork start-method fix (>= v22.10.5)."
- warn "Rebuilding anyway would not change behaviour; installing stock is enough."
- warn "Run: apt-get install --only-upgrade ${PKG}"
- exit 0
- fi
- # --- 8. Add the fix as a quilt patch ---------------------------------------
- info "Creating quilt patch with the multiprocessing fix..."
- export QUILT_PATCHES=debian/patches
- export QUILT_PATCH_OPTS="--reject-format=unified"
- mkdir -p debian/patches
- quilt new fix-multiprocessing-start-method.patch
- quilt add "${TARGET}"
- # Edit the tracked file: ensure the import exists and insert the fix line
- # right after the module logger definition (matching upstream a99fe321).
- python3 - "${TARGET}" <<'PY'
- import io, re, sys
- path = sys.argv[1]
- with io.open(path, "r", encoding="utf-8") as f:
- src = f.read()
- fix_line = "multiprocessing.set_start_method('fork', force=True)\n"
- if not re.search(r"^\s*import\s+multiprocessing\b", src, re.MULTILINE):
- lines = src.splitlines(keepends=True)
- last_import = 0
- for i, line in enumerate(lines):
- if re.match(r"^\s*(import|from)\s+\S", line):
- last_import = i + 1
- lines.insert(last_import, "import multiprocessing\n")
- src = "".join(lines)
- if "set_start_method('fork'" not in src and 'set_start_method("fork"' not in src:
- anchor = re.search(r"^logger\s*=\s*logging\.getLogger\(__name__\).*$",
- src, re.MULTILINE)
- if anchor:
- idx = anchor.end()
- src = src[:idx] + "\n\n" + fix_line + src[idx:]
- else:
- lines = src.splitlines(keepends=True)
- last_import = 0
- for i, line in enumerate(lines):
- if re.match(r"^\s*(import|from)\s+\S", line):
- last_import = i + 1
- lines.insert(last_import, "\n" + fix_line)
- src = "".join(lines)
- with io.open(path, "w", encoding="utf-8") as f:
- f.write(src)
- PY
- quilt refresh
- ok "Patch recorded in debian/patches/."
- # --- 9. Add a changelog entry (required to produce a versioned build) ------
- info "Adding changelog entry..."
- DEBEMAIL="${DEBEMAIL:-openvas-fix@localhost}" \
- DEBFULLNAME="${DEBFULLNAME:-OpenVAS Local Fix}" \
- dch --local "+fork" \
- "Force multiprocessing 'fork' start method (backport of v22.10.5 a99fe321)."
- # --- 10. Build the binary package ------------------------------------------
- info "Building the package with dpkg-buildpackage (binary only)..."
- dpkg-buildpackage -us -uc -b -rfakeroot \
- || die "Package build failed. See output above."
- ok "Package built."
- # --- 11. Report the produced .deb(s) ---------------------------------------
- shopt -s nullglob
- DEBS=( "${WORKDIR}"/*.deb )
- shopt -u nullglob
- [[ ${#DEBS[@]} -gt 0 ]] || die "No .deb produced in ${WORKDIR}."
- echo
- ok "Done. Patched ${PKG} package(s) built:"
- for deb in "${DEBS[@]}"; do
- info " ${deb}"
- done
- info "Install manually with:"
- info " sudo apt-get install --allow-downgrades ${DEBS[*]}"
Advertisement
Add Comment
Please, Sign In to add comment