On 29/01/14 8:59 PM, Sviatoslav Chagaev wrote:
(amd64, current)

When unloading, ld.so removes elements from grpref list too soon, not
allowing code which runs later to destroy objects in the list.
Next time we dlopen, there are undead objects with e.g. freed elements
in child list. Sooner or later something bad happens, in my case
div by zero.

This fixes the floating point exception experienced with plaympeg2 from
devel/smpeg2.

Patch:

Index: libexec/ld.so/library_subr.c
===================================================================
RCS file: /OpenBSD/src/libexec/ld.so/library_subr.c,v
retrieving revision 1.39
diff -u -p -r1.39 library_subr.c
--- libexec/ld.so/library_subr.c        3 Dec 2013 01:47:05 -0000       1.39
+++ libexec/ld.so/library_subr.c        30 Jan 2014 01:21:23 -0000
@@ -453,11 +453,9 @@ _dl_notify_unload_shlib(elf_object_t *ob
                        _dl_child_refcnt_decrement(n->data);

        if (OBJECT_DLREF_CNT(object) == 0) {
-               while ((n = TAILQ_FIRST(&object->grpref_list)) != NULL) {
-                       TAILQ_REMOVE(&object->grpref_list, n, next_sib);
+               TAILQ_FOREACH(n, &object->grpref_list, next_sib) {
                        n->data->grprefcount--;
                        _dl_notify_unload_shlib(n->data);
-                       _dl_free(n);
                }
        }
  }



How to reproduce (synthesized from libsdl2):

#include <unistd.h>
#include <err.h>
#include <dlfcn.h>
#include <stdio.h>
#include <stdlib.h>

struct lib {
        const char      *name;
        void            *handle;
};

static void
loadlibs(struct lib *libs)
{
        puts("loading");
        for (; libs->name != NULL; ++libs) {
                libs->handle = dlopen(libs->name, RTLD_NOW);
                if (libs->handle == NULL)
                        errx(1, "dlopen: %s: %s", libs->name, dlerror());
        }
}

static void
unloadlibs(struct lib *libs)
{
        puts("unloading");
        for (; libs->name != NULL; ++libs) {
                if (dlclose(libs->handle))
                        errx(1, "dlclose: %s: %s", libs->name, dlerror());
        }
}

int
main(int argc, char **argv)
{
        struct lib libs[] = {
                { "libX11.so" },
                { "libXcursor.so" },
                { "libXrandr.so" },
                { NULL },
        };

        loadlibs(libs);
        unloadlibs(libs);
        loadlibs(libs); /* XXX crash! */

        return 0;
}




--
This message has been scanned for viruses and
dangerous content by MailScanner, and is
believed to be clean.

Reply via email to