[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#31469: marked as done (libc6: dlopen() succeeds when it shouldn't)



Your message dated Wed, 19 Apr 2000 11:35:07 -0700
with message-id <p04310106b523ac091c55@[206.163.71.146]>
and subject line Bug#31469: libc6: dlopen() succeeds when it shouldn't
has caused the attached Bug report to be marked as done.

This means that you claim that the problem has been dealt with.
If this is not the case it is now your responsibility to reopen the
Bug report if necessary, and/or fix the problem forthwith.

(NB: If you are a system administrator and have no idea what I am
talking about this indicates a serious mail system misconfiguration
somewhere.  Please contact me immediately.)

Darren Benham
(administrator, Debian Bugs database)

--------------------------------------
Received: (at submit) by bugs.debian.org; 4 Jan 1999 16:25:09 +0000
Received: (qmail 14971 invoked from network); 4 Jan 1999 16:25:09 -0000
Received: from jhmail.hcf.jhu.edu (HELO jhuml1.hcf.jhu.edu) (128.220.2.86)
  by master.debian.org with SMTP; 4 Jan 1999 16:25:09 -0000
Received: from cush (ppp105.hcf.jhu.edu [128.220.222.105])
 by jhmail.hcf.jhu.edu (PMDF V5.2-29 #26381)
 with ESMTP id <01J653AQTMI6DIYDHH@jhmail.hcf.jhu.edu> for
 submit@bugs.debian.org; Mon, 4 Jan 1999 11:24:36 EDT
Received: from martind by cush with local (Exim 1.891 #4 (Debian))
	id 0zxCnQ-0005RS-00; Mon, 04 Jan 1999 11:24:00 -0500
Date: Mon, 04 Jan 1999 11:24:00 -0500
From: Daniel Martin <Daniel.Martin@jhu.edu>
Subject: libc6: dlopen() succeeds when it shouldn't
Sender: Daniel Martin <Daniel.Martin@jhu.edu>
To: submit@bugs.debian.org
Message-id: <E0zxCnQ-0005RS-00@cush>
X-Mailer: bug 3.1.7

Package: libc6
Version: 2.0.7u-7.1

This is a bit tricky to explain.
When one uses dlopen(), one is supposed to get a NULL returned if
there is some error opening the file, and a non-NULL value otherwise.
If dlopen() is called on a file that is already open, it returns the
same handle.

Here's the kicker - if for some reason a module file can be found, but
for some other reason the module can't be loaded (say, if there's an
undefined symbol somewhere and the module was loaded with RTLD_NOW),
if the module is loaded a _second_ time, dlopen claims to have
succeeded.  This is bad; dlopen should return NULL the second time the
file is opened too.

Below is a shar archive of some code demonstrating the problem - extract 
it and run ./showbug.sh - it'll demonstrate the bug (and will leave a
core file behind).

The code works by loading modules given it on the command line, and
then attempting to execute a certain routine in each module loaded.
With modules that have no unresolved symbols, there isn't a problem;
however, if there's a problem loading a module once, it can lead to
code that branches off any which way.

-- System Information
Debian Release: slink
Kernel Version: Linux cush 2.0.35 #2 Fri Nov 13 01:49:13 EST 1998 i586 unknown

Versions of the packages libc6 depends on:
ii  ldso            1.9.9-5        The Linux dynamic linker, library and utilit

#!/bin/sh
# This is a psuedo-shar archive, created by hand.  HA!
patch <<EOPATCHDATA
diff -Pru dlshowbugmain.c dlshowbugmain.c
--- dlshowbugmain.c	Wed Dec 31 19:00:00 1969
+++ dlshowbugmain.c	Mon Jan  4 10:58:36 1999
@@ -0,0 +1,65 @@
+#include<stdio.h>
+#include <stdlib.h>
+#include <dlfcn.h>
+
+typedef void (*doit_t)(int);
+
+int main (int argc, char *argv[]) {
+  int i;
+  void **handles;
+  doit_t doit;
+  char *err;
+  int flag = 0;
+
+  if (!strcmp("-c", argv[1])) {
+    flag = 1;
+    argv++; argc--;
+  }
+  handles = calloc(argc - 1, sizeof(void *));
+  for (i=1; i < argc; i++) {
+    handles[i-1] = dlopen(argv[i], RTLD_NOW);
+    if (handles[i-1] == NULL) {
+      printf("Error doing a dlopen on \"%s\"[%d]: %s\n",
+             argv[i], i, dlerror());
+      if (flag) {
+        handles[i-1] = dlopen(argv[i], RTLD_NOW);
+        if (handles[i-1] != NULL) {
+          printf("BAD: Second dlopen on \"%s\"[%d] succeeded.", argv[i], i);
+          printf("  Closing it back up.\n");
+          dlclose(handles[i-1]);
+          printf("Closing a second time.\n");
+          dlclose(handles[i-1]);
+          err = dlerror();
+          if (err) printf("\tDlerror: %s\n", err);
+          else printf("\tNo Dlerror\n");
+        }
+        handles[i-1] = NULL;
+      }
+    } else
+      printf("Dlopen on \"%s\"[%d] succeeded.\n", argv[i], i);
+  }
+  printf("Dlopening completed.\n");
+  for (i=1; i < argc; i++) {
+    if (handles[i-1] == NULL) continue;
+    doit = (doit_t) dlsym(handles[i-1], "doit");
+    if (doit != NULL) {
+      (doit)(i);
+    } else {
+      printf("Error doing a dlsym on \"%s\"[%d]: %s\n",
+             argv[i], i, dlerror());
+    }
+  }
+  printf("Dlsyming completed.\n");
+  for (i=1; i < argc; i++) {
+    err = dlerror();  /* Clear old error, if any */
+    if (handles[i-1] == NULL) continue;
+    dlclose(handles[i-1]);
+    err = dlerror();
+    if (err) {
+      printf("Error doing a dlclose on \"%s\"[%d]: %s\n",
+             argv[i], i, err);
+    }
+  }
+  printf("Dlclosing done.\n");
+  free(handles);
+}
diff -Pru dlshowbugmod.c dlshowbugmod.c
--- dlshowbugmod.c	Wed Dec 31 19:00:00 1969
+++ dlshowbugmod.c	Mon Jan  4 10:51:00 1999
@@ -0,0 +1,9 @@
+#include <stdio.h>
+
+extern void sillyfuncname(char *s);
+
+void doit(int pos) {
+  char s[80];
+  sprintf(s, "Module X appears to be at position %d.\n", pos);
+  sillyfuncname(s);
+}
diff -Pru showbug.sh showbug.sh
--- showbug.sh	Wed Dec 31 19:00:00 1969
+++ showbug.sh	Mon Jan  4 10:56:14 1999
@@ -0,0 +1,10 @@
+#!/bin/sh
+set -v
+cc -o dlshowbugmain dlshowbugmain.c -rdynamic -g -ldl
+cc -o dlshowbugmod.so dlshowbugmod.c -fpic -shared -g
+#first run
+./dlshowbugmain ./dlshowbugmod.so
+#That's as it should be.  Now:
+./dlshowbugmain ./dlshowbugmod.so ./dlshowbugmod.so
+#Gah!  Can this be prevented?
+./dlshowbugmain -c ./dlshowbugmod.so ./dlshowbugmod.so
EOPATCHDATA
chmod 0644 dlshowbugmain.c dlshowbugmod.c
chmod 0755 showbug.sh
---------------------------------------
Received: (at 31469-done) by bugs.debian.org; 21 Apr 2000 19:55:53 +0000
Received: (qmail 27323 invoked from network); 21 Apr 2000 19:55:32 -0000
Received: from cerberus.espy.org (mail@206.163.71.145)
  by master.debian.org with SMTP; 21 Apr 2000 19:55:32 -0000
Received: from hercules.espy.org ([206.163.71.146]) [::ffff:206.163.71.146] 
	by cerberus.espy.org with esmtp (Exim 3.12 #1 (Debian GNU/Linux))
	id 12ijWV-000258-00; Fri, 21 Apr 2000 12:55:31 -0700
Mime-Version: 1.0
X-Sender: jk@mail.espy.org
Message-Id: <p04310106b523ac091c55@[206.163.71.146]>
Date: Wed, 19 Apr 2000 11:35:07 -0700
To: 31469-done@bugs.debian.org
From: Joel Klecker <jk@espy.org>
Subject: Re: Bug#31469: libc6: dlopen() succeeds when it shouldn't
Content-Type: text/plain; charset="us-ascii"

>Package: libc6
>Version: 2.0.7u-7.1
>
>This is a bit tricky to explain.
>When one uses dlopen(), one is supposed to get a NULL returned if
>there is some error opening the file, and a non-NULL value otherwise.
>If dlopen() is called on a file that is already open, it returns the
>same handle.
>
>Here's the kicker - if for some reason a module file can be found, but
>for some other reason the module can't be loaded (say, if there's an
>undefined symbol somewhere and the module was loaded with RTLD_NOW),
>if the module is loaded a _second_ time, dlopen claims to have
>succeeded.  This is bad; dlopen should return NULL the second time the
>file is opened too.
>
>Below is a shar archive of some code demonstrating the problem - extract
>it and run ./showbug.sh - it'll demonstrate the bug (and will leave a
>core file behind).
>
>The code works by loading modules given it on the command line, and
>then attempting to execute a certain routine in each module loaded.
>With modules that have no unresolved symbols, there isn't a problem;
>however, if there's a problem loading a module once, it can lead to
>code that branches off any which way.
>
>-- System Information
>Debian Release: slink
>Kernel Version: Linux cush 2.0.35 #2 Fri Nov 13 01:49:13 EST 1998 i586 unknown
>
>Versions of the packages libc6 depends on:
>ii  ldso            1.9.9-5        The Linux dynamic linker, library and
>utilit

This is fixed in glibc 2.1, observe...

jk::pts/0::cerberus::% ./showbug.sh
cc -o dlshowbugmain dlshowbugmain.c -rdynamic -g -ldl
cc -o dlshowbugmod.so dlshowbugmod.c -fpic -shared -g
#first run
./dlshowbugmain ./dlshowbugmod.so
Error doing a dlopen on "./dlshowbugmod.so"[1]: ./dlshowbugmod.so:
undefined symbol: sillyfuncname
Dlopening completed.
Dlsyming completed.
Dlclosing done.
#That's as it should be.  Now:
./dlshowbugmain ./dlshowbugmod.so ./dlshowbugmod.so
Error doing a dlopen on "./dlshowbugmod.so"[1]: ./dlshowbugmod.so:
undefined symbol: sillyfuncname
Error doing a dlopen on "./dlshowbugmod.so"[2]: ./dlshowbugmod.so:
undefined symbol: sillyfuncname
Dlopening completed.
Dlsyming completed.
Dlclosing done.
#Gah!  Can this be prevented?
./dlshowbugmain -c ./dlshowbugmod.so ./dlshowbugmod.so
Error doing a dlopen on "./dlshowbugmod.so"[1]: ./dlshowbugmod.so:
undefined symbol: sillyfuncname
Error doing a dlopen on "./dlshowbugmod.so"[2]: ./dlshowbugmod.so:
undefined symbol: sillyfuncname
Dlopening completed.
Dlsyming completed.
Dlclosing done.
-- 
Joel Klecker (aka Espy)                    Debian GNU/Linux Developer
<URL:mailto:jk@espy.org>                 <URL:mailto:espy@debian.org>
<URL:http://web.espy.org/>               <URL:http://www.debian.org/>


Reply to: