From 1b2f87733318648b25bace96ac3d9200d9a208e2 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 15:33:00 +0200 Subject: [PATCH 01/10] feat: add support for (self) signing kernels (for SecureBoot, resolves #75) --- README.md | 39 +++++++++++++++++++-------------------- ubuntu-mainline-kernel.sh | 38 +++++++++++++++++++++++++++++++++++++- 2 files changed, 56 insertions(+), 21 deletions(-) diff --git a/README.md b/README.md index 19c021b..d33766f 100644 --- a/README.md +++ b/README.md @@ -1,18 +1,16 @@ -ubuntu-mainline-kernel.sh -================= +# ubuntu-mainline-kernel.sh Bash script for Ubuntu (and derivatives as LinuxMint) to easily (un)install kernels from the [Ubuntu Kernel PPA](http://kernel.ubuntu.com/~kernel-ppa/mainline/). -Warnings ------------------ +## Warnings + :warning: Use this script at your own risk. Be aware that the kernels installed by this script are [unsupported](https://wiki.ubuntu.com/Kernel/MainlineBuilds#Support_.28BEWARE:_there_is_none.29) :unlock: Do not use this script if you don't have to or don't know what you are doing. You won't be [covered](https://github.com/pimlie/ubuntu-mainline-kernel.sh/issues/32) by any security guarantees. The intended purpose by Ubuntu for the mainline ppa kernels is for debugging issues. :information_source: We strongly advise to keep the default Ubuntu kernel installed as there is no safeguard that at least one kernel is installed on your system. -Install ----------------- +## Install ``` apt install wget wget https://raw.githubusercontent.com/pimlie/ubuntu-mainline-kernel.sh/master/ubuntu-mainline-kernel.sh @@ -26,8 +24,14 @@ wget https://raw.githubusercontent.com/pimlie/ubuntu-mainline-kernel.sh/master/U mv UbuntuMainlineKernel.desktop ~/.config/autostart/ ``` -Usage ------------------ +## SecureBoot + +> :warning: There is no support for creating and enrolling your own MOK. If you don't know how to do that then you could use the `mok-setup.sh` script from [berglh/ubuntu-sb-kernel-signing](https://github.com/berglh/ubuntu-sb-kernel-signing) to help you get started (at your own risk) + +The script supports self signing the mainline kernels. Edit the script and set `sign_kernel=1` and +update the paths to your MOK key & certificate. (The default paths are the ones as created by the `mok-setup.sh` script from [berglh/ubuntu-sb-kernel-signing](https://github.com/berglh/ubuntu-sb-kernel-signing)) + +## Usage ``` Usage: ubuntu-mainline-kernel.sh -c|-l|-r|-u @@ -61,16 +65,14 @@ Optional: --yes Assume yes on all questions (use with caution!) ``` -Elevated privileges -------------------- +## Elevated privileges This script needs elevated privileges when installing or uninstalling kernels. Either run this script with sudo or configure the path to sudo within the script to sudo automatically -Example output -------------------- +## Example output Install latest version: ``` @@ -105,21 +107,18 @@ Are you really sure? (y/N) Kernel v4.8.6 successfully purged ``` -Dependencies ----------------- +## Dependencies + * bash * gnucoreutils * dpkg * wget (since 2018-12-14 as kernel ppa is now https only) -Optional dependencies ----------------- +## Optional dependencies + * libnotify-bin (to show notify bubble when new version is found) * bsdmainutils (format output of -l, -r with column) * gpg (to check the signature of the checksum file) * sha1sum/sha256sum (to check the .deb checksums) +* sbsigntool (to sign kernel images for SecureBoot) * sudo - -TODO ------------------ -- [ ] Support daily kernel builds (on hold until there is significant demand for this, PRs are also welcome) diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index 3286ca1..2e21feb 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -7,6 +7,11 @@ ppa_host="kernel.ubuntu.com" ppa_index="/~kernel-ppa/mainline/" ppa_key="17C622B0" +# Machine-Owner-Key for Secure Boot +sign_kernel=0 +mokKey="/var/lib/shim-signed/mok/MOK-Kernel.priv" +mokCert="/var/lib/shim-signed/mok/MOK-Kernel.pem" + # If quiet=1 then no log messages are printed (except errors) quiet=0 @@ -40,7 +45,7 @@ wget=$(command -v wget) cleanup_files=1 # (internal) If do_install=0 downloaded deb files will not be installed -do_install=1 +do_install=0 # (internal) If use_lowlatency=1 then the lowlatency kernel will be installed use_lowlatency=0 @@ -612,6 +617,11 @@ Optional: warn "Disable signature check, gpg not available" } + [[ $sign_kernel -eq 1 && (! -s "$mokKey" || ! -s "$mokCert") ]] && { + err "Could not find machine owner key" + exit 1 + } + IFS=$'\n' ppa_uri=$ppa_index${version%\.0}"/" @@ -751,6 +761,32 @@ Optional: log "deb files have been saved to $workdir" fi + if [ $sign_kernel -eq 1 ]; then + kernelImg="" + for deb in "${debs[@]}"; do + # match deb file that starts with linux-image- + if [[ "$deb" == "linux-image-"* ]]; then + imagePkgName="${deb/_*}" + + # The image deb normally only adds one file (the kernal image) to + # the /boot folder, find it so we can sign it + kernelImg="$(grep /boot/ <<< "$(dpkg -L "$imagePkgName")")" + fi + done + + if [ -n "$kernelImg" ] && [ -x "$(command -v sbsign)" ]; then + if $sudo sbverify --cert "$mokCert" "$kernelImg" >/dev/null; then + echo "Kernel image $kernelImg is already signed by the provided MOK" + elif $sudo sbverify --list "$kernelImg" | grep -v "No signature table present"; then + echo "Kernel image $kernelImg is already signed by another MOK" + else + echo -n "Signing kernel image" + $sudo sbsign --key "$mokKey" --cert "$mokCert" --output "$kernelImg" "$kernelImg" + echo "" + fi + fi + fi + if [ $cleanup_files -eq 1 ]; then log "Cleaning up work folder" rm -f "$workdir"*.deb From da68ccc06c1ae6947ade2cfe39afccda97a4cd21 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 15:36:31 +0200 Subject: [PATCH 02/10] chore: add gitattributes for better win support (resolves #84) --- .gitattributes | 1 + 1 file changed, 1 insertion(+) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..dfdb8b7 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf From e6b52b35989acd2ea0168a4cf0bd75b67563ce44 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 15:43:47 +0200 Subject: [PATCH 03/10] chore: improve check for gpg (possibly resolves #73) --- ubuntu-mainline-kernel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index 2e21feb..e0ac142 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -611,7 +611,7 @@ Optional: cd "$workdir" || exit 1 - [ $check_signature -eq 1 ] && [ -z "$(command -v gpg)" ] && { + [ $check_signature -eq 1 ] && [ ! -x "$(command -v gpg)" ] && { check_signature=0 warn "Disable signature check, gpg not available" From 742f4ea77d11a79c6a45a661cd1716edbb715614 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 15:46:45 +0200 Subject: [PATCH 04/10] fix: enable do_install again after debugging --- ubuntu-mainline-kernel.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index e0ac142..ca5a051 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -45,7 +45,7 @@ wget=$(command -v wget) cleanup_files=1 # (internal) If do_install=0 downloaded deb files will not be installed -do_install=0 +do_install=1 # (internal) If use_lowlatency=1 then the lowlatency kernel will be installed use_lowlatency=0 From 923e5e0a55a7e3f935457f97cc74ca1fe86a2d96 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 16:01:23 +0200 Subject: [PATCH 05/10] fix #61: log error when latest remote version is empty --- ubuntu-mainline-kernel.sh | 41 +++++++++++++++++++++++++++------------ 1 file changed, 29 insertions(+), 12 deletions(-) diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index ca5a051..b5d07c2 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -405,23 +405,30 @@ load_remote_versions () { [ -z "$1" ] && log fi - IFS=$'\n' - while read -r line; do - # reinstate original rc suffix join character - if [[ $line =~ ^([^~]+)~([^~]+)$ ]]; then - [[ $use_rc -eq 0 ]] && continue - line="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}" - fi - [[ -n "$2" ]] && [[ ! "$line" =~ $2 ]] && continue - REMOTE_VERSIONS+=("$line") - done < <(parse_remote_versions | sort -V) - unset IFS + if [ -n "$remote_html_cache" ]; then + IFS=$'\n' + while read -r line; do + # reinstate original rc suffix join character + if [[ $line =~ ^([^~]+)~([^~]+)$ ]]; then + [[ $use_rc -eq 0 ]] && continue + line="${BASH_REMATCH[1]}-${BASH_REMATCH[2]}" + fi + [[ -n "$2" ]] && [[ ! "$line" =~ $2 ]] && continue + REMOTE_VERSIONS+=("$line") + done < <(parse_remote_versions | sort -V) + unset IFS + fi fi } latest_remote_version () { load_remote_versions 1 "$1" - echo "${REMOTE_VERSIONS[${#REMOTE_VERSIONS[@]}-1]}" + + if [ ${#REMOTE_VERSIONS[@]} -gt 0 ]; then + echo "${REMOTE_VERSIONS[${#REMOTE_VERSIONS[@]}-1]}" + else + echo "" + fi } check_environment () { @@ -483,6 +490,11 @@ Optional: latest_version=$(latest_remote_version) log ": $latest_version" + if [ -z "$latest_version" ]; then + err "Could not find latest version" + exit 1 + fi + logn "Finding latest installed version" installed_version=$(latest_local_version) installed_version=${installed_version%-*} @@ -563,6 +575,11 @@ Optional: version=$(latest_remote_version) log + if [ -z "$version" ]; then + err "Could not find latest version" + exit 1 + fi + if containsElement "$version" "${LOCAL_VERSIONS[@]}"; then logn "Latest version is $version but seems its already installed" else From 08681bfad37e1732fce0261cab0d8ec9a63464e7 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 16:12:49 +0200 Subject: [PATCH 06/10] chore: add msg about low-latency kernels --- README.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index d33766f..3747c8b 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # ubuntu-mainline-kernel.sh -Bash script for Ubuntu (and derivatives as LinuxMint) to easily (un)install kernels from the [Ubuntu Kernel PPA](http://kernel.ubuntu.com/~kernel-ppa/mainline/). +Bash script for Ubuntu (and derivatives as LinuxMint) to easily (un)install kernels from the [Ubuntu Kernel PPA](https://kernel.ubuntu.com/~kernel-ppa/mainline/). ## Warnings @@ -65,6 +65,8 @@ Optional: --yes Assume yes on all questions (use with caution!) ``` +> :information_source: Since ~v5.18 Ubuntu does not publish low-latency mainline kernels anymore, see this [AskUbuntu](https://askubuntu.com/questions/1397410/where-are-latest-mainline-low-latency-kernel-packages) for more info + ## Elevated privileges This script needs elevated privileges when installing or uninstalling kernels. From 864d55b602a47f713659307cd23d06bc255fc68d Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 16:21:03 +0200 Subject: [PATCH 07/10] fix #72: check if user entered a valid index on uninstall and exit otherwise --- ubuntu-mainline-kernel.sh | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index b5d07c2..e6d214c 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -832,7 +832,17 @@ Optional: read -rn1 index echo "" + if ! [[ $index == +([0-9]) ]]; then + echo "No number entered, exiting" + exit 0 + fi + uninstall_version=${LOCAL_VERSIONS[$index]} + + if [ -z "$uninstall_version" ]; then + echo "Version not found" + exit 0 + fi elif containsElement "v${action_data[0]#v}" "${LOCAL_VERSIONS[@]}"; then uninstall_version="v"${action_data[0]#v} else From bb7ca7d38b5259b9f2f2548500fbf4f2385730af Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 16:26:28 +0200 Subject: [PATCH 08/10] fix #74: exit when gpg key could not be imported & mention possible workaround in readme --- README.md | 3 +++ ubuntu-mainline-kernel.sh | 4 ++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 3747c8b..aef7f2d 100644 --- a/README.md +++ b/README.md @@ -124,3 +124,6 @@ Kernel v4.8.6 successfully purged * sha1sum/sha256sum (to check the .deb checksums) * sbsigntool (to sign kernel images for SecureBoot) * sudo + +## Known issues (with workarounds) +- GPG is unable to import the key behind a proxy: #74 diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index e6d214c..b32f2e4 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -731,8 +731,8 @@ Optional: log "ok" else logn "failed" - warn "Unable to check signature" - check_signature=0 + err "Unable to import ppa key" + exit 1 fi fi From c18c6b44272472011144f394d9bd1988a9ec8538 Mon Sep 17 00:00:00 2001 From: pimlie Date: Sun, 28 May 2023 16:49:14 +0200 Subject: [PATCH 09/10] feat #46: add self update option --- README.md | 1 + ubuntu-mainline-kernel.sh | 20 ++++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/README.md b/README.md index aef7f2d..7ce83e2 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,7 @@ Arguments: is supplied it will search for that -u [VERSION] Uninstall the specified kernel version. If version is omitted, a list of max 10 installed kernel versions is displayed + --update Update this script by redownloading it from github -h Show this message Optional: diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index b32f2e4..c53cb4c 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -12,6 +12,8 @@ sign_kernel=0 mokKey="/var/lib/shim-signed/mok/MOK-Kernel.priv" mokCert="/var/lib/shim-signed/mok/MOK-Kernel.pem" +self_update_url="https://raw.githubusercontent.com/pimlie/ubuntu-mainline-kernel.sh/master/ubuntu-mainline-kernel.sh" + # If quiet=1 then no log messages are printed (except errors) quiet=0 @@ -241,6 +243,9 @@ while (( "$#" )); do debug_target="/dev/stderr" quiet=0 ;; + --update) + run_action="update" + ;; -h|--help) run_action="help" ;; @@ -463,6 +468,7 @@ Arguments: is supplied it will search for that -u [VERSION] Uninstall the specified kernel version. If version is omitted, a list of max 10 installed kernel versions is displayed + --update Update this script by redownloading it from github -h Show this message Optional: @@ -482,7 +488,21 @@ Optional: " exit 2 ;; + update) + check_environment + + self="$(readlink -f "$0")" + $wget -q -O "$self.tmp" "$self_update_url" + if [ ! -s "$self.tmp" ]; then + rm "$self.tmp" + err "Update failed, downloaded file is empty" + exit 1 + else + mv "$self.tmp" "$self" + echo "Script updated" + fi + ;; check) check_environment From 617171ebea0a506d57659f43bc07fb591e3c4a56 Mon Sep 17 00:00:00 2001 From: Pim Date: Mon, 22 Jan 2024 18:38:04 +0100 Subject: [PATCH 10/10] feat: add experimental support to locally build new kernel versions (#86) * feat: add experimental support to locally build new kernel versions * fix: shellcheck issues * chore: revert to default option value --- README.md | 18 +++ ubuntu-mainline-kernel.sh | 305 ++++++++++++++++++++++++++++++++------ 2 files changed, 280 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index 7ce83e2..303b643 100644 --- a/README.md +++ b/README.md @@ -39,6 +39,7 @@ Download & install the latest kernel available from kernel.ubuntu.com Arguments: -c Check if a newer kernel version is available + -b [VERSION] Build kernel VERSION locally and then install it (requires git & docker) -i [VERSION] Install kernel VERSION, see -l for list. You don't have to prefix with v. E.g. -i 4.9 is the same as -i v4.9. If version is omitted the latest available version will be installed @@ -74,6 +75,23 @@ This script needs elevated privileges when installing or uninstalling kernels. Either run this script with sudo or configure the path to sudo within the script to sudo automatically +## Building kernels locally *(EXPERIMENTAL)* + +> :warning: YMMV, this is experimental support. Don't build kernel's if you don't know what you are doing + +> :warning: If the build fails, please debug yourself and create a PR with fixes if needed. Also if you don't know how to debug the build failure, then you probably shouldn't be building your own kernels! + +> :information_source: There are no plans to add full fledged support for building kernels. This functionality might stay experimental for a long time + +The mainline kernel ppa only supports the latest Ubuntu release. But newer Ubuntu releases could use newer library versions then the current LTS releases (f.e. both libssl or glibc version issues have existed in the past). Which means that you won't be able to (fully) install the newer kernel anymore. + +When that happens you could try to build your own kernel releases by using the `--build VERSION` argument (f.e. `-b 6.7.0`). + +Kernel building support is provided by [TuxInvader/focal-mainline-builder](https://github.com/TuxInvader/focal-mainline-builder) so requires: + +- git & docker +- quite a bit of free disk space (~3GB to checkout the kernel source, maybe ~10GB or more during build) +- can take quite a while depending on how fast your computer is ## Example output diff --git a/ubuntu-mainline-kernel.sh b/ubuntu-mainline-kernel.sh index c53cb4c..0ea67cc 100755 --- a/ubuntu-mainline-kernel.sh +++ b/ubuntu-mainline-kernel.sh @@ -37,6 +37,15 @@ sudo="" # Path to wget command wget=$(command -v wget) +# Path where git kernel source is checked out when building the kernel +build_src_path="/usr/local/src/mainline-kernel/" + +# Path where git kernel source is checked out when building the kernel +build_deb_path="/opt/mainline-kernel/" + +# Which packages to install after build (comma separated, only used when building the kernel locally) +build_pkgs="linux-headers,linux-image-unsigned,linux-modules" + ##### ## Below are internal variables of which most can be toggled by command options ## DON'T CHANGE THESE MANUALLY @@ -153,6 +162,11 @@ while (( "$#" )); do single_action run_action="check" ;; + -b|--build) + single_action + run_action="build" + argarg_required=1 + ;; -l|--local-list) single_action run_action="local-list" @@ -284,6 +298,22 @@ containsElement () { return 1 } +monitor_background_command () { + local pid=$1 + + printf ' ' + while :; do for c in / - \\ \|; do + if ps -p "$pid" >/dev/null; then + printf '\b%s' "$c" + sleep 1 + else + break 2 + fi + done; done + + printf '\b ' +} + download () { host=$1 uri=$2 @@ -436,11 +466,78 @@ latest_remote_version () { fi } +check_requested_version () { + local requested_version="$1" + + if [ -z "${requested_version}" ]; then + logn "Finding latest version available on $ppa_host" + version=$(latest_remote_version) + log + + if [ -z "$version" ]; then + err "Could not find latest version" + exit 1 + fi + + if containsElement "$version" "${LOCAL_VERSIONS[@]}"; then + logn "Latest version is $version but seems its already installed" + else + logn "Latest version is: $version" + fi + + if [ $do_install -gt 0 ] && [ $assume_yes -eq 0 ];then + logn ", continue? (y/N) " + [ $quiet -eq 0 ] && read -rsn1 continue + log + + [ "$continue" != "y" ] && [ "$continue" != "Y" ] && { exit 0; } + else + log + fi + else + load_remote_versions + + version="" + if containsElement "v${requested_version#v}" "${REMOTE_VERSIONS[@]}"; then + version="v"${requested_version#v} + fi + + [[ -z "$version" ]] && { + err "Version '${requested_version}' not found" + exit 2 + } + shift + + if [ $do_install -gt 0 ] && containsElement "$version" "${LOCAL_VERSIONS[@]}" && [ $assume_yes -eq 0 ]; then + logn "It seems version $version is already installed, continue? (y/N) " + [ $quiet -eq 0 ] && read -rsn1 continue + log + + [ "$continue" != "y" ] && [ "$continue" != "Y" ] && { exit 0; } + fi + fi +} + check_environment () { if [ $use_https -eq 1 ] && [ -z "$wget" ]; then err "Abort, wget not found. Please apt install wget" exit 3 fi + + local required_commands=("$@") + if [ ${#required_commands[@]} -gt 0 ]; then + local missing_commands=() + for cmd in "${required_commands[@]}"; do + if ! command -v "$cmd" >/dev/null; then + missing_commands+=("$cmd") + fi + done + + if [ ${#missing_commands[@]} -gt 0 ]; then + err "Abort, some required commands are missing. Please install: ${missing_commands[*]}" + exit 3 + fi + fi } guard_run_as_root () { @@ -459,6 +556,7 @@ Download & install the latest kernel available from $ppa_host$ppa_uri Arguments: -c Check if a newer kernel version is available + -b [VERSION] Build kernel VERSION locally and then install it (requires git & docker) -i [VERSION] Install kernel VERSION, see -l for list. You don't have to prefix with v. E.g. -i 4.9 is the same as -i v4.9. If version is omitted the latest available version will be installed @@ -564,9 +662,9 @@ Optional: # shellcheck disable=SC2015 [[ -n "$(command -v column)" ]] && { column="column -x"; } || { column="cat"; } - (for version in "${LOCAL_VERSIONS[@]}"; do - if [ -z "${action_data[0]}" ] || [[ "$version" =~ ${action_data[0]} ]]; then - echo "$version" + (for local_version in "${LOCAL_VERSIONS[@]}"; do + if [ -z "${action_data[0]}" ] || [[ "$local_version" =~ ${action_data[0]} ]]; then + echo "$local_version" fi done) | $column ;; @@ -577,67 +675,188 @@ Optional: # shellcheck disable=SC2015 [[ -n "$(command -v column)" ]] && { column="column -x"; } || { column="cat"; } - (for version in "${REMOTE_VERSIONS[@]}"; do - if [ -z "${action_data[0]}" ] || [[ "$version" =~ ${action_data[0]} ]]; then - echo "$version" + (for remote_version in "${REMOTE_VERSIONS[@]}"; do + if [ -z "${action_data[0]}" ] || [[ "$remote_version" =~ ${action_data[0]} ]]; then + echo "$remote_version" fi done) | $column ;; - install) + build) # only ensure running if the kernel files should be installed - [ $do_install -eq 1 ] && guard_run_as_root + guard_run_as_root - check_environment + check_environment git docker load_local_versions + check_requested_version "${action_data[0]}" + + [ ! -d "$build_src_path" ] && { + mkdir -p "$build_src_path" 2>/dev/null + } + [ ! -x "$build_src_path" ] && { + err "$build_src_path is not writable" + exit 1 + } + + expected_debs_count=$(echo "$build_pkgs" | tr "," "\n" | wc -l) + if [[ $build_pkgs == *"linux-headers"* ]]; then + # headers come in two packages + ((expected_debs_count++)) + fi + + existing_debs_count=0 + build_kernel=1 + + if [ -d "$build_deb_path/$version/" ]; then + existing_debs_count=$(eval "ls -1 $build_deb_path$version/{$build_pkgs}-${version#v}*.deb | wc -l") + fi - if [ -z "${action_data[0]}" ]; then - logn "Finding latest version available on $ppa_host" - version=$(latest_remote_version) + if [ "$existing_debs_count" -eq "$expected_debs_count" ]; then + read -rsn1 -p "Packages already exists for $version, use existing debs? (Y/n)" continue log - if [ -z "$version" ]; then - err "Could not find latest version" - exit 1 + if [ "${continue:-y}" == "y" ] || [ "$continue" == "Y" ]; then + build_kernel=0 fi + fi - if containsElement "$version" "${LOCAL_VERSIONS[@]}"; then - logn "Latest version is $version but seems its already installed" - else - logn "Latest version is: $version" + if [ $build_kernel -eq 1 ]; then + if [ -d "$build_src_path" ]; then + read -rsn1 -p "Folder $build_src_path exists, remove it? (Y/n)" continue + + if [ "${continue:-y}" == "y" ] || [ "$continue" == "Y" ]; then + $sudo rm -Rf "$build_src_path" + log + else + log + log "Cannot clone kernel source to $build_src_path as the folder already exists" + exit 1 + fi + fi + + log "Checking out kernel source from git (is ~2GB, so can take a while) " + branch_version="${version%.0}" # remove last .0 if exists, cause branch name is v6.7 not v6.7.0 + git clone --depth=1 -b "cod/mainline/$branch_version" git://git.launchpad.net/~ubuntu-kernel-test/ubuntu/+source/linux/+git/mainline-crack "$build_src_path" >"$debug_target" 2>&1 & + monitor_background_command $! + + imageName="tuxinvader/jammy-mainline-builder:latest" + + # If version ends on .0 then build or own builder container using tuxinvader's as base + # to fix the branch name checkout cause the branch name is v6.7 and not v6.7.0 + if [[ $version =~ \.0 ]]; then + imageName="mainline-builder" + # Build docker image if not yet exists + if [ -z "$(docker images -q mainline-builder)" ]; then + log "Building docker image" + docker build -t mainline-builder -<$debug_target 2>&1 else - log + warn "Did not find any .deb files to install" fi else - load_remote_versions + log "deb files have been saved to $build_deb_path$version/" + fi - version="" - if containsElement "v${action_data[0]#v}" "${REMOTE_VERSIONS[@]}"; then - version="v"${action_data[0]#v} - fi + if [ $sign_kernel -eq 1 ]; then + kernelImg="" + for deb in "${debs[@]}"; do + deb="$(basename "$deb")" - [[ -z "$version" ]] && { - err "Version '${action_data[0]}' not found" - exit 2 - } - shift + # match deb file that starts with linux-image- + if [[ "$deb" == "linux-image-"* ]]; then + imagePkgName="${deb/_*}" - if [ $do_install -gt 0 ] && containsElement "$version" "${LOCAL_VERSIONS[@]}" && [ $assume_yes -eq 0 ]; then - logn "It seems version $version is already installed, continue? (y/N) " - [ $quiet -eq 0 ] && read -rsn1 continue - log + # The image deb normally only adds one file (the kernal image) to + # the /boot folder, find it so we can sign it + kernelImg="$(grep /boot/ <<< "$(dpkg -L "$imagePkgName")")" + fi + done - [ "$continue" != "y" ] && [ "$continue" != "Y" ] && { exit 0; } + if [ -n "$kernelImg" ] && [ -x "$(command -v sbsign)" ]; then + if $sudo sbverify --cert "$mokCert" "$kernelImg" >/dev/null; then + log "Kernel image $kernelImg is already signed by the provided MOK" + elif $sudo sbverify --list "$kernelImg" | grep -v "No signature table present"; then + log "Kernel image $kernelImg is already signed by another MOK" + else + logn "Signing kernel image" + $sudo sbsign --key "$mokKey" --cert "$mokCert" --output "$kernelImg" "$kernelImg" + log + fi fi fi + if [ $cleanup_files -eq 1 ] && [ -d "$workdir$version/" ]; then + log "Cleaning up work folder" + rm -f "$workdir$version/"*.buildinfo + rm -f "$workdir$version/"*.changes + rm -f "$workdir$version/"*.deb + rmdir "$workdir$version/" + rmdir "$workdir" + fi + ;; + install) + # only ensure running if the kernel files should be installed + [ $do_install -eq 1 ] && guard_run_as_root + + check_environment + load_local_versions + check_requested_version "${action_data[0]}" + [ ! -d "$workdir" ] && { mkdir -p "$workdir" 2>/dev/null } @@ -813,13 +1032,13 @@ Optional: if [ -n "$kernelImg" ] && [ -x "$(command -v sbsign)" ]; then if $sudo sbverify --cert "$mokCert" "$kernelImg" >/dev/null; then - echo "Kernel image $kernelImg is already signed by the provided MOK" + log "Kernel image $kernelImg is already signed by the provided MOK" elif $sudo sbverify --list "$kernelImg" | grep -v "No signature table present"; then - echo "Kernel image $kernelImg is already signed by another MOK" + log "Kernel image $kernelImg is already signed by another MOK" else - echo -n "Signing kernel image" + logn "Signing kernel image" $sudo sbsign --key "$mokKey" --cert "$mokCert" --output "$kernelImg" "$kernelImg" - echo "" + log fi fi fi