Bug 2218096 - check_caveats dead loops when executing with ja_JP.SJIS locale
Summary: check_caveats dead loops when executing with ja_JP.SJIS locale
Keywords:
Status: ASSIGNED
Alias: None
Product: Red Hat Enterprise Linux 8
Classification: Red Hat
Component: microcode_ctl
Version: 8.8
Hardware: All
OS: Linux
high
high
Target Milestone: rc
: ---
Assignee: Eugene Syromiatnikov
QA Contact: Jeff Bastian
URL:
Whiteboard:
Depends On:
Blocks: 2218104
TreeView+ depends on / blocked
 
Reported: 2023-06-28 07:00 UTC by Renaud Métrich
Modified: 2023-08-16 07:29 UTC (History)
0 users

Fixed In Version:
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
: 2218104 (view as bug list)
Environment:
Last Closed:
Type: Bug
Target Upstream Version:
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
Red Hat Issue Tracker RHELPLAN-161029 0 None None None 2023-06-28 07:00:52 UTC
Red Hat Knowledge Base (Solution) 7021713 0 None None None 2023-06-28 08:23:35 UTC

Description Renaud Métrich 2023-06-28 07:00:24 UTC
Description of problem:

When the system is configured with ja_JP.SJIS locale (see https://access.redhat.com/solutions/202713), it appears that executing the following command (which is executed as part of reinstalling the microcode_ctl package for example) dead loops:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
# export LANG=ja_JP.sjis
# /bin/bash -eu /usr/libexec/microcode_ctl/check_caveats -k 4.18.0-425.19.2.el8_7.x86_64 -c intel-06-8e-9e-0x-dell
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Digging further, there is an issue when the script tries to remove from shortest front pattern on line 346 (instrumented code, should be line 345):
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
 305         while [ -n "$opts" ]; do
 :
 345                 debug "was '$opts', opt='$opt'"
 346                 opts="${opts#"${opt}"}"
 347                 debug "now '$opts'"
 348                 continue
 :
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

In debug mode, we can see that the "mode=fail-equal" is not removed from the $opts variable, causing the dead loop to occur:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
 :
was 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."', opt='mode=fail-equal'
now 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."'
was 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."', opt='mode=fail-equal'
now 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."'
was 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."', opt='mode=fail-equal'
now 'mode=fail-equal no-model-mode=success key=bios_vendor val="Dell Inc."'
 :
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

The issue is with the double-quotes used multiple times:
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
opts="${opts#"${opt}"}"
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

should be

-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
opts="${opts#${opt}}"
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

But this doesn't solve the issue completely, because even with fixing this, the issue persists with last token ("Dell Inc."), which somehow starts containg a double quote at the end because of some quoting handling on lines 315-322 (instrumented code):

-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
 305         while [ -n "$opts" ]; do
 306                 opt="${opts%%[  ]*}"
 307                 [ -n "${opt}" ] || { opts="${opts#[     ]}"; continue; }
 308                 debug "(308) opt='$opt'"
 :
 315                 # Handle possible quoting
 316                 [ "x${opt#val=}" = "x${opt}" ] || {
 317                         case "${opt#val=}" in
 318                         [\']*) opt_="${opts#val=\'}"; val="${opt_%%\'*}"; opt="val='${val}'" ;;
 319                         [\"]*) opt_="${opts#val=\"}"; val="${opt_%%\"*}"; opt="val=\"${val}\"" ;;
 320                         *)    val="${opt#val=}" ;;
 321                         esac
 322                 } 
 323                 debug "(323) opt='$opt'"
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Result with instrumentation (and line 346 "fixed"):
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------
was 'key=bios_vendor val="Dell Inc."', opt='key=bios_vendor'
now ' val="Dell Inc."'
(308) opt='val="Dell'
(323) opt='val="Dell Inc.""'
                         ^^^^^ doubled double quote

was 'val="Dell Inc."', opt='val="Dell Inc.""'
now 'val="Dell Inc."'
(308) opt='val="Dell'
(323) opt='val="Dell Inc.""'
 :
-------- 8< ---------------- 8< ---------------- 8< ---------------- 8< --------

Original line 345 has to be fixed, and, to avoid any other possible issue with locale, "LANG=C" should be set at the beginning of the script to make sure we control the behavior.

Version-Release number of selected component (if applicable):

microcode_ctl

How reproducible:

Always

Steps to Reproduce:
1. Create the special locale

    # yum -y install glibc-locale-source glibc-langpack-ja
    # localedef -f SHIFT_JIS -i ja_JP ja_JP.SJIS

2. Set the locale in the environment and execute the script

    # export LANG=ja_JP.sjis
    # /bin/bash -eu /usr/libexec/microcode_ctl/check_caveats -k 4.18.0-425.19.2.el8_7.x86_64 -c intel-06-8e-9e-0x-dell

Actual results:

Spin on the CPU

Expected results:

Script proceeds properly

Comment 1 Eugene Syromiatnikov 2023-06-28 07:22:41 UTC
The quotes are necessary to avoid expansion of the $opt's value (try, for example, to put an asterisk ("*") as a parameter), but the export LC_ALL=C in the beginning is indeed required to avoid any unexpected behaviour.

Comment 2 Eugene Syromiatnikov 2023-06-28 07:24:46 UTC
(As a side note, when I tried to reproduce the issue on RHEL 9.2, I got the different beaviour when the parameters are not parsed at all)


Note You need to log in before you can comment on or make changes to this bug.