From owner-freebsd-bugs Tue Sep 3 19:20: 9 2002 Delivered-To: freebsd-bugs@hub.freebsd.org Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 4F52437B401 for ; Tue, 3 Sep 2002 19:20:02 -0700 (PDT) Received: from freefall.freebsd.org (freefall.FreeBSD.org [216.136.204.21]) by mx1.FreeBSD.org (Postfix) with ESMTP id 21BFA43E6E for ; Tue, 3 Sep 2002 19:20:02 -0700 (PDT) (envelope-from gnats@FreeBSD.org) Received: from freefall.freebsd.org (gnats@localhost [127.0.0.1]) by freefall.freebsd.org (8.12.4/8.12.4) with ESMTP id g842K2JU043602 for ; Tue, 3 Sep 2002 19:20:02 -0700 (PDT) (envelope-from gnats@freefall.freebsd.org) Received: (from gnats@localhost) by freefall.freebsd.org (8.12.4/8.12.4/Submit) id g842K1ss043601; Tue, 3 Sep 2002 19:20:01 -0700 (PDT) Received: from mx1.FreeBSD.org (mx1.FreeBSD.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id 1968737B400 for ; Tue, 3 Sep 2002 19:17:38 -0700 (PDT) Received: from www.freebsd.org (www.FreeBSD.org [216.136.204.117]) by mx1.FreeBSD.org (Postfix) with ESMTP id B090F43E42 for ; Tue, 3 Sep 2002 19:17:37 -0700 (PDT) (envelope-from nobody@FreeBSD.org) Received: from www.freebsd.org (localhost [127.0.0.1]) by www.freebsd.org (8.12.4/8.12.4) with ESMTP id g842HbOT078577 for ; Tue, 3 Sep 2002 19:17:37 -0700 (PDT) (envelope-from nobody@www.freebsd.org) Received: (from nobody@localhost) by www.freebsd.org (8.12.4/8.12.4/Submit) id g842Hb67078576; Tue, 3 Sep 2002 19:17:37 -0700 (PDT) Message-Id: <200209040217.g842Hb67078576@www.freebsd.org> Date: Tue, 3 Sep 2002 19:17:37 -0700 (PDT) From: Eric Albert To: freebsd-gnats-submit@FreeBSD.org X-Send-Pr-Version: www-1.0 Subject: bin/42397: dlclose for a module loaded with RTLD_GLOBAL can access freed memory and crash Sender: owner-freebsd-bugs@FreeBSD.ORG Precedence: bulk List-ID: List-Archive: (Web Archive) List-Help: (List Instructions) List-Subscribe: List-Unsubscribe: X-Loop: FreeBSD.org >Number: 42397 >Category: bin >Synopsis: dlclose for a module loaded with RTLD_GLOBAL can access freed memory and crash >Confidential: no >Severity: serious >Priority: medium >Responsible: freebsd-bugs >State: open >Quarter: >Keywords: >Date-Required: >Class: sw-bug >Submitter-Id: current-users >Arrival-Date: Tue Sep 03 19:20:01 PDT 2002 >Closed-Date: >Last-Modified: >Originator: Eric Albert >Release: 4.5 >Organization: >Environment: FreeBSD ithilien.qualarius.org 4.5-RELEASE FreeBSD 4.5-RELEASE #0: Mon Jan 28 14:31:56 GMT 2002 murray@builder.freebsdmall.com:/usr/src/sys/compile/GENERIC i386 >Description: Consider two modules, A and B, where A links against B (B is in A's DAG). If both A and B are loaded via dlopen with the RTLD_GLOBAL flag, then B is unloaded via dlclose, when A is unloaded via dlclose B will not be removed from the list of global libraries. Any future symbol lookups in the application -- any standard function call inside or between a shared object -- can crash. Specifically, in unload_object in src/libexec/rtld-elf/rtld.c, root is removed from list_global. Any object in root's DAG whose refcount drops to 0 is freed, but isn't removed from list_global. Any future reference to list_global will access freed memory if any one of those objects in root's DAG was loaded with RTLD_GLOBAL. >How-To-Repeat: Detecting the problem is dependent on the system's behavior when accessing freed memory, so it isn't easy to demonstrate the issue. It's easy to describe how to see it via code inspection, though: Shared library A links against B. In the application, A is loaded via dl_open(/path/to/A, RTLD_GLOBAL). This inserts A into the global list, with B in its DAG. B is loaded via dl_open(/path/to/B, RTLD_GLOBAL). This modifies the refcount on B and inserts B into the global list (if the first step didn't do that; I'm not sure). B is unloaded via dl_close. B's refcount drops to 1, and nothing is unloaded. A is unloaded via dl_close. A's refcount drops to 0. A is removed from the global list. B's refcount drops to 0. In unload_object in src/libexec/rtld-elf/rtld.c, B's underlying data structure is freed, but B is not removed from the global list. The application calls additional functions in other libraries, prompting a symbol lookup. Since B is still in the global list, access to B's element in that list can cause a crash. >Fix: [Not tested] Take the objlist_remove(&list_global, root) line in unload_object and copy it inside the while loop in that function, to be called with obj instead of root if obj->refcount == 0. >Release-Note: >Audit-Trail: >Unformatted: To Unsubscribe: send mail to majordomo@FreeBSD.org with "unsubscribe freebsd-bugs" in the body of the message