Current uClibc-ng version incorrectly calculates clockid
in pthread_getcpuclockid (at least for modern kernels). The simplest test
program
#include <time.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
int main()
{
clockid_t clk;
struct timespec ts;
const int err = pthread_getcpuclockid(pthread_self(), &clk);
if (err != 0) {
errno = err;
perror("pthread_getcpuclockid");
return EXIT_FAILURE;
}
if (clock_gettime(clk, &ts) == -1) {
perror("clock_gettime");
return EXIT_FAILURE;
}
printf("Thread time is %lu.%06lu.\n",
ts.tv_sec,
ts.tv_nsec / 1000);
return EXIT_SUCCESS;
}
fails with
clock_gettime: Invalid argument
Tested on Linux 3.4 / MIPS built with GCC 5.4.0.
Other implementations, for example musl, use a simple calculation
https://git.musl-libc.org/cgit/musl/tree/src/thread/pthread_getcpuclockid.c
Looks strange, but the official glibc repository
https://sourceware.org/git/?p=glibc.git;a=blob_plain;f=nptl/pthread_getcpuc…
has the same implementation as in uClibc-ng.
This fork
https://github.com/lattera/glibc/blob/master/nptl/sysdeps/unix/sysv/linux/p…
use more accurate approach relying on __NR_clock_getres (defined in the
kernel since 2.6.24) with MAKE_THREAD_CPUCLOCK macro copied from the kernel
(
http://lxr.free-electrons.com/source/include/linux/posix-timers.h?v=2.6.24#…,
Linux
4.10 has the same one).
I propose an intermediate solution: use MAKE_THREAD_CPUCLOCK like
computation of clockid when __NR_clock_getres defined and do a fallback to
an older implementation when not.
Hi embedded hackers,
I released 1.0.24 today. Mostly bugfixes and cleanups.
The aarch64 c++ issue is fixed and the long double wrappers
are available for all architectures now. (lvm2 build issues)
I removed old fnmatch/regex implementations to simplify the
code base.
have fun,
Waldemar
Inner loop was using same counter variable (i) as the outer loop, therefore
making outer loop terminate before it visited all of the ELF program segments.
Surrounding code in this inner loop clearly shows the intention that this loop
should not affect the outer one, therefore leading me to the conclusion that
this should be a bug an not expected code.
This bug was detected due to some other bug in ARC binutils that kept setting
TEXTREL for any PIE application.
Apart from the but, I have also moved the debug message inside of the TEXTREL
condition as mprotect is only really called if TELTREL is set.
---
ldso/ldso/ldso.c | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 4e8a49e..a077f20 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -668,12 +668,13 @@ of this helper program; chances are you did not intend to run this program.\n\
* dynamic linking. We can set the protection back
* again once we are done.
*/
- _dl_debug_early("calling mprotect on the application program\n");
/* Now cover the application program. */
if (app_tpnt->dynamic_info[DT_TEXTREL]) {
+ int j;
ElfW(Phdr) *ppnt_outer = ppnt;
+ _dl_debug_early("calling mprotect on the application program\n");
ppnt = (ElfW(Phdr) *) auxvt[AT_PHDR].a_un.a_val;
- for (i = 0; i < auxvt[AT_PHNUM].a_un.a_val; i++, ppnt++) {
+ for (j = 0; j < auxvt[AT_PHNUM].a_un.a_val; j++, ppnt++) {
if (ppnt->p_type == PT_LOAD && !(ppnt->p_flags & PF_W))
_dl_mprotect((void *) (DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & PAGE_ALIGN),
(DL_RELOC_ADDR(app_tpnt->loadaddr, ppnt->p_vaddr) & ADDR_ALIGN) +
--
2.9.0
_dl_zalloc callers don't check for allocaton failure. It kind of makes
sense since such early allocations are unlikely to fail, and even if
they do, ldso would segv anyways thus bringing the issue to attention.
However there's a gcc nuance which led to this patch.
It seems gcc at -O2 (for DODEBUG build), does additional coge gen
analysis for pointer dereference from erroneous paths and it "isolates"
such code paths with a intrinsic abort/trap etc.
The ldso code fragment which was triggering this:
| add_ldso(struct dyn_elf *rpnt)
| if (rpnt)
| ...
| else
| rpnt = _dl_zalloc()
|
| rpnt->dyn = tpnt <---- potential NULL pointer deref
ARC gcc currently generates an abort() call which doesn't exist in ldso,
causing link errors (with a newer vrsion of binutils).
ARM gcc 6.2.1 behaves similarly, altough instead of abort, it generates
a trap inducing UDF instruction
| 367c: ebfffb79 bl 2468 <_dl_malloc>
| 3680: e51b2068 ldr r2, [fp, #-104] ; 0xffffff98
| 3684: e3500000 cmp r0, #0
| 3688: 0a000006 beq 36a8 <_dl_add_elf_hash_table+0x280>
| ...
| 36a8: e5862000 str r2, [r6]
| 36ac: e7f000f0 udf #
So add an explict dl_exit() in dl_zalloc error case to beat the
compiler.
Note that this error propagagtion analysis stops if the function in
consideration (_dl_zalloc) is NOT inlined. Hence the reason it only
shows up for DODEBUG builds which builds ldso at -O2 which is more
aggressive about inlining.
If this patch is not considered worth applying then the workaround
suggested by Claudiu is to to build ldso with
-fno-isolate-erroneous-paths-dereference
Signed-off-by: Vineet Gupta <vgupta(a)synopsys.com>
---
ldso/ldso/ldso.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/ldso/ldso/ldso.c b/ldso/ldso/ldso.c
index 4e8a49ef5f91..539975bcfb0c 100644
--- a/ldso/ldso/ldso.c
+++ b/ldso/ldso/ldso.c
@@ -259,6 +259,8 @@ static void *_dl_zalloc(size_t size)
void *p = _dl_malloc(size);
if (p)
_dl_memset(p, 0, size);
+ else
+ _dl_exit(1);
return p;
}
--
2.7.4
Hi,
What do you think about following patch?
We had some discussion about this recently on the buildroot
mailinglist. Any other use cases other than rpcbind/nfs-utils you
can think of?
best regards
Waldemar
Hi,
I released uClibc-ng 1.0.23 yesterday.
Mostly bugfixes. I have removed the internal RPC
implementation, which is mostly unusable nowadays
as most applications force libtirpc usage (like
rpcbind).
For nios2 I added some ld.so code with the help
of Thorsten, but it is still unusable.
best regards
Waldemar