Skip to content

Commit

Permalink
Kernel switching module: hardening
Browse files Browse the repository at this point in the history
  • Loading branch information
igorpecovnik committed Dec 6, 2024
1 parent ae2789f commit c2ca7ff
Show file tree
Hide file tree
Showing 6 changed files with 250 additions and 176 deletions.
22 changes: 11 additions & 11 deletions tools/json/config.system.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,22 @@
"description": "Enable Armbian firmware upgrades",
"about": "This will enable Armbian kernel upgrades that are currently put on hold.",
"command": [
"armbian_fw_manipulate unhold"
"module_armbianfirmware unhold"
],
"status": "Stable",
"author": "@igorpecovnik",
"condition": "[[ -n \"$(apt-mark showhold)\" ]]"
"condition": "module_armbianfirmware hold status"
},
{
"id": "SY002",
"description": "Disable Armbian kernel upgrades",
"about": "Disable Armbian kernel/firmware upgrades",
"command": [
"armbian_fw_manipulate hold"
"module_armbianfirmware hold"
],
"status": "Stable",
"author": "@igorpecovnik",
"condition": "[[ -z \"$(apt-mark showhold)\" ]]"
"condition": "! module_armbianfirmware hold status"
},
{
"id": "SY003",
Expand Down Expand Up @@ -230,25 +230,25 @@
},
{
"id": "SY010",
"description": "Switch to rolling release",
"description": "Switch to rolling packages repository",
"about": "This will switch OS to rolling releases.",
"command": [
"set_rolling"
"module_armbianfirmware repository rolling"
],
"status": "Stable",
"author": "@igorpecovnik",
"condition": "grep -q 'apt.armbian.com' /etc/apt/sources.list.d/armbian.list && [[ -z \"$(apt-mark showhold)\" ]]"
"condition": "module_armbianfirmware repository stable status"
},
{
"id": "SY011",
"description": "Switch to stable release",
"description": "Switch to stable packages repository",
"about": "This will switch OS to stable releases",
"command": [
"set_stable"
"module_armbianfirmware repository stable"
],
"status": "Stable",
"author": "@igorpecovnik",
"condition": "grep -q 'beta.armbian.com' /etc/apt/sources.list.d/armbian.list && [[ -z \"$(apt-mark showhold)\" ]]"
"condition": "module_armbianfirmware repository rolling status"
},
{
"id": "SY012",
Expand Down Expand Up @@ -287,7 +287,7 @@
"description": "Install alternative kernels",
"about": "Switching between kernels might change functionality of your device. \n\nIt might fail to boot!",
"command": [
"switch_kernels"
"module_armbianfirmware select"
],
"status": "Stable",
"author": "@igorpecovnik",
Expand Down
84 changes: 0 additions & 84 deletions tools/modules/system/armbian_fw_manipulate.sh

This file was deleted.

239 changes: 239 additions & 0 deletions tools/modules/system/module_armbian_firmware.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,239 @@
declare -A module_options
module_options+=(
["module_armbianfirmware,author"]="@igorpecovnik"
["module_armbianfirmware,feature"]="module_armbianfirmware"
["module_armbianfirmware,example"]="select install show hold unhold repository help"
["module_armbianfirmware,desc"]="Example module unattended interface."
["module_armbianfirmware,status"]="review"
)

function module_armbianfirmware() {
local title="Armbian firmware"
local condition=$(which "$title" 2>/dev/null)

# Convert the example string to an array
local commands
IFS=' ' read -r -a commands <<< "${module_options["module_armbianfirmware,example"]}"

case "$1" in
"${commands[0]}") # choose kernel from the list

# make sure to proceed if this variable is not defined. This can surface on some old builds
[[ -z "${KERNEL_TEST_TARGET}" ]] && KERNEL_TEST_TARGET="legacy,vendor,current,edge"

# by default we define which kernels are suitable
if ! $DIALOG --title "Advanced options" --yesno "Show only mainstream kernels on the list?" 7 60; then
KERNEL_TEST_TARGET="legacy,vendor,current,edge"
fi

# read what is possible to install
local kernel_test_target=$(for kernel_test_target in ${KERNEL_TEST_TARGET//,/ }; do echo "linux-image-${kernel_test_target}-${LINUXFAMILY}"; done;)
local installed_kernel_version=$(dpkg -l | grep '^ii' | grep linux-image | awk '{print $2"="$3}')

# workaroun in case current is not installed
[[ -n ${installed_kernel_version} ]] && local grep_current_kernel=" | grep -v ${installed_kernel_version}"

# main search command
local search_exec="apt-cache show ${kernel_test_target} \
| grep -E \"Package:|Version:|version:|family\" \
| grep -v \"Config-Version\" \
| sed -n -e 's/^.*: //p' \
| sed 's/\.$//g' \
| xargs -n3 -d'\n' \
| sed \"s/ /=/\" $grep_current_kernel"

# construct a list of kernels with their Armbian release versions and kernel version
IFS=$'\n'
local LIST=()
for line in $(eval ${search_exec}); do
LIST+=($(echo $line | awk -F ' ' '{print $1 " "}') $(echo $line | awk -F ' ' '{print "v"$2}'))
done
unset IFS

# generate selection menu
local list_length=$((${#LIST[@]} / 2))
if [ "$list_length" -eq 0 ]; then
$DIALOG --backtitle "$BACKTITLE" --title " Warning " --msgbox "No other kernels available!" 7 31
else
if target_version=$(\
$DIALOG \
--separate-output \
--title "Select kernel" \
--menu "" \
$((${list_length} + 7)) 80 $((${list_length})) "${LIST[@]}" \
3>&1 1>&2 2>&3)
then
# extract branch
local branch=${target_version##*image-}
# call install function
${module_options["module_armbianfirmware,feature"]} ${commands[1]} "${branch%%-*}" "${target_version/*=/}"
fi
fi

;;

"${commands[1]}") # purge old and install selected kernel from desired branch and version

# input parameters
local branch=$2
local version=$3

# generate list
${module_options["module_armbianfirmware,feature"]} ${commands[2]} "${branch}" "${version}" "hide"

# purge and install
for pkg in "${packages[@]}"; do
purge_pkg=$(echo $pkg | sed -e 's/current/*/;s/legacy/*/;s/edge/*/;s/vendor/*/')
apt_install_wrapper apt-get -y --simulate --download-only --allow-change-held-packages --allow-downgrades install ${pkg}
# if test install is succesfull, proceed
if [[ $? == 0 ]]; then
apt_install_wrapper apt-get -y purge ${purge_pkg}
apt_install_wrapper apt-get -y --autoremove --allow-change-held-packages install ${pkg}
fi
done

;;
"${commands[2]}") # generate a list of possible packages to install

# input parameters
local branch="$2"
local version="$3"
local hide="$4"
local repository="$5"

# if branch is not defined, we use the one that is currently installed
[[ -z $branch ]] && local branch=$BRANCH

# if repository is not defined, we use stable one
[[ -z $repository ]] && local repository="apt.armbian.com"

# select Armbian packages we want to searching for
armbian_packages=(
"linux-image-${branch}-${LINUXFAMILY}"
"linux-dtb-${branch}-${LINUXFAMILY}"
)

# install headers only if they were previously installed
if dpkg -l | grep -E "linux-headers" >/dev/null; then
armbian_packages+=("linux-headers-${branch}-${LINUXFAMILY}")
fi

# install full firmware if it was installed previously
if dpkg -l | grep -E "armbian-firmware-full" >/dev/null; then
armbian_packages+=("armbian-firmware-full")
else
armbian_packages+=("armbian-firmware")
fi

# when we select a specific version of Armbian, we need to make sure that version exists
# for each package we want to install. In case desired version does not exists, it installs
# package without specifying version. This prevent breaking install in case some
# package version was removed from repository. Just in case.
packages=""
for pkg in "${armbian_packages[@]}"; do
# use package + version if found else use package if found
if apt-cache show "$pkg" 2> /dev/null \
| grep -E "Package:|^Version:|family" \
| sed -n -e 's/^.*: //p' \
| sed 's/\.$//g' \
| xargs -n2 -d'\n' \
| grep ${pkg} | grep -e ${version} >/dev/null 2>&1; then
packages+="${pkg}=${version} ";
elif
apt-cache show "$pkg" 2> /dev/null \
| grep -E "Package:|^Version:|family" \
| sed -n -e 's/^.*: //p' \
| sed 's/\.$//g' \
| xargs -n2 -d'\n' \
| grep "${pkg}" >/dev/null 2>&1 ; then
packages+="${pkg} ";
fi
done

# if this is called with a parameter hide, we only prepare this list but don't show its content
[[ "$4" != "hide" ]] && echo ${packages[@]}

;;
"${commands[3]}")

local status=$2

# apt-mark hold
${module_options["module_armbianfirmware,feature"]} ${commands[2]} "" "" hide
if [[ "$status" == "status" ]]; then
hold=($(apt-mark showhold))
test=($(for lol in ${packages[@]}; do
for x in ${hold[@]}; do
echo $lol | grep $x
done
done))
[[ -z ${test[@]} ]] && return 1 || return 0
else
apt-mark hold ${packages[@]}
fi

;;
"${commands[4]}")

# apt-mark unhold
${module_options["module_armbianfirmware,feature"]} ${commands[2]} "" "" hide
apt-mark unhold ${packages[@]}
;;
"${commands[5]}")

# Parameter $2 = rolling | stable
# Parameter $3 = status which returns true or false
#
# It switches to rolling or stable Armbian repository and performs list update if this is needed

local repository=$2
local status=$3

if grep -q 'apt.armbian.com' /etc/apt/sources.list.d/armbian.list; then
if [[ "$repository" == "rolling" && "$status" == "status" ]]; then
return 1
elif [[ "$status" == "status" ]]; then
return 0
fi
if [[ "$repository" == "rolling" ]]; then
sed -i "s/http:\/\/[^ ]*/http:\/\/beta.armbian.com/" /etc/apt/sources.list.d/armbian.list
apt_install_wrapper apt-get update
fi
else
if [[ "$repository" == "stable" && "$status" == "status" ]]; then
return 1
elif [[ "$status" == "status" ]]; then
return 0
fi
if [[ "$repository" == "stable" ]]; then
sed -i "s/http:\/\/[^ ]*/http:\/\/apt.armbian.com/" /etc/apt/sources.list.d/armbian.list
apt_install_wrapper apt-get update
fi
fi

# reinstall firmware
[[ "$status" != "status" ]] && ${module_options["module_armbianfirmware,feature"]} ${commands[1]}
;;

"${commands[6]}")
echo -e "\nUsage: ${module_options["module_armbianfirmware,feature"]} <command> <switches>"
echo -e "Commands: ${module_options["module_armbianfirmware,example"]}"
echo "Available commands:"
echo -e "\tselect \t- [stable]|[rolling] TUI to select $title."
echo -e "\tinstall \t- Install $title [\$BRANCH] [\$VERSION]."
echo -e "\tshow \t- Show $title packages."
echo -e "\thold \t- [status] Mark $title packages as held back. When parameter status is used, it returns false or true."
echo -e "\tunhold \t- Unset $title packages set as held back."
echo -e "\trepository\t- [stable]|[rolling] selects repository and performs update."
echo
;;
*)
${module_options["module_armbianfirmware,feature"]} ${commands[6]}
;;
esac
}

# uncomment to test the module
DIALOG=whiptail
source /etc/armbian-release
module_armbianfirmware "$1" "$2" "$3" "$4"
Loading

0 comments on commit c2ca7ff

Please sign in to comment.