From 7f18618aa71c657b60d6c71230006547a7f1aae3 Mon Sep 17 00:00:00 2001 From: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:13:06 +0200 Subject: [PATCH 1/4] fix(bootloader-env): block all fw_setenv options, not only -s/--script The set command compared key and value against '-s', '--script' and their '=' forms. getopt accepts attached values and abbreviations, so a value like '-sFILE' or '--scr=FILE' reached fw_setenv as script mode, and '-cFILE' as an attacker-chosen config, both writing files as root. The adu sudoers rules pass the value unfiltered for omnect_extra_bootargs and omnect_validate_extra_bootargs, so a crafted value could exploit this. Pass '--' instead: key and value are always data, which covers every option rather than a list of known ones. Same for unset and get, whose key reaches fw_setenv/fw_printenv the same way. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> --- .../bootloader-env/bootloader_env_u-boot.sh | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh index bac20b003..1aafb11ef 100644 --- a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh +++ b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh @@ -11,7 +11,7 @@ function help() { function get() { [[ ${argsc} -ne 2 ]] && help && exit 1 local key=${1} - local value=$(fw_printenv ${key}) + local value=$(fw_printenv -- ${key}) value=${value#${key}=} [[ -z "${value}" ]] && echo && exit 2 echo ${value} @@ -27,19 +27,17 @@ function set () { local key=${1} local value=${@:2} - for word in $key $value; do - if [[ "$word" == "-s" || "$word" == "--script" || "$word" == -s=* || "$word" == --script=* ]]; then - echo "Script-file mode is not allowed (flag: $word)"; exit 66; - fi - done - - fw_setenv "${key}" "${value}" + # '--' ends option parsing, so key and value are always treated as data. + # this blocks script mode and every other option, e.g. an attacker-chosen + # config file, which a flag blocklist would miss (getopt accepts attached + # values like -sFILE and abbreviations like --scr=FILE) + fw_setenv -- "${key}" "${value}" } function unset() { [[ ${argsc} -ne 2 ]] && help && exit 1 local key=${1} - fw_setenv "${key}" + fw_setenv -- "${key}" } [[ ${#} -lt 1 ]] && help && exit 1 From 60a6ad3ef6298792e0da4294ad354cf3d556b34e Mon Sep 17 00:00:00 2001 From: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> Date: Fri, 31 Jul 2026 14:41:22 +0200 Subject: [PATCH 2/4] refactor(bootloader-env): pass arguments as arguments The dispatch called "${1} ${@:2}" unquoted, so a value with spaces was split into words and rejoined inside set() via "${@:2}". Two consequences: repeated whitespace collapsed to a single space, and a value containing glob characters was pathname-expanded, e.g. "set omnect_extra_bootargs '*'" stored the listing of the current directory. The argument count was checked against a global taken before the split, which is why the split went unnoticed. Quote the dispatch and take the value from "${2}", so each function gets its arguments as they were passed and can count them itself. Rename the commands to cmd_* as well. set and unset shadowed shell builtins, which only works because bash prefers functions over builtins outside POSIX mode - and set is a POSIX special builtin. The prefix also lets the dispatch check the function exists instead of matching the command against a list as a substring. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> --- .../bootloader-env/bootloader_env_grub.sh | 43 +++++++++---------- .../bootloader-env/bootloader_env_u-boot.sh | 37 ++++++++-------- 2 files changed, 37 insertions(+), 43 deletions(-) diff --git a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh index b1c323841..e9063786b 100644 --- a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh +++ b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh @@ -1,8 +1,6 @@ #!/bin/bash -e set -o pipefail grubenv="/boot/EFI/BOOT/grubenv" -commands=("get" "list" "set" "unset") -argsc=${#} function help() { echo "usage:" @@ -10,37 +8,36 @@ function help() { echo " command: {get,list,set,unset}" } -function get() { - [[ ${argsc} -ne 2 ]] && help && exit 1 - local key=${1} - local value=$(grub-editenv ${grubenv} list | grep ^${key}=) - value=${value#${key}=} +function cmd_get() { + [[ ${#} -ne 1 ]] && help && exit 1 + local key="${1}" + local value=$(grub-editenv "${grubenv}" list | grep "^${key}=") + value="${value#"${key}"=}" [[ -z "${value}" ]] && echo && exit 2 - echo ${value} + echo "${value}" } -function list(){ - [[ ${argsc} -ne 1 ]] && help && exit 1 - grub-editenv ${grubenv} list +function cmd_list() { + [[ ${#} -ne 0 ]] && help && exit 1 + grub-editenv "${grubenv}" list } -function set () { - [[ ${argsc} -ne 3 ]] && help && exit 1 - local key=${1} - local value=${@:2} - grub-editenv ${grubenv} set "${key}"="${value}" +function cmd_set() { + [[ ${#} -ne 2 ]] && help && exit 1 + local key="${1}" + local value="${2}" + grub-editenv "${grubenv}" set "${key}"="${value}" sync } -function unset() { - [[ ${argsc} -ne 2 ]] && help && exit 1 - local key=${1} - grub-editenv ${grubenv} unset "${key}" +function cmd_unset() { + [[ ${#} -ne 1 ]] && help && exit 1 + local key="${1}" + grub-editenv "${grubenv}" unset "${key}" sync } [[ ${#} -lt 1 ]] && help && exit 1 -[[ ! " ${commands[@]} " =~ " ${1} " ]] && help && exit 1 +declare -F "cmd_${1}" > /dev/null || { help; exit 1; } -#exec -${1} ${@:2} +"cmd_${1}" "${@:2}" diff --git a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh index 1aafb11ef..2fe0c8f29 100644 --- a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh +++ b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh @@ -1,6 +1,4 @@ #!/bin/bash -commands=("get" "list" "set" "unset") -argsc=${#} function help() { echo "usage:" @@ -8,24 +6,24 @@ function help() { echo " command: {get,list,set,unset}" } -function get() { - [[ ${argsc} -ne 2 ]] && help && exit 1 - local key=${1} - local value=$(fw_printenv -- ${key}) - value=${value#${key}=} +function cmd_get() { + [[ ${#} -ne 1 ]] && help && exit 1 + local key="${1}" + local value=$(fw_printenv -- "${key}") + value="${value#"${key}"=}" [[ -z "${value}" ]] && echo && exit 2 - echo ${value} + echo "${value}" } -function list(){ - [[ ${argsc} -ne 1 ]] && help && exit 1 +function cmd_list() { + [[ ${#} -ne 0 ]] && help && exit 1 fw_printenv } -function set () { - [[ ${argsc} -ne 3 ]] && help && exit 1 - local key=${1} - local value=${@:2} +function cmd_set() { + [[ ${#} -ne 2 ]] && help && exit 1 + local key="${1}" + local value="${2}" # '--' ends option parsing, so key and value are always treated as data. # this blocks script mode and every other option, e.g. an attacker-chosen @@ -34,14 +32,13 @@ function set () { fw_setenv -- "${key}" "${value}" } -function unset() { - [[ ${argsc} -ne 2 ]] && help && exit 1 - local key=${1} +function cmd_unset() { + [[ ${#} -ne 1 ]] && help && exit 1 + local key="${1}" fw_setenv -- "${key}" } [[ ${#} -lt 1 ]] && help && exit 1 -[[ ! " ${commands[@]} " =~ " ${1} " ]] && help && exit 1 +declare -F "cmd_${1}" > /dev/null || { help; exit 1; } -#exec -${1} ${@:2} +"cmd_${1}" "${@:2}" From 315e858eefe091ca06fde28aea6bafafcf1ad781 Mon Sep 17 00:00:00 2001 From: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> Date: Mon, 3 Aug 2026 13:09:30 +0200 Subject: [PATCH 3/4] fix(bootloader-env): print the value with printf instead of echo A value of -n, -e or -E is an option of echo, so "get" printed nothing and the caller could not tell it apart from an unset key. printf takes no options after the format string, so the value is passed through unchanged. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> --- .../bootloader_env/bootloader-env/bootloader_env_grub.sh | 2 +- .../bootloader_env/bootloader-env/bootloader_env_u-boot.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh index e9063786b..0a7d04062 100644 --- a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh +++ b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_grub.sh @@ -14,7 +14,7 @@ function cmd_get() { local value=$(grub-editenv "${grubenv}" list | grep "^${key}=") value="${value#"${key}"=}" [[ -z "${value}" ]] && echo && exit 2 - echo "${value}" + printf '%s\n' "${value}" } function cmd_list() { diff --git a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh index 2fe0c8f29..24fda3615 100644 --- a/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh +++ b/recipes-omnect/bootloader_env/bootloader-env/bootloader_env_u-boot.sh @@ -12,7 +12,7 @@ function cmd_get() { local value=$(fw_printenv -- "${key}") value="${value#"${key}"=}" [[ -z "${value}" ]] && echo && exit 2 - echo "${value}" + printf '%s\n' "${value}" } function cmd_list() { From a44fb0d5c8d02bb56f21bf488d4fa74971e20526 Mon Sep 17 00:00:00 2001 From: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> Date: Fri, 31 Jul 2026 16:58:26 +0200 Subject: [PATCH 4/4] chore(omnect-device-service): update to 0.45.1 ods 0.45.1 carries the same fw_setenv fix for its own wrapper (sudo/fw_setenv_no_script.sh) that this branch applies to the layer's bootloader_env.sh, so both copies of the defect get fixed together. Recipe regenerated with cargo-bitbake; the crate set did not change. Signed-off-by: Jan Zachmann <50990105+JanZachmann@users.noreply.github.com> (cherry picked from commit 80d0500e903b85a8d0ec9cabe8145c0a9c3afab8) --- ...vice-service_0.45.0.bb => omnect-device-service_0.45.1.bb} | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) rename recipes-omnect/omnect-device-service/{omnect-device-service_0.45.0.bb => omnect-device-service_0.45.1.bb} (99%) diff --git a/recipes-omnect/omnect-device-service/omnect-device-service_0.45.0.bb b/recipes-omnect/omnect-device-service/omnect-device-service_0.45.1.bb similarity index 99% rename from recipes-omnect/omnect-device-service/omnect-device-service_0.45.0.bb rename to recipes-omnect/omnect-device-service/omnect-device-service_0.45.1.bb index c0b746fd5..69b215cf2 100644 --- a/recipes-omnect/omnect-device-service/omnect-device-service_0.45.0.bb +++ b/recipes-omnect/omnect-device-service/omnect-device-service_0.45.1.bb @@ -6,9 +6,9 @@ inherit cargo # DEFAULT_PREFERENCE = "-1" # how to get omnect-device-service could be as easy as but default to a git checkout: -# SRC_URI += "crate://crates.io/omnect-device-service/0.45.0" +# SRC_URI += "crate://crates.io/omnect-device-service/0.45.1" SRC_URI += "git://github.com/omnect/omnect-device-service.git;protocol=https;nobranch=1;branch=main" -SRCREV = "a34303a576874c8b6716d90c403595a2f4892305" +SRCREV = "f5a2c5671d500e2187b651fb51afcc8d0b2d06a4" S = "${WORKDIR}/git" CARGO_SRC_DIR = ""