On Thu May 21, 2026 at 12:25 PM CEST, Paul Barker via lists.openembedded.org 
wrote:
> On Tue, 2026-05-19 at 11:04 +0200, A. Sverdlin wrote:
>> From: Alexander Sverdlin <[email protected]>
>> 
>> The bootparam parsing loop uses "eval" to set shell variables from
>> kernel command line parameters.  Since eval interprets its argument as
>> shell code, a crafted boot parameter such as:
>> 
>>   rootdelay=1";command;"
>> 
>> would be executed as arbitrary shell code during early init.
>
> Hi Alexander,
>
> If you can modify the kernel command line, you can pass options like
> `init=/bin/sh` and then execute arbitrary commands anyway.

I agree, this is can't really be considered a security issure, since if
you have access to the command line, you can execute arbitrary code
anyway...

However it is still worth hardening the parsing, if only to protect
against human errors

Regards
Jeremy
>
>> 
>> Replace the eval-based parser with a single sed invocation that
>> tokenizes /proc/cmdline (respecting double-quoted values) and feeds the
>> result to a while-read loop that uses only "export" for variable
>> assignment, which never interprets the value as code.
>> 
>> The sed script works as follows:
>> - Split the line at unquoted spaces into one token per line.  The regex
>>   treats sequences of non-space/non-quote chars, balanced "..." pairs,
>>   and lone " (for mid-value quotes) as atomic units that are never split.
>> - Strip outer quotes from whole-param-quoted tokens ("param=val").
>> - Strip balanced quotes around parameter values (key="val" -> key=val).
>> - Replace . and - with _ in parameter names (the key part before =),
>>   iterating until none remain.
>> - Print each processed token and loop (P/D).
>> 
>> Additional benefits:
>> - Whitespace inside quoted values is now preserved exactly as specified
>>   (the for-loop word-splitting collapsed multiple spaces)
>> - Reduced from 3+ sed/cut invocations per parameter to a single sed
>>   process for the entire command line
>> 
>> Co-developed-by: GitHub Copilot (Claude)
>> Signed-off-by: Alexander Sverdlin <[email protected]>
>> ---
>>  .../initrdscripts/initramfs-framework/init    | 61 ++++++++-----------
>>  1 file changed, 24 insertions(+), 37 deletions(-)
>> 
>> diff --git a/meta/recipes-core/initrdscripts/initramfs-framework/init 
>> b/meta/recipes-core/initrdscripts/initramfs-framework/init
>> index 67590ad765..97ec62e2da 100755
>> --- a/meta/recipes-core/initrdscripts/initramfs-framework/init
>> +++ b/meta/recipes-core/initrdscripts/initramfs-framework/init
>> @@ -92,43 +92,30 @@ if [ -d $EFI_DIR ];then
>>  fi
>>  
>>  # populate bootparam environment
>> -for p in `cat /proc/cmdline`; do
>> -    if [ -n "$quoted" ]; then
>> -            p_rstripped=${p%\"}
>> -            value="$value $p_rstripped"
>> -            if [ "$p_rstripped" != "$p" ]; then
>> -                    # End of a opt="word1 word2..." parameter 
>> -                    eval "bootparam_${quoted}=\"${value}\""
>> -                    unset quoted
>> -            fi
>> -            continue
>> -    fi
>> -
>> -    opt=`echo $p | cut -d'=' -f1`
>> -    opt=`echo $opt | sed -e 'y/.-/__/'`
>> -    if [ "`echo $p | cut -d'=' -f1`" = "$p" ]; then
>> -            # opt parameter
>> -            eval "bootparam_${opt}=true"
>> -    else
>> -            value="`echo $p | cut -d'=' -f2-`"      # Option value
>> -            value_lstripped=${value#\"}
>> -            value_rstripped=${value%\"}
>> -
>> -            if [ "$value_lstripped" != "$value" ] && [ "$value_rstripped" 
>> != "$value" ]; then
>> -                    # opt="value" parameter
>> -                    eval "bootparam_${opt}=${value_lstripped%\"}"
>> -                    continue
>> -            fi
>> -
>> -            if [ "$value_lstripped" != "$value" ]; then
>> -                    # Start of a opt="word1 word2..." parameter 
>> -                    quoted=${opt}
>> -                    value=${value_lstripped}
>> -                    continue
>> -            fi
>> -            eval "bootparam_${opt}=\"${value}\""
>> -    fi
>> -done
>> +while IFS= read -r token; do
>> +    case "$token" in
>> +    *=*)
>> +            opt="${token%%=*}"
>> +            value="${token#*=}"
>> +            ;;
>> +    *)
>> +            opt="$token"
>> +            value="true"
>> +            ;;
>> +    esac
>> +    export "bootparam_${opt}=${value}"
>> +done <<EOF
>> +$(sed -E '
>> +s/^(([^ "]*|"[^"]*"|")*) +/\1\
>> +/
>> +s/^"(.*)"$/\1/
>> +s/^([^=]*)="(.*)"/\1=\2/
>> +:k
>> +s/^([^=.-]*)[.-]/\1_/
>> +tk
>> +P
>> +D' /proc/cmdline)
>> +EOF
>
> The main issue here is that this replaces comprehensible code with
> incomprehensible line noise, reducing maintainability. If you want to
> remove eval calls from this script, it needs to be done in a different
> way.
>
> Best regards,

-=-=-=-=-=-=-=-=-=-=-=-
Links: You receive all messages sent to this group.
View/Reply Online (#237506): 
https://lists.openembedded.org/g/openembedded-core/message/237506
Mute This Topic: https://lists.openembedded.org/mt/119387617/21656
Group Owner: [email protected]
Unsubscribe: https://lists.openembedded.org/g/openembedded-core/unsub 
[[email protected]]
-=-=-=-=-=-=-=-=-=-=-=-

Reply via email to