Bug 286505 - dlopen deadlocks when target library contains IFUNC
Summary: dlopen deadlocks when target library contains IFUNC
Status: Closed FIXED
Alias: None
Product: Base System
Classification: Unclassified
Component: threads (show other bugs)
Version: Unspecified
Hardware: Any Any
: --- Affects Only Me
Assignee: Konstantin Belousov
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2025-05-01 16:46 UTC by Dapeng Gao
Modified: 2025-05-11 11:27 UTC (History)
1 user (show)

See Also:


Attachments
libthr: implement mask for rtld locks (2.15 KB, patch)
2025-05-01 18:08 UTC, Konstantin Belousov
no flags Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Dapeng Gao 2025-05-01 16:46:11 UTC
An ifunc resolver enters _rtld_bind, which attempts to acquire _rtld_bind_lock. But since we are in the middle of dlopen, the lock has been acquired already, hence deadlocking.

This is similar to bug #286502 but does not involve filter libraries.

Tested on AArch64 but should be reproducible on AMD64. pthread required.

Commands:
cc main.c -lthr -Wl,-rpath=. -o main
cc foo.c -shared -o foo.so
./main

Setup:
$ cat main.c
#include <dlfcn.h>

int main() {
        dlopen("foo.so", RTLD_LAZY);
}

$ cat foo.c
#include <stdio.h>

static void foo_impl() {
}

static void *foo_resolver() {
        puts("foo_resolver()");
        return &foo_impl;
}

void foo() __attribute__((ifunc("foo_resolver")));

void (*foo_ptr)() = &foo;
Comment 1 Konstantin Belousov freebsd_committer freebsd_triage 2025-05-01 18:08:30 UTC
Created attachment 260061 [details]
libthr: implement mask for rtld locks
Comment 2 Dapeng Gao 2025-05-01 21:03:47 UTC
(In reply to Konstantin Belousov from comment #1)

Thanks. Just for my own understanding, does the patch essentially permit a thread to take the same lock more than once? If so, would it still be necessary to have the lock_release/wlock_acquire pair around rtld_resolve_ifunc in reloc_gnu_ifunc_plt?
Comment 3 Konstantin Belousov freebsd_committer freebsd_triage 2025-05-02 07:39:22 UTC
(In reply to Dapeng Gao from comment #2)
In some sense, yes.  We already recurse on read locks (as any r/w lock allows).
Being able to rlock when wlock is already owned is also not a crime, just that
most current r/w locks implementations optimizations do not allow that.

But dropping rtld locks around calls into the user code is generally good,
since it avoids lot of problems besides rtld own locking.  So yes, my intent
is to keep that unlocks.  Unfortunately, it is not easy to do for the ifunc
resolvers in dlopen_object().
Comment 4 Konstantin Belousov freebsd_committer freebsd_triage 2025-05-02 15:40:49 UTC
So I concluded that the approach is too flawed to try to make it work properly.
Instead I decided to fix the thr_rtld locks implementation to allow reader
locks while owning the lock for write.  This passed the libthr tests.

https://reviews.freebsd.org/D50117
Comment 5 commit-hook freebsd_committer freebsd_triage 2025-05-02 18:08:36 UTC
A commit in branch main references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=812c4bf3f17024f192980bbb8a781676cb9cf6b6

commit 812c4bf3f17024f192980bbb8a781676cb9cf6b6
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-02 15:09:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-05-02 18:08:09 +0000

    thr_rtld: accept read lock requests while owning the lock for write

    PR:     286505
    Reviewed by:    olce
    Sponsored by:   The FreeBSD Foundation
    MFC after:      1 week
    Differential revision:  https://reviews.freebsd.org/D50117

 lib/libthr/thread/thr_rtld.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
Comment 6 commit-hook freebsd_committer freebsd_triage 2025-05-10 19:33:33 UTC
A commit in branch stable/14 references this bug:

URL: https://cgit.FreeBSD.org/src/commit/?id=7865d159c5e1b825286777ec236b502ec1261dc0

commit 7865d159c5e1b825286777ec236b502ec1261dc0
Author:     Konstantin Belousov <kib@FreeBSD.org>
AuthorDate: 2025-05-02 15:09:46 +0000
Commit:     Konstantin Belousov <kib@FreeBSD.org>
CommitDate: 2025-05-10 18:57:45 +0000

    thr_rtld: accept read lock requests while owning the lock for write

    PR:     286505

    (cherry picked from commit 812c4bf3f17024f192980bbb8a781676cb9cf6b6)

 lib/libthr/thread/thr_rtld.c | 26 +++++++++++++++++++++-----
 1 file changed, 21 insertions(+), 5 deletions(-)
Comment 7 Mark Linimon freebsd_committer freebsd_triage 2025-05-11 11:27:31 UTC
^Triage: assign to committer who resolved.