Gentoo Websites Logo
Go to: Gentoo Home Documentation Forums Lists Bugs Planet Store Wiki Get Gentoo!

Bug 847493

Summary: app-misc/pax-utils: scanelf symbol search fails with non-stripped binaries
Product: Gentoo Linux Reporter: Sam James <sam>
Component: Current packagesAssignee: Gentoo Toolchain Maintainers <toolchain>
Status: CONFIRMED ---    
Severity: normal CC: arsen, kacper.slominski72, matthew
Priority: Normal    
Version: unspecified   
Hardware: All   
OS: Linux   
See Also: https://github.com/gentoo/pax-utils/pull/9
https://bugs.gentoo.org/show_bug.cgi?id=550482
Whiteboard:
Package list:
Runtime testing required: ---
Bug Depends on:    
Bug Blocks: 549092    

Description Sam James archtester Gentoo Infrastructure gentoo-dev Security 2022-05-26 02:58:14 UTC
Noticed when poking at bug 549092.

Apparently scanelf can't handle pre-stripped binaries for symbol searches. I'm guessing it's trying to parse the debugging information and fails, whereas once stripped, it falls back & it works fine.

readelf (binutils) is fine.

```
$ file /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash
/var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, not stripped

$ readelf -s /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash | grep limit
   155: 0001f8c0   208 OBJECT  LOCAL  DEFAULT   21 limits
   442: 00000000     0 FUNC    GLOBAL DEFAULT  UND getrlimit@GLIBC_2.2
   490: 00000000     0 FUNC    GLOBAL DEFAULT  UND setrlimit@GLIBC_2.2
   510: 0000cbd0   820 FUNC    GLOBAL DEFAULT   14 ulimitcmd

$ scanelf -F '%s %p' -qyRgs '-^(aio_cancel|aio_error|aio_fsync|aio_read|aio_return|aio_suspend|aio_write|lio_listio|alphasort|getdirentries|readdir|readdir_r|scandir|scandirat|versionsort|creat|fallocate|fopen|fopenat|freopen|open|openat|posix_fadvise|posix_fallocate|__open|__open_2|__openat_2|ftw|nftw|glob|globfree|fgetpos|fopen|freopen|fseeko|fsetpos|ftello|tmpfile|mkostemp|mkostemps|mkstemp|mkstemps|mmap|getrlimit|prlimit|setrlimit|sendfile|fstat|fstatat|lstat|stat|__fxstat|__fxstatat|__lxstat|__xstat|fstatfs|statvfs|fstatvfs|lockf|lseek|ftruncate|pread|preadv|pwrite|pwritev|truncate|__pread_chk)(@@.*)?$' /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash

$ strip /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash

$ scanelf -F '%s %p' -qyRgs' ... /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash # same as above
getrlimit,setrlimit /var/tmp/portage/app-shells/dash-0.5.11.5/image/bin/dash
```
Comment 1 Sam James archtester Gentoo Infrastructure gentoo-dev Security 2022-05-26 02:58:59 UTC
We actually forgot to increment the version number. This is 1.3.4:

$ scanelf --version
pax-utils-v1.3.3:
scanelf written for Gentoo by <solar and vapier @ gentoo.org>
Comment 2 Matthew Smith gentoo-dev 2022-08-24 10:14:29 UTC
Seems to be down to symbol versioning, you have two @s in your regex so it doesn't match.

Unsure why we see the symbol versions in scanelf_match_symname on a binary built on an x86 system and not on an amd64 system building with -m32.

$ file dash*
dash: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, not stripped
dash-stripped: ELF 32-bit LSB pie executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 3.2.0, stripped

$ scanelf -F '%s %p' -qyRgs '-^(aio_cancel|aio_error|aio_fsync|aio_read|aio_return|aio_suspend|aio_write|lio_listio|alphasort|getdirentries|readdir|readdir_r|scandir|scandirat|versionsort|creat|fallocate|fopen|fopenat|freopen|open|openat|posix_fadvise|posix_fallocate|__open|__open_2|__openat_2|ftw|nftw|glob|globfree|fgetpos|fopen|freopen|fseeko|fsetpos|ftello|tmpfile|mkostemp|mkostemps|mkstemp|mkstemps|mmap|getrlimit|prlimit|setrlimit|sendfile|fstat|fstatat|lstat|stat|__fxstat|__fxstatat|__lxstat|__xstat|fstatfs|statvfs|fstatvfs|lockf|lseek|ftruncate|pread|preadv|pwrite|pwritev|truncate|__pread_chk)(@.*)?$' dash*
getrlimit@GLIBC_2.2,setrlimit@GLIBC_2.2 dash
getrlimit,setrlimit dash-stripped
Comment 3 Arsen Arsenovic 2022-08-30 19:34:51 UTC
AFAICT, the difference is whether scanelf peeks into symtab or not.
Comment 4 Kacper Słomiński 2022-10-24 21:00:19 UTC
Smaller reproducer that works (for me :p) when compiled on x86_64:

$ cat test.c
#include <stdio.h>

int main() {
	puts("Hello!");
}
$ gcc test.c -o test
$ scanelf -F '%s %p' -qyRgs '-^(puts)(@@.*)?$' test
$ strip test
$ scanelf -F '%s %p' -qyRgs '-^(puts)(@@.*)?$' test
puts test
$ 

Seems like it is what Arsen mentioned, as the "strip" gets rid of .symtab (and leaves .dynsym behind) according to "readelf -s".
Comment 5 Kacper Słomiński 2022-10-25 16:30:38 UTC
Looking a bit further into this, AFAICS we need to look into both .dynsym and .symtab in places that call "scanelf_file_get_symtabs", since .symtab contains the local symbols, and the versioned external symbols, while .dynsym contains unversioned external symbols (with the versions stored in .gnu.version).