Bug 2081583 - valgrind: Missing strncmp intercept for ld.so
Summary: valgrind: Missing strncmp intercept for ld.so
Keywords:
Status: CLOSED ERRATA
Alias: None
Product: Fedora
Classification: Fedora
Component: valgrind
Version: rawhide
Hardware: Unspecified
OS: Unspecified
unspecified
medium
Target Milestone: ---
Assignee: Mark Wielaard
QA Contact: Fedora Extras Quality Assurance
URL:
Whiteboard:
Depends On:
Blocks: 2086540
TreeView+ depends on / blocked
 
Reported: 2022-05-04 05:36 UTC by Aki Tuomi
Modified: 2022-06-03 03:33 UTC (History)
9 users (show)

Fixed In Version: valgrind-3.19.0-2.fc37 valgrind-3.19.0-3.fc36 valgrind-3.19.0-3.fc35
Doc Type: If docs needed, set a value
Doc Text:
Clone Of:
: 2086540 (view as bug list)
Environment:
Last Closed: 2022-06-03 03:06:31 UTC
Type: Bug
Embargoed:


Attachments (Terms of Use)


Links
System ID Private Priority Status Summary Last Updated
KDE Software Compilation 434764 0 NOR UNCONFIRMED iconv_open causes ld.so v2.28 and later to execute optimised strncmp which confuses memcheck 2022-05-13 14:57:43 UTC

Description Aki Tuomi 2022-05-04 05:36:51 UTC
Description of problem:

glibc iconv_open accesses memory past buffer. This might be a security issue.


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

glibc-2.34-32.fc35.src.rpm


How reproducible:

Minimal reproduction:
#include <iconv.h>

int main(void)
{
	iconv_t fd = iconv_open("UTF-8", "EUC-JP");
	iconv_close(fd);
	return 0;
}

Steps to Reproduce:
1. Compile program
2. Run it with valgrind

Actual results:

==185== Invalid read of size 8
==185==    at 0x40044C0: strncmp (strcmp.S:173)
==185==    by 0x400A1AD: is_dst (dl-load.c:215)
==185==    by 0x400B376: _dl_dst_count (dl-load.c:252)
==185==    by 0x400B577: expand_dynamic_string_token (dl-load.c:394)
==185==    by 0x400B6D7: fillin_rpath.isra.0 (dl-load.c:482)
==185==    by 0x400B9C2: decompose_rpath (dl-load.c:653)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==  Address 0x4a63951 is 1 bytes inside a block of size 8 alloc'd
==185==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==185==    by 0x40274CF: malloc (rtld-malloc.h:56)
==185==    by 0x40274CF: strdup (strdup.c:42)
==185==    by 0x400B954: decompose_rpath (dl-load.c:628)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010E8E: _dl_open (dl-open.c:878)


Expected results:

No errors.

Additional info:

Comment 1 Aki Tuomi 2022-05-04 05:38:51 UTC
Full valgrind output showing the out of bounds access:

==185== Memcheck, a memory error detector
==185== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==185== Using Valgrind-3.18.1 and LibVEX; rerun with -h for copyright info
==185== Command: ./test
==185== 
==185== Invalid read of size 8
==185==    at 0x40044C0: strncmp (strcmp.S:173)
==185==    by 0x400A1AD: is_dst (dl-load.c:215)
==185==    by 0x400B376: _dl_dst_count (dl-load.c:252)
==185==    by 0x400B577: expand_dynamic_string_token (dl-load.c:394)
==185==    by 0x400B6D7: fillin_rpath.isra.0 (dl-load.c:482)
==185==    by 0x400B9C2: decompose_rpath (dl-load.c:653)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==  Address 0x4a63951 is 1 bytes inside a block of size 8 alloc'd
==185==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==185==    by 0x40274CF: malloc (rtld-malloc.h:56)
==185==    by 0x40274CF: strdup (strdup.c:42)
==185==    by 0x400B954: decompose_rpath (dl-load.c:628)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010E8E: _dl_open (dl-open.c:878)
==185== 
==185== Invalid read of size 8
==185==    at 0x40044C8: strncmp (strcmp.S:175)
==185==    by 0x400A1AD: is_dst (dl-load.c:215)
==185==    by 0x400B376: _dl_dst_count (dl-load.c:252)
==185==    by 0x400B577: expand_dynamic_string_token (dl-load.c:394)
==185==    by 0x400B6D7: fillin_rpath.isra.0 (dl-load.c:482)
==185==    by 0x400B9C2: decompose_rpath (dl-load.c:653)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==  Address 0x4a63959 is 1 bytes after a block of size 8 alloc'd
==185==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==185==    by 0x40274CF: malloc (rtld-malloc.h:56)
==185==    by 0x40274CF: strdup (strdup.c:42)
==185==    by 0x400B954: decompose_rpath (dl-load.c:628)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010E8E: _dl_open (dl-open.c:878)
==185== 
==185== Invalid read of size 8
==185==    at 0x40044C0: strncmp (strcmp.S:173)
==185==    by 0x400A1AD: is_dst (dl-load.c:215)
==185==    by 0x400B429: _dl_dst_substitute (dl-load.c:294)
==185==    by 0x400B6D7: fillin_rpath.isra.0 (dl-load.c:482)
==185==    by 0x400B9C2: decompose_rpath (dl-load.c:653)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==  Address 0x4a63951 is 1 bytes inside a block of size 8 alloc'd
==185==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==185==    by 0x40274CF: malloc (rtld-malloc.h:56)
==185==    by 0x40274CF: strdup (strdup.c:42)
==185==    by 0x400B954: decompose_rpath (dl-load.c:628)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010E8E: _dl_open (dl-open.c:878)
==185== 
==185== Invalid read of size 8
==185==    at 0x40044C8: strncmp (strcmp.S:175)
==185==    by 0x400A1AD: is_dst (dl-load.c:215)
==185==    by 0x400B429: _dl_dst_substitute (dl-load.c:294)
==185==    by 0x400B6D7: fillin_rpath.isra.0 (dl-load.c:482)
==185==    by 0x400B9C2: decompose_rpath (dl-load.c:653)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==  Address 0x4a63959 is 1 bytes after a block of size 8 alloc'd
==185==    at 0x484486F: malloc (vg_replace_malloc.c:381)
==185==    by 0x40274CF: malloc (rtld-malloc.h:56)
==185==    by 0x40274CF: strdup (strdup.c:42)
==185==    by 0x400B954: decompose_rpath (dl-load.c:628)
==185==    by 0x400D8F2: _dl_map_object (dl-load.c:2124)
==185==    by 0x40082A4: openaux (dl-deps.c:64)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x40086ED: _dl_map_object_deps (dl-deps.c:248)
==185==    by 0x4011341: dl_open_worker_begin (dl-open.c:591)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010A99: dl_open_worker (dl-open.c:777)
==185==    by 0x49EEA07: _dl_catch_exception (in /usr/lib64/libc.so.6)
==185==    by 0x4010E8E: _dl_open (dl-open.c:878)
==185== 
==185== 
==185== HEAP SUMMARY:
==185==     in use at exit: 0 bytes in 0 blocks
==185==   total heap usage: 24 allocs, 24 frees, 36,146 bytes allocated
==185== 
==185== All heap blocks were freed -- no leaks are possible
==185== 
==185== For lists of detected and suppressed errors, rerun with: -s
==185== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

Comment 3 Florian Weimer 2022-05-06 08:01:41 UTC
As far as I can see, this overread in strncmp is just an optimization. The assembler code takes care of not crossing a cache line boundary. The memory allocation is 8 bytes for a string of length 7 ("$ORIGIN"). So it looks all good to me.

It seems that valgrind lacks a redirect for strncmp in the dynamic loader.

Comment 4 Aki Tuomi 2022-05-06 12:15:01 UTC
Sounds reasonable.

Comment 5 Florian Weimer 2022-05-06 12:21:53 UTC
(In reply to Aki Tuomi from comment #4)
> Sounds reasonable.

I'll try to get this bug reclassified as non-security, and will reassign it to valgrind. Thanks for spotting this issue!

Comment 7 Siddhesh Poyarekar 2022-05-09 03:31:02 UTC
(In reply to Florian Weimer from comment #3)
> It seems that valgrind lacks a redirect for strncmp in the dynamic loader.

Reassigning to valgrind to let Mark figure out how to handle this.

Comment 8 Siddhesh Poyarekar 2022-05-09 03:32:01 UTC
Also not a security issue.

Comment 9 Mark Wielaard 2022-05-13 11:45:45 UTC
STRCMP is but STRNCMP isn't intercepted from ld.so.
The following would do the trick (on x86_64 at least):

diff --git a/shared/vg_replace_strmem.c b/shared/vg_replace_strmem.c
index 3b42b3a87..df466f250 100644
--- a/shared/vg_replace_strmem.c
+++ b/shared/vg_replace_strmem.c
@@ -710,6 +710,7 @@ static inline void my_exit ( int x )
  STRNCMP(VG_Z_LIBC_SONAME, __GI_strncmp)
  STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse2)
  STRNCMP(VG_Z_LIBC_SONAME, __strncmp_sse42)
+ STRNCMP(VG_Z_LD_LINUX_X86_64_SO_2, strncmp)
 
 #elif defined(VGO_freebsd)
  STRNCMP(VG_Z_LIBC_SONAME, strncmp)

Comment 10 Mark Wielaard 2022-05-13 23:34:16 UTC
Fixed upstream and in rawhide.
If this looks OK I'll add it to f36 and f35.
See some more analysis in the upstream bug.

Comment 11 Fedora Update System 2022-05-25 20:26:00 UTC
FEDORA-2022-35fc4f5632 has been submitted as an update to Fedora 36. https://bodhi.fedoraproject.org/updates/FEDORA-2022-35fc4f5632

Comment 12 Fedora Update System 2022-05-25 20:33:14 UTC
FEDORA-2022-9e02608a2f has been submitted as an update to Fedora 35. https://bodhi.fedoraproject.org/updates/FEDORA-2022-9e02608a2f

Comment 13 Fedora Update System 2022-05-26 02:33:02 UTC
FEDORA-2022-35fc4f5632 has been pushed to the Fedora 36 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2022-35fc4f5632`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2022-35fc4f5632

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 14 Fedora Update System 2022-05-26 02:33:51 UTC
FEDORA-2022-9e02608a2f has been pushed to the Fedora 35 testing repository.
Soon you'll be able to install the update with the following command:
`sudo dnf upgrade --enablerepo=updates-testing --advisory=FEDORA-2022-9e02608a2f`
You can provide feedback for this update here: https://bodhi.fedoraproject.org/updates/FEDORA-2022-9e02608a2f

See also https://fedoraproject.org/wiki/QA:Updates_Testing for more information on how to test updates.

Comment 15 Fedora Update System 2022-06-03 03:06:31 UTC
FEDORA-2022-35fc4f5632 has been pushed to the Fedora 36 stable repository.
If problem still persists, please make note of it in this bug report.

Comment 16 Fedora Update System 2022-06-03 03:33:58 UTC
FEDORA-2022-9e02608a2f has been pushed to the Fedora 35 stable repository.
If problem still persists, please make note of it in this bug report.


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