Hi,

I see sporadic segmentation faults and this log message on i386:

Dec  9 23:24:54 ot1 /bsd: [cc]91041/433958 pc=affd80b inside cf36000-cf41000: 
bogus syscall

First mmap(2) in ld.so fails with ENOMEM, second call succeeds.
But msyscall(2) uses the address from the first call.

We have to reset exec_start address when we retry.

ok?

bluhm

Index: libexec/ld.so/library_mquery.c
===================================================================
RCS file: /data/mirror/openbsd/cvs/src/libexec/ld.so/library_mquery.c,v
retrieving revision 1.62
diff -u -p -r1.62 library_mquery.c
--- libexec/ld.so/library_mquery.c      30 Nov 2019 23:06:02 -0000      1.62
+++ libexec/ld.so/library_mquery.c      9 Dec 2019 22:43:39 -0000
@@ -112,8 +112,8 @@ _dl_tryload_shlib(const char *libname, i
        Elf_Phdr *ptls = NULL;
        Elf_Addr relro_addr = 0, relro_size = 0;
        struct stat sb;
-       char hbuf[4096], *exec_start = 0;
-       size_t exec_size = 0;
+       char hbuf[4096], *exec_start;
+       size_t exec_size;

 #define ROUND_PG(x) (((x) + align) & ~(align))
 #define TRUNC_PG(x) ((x) & ~(align))
@@ -232,6 +232,8 @@ _dl_tryload_shlib(const char *libname, i
 #define LOFF ((Elf_Addr)lowld->start - lowld->moff)

 retry:
+       exec_start = NULL;
+       exec_size = 0;
        for (ld = lowld; ld != NULL; ld = ld->next) {
                off_t foff;
                int fd, flags;
@@ -264,12 +266,6 @@ retry:

                res = _dl_mmap((void *)(LOFF + ld->moff), ROUND_PG(ld->size),
                    ld->prot, flags | MAP_FIXED | __MAP_NOREPLACE, fd, foff);
-
-               if ((ld->prot & PROT_EXEC) && exec_start == 0) {
-                       exec_start = (void *)(LOFF + ld->moff);
-                       exec_size = ROUND_PG(ld->size);
-               }
-
                if (_dl_mmap_error(res)) {
                        struct load_list *ll;

@@ -281,6 +277,11 @@ retry:

                        lowld->start += ROUND_PG(ld->size);
                        goto retry;
+               }
+
+               if ((ld->prot & PROT_EXEC) && exec_start == NULL) {
+                       exec_start = (void *)(LOFF + ld->moff);
+                       exec_size = ROUND_PG(ld->size);
                }

                ld->start = res;

Reply via email to