livepatching: add automation for livepatch packages. (#3369)
This commit is contained in:
Родитель
7d10a93897
Коммит
6518af92a9
|
@ -1,13 +1,16 @@
|
|||
Summary: Kpatch tooling
|
||||
Name: kpatch
|
||||
Version: 0.9.6
|
||||
Release: 2%{?dist}
|
||||
Release: 4%{?dist}
|
||||
License: GPLv2
|
||||
Vendor: Microsoft Corporation
|
||||
Distribution: Mariner
|
||||
Group: System Environment/Base
|
||||
URL: https://github.com/dynup/kpatch
|
||||
Source0: %{url}/archive/refs/tags/v%{version}.tar.gz#/%{name}-%{version}.tar.gz
|
||||
Patch0: mariner_update.patch
|
||||
|
||||
ExclusiveArch: x86_64
|
||||
|
||||
BuildRequires: binutils
|
||||
BuildRequires: dnf-utils
|
||||
|
@ -17,7 +20,8 @@ BuildRequires: gcc
|
|||
BuildRequires: glibc-devel
|
||||
BuildRequires: kernel-headers
|
||||
|
||||
ExclusiveArch: x86_64
|
||||
Requires: binutils
|
||||
Requires: gawk
|
||||
|
||||
%description
|
||||
Kpatch is a Linux dynamic kernel patching infrastructure which allows you to patch
|
||||
|
@ -31,9 +35,11 @@ It gives more control over uptime without sacrificing security or stability.
|
|||
Summary: Tools for building livepatches with kpatch.
|
||||
Group: Development/Tools
|
||||
|
||||
Requires: mariner-release
|
||||
Requires: numactl-devel
|
||||
Requires: openssl
|
||||
Requires: patch
|
||||
Requires: perl
|
||||
Requires: rpm-build
|
||||
Requires: wget
|
||||
|
||||
|
@ -41,7 +47,7 @@ Requires: wget
|
|||
%{summary}
|
||||
|
||||
%prep
|
||||
%autosetup
|
||||
%autosetup -p1
|
||||
|
||||
%build
|
||||
%make_build
|
||||
|
@ -72,6 +78,12 @@ rm -rf %{buildroot}%{_mandir}
|
|||
%{_bindir}/kpatch-build
|
||||
|
||||
%changelog
|
||||
* Mon Aug 01 2022 Pawel Winogrodzki <pawelwi@microsoft.com> - 0.9.6-4
|
||||
- Adding missing dependency on "awk" and "binutils".
|
||||
|
||||
* Thu Jun 30 2022 Pawel Winogrodzki <pawelwi@microsoft.com> - 0.9.6-3
|
||||
- Add Mariner-specific steps to 'kpatch-build'.
|
||||
|
||||
* Fri Jun 17 2022 Jon Slobodzian <joslobo@microsoft.com> - 0.9.6-2
|
||||
- Fix ARM64 build break (exclusive to AMD64)
|
||||
|
||||
|
|
|
@ -0,0 +1,139 @@
|
|||
From 4f97bfb7590a10b6e8b267dc1f595a57a8d9659f Mon Sep 17 00:00:00 2001
|
||||
From: Pawel Winogrodzki <pawelwi@microsoft.com>
|
||||
Date: Wed, 15 Jun 2022 10:51:00 -0700
|
||||
Subject: [PATCH] Adjustments for CBL-Mariner.
|
||||
|
||||
---
|
||||
kpatch-build/kpatch-build | 61 ++++++++++++++++++++-------------------
|
||||
1 file changed, 31 insertions(+), 30 deletions(-)
|
||||
|
||||
diff --git a/kpatch-build/kpatch-build b/kpatch-build/kpatch-build
|
||||
index 634095d..7766e0d 100755
|
||||
--- a/kpatch-build/kpatch-build
|
||||
+++ b/kpatch-build/kpatch-build
|
||||
@@ -205,21 +205,6 @@ rhel_kernel_version_gte() {
|
||||
[ "${ARCHVERSION}" = "$(echo -e "${ARCHVERSION}\\n$1" | sort -rV | head -n1)" ]
|
||||
}
|
||||
|
||||
-# klp.arch relocations were supported prior to v5.8
|
||||
-# and prior to 4.18.0-240.el8
|
||||
-use_klp_arch()
|
||||
-{
|
||||
- if kernel_is_rhel; then
|
||||
- ! rhel_kernel_version_gte 4.18.0-240.el8
|
||||
- else
|
||||
- ! kernel_version_gte 5.8.0
|
||||
- fi
|
||||
-}
|
||||
-
|
||||
-rhel_kernel_version_gte() {
|
||||
- [ "${ARCHVERSION}" = "$(echo -e "${ARCHVERSION}\\n$1" | sort -rV | head -n1)" ]
|
||||
-}
|
||||
-
|
||||
# klp.arch relocations were supported prior to v5.8
|
||||
# and prior to 4.18.0-284.el8
|
||||
use_klp_arch()
|
||||
@@ -638,13 +623,23 @@ if [[ $DEBUG -eq 1 ]] || [[ $DEBUG -ge 3 ]]; then
|
||||
set -o xtrace
|
||||
fi
|
||||
|
||||
+# Don't check external file.
|
||||
+# shellcheck disable=SC1090
|
||||
+if [[ -z "$USERSRCDIR" ]] && [[ -f "$RELEASE_FILE" ]]; then
|
||||
+ source "$RELEASE_FILE"
|
||||
+ DISTRO="$ID"
|
||||
+fi
|
||||
+
|
||||
if [[ -n "$SRCRPM" ]]; then
|
||||
if [[ -n "$ARCHVERSION" ]]; then
|
||||
warn "--archversion is incompatible with --sourcerpm"
|
||||
exit 1
|
||||
fi
|
||||
rpmname="$(basename "$SRCRPM")"
|
||||
- ARCHVERSION="${rpmname%.src.rpm}.$(uname -m)"
|
||||
+ ARCHVERSION="${rpmname%.src.rpm}"
|
||||
+ if [[ "$DISTRO" != mariner ]]; then
|
||||
+ ARCHVERSION="${ARCHVERSION}.$(uname -m)"
|
||||
+ fi
|
||||
ARCHVERSION="${ARCHVERSION#kernel-}"
|
||||
ARCHVERSION="${ARCHVERSION#alt-}"
|
||||
fi
|
||||
@@ -699,20 +694,15 @@ fi
|
||||
KVER="${ARCHVERSION%%-*}"
|
||||
if [[ "$ARCHVERSION" =~ - ]]; then
|
||||
KREL="${ARCHVERSION##*-}"
|
||||
- KREL="${KREL%.*}"
|
||||
+ if [[ "$DISTRO" != mariner ]]; then
|
||||
+ KREL="${KREL%.*}"
|
||||
+ fi
|
||||
fi
|
||||
[[ "$ARCHVERSION" =~ .el7a. ]] && ALT="-alt"
|
||||
|
||||
[[ -z "$TARGETS" ]] && TARGETS="vmlinux modules"
|
||||
|
||||
-# Don't check external file.
|
||||
-# shellcheck disable=SC1090
|
||||
-if [[ -z "$USERSRCDIR" ]] && [[ -f "$RELEASE_FILE" ]]; then
|
||||
- source "$RELEASE_FILE"
|
||||
- DISTRO="$ID"
|
||||
-fi
|
||||
-
|
||||
-if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = openEuler ]]; then
|
||||
+if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = openEuler ]] || [[ "$DISTRO" = mariner ]]; then
|
||||
[[ -z "$VMLINUX" ]] && VMLINUX="/usr/lib/debug/lib/modules/$ARCHVERSION/vmlinux"
|
||||
[[ -e "$VMLINUX" ]] || die "kernel-debuginfo-$ARCHVERSION not installed"
|
||||
|
||||
@@ -748,9 +738,8 @@ elif [[ -n "$OOT_MODULE" ]]; then
|
||||
fi
|
||||
elif [[ -e "$KERNEL_SRCDIR"/.config ]] && [[ -e "$VERSIONFILE" ]] && [[ "$(cat "$VERSIONFILE")" = "$ARCHVERSION" ]]; then
|
||||
echo "Using cache at $KERNEL_SRCDIR"
|
||||
-
|
||||
else
|
||||
- if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]]; then
|
||||
+ if [[ "$DISTRO" = fedora ]] || [[ "$DISTRO" = rhel ]] || [[ "$DISTRO" = ol ]] || [[ "$DISTRO" = centos ]] || [[ "$DISTRO" = mariner ]]; then
|
||||
|
||||
echo "Fedora/Red Hat distribution detected"
|
||||
|
||||
@@ -760,6 +749,9 @@ else
|
||||
if [[ -z "$SRCRPM" ]]; then
|
||||
if [[ "$DISTRO" = fedora ]]; then
|
||||
wget -P "$TEMPDIR" "http://kojipkgs.fedoraproject.org/packages/kernel/$KVER/$KREL/src/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die
|
||||
+ elif [[ "$DISTRO" = mariner ]]; then
|
||||
+ source "$RELEASE_FILE"
|
||||
+ wget -P "$TEMPDIR" "https://packages.microsoft.com/cbl-mariner/$VERSION_ID/prod/base/srpms/kernel-$KVER-$KREL.src.rpm" 2>&1 | logger || die
|
||||
else
|
||||
command -v yumdownloader &>/dev/null || die "yumdownloader (yum-utils or dnf-utils) not installed"
|
||||
yumdownloader --source --destdir "$TEMPDIR" "kernel$ALT-$KVER-$KREL" 2>&1 | logger || die
|
||||
@@ -773,17 +765,26 @@ else
|
||||
rpmbuild -D "_topdir $RPMTOPDIR" -bp --nodeps "--target=$(uname -m)" "$RPMTOPDIR"/SPECS/kernel$ALT.spec 2>&1 | logger ||
|
||||
die "rpmbuild -bp failed. you may need to run 'yum-builddep kernel' first."
|
||||
|
||||
- mv "$RPMTOPDIR"/BUILD/kernel-*/linux-* "$KERNEL_SRCDIR" 2>&1 | logger || die
|
||||
+ if [[ "$DISTRO" = mariner ]]; then
|
||||
+ mv "$RPMTOPDIR"/BUILD/CBL-Mariner-Linux-Kernel-* "$KERNEL_SRCDIR" 2>&1 | logger || die
|
||||
+ else
|
||||
+ mv "$RPMTOPDIR"/BUILD/kernel-*/linux-* "$KERNEL_SRCDIR" 2>&1 | logger || die
|
||||
+ fi
|
||||
rm -rf "$RPMTOPDIR"
|
||||
rm -rf "$KERNEL_SRCDIR/.git"
|
||||
|
||||
- if [[ "$ARCHVERSION" == *-* ]]; then
|
||||
+ if [[ "$DISTRO" != mariner ]] && [[ "$ARCHVERSION" == *-* ]]; then
|
||||
sed -i "s/^EXTRAVERSION.*/EXTRAVERSION = -${ARCHVERSION##*-}/" "$KERNEL_SRCDIR/Makefile" || die
|
||||
fi
|
||||
|
||||
echo "$ARCHVERSION" > "$VERSIONFILE" || die
|
||||
|
||||
- [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$KERNEL_SRCDIR/configs/kernel$ALT-$KVER-$ARCH.config"
|
||||
+ if [[ "$DISTRO" = mariner ]]; then
|
||||
+ [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$KERNEL_SRCDIR/new_config"
|
||||
+ sed -i "s/CONFIG_LOCALVERSION=\"\"/CONFIG_LOCALVERSION=\"-$KREL\"/" "$CONFIGFILE"
|
||||
+ else
|
||||
+ [[ -z "$CONFIGFILE" ]] && CONFIGFILE="$KERNEL_SRCDIR/configs/kernel$ALT-$KVER-$ARCH.config"
|
||||
+ fi
|
||||
|
||||
(cd "$KERNEL_SRCDIR" && make mrproper 2>&1 | logger) || die
|
||||
|
||||
--
|
||||
2.34.1
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
set -e
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
COMMON_SCRIPTS_FOLDER="$REPO_ROOT/toolkit/scripts"
|
||||
|
||||
export PATH="$PATH:$COMMON_SCRIPTS_FOLDER"
|
||||
|
||||
# shellcheck source=../../toolkit/scripts/specs/specs_tools.sh
|
||||
source "$COMMON_SCRIPTS_FOLDER/specs/specs_tools.sh"
|
||||
|
||||
function update_manifests {
|
||||
local kernel_release_number
|
||||
local package_manifests_dir
|
||||
|
||||
kernel_release_number="$1"
|
||||
|
||||
echo "Updating package manifests."
|
||||
|
||||
package_manifests_dir="$REPO_ROOT/toolkit/resources/manifests/package"
|
||||
sed -i -E "s/(kernel-headers-.*-)[0-9]+(\.cm.*)/\1$kernel_release_number\2/" "$package_manifests_dir"/{pkggen,toolchain}*.txt
|
||||
}
|
||||
|
||||
function bump_spec_releases {
|
||||
local kernel_release_number
|
||||
local specs_dir_path
|
||||
local specs_signed_dir_path
|
||||
local specs_to_bump
|
||||
|
||||
kernel_release_number="$1"
|
||||
|
||||
echo "Bumping kernel specs releases to ($kernel_release_number)."
|
||||
|
||||
specs_dir_path="$REPO_ROOT/SPECS"
|
||||
specs_signed_dir_path="$REPO_ROOT/SPECS-SIGNED"
|
||||
|
||||
specs_to_bump="$specs_dir_path/kernel-headers/kernel-headers.spec $specs_signed_dir_path/kernel-signed/kernel-signed.spec"
|
||||
for spec_to_bump in $specs_to_bump
|
||||
do
|
||||
spec_release_number="$(spec_read_release_number "$spec_to_bump")"
|
||||
if [[ "$kernel_release_number" != "$spec_release_number" ]]
|
||||
then
|
||||
update_spec.sh "Bump release number to match kernel release." "$spec_to_bump"
|
||||
fi
|
||||
done
|
||||
}
|
||||
|
||||
KERNEL_RELEASE_NUMBER="$(spec_read_release_number "$REPO_ROOT/SPECS/kernel/kernel.spec")"
|
||||
|
||||
bump_spec_releases "$KERNEL_RELEASE_NUMBER"
|
||||
update_manifests "$KERNEL_RELEASE_NUMBER"
|
||||
"$COMMON_SCRIPTS_FOLDER"/livepatching/update_livepatches.sh
|
|
@ -0,0 +1,52 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
set -e
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
COMMON_SCRIPTS_FOLDER="$REPO_ROOT/toolkit/scripts"
|
||||
SCRIPT_FOLDER="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
|
||||
|
||||
export PATH="$PATH:$COMMON_SCRIPTS_FOLDER"
|
||||
|
||||
# shellcheck source=../../../toolkit/scripts/specs/specs_tools.sh
|
||||
source "$COMMON_SCRIPTS_FOLDER/specs/specs_tools.sh"
|
||||
|
||||
LIVEPATCH_SPEC_PATH="$1"
|
||||
|
||||
if [[ ! -f "$LIVEPATCH_SPEC_PATH" ]]
|
||||
then
|
||||
echo "Must provide a livepatch spec file as first argument." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Generating signed spec for ($LIVEPATCH_SPEC_PATH)."
|
||||
|
||||
KERNEL_VERSION_RELEASE="$(grep -oP "(?<=kernel_version_release ).*" "$LIVEPATCH_SPEC_PATH")"
|
||||
|
||||
DESCRIPTION="$(spec_query_srpm "$LIVEPATCH_SPEC_PATH" "%{DESCRIPTION}\n")"
|
||||
|
||||
RELEASE_TAG="$(spec_read_release_tag "$LIVEPATCH_SPEC_PATH")"
|
||||
|
||||
CHANGELOG="$(dump_changelog "$LIVEPATCH_SPEC_PATH")"
|
||||
|
||||
# shellcheck disable=SC2034 # Variable used indirectly inside 'create_new_file_from_template'.
|
||||
declare -A TEMPLATE_PLACEHOLDERS=(
|
||||
["@KERNEL_VERSION_RELEASE@"]="$KERNEL_VERSION_RELEASE"
|
||||
["@DESCRIPTION@"]="$DESCRIPTION"
|
||||
["@RELEASE_TAG@"]="$RELEASE_TAG"
|
||||
["@CHANGELOG@"]="$CHANGELOG"
|
||||
)
|
||||
|
||||
LIVEPATCH_SIGNED_SPEC_PATH="$REPO_ROOT/SPECS-SIGNED/livepatch-signed/livepatch-signed-$KERNEL_VERSION_RELEASE.spec"
|
||||
create_new_file_from_template "$SCRIPT_FOLDER/template_livepatch-signed.spec" "$LIVEPATCH_SIGNED_SPEC_PATH" TEMPLATE_PLACEHOLDERS
|
||||
|
||||
# Cgmanifest.json update skipped - already handled by the unsigned version.
|
||||
|
||||
echo "Updating licensing info."
|
||||
|
||||
license_map.py --no_check --update \
|
||||
SPECS/LICENSES-AND-NOTICES/data/licenses.json \
|
||||
SPECS/LICENSES-AND-NOTICES/LICENSES-MAP.md \
|
||||
"$LIVEPATCH_SIGNED_SPEC_PATH"
|
|
@ -0,0 +1,111 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
set -e
|
||||
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
COMMON_SCRIPTS_FOLDER="$REPO_ROOT/toolkit/scripts"
|
||||
SCRIPT_FOLDER="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
|
||||
|
||||
export PATH="$PATH:$COMMON_SCRIPTS_FOLDER"
|
||||
|
||||
# shellcheck source=../../../toolkit/scripts/specs/specs_tools.sh
|
||||
source "$COMMON_SCRIPTS_FOLDER/specs/specs_tools.sh"
|
||||
|
||||
function copy_kernel_sources {
|
||||
echo "Copying kernel config ($LIVEPATCH_CONFIG_FILE) and trusted key ($LIVEPATCH_PUBLIC_KEY_FILE)."
|
||||
|
||||
cp "$KERNEL_CONFIG_PATH" "$LIVEPATCH_SPECS_DIR/$LIVEPATCH_CONFIG_FILE"
|
||||
cp "$KERNEL_PUBLIC_KEY_PATH" "$LIVEPATCH_SPECS_DIR/$LIVEPATCH_PUBLIC_KEY_FILE"
|
||||
}
|
||||
|
||||
function generate_livepatch_signatures {
|
||||
local config_hash
|
||||
local kernel_hash
|
||||
local kernel_tarball_file
|
||||
local public_key_hash
|
||||
|
||||
echo "Generating livepatch signatures."
|
||||
|
||||
config_hash="$(jq -r ".Signatures.config" "$KERNEL_SIGNATURES_PATH")"
|
||||
kernel_tarball_file="kernel-$KERNEL_VERSION.tar.gz"
|
||||
kernel_hash="$(jq -r ".Signatures.\"$kernel_tarball_file\"" "$KERNEL_SIGNATURES_PATH")"
|
||||
public_key_hash="$(jq -r ".Signatures.\"$KERNEL_PUBLIC_KEY_FILE\"" "$KERNEL_SIGNATURES_PATH")"
|
||||
|
||||
jq -n \
|
||||
--arg config_hash "$config_hash" \
|
||||
--arg config_name "$LIVEPATCH_CONFIG_FILE" \
|
||||
--arg kernel_hash "$kernel_hash" \
|
||||
--arg kernel_name "$kernel_tarball_file" \
|
||||
--arg pem_hash "$public_key_hash" \
|
||||
--arg pem_name "$LIVEPATCH_PUBLIC_KEY_FILE" \
|
||||
'{"Signatures": {($config_name): $config_hash, ($kernel_name): $kernel_hash, ($pem_name): $pem_hash}}' \
|
||||
> "$LIVEPATCH_SPECS_DIR/livepatch-$KERNEL_VERSION_RELEASE.signatures.json"
|
||||
}
|
||||
|
||||
function generate_livepatch_spec {
|
||||
local -A template_placeholders
|
||||
local latest_existing_release
|
||||
local patches
|
||||
local same_version_livepatches
|
||||
|
||||
same_version_livepatches="$(find "$LIVEPATCH_SPECS_DIR" -name "livepatch-$KERNEL_VERSION*spec")"
|
||||
if [[ -n "$same_version_livepatches" ]]
|
||||
then
|
||||
echo "Detected older livepatch for the current kernel version - re-using any existing patches."
|
||||
|
||||
latest_existing_release=$(find "$LIVEPATCH_SPECS_DIR" -name "livepatch-$KERNEL_VERSION*spec" | grep -oP "(?<=$KERNEL_VERSION-)\d+" | sort -n | tail -1)
|
||||
patches="$(grep -P "^\s*Patch\d*:.*" "$LIVEPATCH_SPECS_DIR/livepatch-$KERNEL_VERSION-$latest_existing_release".cm*spec)"
|
||||
fi
|
||||
|
||||
# shellcheck disable=SC2034 # Variable used indirectly inside 'create_new_file_from_template'.
|
||||
template_placeholders=(
|
||||
["@KERNEL_VERSION_RELEASE@"]="$KERNEL_VERSION_RELEASE"
|
||||
["@PATCHES@"]="$patches"
|
||||
)
|
||||
create_new_file_from_template "$SCRIPT_FOLDER/template_livepatch.spec" "$LIVEPATCH_SPEC_PATH" template_placeholders
|
||||
|
||||
update_spec.sh "Original version for CBL-Mariner.\n- License verified." "$LIVEPATCH_SPEC_PATH" 1>/dev/null
|
||||
}
|
||||
|
||||
KERNEL_SPECS_DIR="$REPO_ROOT/SPECS/kernel"
|
||||
KERNEL_CONFIG_PATH="$KERNEL_SPECS_DIR/config"
|
||||
KERNEL_PUBLIC_KEYS=("$KERNEL_SPECS_DIR"/cbl-mariner-ca-*.pem)
|
||||
KERNEL_PUBLIC_KEY_PATH="${KERNEL_PUBLIC_KEYS[0]}"
|
||||
KERNEL_PUBLIC_KEY_FILE="$(basename "$KERNEL_PUBLIC_KEY_PATH")"
|
||||
KERNEL_SIGNATURES_PATH="$KERNEL_SPECS_DIR/kernel.signatures.json"
|
||||
KERNEL_SPEC_PATH="$KERNEL_SPECS_DIR/kernel.spec"
|
||||
|
||||
KERNEL_VERSION="$(spec_read_version "$KERNEL_SPEC_PATH")"
|
||||
KERNEL_VERSION_RELEASE="$(spec_query_srpm "$KERNEL_SPEC_PATH" "%{VERSION}-%{RELEASE}\n")"
|
||||
|
||||
LIVEPATCH_CONFIG_FILE="config-$KERNEL_VERSION_RELEASE"
|
||||
LIVEPATCH_PUBLIC_KEY_FILE="mariner-$KERNEL_VERSION_RELEASE.pem"
|
||||
LIVEPATCH_SPECS_DIR="$REPO_ROOT/SPECS/livepatch"
|
||||
LIVEPATCH_SPEC_PATH="$LIVEPATCH_SPECS_DIR/livepatch-$KERNEL_VERSION_RELEASE.spec"
|
||||
|
||||
if [[ -f "$LIVEPATCH_SPEC_PATH" ]]
|
||||
then
|
||||
echo "Livepatch spec ($LIVEPATCH_SPEC_PATH) alread exists. Exiting."
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "Generating empty livepatch spec for kernel ($KERNEL_VERSION_RELEASE) under ($LIVEPATCH_SPEC_PATH)."
|
||||
|
||||
mkdir -p "$LIVEPATCH_SPECS_DIR"
|
||||
|
||||
copy_kernel_sources
|
||||
generate_livepatch_signatures
|
||||
generate_livepatch_spec
|
||||
|
||||
echo "Updating licensing info."
|
||||
|
||||
license_map.py --no_check --update \
|
||||
SPECS/LICENSES-AND-NOTICES/data/licenses.json \
|
||||
SPECS/LICENSES-AND-NOTICES/LICENSES-MAP.md \
|
||||
"$LIVEPATCH_SPEC_PATH"
|
||||
|
||||
echo "Updating the cgmanifest.json."
|
||||
|
||||
update_cgmanifest.py last "$REPO_ROOT/cgmanifest.json" "$LIVEPATCH_SPEC_PATH"
|
|
@ -0,0 +1,98 @@
|
|||
%global debug_package %{nil}
|
||||
|
||||
%define kernel_version_release @KERNEL_VERSION_RELEASE@
|
||||
%define kernel_version %(echo %{kernel_version_release} | grep -oP "^[^-]+")
|
||||
%define kernel_release %(echo %{kernel_version_release} | grep -oP "(?<=-).+")
|
||||
|
||||
# Kpatch module names allow only alphanumeric characters and '_'.
|
||||
%define livepatch_name %(value="%{name}-%{version}-%{release}"; echo "${value//[^a-zA-Z0-9_]/_}")
|
||||
%define livepatch_install_dir %{_libdir}/livepatching/%{kernel_version_release}
|
||||
%define livepatch_module_name %{livepatch_name}.ko
|
||||
%define livepatch_module_path %{livepatch_install_dir}/%{livepatch_module_name}
|
||||
|
||||
%define patch_applicable_for_kernel [[ -f "%{livepatch_module_path}" && "$(uname -r)" == "%{kernel_version_release}" ]]
|
||||
%define patch_installed kpatch list | grep -qP "%{livepatch_name}.*%{kernel_version_release}"
|
||||
%define patch_loaded kpatch list | grep -qP "%{livepatch_name}.*enabled"
|
||||
|
||||
# Install patch if the RUNNING kernel matches.
|
||||
# No-op for initial (empty) livepatch.
|
||||
%define install_if_should \
|
||||
if %{patch_applicable_for_kernel} && ! %{patch_installed} \
|
||||
then \
|
||||
kpatch install %{livepatch_module_path} \
|
||||
fi
|
||||
|
||||
# Load patch, if the RUNNING kernel matches.
|
||||
# No-op for initial (empty) livepatch.
|
||||
%define load_if_should \
|
||||
if %{patch_applicable_for_kernel} && ! %{patch_loaded} \
|
||||
then \
|
||||
kpatch load %{livepatch_module_path} \
|
||||
fi
|
||||
|
||||
%define uninstall_if_should \
|
||||
if %{patch_installed} \
|
||||
then \
|
||||
kpatch uninstall %{livepatch_name} \
|
||||
fi
|
||||
|
||||
%define unload_if_should \
|
||||
if %{patch_loaded} \
|
||||
then \
|
||||
kpatch unload %{livepatch_name} \
|
||||
fi
|
||||
|
||||
Summary: Set of livepatches for kernel %{kernel_version_release}
|
||||
Name: livepatch-%{kernel_version_release}
|
||||
Version: 1.0.0
|
||||
Release: @RELEASE_TAG@
|
||||
License: MIT
|
||||
Vendor: Microsoft Corporation
|
||||
Distribution: Mariner
|
||||
Group: System Environment/Base
|
||||
URL: https://github.com/microsoft/CBL-Mariner
|
||||
Source0: https://github.com/microsoft/CBL-Mariner-Linux-Kernel/archive/rolling-lts/mariner-2/%{kernel_version}.tar.gz#/%{livepatch_module_name}
|
||||
|
||||
ExclusiveArch: x86_64
|
||||
|
||||
Requires: coreutils
|
||||
Requires: livepatching-filesystem
|
||||
|
||||
Requires(post): coreutils
|
||||
Requires(post): kpatch
|
||||
|
||||
Requires(preun): kpatch
|
||||
|
||||
Provides: livepatch = %{kernel_version_release}
|
||||
|
||||
%description
|
||||
@DESCRIPTION@
|
||||
|
||||
%install
|
||||
install -dm 755 %{buildroot}%{livepatch_install_dir}
|
||||
install -m 744 %{SOURCE0} %{buildroot}%{livepatch_module_path}
|
||||
|
||||
%post
|
||||
%load_if_should
|
||||
%install_if_should
|
||||
|
||||
%preun
|
||||
%uninstall_if_should
|
||||
%unload_if_should
|
||||
|
||||
# Re-enable patch on rollbacks to supported kernel.
|
||||
%triggerin -- kernel = %{kernel_version_release}
|
||||
%load_if_should
|
||||
%install_if_should
|
||||
|
||||
# Prevent the patch from being loaded after a reboot to a different kernel.
|
||||
# Previous kernel is still running, do NOT unload the livepatch.
|
||||
%triggerin -- kernel > %{kernel_version_release}, kernel < %{kernel_version_release}
|
||||
%uninstall_if_should
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%dir %{livepatch_install_dir}
|
||||
%{livepatch_module_path}
|
||||
|
||||
@CHANGELOG@
|
|
@ -0,0 +1,127 @@
|
|||
%define kernel_version_release @KERNEL_VERSION_RELEASE@
|
||||
%define kernel_version %(echo %{kernel_version_release} | grep -oP "^[^-]+")
|
||||
%define kernel_release %(echo %{kernel_version_release} | grep -oP "(?<=-).+")
|
||||
|
||||
%define builds_module %([[ -n "$(echo "%{patches}" | grep -oP "CVE-\\d+-\\d+(?=\\.patch)")" ]] && echo 1 || echo 0)
|
||||
|
||||
# Kpatch module names allow only alphanumeric characters and '_'.
|
||||
%define livepatch_name %(value="%{name}-%{version}-%{release}"; echo "${value//[^a-zA-Z0-9_]/_}")
|
||||
%define livepatch_install_dir %{_libdir}/livepatching/%{kernel_version_release}
|
||||
%define livepatch_module_name %{livepatch_name}.ko
|
||||
%define livepatch_module_path %{livepatch_install_dir}/%{livepatch_module_name}
|
||||
|
||||
%define patches_description \
|
||||
%(
|
||||
echo "Patches list ('*' - fixed, '!' - unfixable through livepatching, kernel update required):"
|
||||
for patch in %{patches}
|
||||
do
|
||||
patch_file=$(basename "$patch")
|
||||
|
||||
cve_number="${patch_file%.*}"
|
||||
patch_suffix="${patch_file#*.}"
|
||||
|
||||
if [ "$patch_suffix" = "patch" ]
|
||||
then
|
||||
echo "*$cve_number"
|
||||
else
|
||||
echo "\!$cve_number: $(cat "$patch")"
|
||||
fi
|
||||
done
|
||||
)
|
||||
|
||||
Summary: Set of livepatches for kernel %{kernel_version_release}
|
||||
Name: livepatch-%{kernel_version_release}
|
||||
Version: 1.0.0
|
||||
Release: 0%{?dist}
|
||||
License: MIT
|
||||
Vendor: Microsoft Corporation
|
||||
Distribution: Mariner
|
||||
Group: System Environment/Base
|
||||
URL: https://github.com/microsoft/CBL-Mariner
|
||||
Source0: https://github.com/microsoft/CBL-Mariner-Linux-Kernel/archive/rolling-lts/mariner-2/%{kernel_version}.tar.gz#/kernel-%{kernel_version}.tar.gz
|
||||
Source1: config-%{kernel_version_release}
|
||||
Source2: mariner-%{kernel_version_release}.pem
|
||||
@PATCHES@
|
||||
|
||||
ExclusiveArch: x86_64
|
||||
|
||||
# Must be kept below the "Patch" tags to correctly evaluate %%builds_module.
|
||||
%if %{builds_module}
|
||||
BuildRequires: audit-devel
|
||||
BuildRequires: bash
|
||||
BuildRequires: bc
|
||||
BuildRequires: binutils
|
||||
BuildRequires: bison
|
||||
BuildRequires: diffutils
|
||||
BuildRequires: dwarves
|
||||
BuildRequires: elfutils-libelf-devel
|
||||
BuildRequires: flex
|
||||
BuildRequires: gcc
|
||||
BuildRequires: glib-devel
|
||||
BuildRequires: glibc-devel
|
||||
BuildRequires: kbd
|
||||
BuildRequires: kernel-debuginfo = %{kernel_version_release}
|
||||
BuildRequires: kernel-headers = %{kernel_version_release}
|
||||
BuildRequires: kmod-devel
|
||||
BuildRequires: kpatch-build
|
||||
BuildRequires: libdnet-devel
|
||||
BuildRequires: libmspack-devel
|
||||
BuildRequires: make
|
||||
BuildRequires: openssl
|
||||
BuildRequires: openssl-devel
|
||||
BuildRequires: pam-devel
|
||||
BuildRequires: procps-ng-devel
|
||||
BuildRequires: python3-devel
|
||||
BuildRequires: rpm-build
|
||||
%else
|
||||
%global debug_package %{nil}
|
||||
# endif builds_module
|
||||
%endif
|
||||
|
||||
Provides: livepatch = %{kernel_version_release}
|
||||
|
||||
%description
|
||||
A set of kernel livepatches addressing CVEs present in Mariner's
|
||||
kernel version %{kernel_version_release}.
|
||||
%{patches_description}
|
||||
|
||||
%if %{builds_module}
|
||||
|
||||
%prep
|
||||
%setup -q -n CBL-Mariner-Linux-Kernel-rolling-lts-mariner-2-%{kernel_version}
|
||||
|
||||
cp %{SOURCE1} .config
|
||||
cp %{SOURCE2} certs/mariner.pem
|
||||
|
||||
sed -i 's#CONFIG_SYSTEM_TRUSTED_KEYS=""#CONFIG_SYSTEM_TRUSTED_KEYS="certs/mariner.pem"#' .config
|
||||
sed -i 's/CONFIG_LOCALVERSION=""/CONFIG_LOCALVERSION="-%{kernel_release}"/' .config
|
||||
|
||||
%build
|
||||
# Building cumulative patch.
|
||||
all_patches_file=all.patch
|
||||
for patch in %{patches}
|
||||
do
|
||||
[[ "$patch" == *.patch ]] && cat "$patch" >> $all_patches_file
|
||||
done
|
||||
|
||||
kpatch-build -ddd \
|
||||
--sourcedir . \
|
||||
--vmlinux %{_libdir}/debug/lib/modules/%{kernel_version_release}/vmlinux \
|
||||
--name %{livepatch_name} \
|
||||
$all_patches_file
|
||||
|
||||
%install
|
||||
install -dm 755 %{buildroot}%{livepatch_install_dir}
|
||||
install -m 744 %{livepatch_module_name} %{buildroot}%{livepatch_module_path}
|
||||
|
||||
# endif builds_module
|
||||
%endif
|
||||
|
||||
%files
|
||||
%defattr(-,root,root)
|
||||
%if %{builds_module}
|
||||
%dir %{livepatch_install_dir}
|
||||
%{livepatch_module_path}
|
||||
%endif
|
||||
|
||||
%changelog
|
|
@ -0,0 +1,17 @@
|
|||
#!/bin/bash
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
set -e
|
||||
|
||||
SPECS_DIR="$(git rev-parse --show-toplevel)/SPECS"
|
||||
SCRIPT_FOLDER="$(realpath "$(dirname "${BASH_SOURCE[0]}")")"
|
||||
|
||||
echo "Updating livepatch specs."
|
||||
|
||||
"$SCRIPT_FOLDER"/generate_livepatch_spec.sh
|
||||
|
||||
for livepatch_spec in "$SPECS_DIR/livepatch/"livepatch-*.spec
|
||||
do
|
||||
"$SCRIPT_FOLDER"/generate_livepatch-signed_spec.sh "$livepatch_spec"
|
||||
done
|
|
@ -0,0 +1,221 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Copyright (c) Microsoft Corporation.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
set -e
|
||||
|
||||
# shellcheck source=../../../toolkit/scripts/rpmops.sh
|
||||
source "$(git rev-parse --show-toplevel)"/toolkit/scripts/rpmops.sh
|
||||
|
||||
USER_EMAIL=""
|
||||
USER_NAME=""
|
||||
|
||||
init() {
|
||||
local init_failed=false
|
||||
|
||||
if [[ -z $USER_EMAIL ]]
|
||||
then
|
||||
USER_EMAIL="$(git config user.email)"
|
||||
fi
|
||||
|
||||
if [[ -z $USER_NAME ]]
|
||||
then
|
||||
USER_NAME="$(git config user.name)"
|
||||
fi
|
||||
|
||||
if [[ -z $USER_EMAIL ]]
|
||||
then
|
||||
echo "ERROR: must set git user e-mail. Try running 'git config --local user.email [USER_EMAIL]'." >&2
|
||||
init_failed=true
|
||||
fi
|
||||
|
||||
if [[ -z $USER_NAME ]]
|
||||
then
|
||||
echo "ERROR: must set git user name. Try running 'git config --local user.name [USER_NAME]'." >&2
|
||||
init_failed=true
|
||||
fi
|
||||
|
||||
if $init_failed
|
||||
then
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
add_changelog_entry() {
|
||||
local changelog_header
|
||||
local changelog_indents
|
||||
local changelog_message
|
||||
local epoch
|
||||
local next_release
|
||||
local spec_path
|
||||
local version
|
||||
|
||||
spec_path="$1"
|
||||
changelog_message="$2"
|
||||
|
||||
next_release=$(spec_read_release_number "$spec_path")
|
||||
next_release=$((next_release+1))
|
||||
|
||||
version=$(spec_read_version "$spec_path")
|
||||
|
||||
epoch="$(spec_read_epoch "$spec_path"):"
|
||||
if [[ "$epoch" == "(none):" ]]
|
||||
then
|
||||
epoch=""
|
||||
fi
|
||||
|
||||
changelog_header=$(date "+%a %b %d %Y $USER_NAME <$USER_EMAIL> - $epoch$version-$next_release")
|
||||
|
||||
changelog_indents=$(grep -m 1 -P "^\*.*@.*>" "$spec_path" | sed -E "s/^\*(\s+).*/\1/")
|
||||
if [[ -z "$changelog_indents" ]]
|
||||
then
|
||||
changelog_indents=" "
|
||||
fi
|
||||
|
||||
spec_set_release_number "$spec_path" $next_release
|
||||
sed -i -E "/\s*^%changelog.*/a *$changelog_indents$changelog_header\n-$changelog_indents$changelog_message\n" "$spec_path"
|
||||
# Remove excessive empty lines, if present.
|
||||
sed -i -e :a -e '/^\n*$/{$d;N;ba' -e '}' "$spec_path"
|
||||
}
|
||||
|
||||
create_new_file_from_template() {
|
||||
local -n placeholders
|
||||
local key
|
||||
local target_path
|
||||
local template_path
|
||||
local value
|
||||
|
||||
template_path="$1"
|
||||
target_path="$2"
|
||||
placeholders="$3"
|
||||
|
||||
echo "Creating a new file under \"$target_path\" from template \"$template_path\"."
|
||||
|
||||
mkdir -p "$(dirname "$target_path")"
|
||||
|
||||
cp "$template_path" "$target_path"
|
||||
|
||||
for key in "${!placeholders[@]}"
|
||||
do
|
||||
value="${placeholders[$key]}"
|
||||
awk -i inplace -v r="$value" "{gsub(/$key/,r)}1" "$target_path"
|
||||
done
|
||||
}
|
||||
|
||||
dump_changelog() {
|
||||
local spec_path
|
||||
|
||||
spec_path="$1"
|
||||
|
||||
sed -n '/%changelog/,$p' "$spec_path"
|
||||
}
|
||||
|
||||
parsed_spec_read_patches() {
|
||||
parsed_spec_read_tags "$1" "Patch" "$2"
|
||||
}
|
||||
|
||||
parsed_spec_read_tag() {
|
||||
local spec_path
|
||||
local tag
|
||||
|
||||
spec_path="$1"
|
||||
tag="$2"
|
||||
|
||||
mariner_rpmspec --query --queryformat="%{$tag}\n" --srpm "$spec_path" 2>/dev/null
|
||||
}
|
||||
|
||||
parsed_spec_read_tags() {
|
||||
local -n results_array
|
||||
local spec_path
|
||||
local tag
|
||||
|
||||
spec_path="$1"
|
||||
tag="$2"
|
||||
results_array="$3"
|
||||
|
||||
for result in $(mariner_rpmspec --query --queryformat="[%{$tag}\n]" --srpm "$spec_path" 2>/dev/null | tac)
|
||||
do
|
||||
results_array+=("$result")
|
||||
done
|
||||
}
|
||||
|
||||
spec_query_srpm() {
|
||||
local query_format
|
||||
local spec_path
|
||||
|
||||
spec_path="$1"
|
||||
query_format="$2"
|
||||
|
||||
mariner_rpmspec -q --queryformat="$query_format" --srpm "$spec_path" 2>/dev/null
|
||||
}
|
||||
|
||||
spec_read_release_number() {
|
||||
spec_read_tag_skip_macros "$1" "Release"
|
||||
}
|
||||
|
||||
spec_read_release_tag() {
|
||||
spec_read_tag "$1" "Release"
|
||||
}
|
||||
|
||||
spec_read_tag() {
|
||||
local spec_path
|
||||
local tag
|
||||
|
||||
spec_path="$1"
|
||||
tag="$2"
|
||||
|
||||
grep "^$tag:" "$spec_path" | sed -E "s/$tag:\s+([^#]+)/\1/"
|
||||
}
|
||||
|
||||
spec_read_tag_skip_macros() {
|
||||
local spec_path
|
||||
local tag
|
||||
|
||||
spec_path="$1"
|
||||
tag="$2"
|
||||
|
||||
spec_read_tag "$spec_path" "$tag" | grep -oP "^[^%]+"
|
||||
}
|
||||
|
||||
spec_read_epoch() {
|
||||
parsed_spec_read_tag "$1" "Epoch"
|
||||
}
|
||||
|
||||
spec_read_version() {
|
||||
parsed_spec_read_tag "$1" "Version"
|
||||
}
|
||||
|
||||
spec_set_tag() {
|
||||
local spec_path
|
||||
local tag
|
||||
local value
|
||||
|
||||
spec_path="$1"
|
||||
tag="$2"
|
||||
value="$3"
|
||||
|
||||
sed -i -E "s/($tag:\s+).*/\1$value/" "$spec_path"
|
||||
}
|
||||
|
||||
spec_set_release_number() {
|
||||
local spec_path
|
||||
local value
|
||||
|
||||
spec_path="$1"
|
||||
value="$2"
|
||||
|
||||
spec_set_tag "$spec_path" "Release" "$value%{?dist}"
|
||||
}
|
||||
|
||||
spec_set_version() {
|
||||
local spec_path
|
||||
local value
|
||||
|
||||
spec_path="$1"
|
||||
value="$2"
|
||||
|
||||
spec_set_tag "$spec_path" "Version" "$value"
|
||||
}
|
||||
|
||||
init
|
|
@ -8,8 +8,10 @@
|
|||
# $1 - Changelog message.
|
||||
# ${@:2} - Paths to spec files to update.
|
||||
|
||||
# shellcheck source=../../toolkit/scripts/rpmops.sh
|
||||
source "$(git rev-parse --show-toplevel)"/toolkit/scripts/rpmops.sh
|
||||
REPO_ROOT="$(git rev-parse --show-toplevel)"
|
||||
|
||||
# shellcheck source=../../toolkit/scripts/specs/specs_tools.sh
|
||||
source "$REPO_ROOT"/toolkit/scripts/specs/specs_tools.sh
|
||||
|
||||
changelog_message="$1"
|
||||
|
||||
|
@ -19,21 +21,6 @@ then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
user_email="$(git config user.email)"
|
||||
user_name="$(git config user.name)"
|
||||
|
||||
if [[ -z $user_email ]]
|
||||
then
|
||||
echo "ERROR: must set git user e-mail. Try running 'git config --local user.email [user_email]'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [[ -z $user_name ]]
|
||||
then
|
||||
echo "ERROR: must set git user name. Try running 'git config --local user.name [user_name]'." >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for spec_path in "${@:2}"
|
||||
do
|
||||
if [[ ! -f "$spec_path" ]]
|
||||
|
@ -44,18 +31,5 @@ do
|
|||
|
||||
echo "Updating '$spec_path'."
|
||||
|
||||
release=$(grep -oP "^Release:\s*\d+" "$spec_path" | grep -oP "\d+$")
|
||||
release=$((release+1))
|
||||
version=$(mariner_rpmspec --srpm -q "$spec_path" --qf "%{VERSION}\n" 2>/dev/null)
|
||||
|
||||
epoch="$(mariner_rpmspec --srpm -q "$spec_path" --qf "%{EPOCH}\n" 2>/dev/null):"
|
||||
if [[ "$epoch" == "(none):" ]]
|
||||
then
|
||||
epoch=""
|
||||
fi
|
||||
|
||||
sed -i -E "s/^(Release:\s*).*/\1$release%{?dist}/" "$spec_path"
|
||||
changelog_header=$(date "+%a %b %d %Y $user_name <$user_email> - $epoch$version-$release")
|
||||
changelog_indents=$(grep -m 1 -P "^\*.*@.*>" "$spec_path" | sed -E "s/^\*(\s+).*/\1/")
|
||||
sed -i -E "/\s*^%changelog.*/a *$changelog_indents$changelog_header\n-$changelog_indents$changelog_message\n" "$spec_path"
|
||||
add_changelog_entry "$spec_path" "$changelog_message"
|
||||
done
|
||||
|
|
Загрузка…
Ссылка в новой задаче