RHEL Engineering is moving the tracking of its product development work on RHEL 6 through RHEL 9 to Red Hat Jira (issues.redhat.com). If you're a Red Hat customer, please continue to file support cases via the Red Hat customer portal. If you're not, please head to the "RHEL project" in Red Hat Jira and file new tickets here. Individual Bugzilla bugs in the statuses "NEW", "ASSIGNED", and "POST" are being migrated throughout September 2023. Bugs of Red Hat partners with an assigned Engineering Partner Manager (EPM) are migrated in late September as per pre-agreed dates. Bugs against components "kernel", "kernel-rt", and "kpatch" are only migrated if still in "NEW" or "ASSIGNED". If you cannot log in to RH Jira, please consult article #7032570. That failing, please send an e-mail to the RH Jira admins at rh-issues@redhat.com to troubleshoot your issue as a user management inquiry. The email creates a ServiceNow ticket with Red Hat. Individual Bugzilla bugs that are migrated will be moved to status "CLOSED", resolution "MIGRATED", and set with "MigratedToJIRA" in "Keywords". The link to the successor Jira issue will be found under "Links", have a little "two-footprint" icon next to it, and direct you to the "RHEL project" in Red Hat Jira (issue links are of type "https://issues.redhat.com/browse/RHEL-XXXX", where "X" is a digit). This same link will be available in a blue banner at the top of the page informing you that that bug has been migrated.
Bug 1993976 - valgrind finds Conditional jump or move depends on uninitialised value(s) in perl-XML-Parser
Summary: valgrind finds Conditional jump or move depends on uninitialised value(s) in ...
Keywords:
Status: CLOSED ERRATA
Alias: None
Deadline: 2022-06-13
Product: Red Hat Enterprise Linux 9
Classification: Red Hat
Component: valgrind
Version: 9.0
Hardware: s390x
OS: Unspecified
unspecified
unspecified
Target Milestone: beta
: ---
Assignee: Mark Wielaard
QA Contact: Jesus Checa
Jacob Taylor Valdez
URL:
Whiteboard:
: 2052848 (view as bug list)
Depends On:
Blocks:
TreeView+ depends on / blocked
 
Reported: 2021-08-16 13:19 UTC by Martin Kyral
Modified: 2022-11-15 11:11 UTC (History)
10 users (show)

Fixed In Version: valgrind-3.19.0-3.el9
Doc Type: Bug Fix
Doc Text:
.Valgrind override of `glibc` `memmem` function installed on IBMz15 architecture Previously, a missing valgrind override of the `glibc` `memmem` function lead to false positive warnings of: ---- Conditional jump or move depends on uninitialised value(s) ---- This update includes a valgrind override of the `glibc` `memmem` function and, as a result, there are no longer false positive warnings when using the `memmem` function in programs running under valgrind on the IBMz15 architecture.
Clone Of:
Environment:
Last Closed: 2022-11-15 10:16:30 UTC
Type: Bug
Target Upstream Version:
Embargoed:
pm-rhel: mirror+


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
KDE Software Compilation 454040 0 NOR ASSIGNED s390x: False-positive memcheck:cond in memmem on arch13 systems 2022-05-19 13:09:51 UTC
Red Hat Issue Tracker RHELPLAN-93656 0 None None None 2021-08-16 13:21:57 UTC
Red Hat Product Errata RHBA-2022:8066 0 None None None 2022-11-15 10:16:35 UTC

Description Martin Kyral 2021-08-16 13:19:39 UTC
Description of problem:

On s390x, the /CoreOS/perl-XML-Parser/Regression/bz1658512-buffer-overwrite-in-parse_stream-with-wide-characters test fails with:

::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
::   invalid write
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

:: [ 08:44:45 ] :: [  BEGIN   ] :: no invalid writes in parse_stream() function from Expat.xs :: actually running 'perl -CO -e 'print q{<root>} . qq{\x{010d}} x 2**16 . q{</root>}' | valgrind --error-exitcode=1 -- xpath -q -e '/foo''
==26655== Memcheck, a memory error detector
==26655== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==26655== Using Valgrind-3.17.0 and LibVEX; rerun with -h for copyright info
==26655== Command: /usr/bin/xpath -q -e /foo
==26655== 
==26655== Conditional jump or move depends on uninitialised value(s)
==26655==    at 0x4CBB656: __memmem_arch13 (in /usr/lib64/libc.so.6)
==26655==    by 0x49B2B0F: UnknownInlinedFun (pp_ctl.c:3954)
==26655==    by 0x49B2B0F: Perl_pp_require (pp_ctl.c:4391)
==26655==    by 0x4961611: Perl_runops_standard (run.c:41)
==26655==    by 0x48D3ECD: Perl_call_sv (perl.c:3092)
==26655==    by 0x48D4D6B: Perl_call_list (perl.c:5131)
==26655==    by 0x48C30F3: S_process_special_blocks (op.c:11751)
==26655==    by 0x48C4931: Perl_newATTRSUB_x (op.c:11677)
==26655==    by 0x48C54F7: Perl_utilize (op.c:8839)
==26655==    by 0x4901F33: Perl_yyparse (perly.y:347)
==26655==    by 0x49B0BA1: S_doeval_compile (pp_ctl.c:3544)
==26655==    by 0x49B2439: UnknownInlinedFun (pp_ctl.c:4367)
==26655==    by 0x49B2439: Perl_pp_require (pp_ctl.c:4391)
==26655==    by 0x4961611: Perl_runops_standard (run.c:41)
==26655== 
==26655== 
==26655== HEAP SUMMARY:
==26655==     in use at exit: 6,910,458 bytes in 29,376 blocks
==26655==   total heap usage: 86,694 allocs, 57,318 frees, 16,711,890 bytes allocated
==26655== 
==26655== LEAK SUMMARY:
==26655==    definitely lost: 23,047 bytes in 31 blocks
==26655==    indirectly lost: 62,300 bytes in 30 blocks
==26655==      possibly lost: 6,808,766 bytes in 29,270 blocks
==26655==    still reachable: 16,345 bytes in 45 blocks
==26655==                       of which reachable via heuristic:
==26655==                         newarray           : 29,288 bytes in 894 blocks
==26655==         suppressed: 0 bytes in 0 blocks
==26655== Rerun with --leak-check=full to see details of leaked memory
==26655== 
==26655== Use --track-origins=yes to see where uninitialised values come from
==26655== For lists of detected and suppressed errors, rerun with: -s
==26655== ERROR SUMMARY: 10 errors from 1 contexts (suppressed: 0 from 0)
:: [ 08:45:03 ] :: [   FAIL   ] :: no invalid writes in parse_stream() function from Expat.xs (Expected 0, got 1)
::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::


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

perl-5.32.1-479.el9.s390x


How reproducible:


Steps to Reproduce:
1.
2.
3.

Actual results:


Expected results:


Additional info:
it may be a problem with valgrind or glibc. If it is the case, please reassign.

Comment 1 Jitka Plesnikova 2022-02-10 08:46:56 UTC
*** Bug 2052848 has been marked as a duplicate of this bug. ***

Comment 2 Michal Josef Spacek 2022-04-26 11:57:22 UTC
After upgrade of valgrind to valgrind-3.18.1-9.el9 issue is still here.

Test on components:
valgrind-3.18.1-9.el9
perl-5.32.1-479.el9
perl-XML-Parser-2.46-9.el9

architecture: s390x

Comment 3 Michal Josef Spacek 2022-04-26 13:13:14 UTC
Tested on rawhide and result is same.

Components:
perl-5.34.1-486.fc37.s390x
perl-XML-Parser-2.46-10.fc36.s390x
perl-XML-XPath-1.44-12.fc36.noarch
valgrind-3.18.1-9.fc36.s390x

Comment 4 Michal Josef Spacek 2022-05-02 13:53:33 UTC
This issue isn't related to perl-XML-Parser. 
Issue is with parsing of module name (require). Probably some length of module name.
Still investigating.

Comment 5 Michal Josef Spacek 2022-05-12 10:01:03 UTC
Reproducer:
[root@s390x-kvm-002 test]# cat BarXXXXXXXXXXXXXXX.pm
package BarXXXXXXXXXXXXXXX;

1;
[root@s390x-kvm-002 test]# valgrind --error-exitcode=1 perl -e "use lib '.'; require BarXXXXXXXXXXXXXXX;"
==21978== Memcheck, a memory error detector
==21978== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==21978== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==21978== Command: perl -e use\ lib\ '.';\ require\ BarXXXXXXXXXXXXXXX;
==21978==
==21978== Conditional jump or move depends on uninitialised value(s)
==21978==    at 0x4C38218: __memmem_arch13 (in /usr/lib64/libc.so.6)
==21978==    by 0x49B5B0F: Perl_pp_require (in /usr/lib64/libperl.so.5.32.1)
==21978==    by 0x4964611: Perl_runops_standard (in /usr/lib64/libperl.so.5.32.1)
==21978==    by 0x48DA705: perl_run (in /usr/lib64/libperl.so.5.32.1)
==21978==    by 0x108E57: main (in /usr/bin/perl)
==21978==
==21978==
==21978== HEAP SUMMARY:
==21978==     in use at exit: 523,763 bytes in 2,004 blocks
==21978==   total heap usage: 6,864 allocs, 4,860 frees, 1,063,483 bytes allocated
==21978==
==21978== LEAK SUMMARY:
==21978==    definitely lost: 19,995 bytes in 29 blocks
==21978==    indirectly lost: 52,556 bytes in 23 blocks
==21978==      possibly lost: 450,848 bytes in 1,951 blocks
==21978==    still reachable: 364 bytes in 1 blocks
==21978==                       of which reachable via heuristic:
==21978==                         newarray           : 1,088 bytes in 34 blocks
==21978==         suppressed: 0 bytes in 0 blocks
==21978== Rerun with --leak-check=full to see details of leaked memory
==21978==
==21978== Use --track-origins=yes to see where uninitialised values come from
==21978== For lists of detected and suppressed errors, rerun with: -s
==21978== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

Comment 6 Michal Josef Spacek 2022-05-16 12:36:11 UTC
Issue is present on last Fedora rawhide
* glibc-2.35.9000-17.fc37.src.rpm
* perl-5.34.1-486.fc37.src.rpm

Tested on compiled perl 5.35.11 on same machine and still here.

Comment 7 Michal Josef Spacek 2022-05-16 14:14:42 UTC
Affected on S390/arch14 only

Comment 10 Michal Josef Spacek 2022-05-16 14:39:10 UTC
Sorry, i mean arch13 not arch14.(In reply to Michal Josef Spacek from comment #7)
> Affected on S390/arch14 only

Sorry, i mean S390/arch13

Comment 11 Florian Weimer 2022-05-16 14:46:25 UTC
Could you install glibc debugging information and run the test under vgdb, with

valgrind --vgdb-error=1

? Then valgrind will print instructions to attach GDB, and you should be able to use that to extract the memmem arguments. We'll need both the memory contents there and the alignment. Thanks!

(I'm reassigning to valgrind for awareness/further debugging. Also Cc:ing the IBM team.)

Comment 12 Michal Josef Spacek 2022-05-16 15:11:16 UTC
(gdb) target remote | /usr/libexec/valgrind/../../bin/vgdb --pid=52142
Remote debugging using | /usr/libexec/valgrind/../../bin/vgdb --pid=52142
relaying data between gdb and process 52142
warning: remote target does not support file transfer, attempting to access files from local filesystem.
Reading symbols from /usr/libexec/valgrind/vgpreload_core-s390x-linux.so...
Reading symbols from /usr/libexec/valgrind/vgpreload_memcheck-s390x-linux.so...
Reading symbols from /lib64/libperl.so.5.34...
Reading symbols from /root/.cache/debuginfod_client/e4fb94a27875065be6e02943c56103e2c27a908d/debuginfo...
Reading symbols from /lib64/libc.so.6...
Reading symbols from /usr/lib/debug/usr/lib64/libc.so.6-2.35.9000-17.fc37.s390x.debug...
Reading symbols from /lib64/libm.so.6...
Reading symbols from /usr/lib/debug/usr/lib64/libm.so.6-2.35.9000-17.fc37.s390x.debug...
Reading symbols from /lib64/libcrypt.so.2...
Reading symbols from /root/.cache/debuginfod_client/8ca706b59fc1b92ed2d377a10bf07963c8e83744/debuginfo...
Reading symbols from /lib/ld64.so.1...
__memmem_arch13 () at ../sysdeps/s390/memmem-arch13.S:65
65              brc     9,.Lend_no_match        /* Jump away if cc == 0 || cc == 3.  */

(gdb) bt
#0  __memmem_arch13 () at ../sysdeps/s390/memmem-arch13.S:65
#1  0x00000000049ba502 in S_require_file (sv=<optimized out>, my_perl=0x4e8f040) at pp_ctl.c:3969
#2  Perl_pp_require (my_perl=0x4e8f040) at pp_ctl.c:4394
#3  0x0000000004968812 in Perl_runops_standard (my_perl=0x4e8f040) at run.c:41
#4  0x00000000048df7f6 in S_run_body (oldscope=<optimized out>, my_perl=<optimized out>) at perl.c:2743
#5  perl_run (my_perl=0x4e8f040) at perl.c:2666
#6  0x00000000001093b8 in main (argc=<optimized out>, argv=<optimized out>, env=<optimized out>) at perlmain.c:110

Comment 13 Florian Weimer 2022-05-16 15:25:00 UTC
Thanks. Is it possible to recover the arguments at the call site in S_require_file? And dump the memory at those locations using GDB?

Comment 14 Mark Wielaard 2022-05-16 15:35:12 UTC
Is the reproducer:
valgrind --error-exitcode=1 perl -e "use lib '.'; require BarXXXXXXXXXXXXXXX;"

I assume __memmem_arch13 is a s390x optimized version of memmem.

Is arch13 z15? If so, I assume it doesn't happen on z14?

How exactly is memmem called from pp_ctl.c:3969 ?

Comment 15 Florian Weimer 2022-05-16 15:39:20 UTC
(In reply to Mark Wielaard from comment #14)
> I assume __memmem_arch13 is a s390x optimized version of memmem.
> 
> Is arch13 z15? If so, I assume it doesn't happen on z14?

All correct.

Comment 16 Mark Wielaard 2022-05-16 15:51:24 UTC
Replicated using valgrind --gdb-error=0 --error-exitcode=1 perl -e "use lib '.'; require BarXXXXXXXXXXXXXXX;"
And gdb target remote | vgdb

Dump of assembler code for function __memmem_arch13:
   0x0000000004c30e40 <+0>:	clgrjl	%r3,%r5,0x4c30e9e <__memmem_arch13+94>
   0x0000000004c30e46 <+6>:	clgfi	%r5,9
   0x0000000004c30e4c <+12>:	jgh	0x4cbf470 <__memmem_vx>
   0x0000000004c30e52 <+18>:	aghik	%r0,%r5,-1
   0x0000000004c30e58 <+24>:	bl	0(%r14)
   0x0000000004c30e5c <+28>:	vll	%v18,%r0,0(%r4)
   0x0000000004c30e62 <+34>:	vlvgb	%v19,%r5,7
   0x0000000004c30e68 <+40>:	clgijh	%r3,16,0x4c30ea4 <__memmem_arch13+100>
   0x0000000004c30e6e <+46>:	aghik	%r0,%r3,-1
   0x0000000004c30e74 <+52>:	vll	%v16,%r0,0(%r2)
   0x0000000004c30e7a <+58>:	sgr	%r3,%r5
   0x0000000004c30e7e <+62>:	jl	0x4c30e9e <__memmem_arch13+94>
   0x0000000004c30e82 <+66>:	vstrsb	%v20,%v16,%v18,%v19
=> 0x0000000004c30e88 <+72>:	jnlh	0x4c30e9e <__memmem_arch13+94>
   0x0000000004c30e8c <+76>:	vlgvb	%r1,%v20,7
   0x0000000004c30e92 <+82>:	clgrjh	%r1,%r3,0x4c30e9e <__memmem_arch13+94>
   0x0000000004c30e98 <+88>:	la	%r2,0(%r1,%r2)
   0x0000000004c30e9c <+92>:	br	%r14
   0x0000000004c30e9e <+94>:	lghi	%r2,0
   0x0000000004c30ea2 <+98>:	br	%r14

Which is called as:

#1  0x00000000049b6b10 in S_require_file (sv=<optimized out>, 
    my_perl=0x4e9f040) at pp_ctl.c:3954
3954	                if (ninstr(name, name + package_len, slashdot,
(gdb) list
3949	                    DIE(aTHX_ "Bareword in require maps to disallowed filename \"%" SVf "\"", sv);
3950	                if (memchr(name, 0, package_len)) {
3951	                    /* diag_listed_as: Bareword in require contains "%s" */
3952	                    DIE(aTHX_ "Bareword in require contains \"\\0\"");
3953	                }
3954	                if (ninstr(name, name + package_len, slashdot,
3955	                           slashdot + sizeof(slashdot))) {
3956	                    /* diag_listed_as: Bareword in require contains "%s" */
3957	                    DIE(aTHX_ "Bareword in require contains \"/.\"");
3958	                }

Where ninstr is defined as:

#ifdef HAS_MEMMEM
#   define ninstr(big, bigend, little, lend)                                \
            ((char *) memmem((big), (bigend) - (big),                       \
                             (little), (lend) - (little)))
#else
#   define ninstr(a,b,c,d) Perl_ninstr(a,b,c,d)
#endif

(gdb) print name
$1 = <optimized out>
(gdb) print package_len
$2 = 18
(gdb) print slashdot
$3 = "/."

3954	                if (ninstr(name, name + package_len, slashdot,
   0x00000000049b6afa <+6122>:	lgdr	%r2,%f11
   0x00000000049b6afe <+6126>:	lgr	%r3,%r10
   0x00000000049b6b02 <+6130>:	lghi	%r5,2
   0x00000000049b6b06 <+6134>:	la	%r4,296(%r15)
   0x00000000049b6b0a <+6138>:	brasl	%r14,0x48a9048 <memmem@plt>
=> 0x00000000049b6b10 <+6144>:	cgijne	%r2,0,0x49b767a <Perl_pp_require+9066>

3955	                           slashdot + sizeof(slashdot))) {
3956	                    /* diag_listed_as: Bareword in require contains "%s" */
3957	                    DIE(aTHX_ "Bareword in require contains \"/.\"");
   0x00000000049b767a <+9066>:	lgr	%r2,%r11
   0x00000000049b767e <+9070>:	larl	%r3,0x4ba9536
   0x00000000049b7684 <+9076>:	brasl	%r14,0x48a96c8 <Perl_die@plt>

Comment 17 Michal Josef Spacek 2022-05-16 15:58:46 UTC
(gdb) print name
$9 = 0x5009d20 "Bar", 'X' <repeats 15 times>, ".pm"
(gdb) print package_len
$10 = 18
(gdb) print slashdot
$11 = "/."

Comment 18 Andreas Arnez 2022-05-16 18:25:00 UTC
(In reply to Mark Wielaard from comment #16)
> Replicated using valgrind --gdb-error=0 --error-exitcode=1 perl -e "use lib
> '.'; require BarXXXXXXXXXXXXXXX;"
> [...]
Using the same method, I reproduced this as well.  In my testing the "vector string search" instruction (vstrsb) yields the condition code which is then used for a conditional jump:
     0x0000000004caabb0 <+64>:	vstrsb	%v20,%v16,%v18,%v19
  => 0x0000000004caabb6 <+70>:	jnlh	0x4caabcc <__memmem_arch13+92>
The input operands to vstrsb are as follows:
  v16 = "XX.pm"   (7 bytes defined)
  v18 = "./"      (all defined)
  v19 = {[7] = 2} (only byte 7 defined)
The reason for v16 to be partially defined is that it was loaded from the end of a malloc'd block and the last 9 bytes were outside that block.
v19 is partially defined as well; that's OK because only byte 7 is used by the instruction.
Now, unfortunately the conditional jump indeed depends on the undefined bytes in v16.  If these bytes contained the pattern "./" (full match), the jump would not be taken, otherwise it is.

It is possible that the function's end result is still independent from this jump being taken or not.  If so, we'd probably have to add a suppression.

Comment 19 Mark Wielaard 2022-05-17 07:29:26 UTC
(In reply to Andreas Arnez from comment #18)
> Using the same method, I reproduced this as well.  In my testing the "vector
> string search" instruction (vstrsb) yields the condition code which is then
> used for a conditional jump:
>      0x0000000004caabb0 <+64>:	vstrsb	%v20,%v16,%v18,%v19
>   => 0x0000000004caabb6 <+70>:	jnlh	0x4caabcc <__memmem_arch13+92>
> The input operands to vstrsb are as follows:
>   v16 = "XX.pm"   (7 bytes defined)
>   v18 = "./"      (all defined)
>   v19 = {[7] = 2} (only byte 7 defined)
> The reason for v16 to be partially defined is that it was loaded from the
> end of a malloc'd block and the last 9 bytes were outside that block.
> v19 is partially defined as well; that's OK because only byte 7 is used by
> the instruction.
> Now, unfortunately the conditional jump indeed depends on the undefined
> bytes in v16.  If these bytes contained the pattern "./" (full match), the
> jump would not be taken, otherwise it is.

The glibc source code sysdeps/s390/memmem-arch13.S is nicely commented and I believe we end up here:

.Lhaystack_smaller_16:
        sgr     %r3,%r5                 /* r3 = largest valid match-index.  */
        jl      .Lend_no_match          /* Haystack-len < needle-len?  */
        vstrs   %v20,%v16,%v18,%v19,0,0
        /* Vector string search without zero search where v20 will contain
           the index of a partial/full match or 16 (index is named k).
           cc=0 (no match; k=16): .Lend_no_match
           cc=1 (only available with zero-search): Ignore
           cc=2 (full match; k<16): Needle found, but could be beyond haystack!
           cc=3 (partial match; k<16): Always at end of v16 and thus beyond!  */
        brc     9,.Lend_no_match        /* Jump away if cc == 0 || cc == 3.  */
        vlgvb   %r1,%v20,7
        /* Verify that the full-match (cc=2) is valid!  */
        clgrjh  %r1,%r3,.Lend_no_match  /* Jump away if match is beyond.  */
        la      %r2,0(%r1,%r2)
        br      %r14
.Lend_no_match:
        lghi    %r2,0
        br      %r14

Assuming the code correctly checks the end of Haystack is indeed accessible then this seems correct since if the match was beyond the end then an extra check (that I don't think valgrind memcheck can know about) masks away the undefined bits.

> It is possible that the function's end result is still independent from this
> jump being taken or not.  If so, we'd probably have to add a suppression.

Maybe we could add a valgrind intercept for memmem in vg_replace_strmem.c just for s390x?

Comment 20 Andreas Arnez 2022-05-19 12:35:30 UTC
(In reply to Mark Wielaard from comment #19)
> [...]
> Maybe we could add a valgrind intercept for memmem in vg_replace_strmem.c
> just for s390x?
Right, that might be the easiest way.  I've opened an upstream Bug and attached a patch that does this:
  https://bugs.kde.org/show_bug.cgi?id=454040

Comment 27 errata-xmlrpc 2022-11-15 10:16:30 UTC
Since the problem described in this bug report should be
resolved in a recent advisory, it has been closed with a
resolution of ERRATA.

For information on the advisory (valgrind bug fix and enhancement update), and where to find the updated
files, follow the link below.

If the solution does not work for you, open a new bug report.

https://access.redhat.com/errata/RHBA-2022:8066


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